Update from https://crrev.com/327068

This rolls in //base, //build and //sandbox/linux and updates other
things to match, in particular:

*) Update build_v8.patch
*) Add junit, mockito and roboelectric to DEPS for android test rules
*) Update DEPS for grit
*) Fix up various GN files for os->target_os rename
*) Fix up a few places that were using //base/float_util to use std::isnan
*) Fix up a few places using ApiCompatibilityUtil to use Android SDK directly

as well as a few miscellaneous fixes.

Many portions based on ncbray's work in
https://codereview.chromium.org/1108173002/

R=ncbray@chromium.org
TBR=ncbray@chromium.org

Review URL: https://codereview.chromium.org/1124763003
diff --git a/.gitignore b/.gitignore
index f3526e1..9af90fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,11 +53,14 @@
 /third_party/llvm/
 /third_party/llvm-build/
 /third_party/lss/
+/third_party/junit/src/
 /third_party/mesa/src/
+/third_party/mockito/src/
 /third_party/nss/
 /third_party/pdfium/
 /third_party/pywebsocket/src/
 /third_party/requests/src/
+/third_party/robolectric/src/
 /third_party/sfntly/cpp/
 /third_party/skia/
 /third_party/smhasher/src/
diff --git a/DEPS b/DEPS
index d02c0ab..b16c545 100644
--- a/DEPS
+++ b/DEPS
@@ -24,14 +24,14 @@
   'skia_revision': '409fd66a5afcef5f165f7ccec7c3473add231752',
   'v8_revision': '230d131d173ab2d60291d303177bc04ec3f6e519',
   'angle_revision': 'bdd419f9f5b006e913606e7363125942c8ae06bc',
-  'buildtools_revision': '3b302fef93f7cc58d9b8168466905237484b2772',
+  'buildtools_revision': '15308f469a704c45d15567fa69cd94ce07ad0e1b',
   'dart_revision': '45304',
   'dart_observatory_packages_revision': '43830',
   'pdfium_revision': 'b0115665b0f33971f1b7077740d51e155583cec0',
   'boringssl_revision': '642f1498d056dbba3e50ed5a232ab2f482626dec',
   'lss_revision': 'e079768b7e3a94dcbe7d338496c0c3bde7151b6e',
   'nss_revision': 'bb4e75a43d007518ae7d618665ea2f25b0c60b63',
-  'nacl_revision': '19f11aa481261f38f2a1e9a04e41a7e12aa70e32',
+  'nacl_revision': '87d5dd90911a0657c27574f78e86b7dfc4ad8b29',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -60,7 +60,7 @@
    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '7c81740601355556e630da515b74d889ba2f8d08',
 
   'src/tools/grit':
-    Var('chromium_git') + '/external/grit-i18n.git' + '@' + '0287c187b11ed53590254e4d817e836a44a7a1a7', # from svn revision 186
+    Var('chromium_git') + '/external/grit-i18n.git' + '@' + 'c1b1591a05209c1ad467e845ba8543c22f9072af', # from svn revision 189
 
   'src/v8':
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
@@ -134,6 +134,15 @@
     'src/third_party/jsr-305/src':
         Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
 
+    'src/third_party/junit/src':
+      Var('chromium_git') + '/external/junit.git' + '@' + '45a44647e7306262162e1346b750c3209019f2e1',
+
+    'src/third_party/mockito/src':
+      Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'ed99a52e94a84bd7c467f2443b475a22fcc6ba8e',
+
+    'src/third_party/robolectric/lib':
+      Var('chromium_git') + '/chromium/third_party/robolectric.git' + '@' + '6b63c99a8b6967acdb42cbed0adb067c80efc810',
+
     'src/third_party/android_tools':
      Var('chromium_git') + '/android_tools.git' + '@' + 'a1ffd63322c438627d78ea56eb73fb8779e06950',
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 8b9b5bf..2db7261 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -13,6 +13,18 @@
   defines = [ "BASE_IMPLEMENTATION" ]
 }
 
+if (is_win) {
+  # This is in a separate config so the flags can be applied to dependents.
+  # ldflags in GN aren't automatically inherited.
+  config("base_win_linker_flags") {
+    ldflags = [
+      "/DELAYLOAD:cfgmgr32.dll",
+      "/DELAYLOAD:powrprof.dll",
+      "/DELAYLOAD:setupapi.dll",
+    ]
+  }
+}
+
 source_set("base_paths") {
   sources = [
     "base_paths.cc",
@@ -79,6 +91,8 @@
     "android/important_file_writer_android.h",
     "android/java_handler_thread.cc",
     "android/java_handler_thread.h",
+    "android/java_runtime.cc",
+    "android/java_runtime.h",
     "android/jni_android.cc",
     "android/jni_android.h",
     "android/jni_array.cc",
@@ -104,6 +118,8 @@
     "android/path_utils.h",
     "android/record_histogram.cc",
     "android/record_histogram.h",
+    "android/record_user_action.cc",
+    "android/record_user_action.h",
     "android/scoped_java_ref.cc",
     "android/scoped_java_ref.h",
     "android/sys_utils.cc",
@@ -149,8 +165,8 @@
     "callback_internal.cc",
     "callback_internal.h",
     "cancelable_callback.h",
-    "chromeos/memory_pressure_observer_chromeos.cc",
-    "chromeos/memory_pressure_observer_chromeos.h",
+    "chromeos/memory_pressure_monitor_chromeos.cc",
+    "chromeos/memory_pressure_monitor_chromeos.h",
     "command_line.cc",
     "command_line.h",
     "compiler_specific.h",
@@ -217,7 +233,6 @@
     "files/scoped_file.h",
     "files/scoped_temp_dir.cc",
     "files/scoped_temp_dir.h",
-    "float_util.h",
     "format_macros.h",
     "gtest_prod_util.h",
     "guid.cc",
@@ -320,6 +335,7 @@
     "message_loop/message_pump_win.h",
     "move.h",
     "native_library.h",
+    "native_library_ios.mm",
     "native_library_mac.mm",
     "native_library_posix.cc",
     "native_library_win.cc",
@@ -366,6 +382,8 @@
     "power_monitor/power_observer.h",
     "profiler/alternate_timer.cc",
     "profiler/alternate_timer.h",
+    "profiler/native_stack_sampler.cc",
+    "profiler/native_stack_sampler.h",
     "profiler/scoped_profile.cc",
     "profiler/scoped_profile.h",
     "profiler/scoped_tracker.cc",
@@ -480,6 +498,8 @@
     "third_party/dmg_fp/g_fmt.cc",
     "third_party/icu/icu_utf.cc",
     "third_party/icu/icu_utf.h",
+    "third_party/nspr/prtime.cc",
+    "third_party/nspr/prtime.h",
     "third_party/superfasthash/superfasthash.c",
     "thread_task_runner_handle.cc",
     "thread_task_runner_handle.h",
@@ -623,7 +643,6 @@
     ":base_static",
     "//base/allocator:allocator_extension_thunks",
     "//base/third_party/dynamic_annotations",
-    "//base/third_party/nspr",
     "//third_party/modp_b64",
   ]
 
@@ -731,11 +750,7 @@
       "powrprof.lib",
       "setupapi.lib",
     ]
-    ldflags = [
-      "/DELAYLOAD:cfgmgr32.dll",
-      "/DELAYLOAD:powrprof.dll",
-      "/DELAYLOAD:setupapi.dll",
-    ]
+    all_dependent_configs = [ ":base_win_linker_flags" ]
   } else if (!is_nacl) {
     # Non-Windows.
     deps += [ "//third_party/libevent" ]
@@ -881,7 +896,7 @@
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 }
 
-if (is_linux && !is_chromeos) {
+if (is_win || (is_linux && !is_chromeos)) {
   # TODO(GYP): Figure out which of these work and are needed on other platforms.
   test("base_perftests") {
     sources = [
@@ -899,7 +914,7 @@
     ]
 
     if (is_android) {
-      deps += [ "//testing/android:native_test_native_code" ]
+      deps += [ "//testing/android/native_test:native_test_native_code" ]
     }
   }
 
@@ -938,7 +953,7 @@
   }
 }
 
-source_set("prefs") {
+component("prefs") {
   sources = [
     "prefs/base_prefs_export.h",
     "prefs/default_pref_store.cc",
@@ -1026,17 +1041,6 @@
   ]
 }
 
-# TODO(pasko): Remove this target when crbug.com/424562 is fixed.
-source_set("protect_file_posix") {
-  sources = [
-    "files/protect_file_posix.cc",
-  ]
-
-  deps = [
-    "//base",
-  ]
-}
-
 if (is_win) {
   # Target to manually rebuild pe_image_test.dll which is checked into
   # base/test/data/pe_image.
@@ -1082,7 +1086,7 @@
     "callback_unittest.cc",
     "callback_unittest.nc",
     "cancelable_callback_unittest.cc",
-    "chromeos/memory_pressure_observer_chromeos_unittest.cc",
+    "chromeos/memory_pressure_monitor_chromeos_unittest.cc",
     "command_line_unittest.cc",
     "containers/adapters_unittest.cc",
     "containers/hash_tables_unittest.cc",
@@ -1102,6 +1106,7 @@
     "file_version_info_unittest.cc",
     "files/dir_reader_posix_unittest.cc",
     "files/file_path_unittest.cc",
+    "files/file_path_watcher_unittest.cc",
     "files/file_proxy_unittest.cc",
     "files/file_unittest.cc",
     "files/file_util_proxy_unittest.cc",
@@ -1169,6 +1174,7 @@
     "metrics/sample_vector_unittest.cc",
     "metrics/sparse_histogram_unittest.cc",
     "metrics/statistics_recorder_unittest.cc",
+    "move_unittest.cc",
     "numerics/safe_numerics_unittest.cc",
     "observer_list_unittest.cc",
     "os_compat_android_unittest.cc",
@@ -1236,6 +1242,7 @@
     "test/histogram_tester_unittest.cc",
     "test/test_reg_util_win_unittest.cc",
     "test/trace_event_analyzer_unittest.cc",
+    "test/user_action_tester_unittest.cc",
     "threading/non_thread_safe_unittest.cc",
     "threading/platform_thread_unittest.cc",
     "threading/sequenced_worker_pool_unittest.cc",
@@ -1292,7 +1299,6 @@
     "//base/test:run_all_unittests",
     "//base/test:test_support",
     "//base/third_party/dynamic_annotations",
-    "//base/third_party/nspr",
     "//base/trace_event:trace_event_unittests",
     "//testing/gmock",
     "//testing/gtest",
@@ -1339,6 +1345,8 @@
   if (is_linux) {
     sources -= [ "file_version_info_unittest.cc" ]
     sources += [ "nix/xdg_util_unittest.cc" ]
+    deps += [ "//base/test:malloc_wrapper" ]
+
     if (use_glib) {
       configs += [ "//build/config/linux:glib" ]
     }
@@ -1354,7 +1362,7 @@
   }
 
   if (is_android) {
-    deps += [ "//testing/android:native_test_native_code" ]
+    deps += [ "//testing/android/native_test:native_test_native_code" ]
     set_sources_assignment_filter([])
     sources += [ "debug/proc_maps_linux_unittest.cc" ]
     set_sources_assignment_filter(sources_assignment_filter)
@@ -1390,10 +1398,22 @@
       "android/java/src/org/chromium/base/TraceEvent.java",
       "android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
       "android/java/src/org/chromium/base/metrics/RecordHistogram.java",
+      "android/java/src/org/chromium/base/metrics/RecordUserAction.java",
     ]
+
+    deps = [
+      ":android_runtime_jni_headers",
+    ]
+
     jni_package = "base"
   }
 
+  # GYP: //base.gyp:android_runtime_jni_headers
+  generate_jar_jni("android_runtime_jni_headers") {
+    jni_package = "base"
+    classes = [ "java/lang/Runtime.class" ]
+  }
+
   # GYP: //base.gyp:base_java
   android_library("base_java") {
     srcjar_deps = [
@@ -1432,6 +1452,15 @@
     DEPRECATED_java_in_dir = "test/android/javatests/src"
   }
 
+  # GYP: //base.gyp:base_junit_tests
+  junit_binary("base_junit_tests") {
+    java_files = [ "android/junit/src/org/chromium/base/LogTest.java" ]
+    deps = [
+      ":base_java",
+      ":base_java_test_support",
+    ]
+  }
+
   # GYP: //base.gyp:base_java_application_state
   # GYP: //base.gyp:base_java_library_load_from_apk_status_codes
   # GYP: //base.gyp:base_java_library_process_type
diff --git a/base/OWNERS b/base/OWNERS
index 5d3e38b..9890491 100644
--- a/base/OWNERS
+++ b/base/OWNERS
@@ -1,6 +1,5 @@
 mark@chromium.org
 darin@chromium.org
-ajwong@chromium.org
 thakis@chromium.org
 danakj@chromium.org
 rvargas@chromium.org
diff --git a/base/android/base_jni_registrar.cc b/base/android/base_jni_registrar.cc
index 7439d3c..43ba635 100644
--- a/base/android/base_jni_registrar.cc
+++ b/base/android/base_jni_registrar.cc
@@ -14,6 +14,7 @@
 #include "base/android/field_trial_list.h"
 #include "base/android/important_file_writer_android.h"
 #include "base/android/java_handler_thread.h"
+#include "base/android/java_runtime.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_registrar.h"
 #include "base/android/jni_utils.h"
@@ -22,6 +23,7 @@
 #include "base/android/path_service_android.h"
 #include "base/android/path_utils.h"
 #include "base/android/record_histogram.h"
+#include "base/android/record_user_action.h"
 #include "base/android/sys_utils.h"
 #include "base/android/thread_utils.h"
 #include "base/android/trace_event_binding.h"
@@ -55,6 +57,8 @@
     {"PathUtils", base::android::RegisterPathUtils},
     {"PowerMonitor", base::RegisterPowerMonitor},
     {"RecordHistogram", base::android::RegisterRecordHistogram},
+    {"RecordUserAction", base::android::RegisterRecordUserAction},
+    {"Runtime", base::android::JavaRuntime::Register},
     {"SystemMessageHandler", base::MessagePumpForUI::RegisterBindings},
     {"SysUtils", base::android::SysUtils::Register},
     {"ThreadUtils", base::RegisterThreadUtils},
diff --git a/base/android/build_info.h b/base/android/build_info.h
index e4e84e8..9d73bdb 100644
--- a/base/android/build_info.h
+++ b/base/android/build_info.h
@@ -18,8 +18,6 @@
 // This enumeration maps to the values returned by BuildInfo::sdk_int(),
 // indicating the Android release associated with a given SDK version.
 enum SdkVersion {
-  SDK_VERSION_ICE_CREAM_SANDWICH = 14,
-  SDK_VERSION_ICE_CREAM_SANDWICH_MR1 = 15,
   SDK_VERSION_JELLY_BEAN = 16,
   SDK_VERSION_JELLY_BEAN_MR1 = 17,
   SDK_VERSION_JELLY_BEAN_MR2 = 18,
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index 71b79b1..40cb035 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -4,11 +4,9 @@
 
 package org.chromium.base;
 
-import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -20,16 +18,12 @@
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
-import android.os.Bundle;
 import android.os.PowerManager;
 import android.provider.Settings;
 import android.view.View;
 import android.view.ViewGroup.MarginLayoutParams;
-import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.WindowManager;
-import android.widget.ImageView;
-import android.widget.RemoteViews;
 import android.widget.TextView;
 
 /**
@@ -241,122 +235,9 @@
         }
     }
 
-    /**
-     * @see android.view.View#postInvalidateOnAnimation()
-     */
-    public static void postInvalidateOnAnimation(View view) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            view.postInvalidateOnAnimation();
-        } else {
-            view.postInvalidate();
-        }
-    }
-
-    /**
-     * @see android.view.View#postOnAnimation()
-     */
-    public static void postOnAnimation(View view, Runnable action) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            view.postOnAnimation(action);
-        } else {
-            view.postDelayed(action, getFrameTime());
-        }
-    }
-
-    /**
-     * @see android.view.View#postOnAnimationDelayed()
-     */
-    public static void postOnAnimationDelayed(View view, Runnable action, long delayMillis) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            view.postOnAnimationDelayed(action, delayMillis);
-        } else {
-            view.postDelayed(action, getFrameTime() + delayMillis);
-        }
-    }
-
-    private static long getFrameTime() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
-            return ValueAnimator.getFrameDelay();
-        } else {
-            // Any reasonable fake frame delay will have to do.
-            return 10;
-        }
-    }
-
-    /**
-     * @see android.widget.RemoteViews#setContentDescription(int, CharSequence)
-     */
-    public static void setContentDescriptionForRemoteView(RemoteViews remoteViews, int viewId,
-            CharSequence contentDescription) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
-            remoteViews.setContentDescription(viewId, contentDescription);
-        } else {
-            // setContentDescription() is unavailable in earlier versions.
-        }
-    }
-
-    /**
-     * @see android.app.Activity#startActivity(Intent, Bundle)
-     */
-    public static void startActivity(Context context, Intent intent, Bundle options) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            context.startActivity(intent, options);
-        } else {
-            context.startActivity(intent);
-        }
-    }
-
-    /**
-     * @see android.app.ActivityOptions#toBundle()
-     */
-    public static Bundle toBundle(ActivityOptions options) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            return options.toBundle();
-        } else {
-            return null;
-        }
-    }
-
     // These methods have a new name, and the old name is deprecated.
 
     /**
-     * @see android.view.View#setBackground(Drawable)
-     */
-    @SuppressWarnings("deprecation")
-    public static void setBackgroundForView(View view, Drawable drawable) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            view.setBackground(drawable);
-        } else {
-            view.setBackgroundDrawable(drawable);
-        }
-    }
-
-    /**
-     * @see android.view.ViewTreeObserver#removeOnGlobalLayoutListener()
-     */
-    @SuppressWarnings("deprecation")
-    public static void removeOnGlobalLayoutListener(
-            View view, ViewTreeObserver.OnGlobalLayoutListener listener) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            view.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
-        } else {
-            view.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
-        }
-    }
-
-    /**
-     * @see android.widget.ImageView#setImageAlpha(int)
-     */
-    @SuppressWarnings("deprecation")
-    public static void setImageAlpha(ImageView iv, int alpha) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            iv.setImageAlpha(alpha);
-        } else {
-            iv.setAlpha(alpha);
-        }
-    }
-
-    /**
      * @see android.app.PendingIntent#getCreatorPackage()
      */
     @SuppressWarnings("deprecation")
@@ -494,13 +375,4 @@
             return res.getDrawable(id);
         }
     }
-
-    /**
-     * @see android.view.View#announceForAccessibility(CharSequence text)
-     */
-    public static void announceForAccessibility(View view, CharSequence text) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            view.announceForAccessibility(text);
-        }
-    }
 }
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java
index af02ea2..8c36b61 100644
--- a/base/android/java/src/org/chromium/base/ApplicationStatus.java
+++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -309,9 +309,8 @@
             if (sCachedApplicationState == null) {
                 sCachedApplicationState = determineApplicationState();
             }
+            return sCachedApplicationState.intValue();
         }
-
-        return sCachedApplicationState.intValue();
     }
 
     /**
diff --git a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
index 8f7d39d..2946f6f 100644
--- a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
+++ b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
@@ -8,6 +8,7 @@
 import android.app.Application;
 import android.content.Context;
 import android.os.Bundle;
+import android.view.KeyEvent;
 import android.view.Window;
 
 /**
@@ -47,6 +48,17 @@
                             listener.onWindowFocusChanged(activity, hasFocus);
                         }
                     }
+
+                    @Override
+                    public boolean dispatchKeyEvent(KeyEvent event) {
+                        // TODO(aurimas): remove this once AppCompatDelegateImpl no longer steals
+                        // KEYCODE_MENU. (see b/20529185)
+                        if (event.getKeyCode() == KeyEvent.KEYCODE_MENU
+                                && activity.dispatchKeyEvent(event)) {
+                            return true;
+                        }
+                        return super.dispatchKeyEvent(event);
+                    }
                 });
             }
 
diff --git a/base/android/java/src/org/chromium/base/Log.java b/base/android/java/src/org/chromium/base/Log.java
new file mode 100644
index 0000000..99d755d
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/Log.java
@@ -0,0 +1,357 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.text.TextUtils;
+
+import org.chromium.base.annotations.NoSideEffects;
+
+import java.util.Locale;
+
+/**
+ * Utility class for Logging.
+ *
+ * <p>
+ * Defines logging access points for each feature. They format and forward the logs to
+ * {@link android.util.Log}, allowing to standardize the output, to make it easy to identify
+ * the origin of logs, and enable or disable logging in different parts of the code.
+ * </p>
+ * <p>
+ * Please make use of the formatting capability of the logging methods rather than doing
+ * concatenations in the calling code. In the release builds of Chrome, debug and verbose log
+ * calls will be stripped out of the binary. Concatenations and method calls however will still
+ * remain and be executed. If they can't be avoided, try to generate the logs in a method annotated
+ * with {@link NoSideEffects}. Another possibility is to use
+ * {@link android.util.Log#isLoggable(String, int)}, with {@link Log#makeTag(String)} to get the
+ * correct tag.
+ * </p>
+ *
+ * Usage:
+ * <pre>
+ * private void myMethod(String awesome) {
+ *   Log.i("Group", "My %s message.", awesome);
+ *   Log.d("Group", "My debug message");
+ * }
+ * </pre>
+ *
+ * Logcat output:
+ * <pre>
+ * I/chromium.Group (999): My awesome message
+ * D/chromium.Group (999): [MyClass.java:42] My debug message
+ * </pre>
+ *
+ * Set the log level for a given group:
+ * <pre>
+ * $ adb shell setprop log.tag.chromium.Group VERBOSE
+ * </pre>
+ */
+public class Log {
+    private static final String BASE_TAG = "chromium";
+
+    private Log() {
+        // Static only access
+    }
+
+    /** Returns a formatted log message, using the supplied format and arguments.*/
+    private static String formatLog(String messageTemplate, Object... params) {
+        if (params != null && params.length != 0) {
+            messageTemplate = String.format(Locale.US, messageTemplate, params);
+        }
+
+        return messageTemplate;
+    }
+
+    /**
+     * Returns a formatted log message, using the supplied format and arguments.
+     * The message will be prepended with the filename and line number of the call.
+     */
+    private static String formatLogWithStack(String messageTemplate, Object... params) {
+        return "[" + getCallOrigin() + "] " + formatLog(messageTemplate, params);
+    }
+
+    /**
+     * Returns a full tag for the provided group tag. Full tags longer than 23 characters
+     * will cause a runtime exception later. (see {@link android.util.Log#isLoggable(String, int)})
+     *
+     * @param groupTag {@code null} and empty string are allowed.
+     */
+    public static String makeTag(String groupTag) {
+        if (TextUtils.isEmpty(groupTag)) return BASE_TAG;
+        return BASE_TAG + "." + groupTag;
+    }
+
+    /**
+     * Sends a {@link android.util.Log#VERBOSE} log message.
+     *
+     * For optimization purposes, only the fixed parameters versions are visible. If you need more
+     * than 7 parameters, consider building your log message using a function annotated with
+     * {@link NoSideEffects}.
+     *
+     * @param groupTag Used to identify the source of a log message. It usually refers to the
+     *                 package or feature, to logically group related logs.
+     *
+     * @param messageTemplate The message you would like logged. It is to be specified as a format
+     *                        string.
+     * @param args Arguments referenced by the format specifiers in the format string. If the last
+     *             one is a {@link Throwable}, its trace will be printed.
+     */
+    private static void verbose(String groupTag, String messageTemplate, Object... args) {
+        String tag = makeTag(groupTag);
+        if (android.util.Log.isLoggable(tag, android.util.Log.VERBOSE)) {
+            String message = formatLogWithStack(messageTemplate, args);
+            Throwable tr = getThrowableToLog(args);
+            if (tr != null) {
+                android.util.Log.v(tag, message, tr);
+            } else {
+                android.util.Log.v(tag, message);
+            }
+        }
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 0 arg version. */
+    public static void v(String groupTag, String message) {
+        verbose(groupTag, message);
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 1 arg version. */
+    public static void v(String groupTag, String messageTemplate, Object arg1) {
+        verbose(groupTag, messageTemplate, arg1);
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 2 args version */
+    public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2) {
+        verbose(groupTag, messageTemplate, arg1, arg2);
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 3 args version */
+    public static void v(
+            String groupTag, String messageTemplate, Object arg1, Object arg2, Object arg3) {
+        verbose(groupTag, messageTemplate, arg1, arg2, arg3);
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 4 args version */
+    public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4) {
+        verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4);
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 5 args version */
+    public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4, Object arg5) {
+        verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 6 args version */
+    public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4, Object arg5, Object arg6) {
+        verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    /** Sends a {@link android.util.Log#VERBOSE} log message. 7 args version */
+    public static void v(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) {
+        verbose(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    /**
+     * Sends a {@link android.util.Log#DEBUG} log message.
+     *
+     * For optimization purposes, only the fixed parameters versions are visible. If you need more
+     * than 7 parameters, consider building your log message using a function annotated with
+     * {@link NoSideEffects}.
+     *
+     * @param groupTag Used to identify the source of a log message. It usually refers to the
+     *                 package or feature, to logically group related logs.
+     *
+     * @param messageTemplate The message you would like logged. It is to be specified as a format
+     *                        string.
+     * @param args Arguments referenced by the format specifiers in the format string. If the last
+     *             one is a {@link Throwable}, its trace will be printed.
+     */
+    private static void debug(String groupTag, String messageTemplate, Object... args) {
+        String tag = makeTag(groupTag);
+        if (android.util.Log.isLoggable(tag, android.util.Log.VERBOSE)) {
+            String message = formatLogWithStack(messageTemplate, args);
+            Throwable tr = getThrowableToLog(args);
+            if (tr != null) {
+                android.util.Log.d(tag, message, tr);
+            } else {
+                android.util.Log.d(tag, message);
+            }
+        }
+    }
+
+    /** Sends a {@link android.util.Log#DEBUG} log message. 0 arg version. */
+    public static void d(String groupTag, String message) {
+        debug(groupTag, message);
+    }
+
+    /** Sends a {@link android.util.Log#DEBUG} log message. 1 arg version. */
+    public static void d(String groupTag, String messageTemplate, Object arg1) {
+        debug(groupTag, messageTemplate, arg1);
+    }
+    /** Sends a {@link android.util.Log#DEBUG} log message. 2 args version */
+    public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2) {
+        debug(groupTag, messageTemplate, arg1, arg2);
+    }
+    /** Sends a {@link android.util.Log#DEBUG} log message. 3 args version */
+    public static void d(
+            String groupTag, String messageTemplate, Object arg1, Object arg2, Object arg3) {
+        debug(groupTag, messageTemplate, arg1, arg2, arg3);
+    }
+
+    /** Sends a {@link android.util.Log#DEBUG} log message. 4 args version */
+    public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4) {
+        debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4);
+    }
+
+    /** Sends a {@link android.util.Log#DEBUG} log message. 5 args version */
+    public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4, Object arg5) {
+        debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    /** Sends a {@link android.util.Log#DEBUG} log message. 6 args version */
+    public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4, Object arg5, Object arg6) {
+        debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    /** Sends a {@link android.util.Log#DEBUG} log message. 7 args version */
+    public static void d(String groupTag, String messageTemplate, Object arg1, Object arg2,
+            Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) {
+        debug(groupTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    /**
+     * Sends an {@link android.util.Log#INFO} log message.
+     *
+     * @param groupTag Used to identify the source of a log message. It usually refers to the
+     *                 package or feature, to logically group related logs.
+     * @param messageTemplate The message you would like logged. It is to be specified as a format
+     *                        string.
+     * @param args Arguments referenced by the format specifiers in the format string. If the last
+     *             one is a {@link Throwable}, its trace will be printed.
+     */
+    public static void i(String groupTag, String messageTemplate, Object... args) {
+        String tag = makeTag(groupTag);
+        if (android.util.Log.isLoggable(tag, android.util.Log.INFO)) {
+            String message = formatLog(messageTemplate, args);
+            Throwable tr = getThrowableToLog(args);
+            if (tr != null) {
+                android.util.Log.i(tag, message, tr);
+            } else {
+                android.util.Log.i(tag, message);
+            }
+        }
+    }
+
+    /**
+     * Sends a {@link android.util.Log#WARN} log message.
+     *
+     * @param groupTag Used to identify the source of a log message. It usually refers to the
+     *                 package or feature, to logically group related logs.
+     * @param messageTemplate The message you would like logged. It is to be specified as a format
+     *                        string.
+     * @param args Arguments referenced by the format specifiers in the format string. If the last
+     *             one is a {@link Throwable}, its trace will be printed.
+     */
+    public static void w(String groupTag, String messageTemplate, Object... args) {
+        String tag = makeTag(groupTag);
+        if (android.util.Log.isLoggable(tag, android.util.Log.WARN)) {
+            String message = formatLog(messageTemplate, args);
+            Throwable tr = getThrowableToLog(args);
+            if (tr != null) {
+                android.util.Log.w(tag, message, tr);
+            } else {
+                android.util.Log.w(tag, message);
+            }
+        }
+    }
+
+    /**
+     * Sends an {@link android.util.Log#ERROR} log message.
+     *
+     * @param groupTag Used to identify the source of a log message. It usually refers to the
+     *                 package or feature, to logically group related logs.
+     * @param messageTemplate The message you would like logged. It is to be specified as a format
+     *                        string.
+     * @param args Arguments referenced by the format specifiers in the format string. If the last
+     *             one is a {@link Throwable}, its trace will be printed.
+     */
+    public static void e(String groupTag, String messageTemplate, Object... args) {
+        String tag = makeTag(groupTag);
+        if (android.util.Log.isLoggable(tag, android.util.Log.ERROR)) {
+            String message = formatLog(messageTemplate, args);
+            Throwable tr = getThrowableToLog(args);
+            if (tr != null) {
+                android.util.Log.e(tag, message, tr);
+            } else {
+                android.util.Log.e(tag, message);
+            }
+        }
+    }
+
+    /**
+     * What a Terrible Failure: Used for conditions that should never happen, and logged at
+     * the {@link android.util.Log#ASSERT} level. Depending on the configuration, it might
+     * terminate the process.
+     *
+     * @see android.util.Log#wtf(String, String, Throwable)
+     *
+     * @param groupTag Used to identify the source of a log message. It usually refers to the
+     *                 package or feature, to logically group related logs.
+     * @param messageTemplate The message you would like logged. It is to be specified as a format
+     *                        string.
+     * @param args Arguments referenced by the format specifiers in the format string. If the last
+     *             one is a {@link Throwable}, its trace will be printed.
+     */
+    public static void wtf(String groupTag, String messageTemplate, Object... args) {
+        String tag = makeTag(groupTag);
+        if (android.util.Log.isLoggable(tag, android.util.Log.ERROR)) {
+            String message = formatLog(messageTemplate, args);
+            Throwable tr = getThrowableToLog(args);
+            if (tr != null) {
+                android.util.Log.wtf(tag, message, tr);
+            } else {
+                android.util.Log.wtf(tag, message);
+            }
+        }
+    }
+
+    private static Throwable getThrowableToLog(Object[] args) {
+        if (args == null || args.length == 0) return null;
+
+        Object lastArg = args[args.length - 1];
+
+        if (!(lastArg instanceof Throwable)) return null;
+        return (Throwable) lastArg;
+    }
+
+    /** Returns a string form of the origin of the log call, to be used as secondary tag.*/
+    private static String getCallOrigin() {
+        StackTraceElement[] st = Thread.currentThread().getStackTrace();
+
+        // The call stack should look like:
+        //   n [a variable number of calls depending on the vm used]
+        //  +0 getCallOrigin()
+        //  +1 privateLogFunction: verbose or debug
+        //  +2 formatLogWithStack()
+        //  +3 logFunction: v or d
+        //  +4 caller
+
+        int callerStackIndex;
+        String logClassName = Log.class.getName();
+        for (callerStackIndex = 0; callerStackIndex < st.length; callerStackIndex++) {
+            if (st[callerStackIndex].getClassName().equals(logClassName)) {
+                callerStackIndex += 4;
+                break;
+            }
+        }
+
+        return st[callerStackIndex].getFileName() + ":" + st[callerStackIndex].getLineNumber();
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/PackageUtils.java b/base/android/java/src/org/chromium/base/PackageUtils.java
new file mode 100644
index 0000000..ab554cd
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/PackageUtils.java
@@ -0,0 +1,37 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+/**
+ * This class provides package checking related methods.
+ */
+public class PackageUtils {
+    /**
+     * Retrieves the version of the given package installed on the device.
+     *
+     * @param context Any context.
+     * @param packageName Name of the package to find.
+     * @return The package's version code if found, -1 otherwise.
+     */
+    public static int getPackageVersion(Context context, String packageName) {
+        int versionCode = -1;
+        PackageManager pm = context.getPackageManager();
+        try {
+            PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
+            if (packageInfo != null) versionCode = packageInfo.versionCode;
+        } catch (PackageManager.NameNotFoundException e) {
+            // Do nothing, versionCode stays -1
+        }
+        return versionCode;
+    }
+
+    private PackageUtils() {
+        // Hide constructor
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java
index d70c0cc..5da080e 100644
--- a/base/android/java/src/org/chromium/base/PathUtils.java
+++ b/base/android/java/src/org/chromium/base/PathUtils.java
@@ -6,26 +6,58 @@
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.os.AsyncTask;
 import android.os.Environment;
 
+import java.util.concurrent.ExecutionException;
+
 /**
  * This class provides the path related methods for the native library.
  */
 public abstract class PathUtils {
 
-    private static String sDataDirectorySuffix;
+    private static final int DATA_DIRECTORY = 0;
+    private static final int DATABASE_DIRECTORY = 1;
+    private static final int CACHE_DIRECTORY = 2;
+    private static final int NUM_DIRECTORIES = 3;
+    private static AsyncTask<String, Void, String[]> sDirPathFetchTask;
 
     // Prevent instantiation.
     private PathUtils() {}
 
     /**
-     * Sets the suffix that should be used for the directory where private data is to be stored
-     * by the application.
+     * Starts an asynchronous task to fetch the path of the directory where private data is to be
+     * stored by the application.
+     *
      * @param suffix The private data directory suffix.
      * @see Context#getDir(String, int)
      */
-    public static void setPrivateDataDirectorySuffix(String suffix) {
-        sDataDirectorySuffix = suffix;
+    public static void setPrivateDataDirectorySuffix(String suffix, Context context) {
+        final Context appContext = context.getApplicationContext();
+        sDirPathFetchTask = new AsyncTask<String, Void, String[]>() {
+            @Override
+            protected String[] doInBackground(String... dataDirectorySuffix) {
+                String[] paths = new String[NUM_DIRECTORIES];
+                paths[DATA_DIRECTORY] =
+                        appContext.getDir(dataDirectorySuffix[0], Context.MODE_PRIVATE).getPath();
+                paths[DATABASE_DIRECTORY] = appContext.getDatabasePath("foo").getParent();
+                paths[CACHE_DIRECTORY] = appContext.getCacheDir().getPath();
+                return paths;
+            }
+        }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, suffix);
+    }
+
+    /**
+     * @param index The index of the cached directory path.
+     * @return The directory path requested, or null if not available.
+     */
+    private static String getDirectoryPath(int index) {
+        try {
+            return sDirPathFetchTask.get()[index];
+        } catch (InterruptedException e) {
+        } catch (ExecutionException e) {
+        }
+        return null;
     }
 
     /**
@@ -33,11 +65,8 @@
      */
     @CalledByNative
     public static String getDataDirectory(Context appContext) {
-        if (sDataDirectorySuffix == null) {
-            throw new IllegalStateException(
-                    "setDataDirectorySuffix must be called before getDataDirectory");
-        }
-        return appContext.getDir(sDataDirectorySuffix, Context.MODE_PRIVATE).getPath();
+        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
+        return getDirectoryPath(DATA_DIRECTORY);
     }
 
     /**
@@ -45,8 +74,8 @@
      */
     @CalledByNative
     public static String getDatabaseDirectory(Context appContext) {
-        // Context.getDatabasePath() returns path for the provided filename.
-        return appContext.getDatabasePath("foo").getParent();
+        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
+        return getDirectoryPath(DATABASE_DIRECTORY);
     }
 
     /**
@@ -55,7 +84,8 @@
     @SuppressWarnings("unused")
     @CalledByNative
     public static String getCacheDirectory(Context appContext) {
-        return appContext.getCacheDir().getPath();
+        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
+        return getDirectoryPath(CACHE_DIRECTORY);
     }
 
     /**
diff --git a/base/android/java/src/org/chromium/base/AccessedByNative.java b/base/android/java/src/org/chromium/base/annotations/AccessedByNative.java
similarity index 93%
rename from base/android/java/src/org/chromium/base/AccessedByNative.java
rename to base/android/java/src/org/chromium/base/annotations/AccessedByNative.java
index 3e163fc..6df7c11 100644
--- a/base/android/java/src/org/chromium/base/AccessedByNative.java
+++ b/base/android/java/src/org/chromium/base/annotations/AccessedByNative.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.base;
+package org.chromium.base.annotations;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java b/base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java
similarity index 96%
rename from base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java
rename to base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java
index d5e9b74..c0abcbe 100644
--- a/base/android/java/src/org/chromium/base/CalledByNativeUnchecked.java
+++ b/base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.base;
+package org.chromium.base.annotations;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java b/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java
new file mode 100644
index 0000000..803c3f9
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/annotations/NoSideEffects.java
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to indicate to proguard methods that have no side effects and can be
+ * safely removed if their return value is not used. This is to be used with
+ * {@link org.chromium.base.Log}'s method, that can also be removed by proguard. That way
+ * expensive calls can be left in debug builds but removed in release.
+ */
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+public @interface NoSideEffects {}
diff --git a/base/android/java/src/org/chromium/base/UsedByReflection.java b/base/android/java/src/org/chromium/base/annotations/UsedByReflection.java
similarity index 95%
rename from base/android/java/src/org/chromium/base/UsedByReflection.java
rename to base/android/java/src/org/chromium/base/annotations/UsedByReflection.java
index 7d18fb0..a2af704 100644
--- a/base/android/java/src/org/chromium/base/UsedByReflection.java
+++ b/base/android/java/src/org/chromium/base/annotations/UsedByReflection.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.base;
+package org.chromium.base.annotations;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Target;
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 484c6bc..7dc015d 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -14,6 +14,7 @@
 import org.chromium.base.CommandLine;
 import org.chromium.base.JNINamespace;
 import org.chromium.base.TraceEvent;
+import org.chromium.base.VisibleForTesting;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -127,6 +128,7 @@
      *
      * @throws ProcessInitException
      */
+    @VisibleForTesting
     public void ensureInitialized() throws ProcessInitException {
         ensureInitialized(null, false);
     }
@@ -353,9 +355,14 @@
                         } else {
                             // The library is in its own file.
                             Log.i(TAG, "Loading " + library);
-                            ApplicationInfo applicationInfo = context.getApplicationInfo();
-                            mLoadedFrom.put(library, new File(applicationInfo.nativeLibraryDir,
-                                                              libFilePath).getAbsolutePath());
+                            if (context != null) {
+                                ApplicationInfo applicationInfo = context.getApplicationInfo();
+                                File file = new File(applicationInfo.nativeLibraryDir, libFilePath);
+                                mLoadedFrom.put(library, file.getAbsolutePath());
+                            } else {
+                                Log.i(TAG, "No context, cannot locate the native library file for "
+                                        + library);
+                            }
                         }
 
                         // Load the library.
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java
index dbeb758..7e50998 100644
--- a/base/android/java/src/org/chromium/base/library_loader/Linker.java
+++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -10,10 +10,10 @@
 import android.os.Parcelable;
 import android.util.Log;
 
-import org.chromium.base.AccessedByNative;
 import org.chromium.base.CalledByNative;
 import org.chromium.base.SysUtils;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.AccessedByNative;
 
 import java.io.FileNotFoundException;
 import java.util.HashMap;
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
index c1f6d36..2f4356b 100644
--- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -35,7 +35,7 @@
      * Java equivalent of the UMA_HISTOGRAM_ENUMERATION C++ macro.
      * @param name name of the histogram
      * @param sample sample to be recorded, at least 0 and at most |boundary| - 1
-     * @param boundary upper bound for legal sample values - all sample values has to be strictly
+     * @param boundary upper bound for legal sample values - all sample values have to be strictly
      *        lower than |boundary|
      */
     public static void recordEnumeratedHistogram(String name, int sample, int boundary) {
@@ -43,13 +43,48 @@
     }
 
     /**
-     * Records a sample in a count histogram of the given name. This is the Java equivalent of the
+     * Records a sample in a count histogram. This is the Java equivalent of the
      * UMA_HISTOGRAM_COUNTS C++ macro.
      * @param name name of the histogram
      * @param sample sample to be recorded, at least 1 and at most 999999
      */
     public static void recordCountHistogram(String name, int sample) {
-        nativeRecordCountHistogram(name, System.identityHashCode(name), sample);
+        recordCustomCountHistogram(name, sample, 1, 1000000, 50);
+    }
+
+    /**
+     * Records a sample in a count histogram. This is the Java equivalent of the
+     * UMA_HISTOGRAM_COUNTS_100 C++ macro.
+     * @param name name of the histogram
+     * @param sample sample to be recorded, at least 1 and at most 99
+     */
+    public static void recordCount100Histogram(String name, int sample) {
+        recordCustomCountHistogram(name, sample, 1, 100, 50);
+    }
+
+    /**
+     * Records a sample in a count histogram. This is the Java equivalent of the
+     * UMA_HISTOGRAM_CUSTOM_COUNTS C++ macro.
+     * @param name name of the histogram
+     * @param sample sample to be recorded, at least |min| and at most |max| - 1
+     * @param min lower bound for expected sample values
+     * @param max upper bounds for expected sample values
+     * @param numBuckets the number of buckets
+     */
+    public static void recordCustomCountHistogram(
+            String name, int sample, int min, int max, int numBuckets) {
+        nativeRecordCustomCountHistogram(
+                name, System.identityHashCode(name), sample, min, max, numBuckets);
+    }
+
+    /**
+    * Records a sparse histogram. This is the Java equivalent of UMA_HISTOGRAM_SPARSE_SLOWLY.
+    * @param name name of the histogram
+    * @param sample sample to be recorded. All values of |sample| are valid, including negative
+    *        values.
+    */
+    public static void recordSparseSlowlyHistogram(String name, int sample) {
+        nativeRecordSparseHistogram(name, System.identityHashCode(name), sample);
     }
 
     /**
@@ -133,7 +168,9 @@
     private static native void nativeRecordBooleanHistogram(String name, int key, boolean sample);
     private static native void nativeRecordEnumeratedHistogram(
             String name, int key, int sample, int boundary);
-    private static native void nativeRecordCountHistogram(String name, int key, int sample);
+    private static native void nativeRecordCustomCountHistogram(
+            String name, int key, int sample, int min, int max, int numBuckets);
+    private static native void nativeRecordSparseHistogram(String name, int key, int sample);
 
     private static native int nativeGetHistogramValueCountForTesting(String name, int sample);
     private static native void nativeInitialize();
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
new file mode 100644
index 0000000..d7cc32c
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
@@ -0,0 +1,36 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.metrics;
+
+import org.chromium.base.JNINamespace;
+import org.chromium.base.ThreadUtils;
+
+/**
+ * Java API for recording UMA actions.
+ *
+ * WARNINGS:
+ * JNI calls are relatively costly - avoid using in performance-critical code.
+ *
+ * We use a script (extract_actions.py) to scan the source code and extract actions. A string
+ * literal (not a variable) must be passed to record().
+ */
+@JNINamespace("base::android")
+public class RecordUserAction {
+    public static void record(final String action) {
+        if (ThreadUtils.runningOnUiThread()) {
+            nativeRecordUserAction(action);
+            return;
+        }
+
+        ThreadUtils.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                nativeRecordUserAction(action);
+            }
+        });
+    }
+
+    private static native void nativeRecordUserAction(String action);
+}
diff --git a/base/android/java_runtime.cc b/base/android/java_runtime.cc
new file mode 100644
index 0000000..5be9adf
--- /dev/null
+++ b/base/android/java_runtime.cc
@@ -0,0 +1,25 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/java_runtime.h"
+
+#include "jni/Runtime_jni.h"
+
+namespace base {
+namespace android {
+
+bool JavaRuntime::Register(JNIEnv* env) {
+  return JNI_Runtime::RegisterNativesImpl(env);
+}
+
+void JavaRuntime::GetMemoryUsage(long* total_memory, long* free_memory) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  base::android::ScopedJavaLocalRef<jobject> runtime =
+      JNI_Runtime::Java_Runtime_getRuntime(env);
+  *total_memory = JNI_Runtime::Java_Runtime_totalMemory(env, runtime.obj());
+  *free_memory = JNI_Runtime::Java_Runtime_freeMemory(env, runtime.obj());
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/base/android/java_runtime.h b/base/android/java_runtime.h
new file mode 100644
index 0000000..bde4c5c
--- /dev/null
+++ b/base/android/java_runtime.h
@@ -0,0 +1,28 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_JAVA_RUNTIME_H
+#define BASE_ANDROID_JAVA_RUNTIME_H
+
+#include "base/android/scoped_java_ref.h"
+#include "base/base_export.h"
+
+namespace base {
+namespace android {
+
+// Wrapper class for using the java.lang.Runtime object from jni.
+class BASE_EXPORT JavaRuntime {
+ public:
+  // Registers the jni class (once per process).
+  static bool Register(JNIEnv* env);
+
+  // Fills the total memory used and memory allocated for objects by the java
+  // heap in the current process. Returns true on success.
+  static void GetMemoryUsage(long* total_memory, long* free_memory);
+};
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_JAVA_RUNTIME_H
diff --git a/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java b/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java
new file mode 100644
index 0000000..45b3e21
--- /dev/null
+++ b/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java
@@ -0,0 +1,71 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.os.Build;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test of ApiCompatibilityUtils
+ */
+public class ApiCompatibilityUtilsTest extends InstrumentationTestCase {
+    private static final long WAIT_TIMEOUT_IN_MS = 5000;
+    private static final long SLEEP_INTERVAL_IN_MS = 50;
+
+    static class MockActivity extends Activity {
+        int mFinishAndRemoveTaskCallbackCount;
+        int mFinishCallbackCount;
+        boolean mIsFinishing;
+
+        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+        @Override
+        public void finishAndRemoveTask() {
+            mFinishAndRemoveTaskCallbackCount++;
+            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) mIsFinishing = true;
+        }
+
+        @Override
+        public void finish() {
+            mFinishCallbackCount++;
+            mIsFinishing = true;
+        }
+
+        @Override
+        public boolean isFinishing() {
+            return mIsFinishing;
+        }
+    }
+
+    @SmallTest
+    public void testFinishAndRemoveTask() throws InterruptedException {
+        MockActivity activity = new MockActivity();
+        ApiCompatibilityUtils.finishAndRemoveTask(activity);
+
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
+            assertEquals(1, activity.mFinishAndRemoveTaskCallbackCount);
+            assertEquals(0, activity.mFinishCallbackCount);
+        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
+            long startTime = SystemClock.uptimeMillis();
+            while (activity.mFinishCallbackCount == 0
+                    && SystemClock.uptimeMillis() - startTime < WAIT_TIMEOUT_IN_MS) {
+                Thread.sleep(SLEEP_INTERVAL_IN_MS);
+            }
+
+            // MockActivity#finishAndRemoveTask() never sets isFinishing() to true for LOLLIPOP to
+            // simulate an exceptional case. In that case, MockActivity#finish() should be called
+            // after 3 tries.
+            assertEquals(3, activity.mFinishAndRemoveTaskCallbackCount);
+            assertEquals(1, activity.mFinishCallbackCount);
+        } else {
+            assertEquals(0, activity.mFinishAndRemoveTaskCallbackCount);
+            assertEquals(1, activity.mFinishCallbackCount);
+        }
+        assertTrue(activity.mIsFinishing);
+    }
+}
diff --git a/base/android/javatests/src/org/chromium/base/ObserverListTest.java b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
index 599534a..973682b 100644
--- a/base/android/javatests/src/org/chromium/base/ObserverListTest.java
+++ b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
@@ -72,8 +72,7 @@
 
     private static <T> int getSizeOfIterable(Iterable<T> iterable) {
         int num = 0;
-        for (T el : iterable)
-            num++;
+        for (T el : iterable) num++;
         return num;
     }
 
@@ -91,8 +90,7 @@
         observerList.addObserver(a);
         observerList.addObserver(b);
 
-        for (Observer obs : observerList)
-            obs.observe(10);
+        for (Observer obs : observerList) obs.observe(10);
 
         // Removing an observer not in the list should do nothing.
         observerList.removeObserver(e);
@@ -101,8 +99,7 @@
         observerList.addObserver(c);
         observerList.addObserver(d);
 
-        for (Observer obs : observerList)
-            obs.observe(10);
+        for (Observer obs : observerList) obs.observe(10);
 
         // observe should be called twice on a.
         assertEquals(20, a.mTotal);
@@ -129,8 +126,7 @@
         observerList.addObserver(a);
         observerList.addObserver(b);
 
-        for (Observer obs : observerList)
-            obs.observe(10);
+        for (Observer obs : observerList) obs.observe(10);
 
         assertTrue(observerList.hasObserver(c));
         assertEquals(10, a.mTotal);
@@ -248,7 +244,6 @@
 
         // If we remove an object while iterating, it will be replaced by 'null'.
         observerList.addObserver(a);
-        Iterator<Object> iterator = observerList.iterator();
         assertTrue(observerList.removeObserver(a));
         assertFalse(observerList.removeObserver(null));
     }
diff --git a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java
index 732fe6e..89bee99 100644
--- a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java
+++ b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java
@@ -6,11 +6,11 @@
 
 import android.graphics.Rect;
 
-import org.chromium.base.AccessedByNative;
 import org.chromium.base.CalledByNative;
-import org.chromium.base.CalledByNativeUnchecked;
 import org.chromium.base.JNINamespace;
 import org.chromium.base.NativeClassQualifiedName;
+import org.chromium.base.annotations.AccessedByNative;
+import org.chromium.base.annotations.CalledByNativeUnchecked;
 
 import java.util.ArrayList;
 import java.util.Iterator;
diff --git a/base/android/junit/src/org/chromium/base/LogTest.java b/base/android/junit/src/org/chromium/base/LogTest.java
new file mode 100644
index 0000000..14726fe
--- /dev/null
+++ b/base/android/junit/src/org/chromium/base/LogTest.java
@@ -0,0 +1,93 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowLog;
+
+import java.util.List;
+
+/** Unit tests for {@link Log}. */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {LogTest.PermissiveShadowLog.class})
+public class LogTest {
+    /** Test method for {@link Log#makeTag(String)} */
+    @Test
+    public void testMakeTag() {
+        assertEquals("chromium.Foo", Log.makeTag("Foo"));
+        assertEquals("chromium", Log.makeTag(null));
+        assertEquals("chromium", Log.makeTag(""));
+    }
+
+    /** Tests that the computed call origin is the correct one. */
+    @Test
+    public void callOriginTest() {
+        Log.d("Foo", "Bar");
+
+        List<ShadowLog.LogItem> logs = ShadowLog.getLogs();
+        assertEquals("Only one log should be written", 1, logs.size());
+
+        assertTrue("The origin of the log message (" + logs.get(0).msg + ") looks wrong.",
+                logs.get(0).msg.matches("\\[LogTest.java:\\d+\\].*"));
+    }
+
+    /** Tests that exceptions provided to the log functions are properly recognized and printed. */
+    @Test
+    public void exceptionLoggingTest() {
+        Throwable t = new Throwable() {
+            @Override
+            public String toString() {
+                return "MyThrowable";
+            }
+        };
+
+        Throwable t2 = new Throwable() {
+            @Override
+            public String toString() {
+                return "MyOtherThrowable";
+            }
+        };
+
+        List<ShadowLog.LogItem> logs = ShadowLog.getLogs();
+
+        // The throwable gets printed out
+        Log.i("Foo", "Bar", t);
+        assertEquals(t, logs.get(logs.size() - 1).throwable);
+        assertEquals("Bar", logs.get(logs.size() - 1).msg);
+
+        // The throwable can be both added to the message itself and printed out
+        Log.i("Foo", "Bar %s", t);
+        assertEquals(t, logs.get(logs.size() - 1).throwable);
+        assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg);
+
+        // Non throwable are properly identified
+        Log.i("Foo", "Bar %s", t, "Baz");
+        assertNull(logs.get(logs.size() - 1).throwable);
+        assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg);
+
+        // The last throwable is the one used that is going to be printed out
+        Log.i("Foo", "Bar %s %s", t, t2);
+        assertEquals(t2, logs.get(logs.size() - 1).throwable);
+        assertEquals("Bar MyThrowable MyOtherThrowable", logs.get(logs.size() - 1).msg);
+    }
+
+    /** Needed to allow debug/verbose logging that is disabled by default. */
+    @Implements(android.util.Log.class)
+    public static class PermissiveShadowLog extends ShadowLog {
+        @Implementation
+        public static boolean isLoggable(String tag, int level) {
+            return true;
+        }
+    }
+}
diff --git a/base/android/linker/BUILD.gn b/base/android/linker/BUILD.gn
index 4817d88..190ea47 100644
--- a/base/android/linker/BUILD.gn
+++ b/base/android/linker/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/config/android/config.gni")
 
 assert(is_android)
-assert(!is_android_webview_build)
 
 # GYP: //base/base.gyp:chromium_android_linker
 shared_library("chromium_android_linker") {
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
index 1a11639..b79eaf4 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -128,6 +128,50 @@
   return true;
 }
 
+// Initialize a jfieldID corresponding to the static field of a given |clazz|,
+// with name |field_name| and signature |field_sig|.
+// |env| is the current JNI environment handle.
+// On success, return true and set |*field_id|.
+bool InitStaticFieldId(JNIEnv* env,
+                       jclass clazz,
+                       const char* field_name,
+                       const char* field_sig,
+                       jfieldID* field_id) {
+  *field_id = env->GetStaticFieldID(clazz, field_name, field_sig);
+  if (!*field_id) {
+    LOG_ERROR("Could not find ID for static field '%s'", field_name);
+    return false;
+  }
+  LOG_INFO(
+      "%s: Found ID %p for static field '%s'",
+      __FUNCTION__, *field_id, field_name);
+  return true;
+}
+
+// Initialize a jint corresponding to the static integer field of a class
+// with class name |class_name| and field name |field_name|.
+// |env| is the current JNI environment handle.
+// On success, return true and set |*value|.
+bool InitStaticInt(JNIEnv* env,
+                   const char* class_name,
+                   const char* field_name,
+                   jint* value) {
+  jclass clazz;
+  if (!InitClassReference(env, class_name, &clazz))
+    return false;
+
+  jfieldID field_id;
+  if (!InitStaticFieldId(env, clazz, field_name, "I", &field_id))
+    return false;
+
+  *value = env->GetStaticIntField(clazz, field_id);
+  LOG_INFO(
+      "%s: Found value %d for class '%s', static field '%s'",
+      __FUNCTION__, *value, class_name, field_name);
+
+  return true;
+}
+
 // A class used to model the field IDs of the org.chromium.base.Linker
 // LibInfo inner class, used to communicate data with the Java side
 // of the linker.
@@ -190,6 +234,23 @@
 
 static LibInfo_class s_lib_info_fields;
 
+// Retrieve the SDK build version and pass it into the crazy linker. This
+// needs to be done early in initialization, before any other crazy linker
+// code is run.
+// |env| is the current JNI environment handle.
+// On success, return true.
+bool InitSDKVersionInfo(JNIEnv* env) {
+  jint value = 0;
+  if (!InitStaticInt(env, "android/os/Build$VERSION", "SDK_INT", &value))
+    return false;
+
+  crazy_set_sdk_build_version(static_cast<int>(value));
+  LOG_INFO("%s: Set SDK build version to %d",
+           __FUNCTION__, static_cast<int>(value));
+
+  return true;
+}
+
 // The linker uses a single crazy_context_t object created on demand.
 // There is no need to protect this against concurrent access, locking
 // is already handled on the Java side.
@@ -758,6 +819,11 @@
     return -1;
   }
 
+  // Initialize SDK version info.
+  LOG_INFO("%s: Retrieving SDK version info", __FUNCTION__);
+  if (!InitSDKVersionInfo(env))
+    return -1;
+
   // Register native methods.
   jclass linker_class;
   if (!InitClassReference(env,
diff --git a/base/android/record_histogram.cc b/base/android/record_histogram.cc
index 8b7f7bd..9a68dec 100644
--- a/base/android/record_histogram.cc
+++ b/base/android/record_histogram.cc
@@ -10,6 +10,7 @@
 #include "base/android/jni_string.h"
 #include "base/lazy_instance.h"
 #include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/synchronization/lock.h"
 #include "base/time/time.h"
@@ -60,28 +61,42 @@
     return InsertLocked(j_histogram_key, histogram);
   }
 
-  HistogramBase* CountHistogram(JNIEnv* env,
-                                jstring j_histogram_name,
-                                jint j_histogram_key) {
-    // These values are based on the hard-coded constants in the
-    // UMA_HISTOGRAM_COUNTS macro from base/metrics/histogram_macros.h.
-    const int histogram_min = 1;
-    const int histogram_max = 1000000;
-    const int histogram_num_buckets = 50;
-
+  HistogramBase* CustomCountHistogram(JNIEnv* env,
+                                      jstring j_histogram_name,
+                                      jint j_histogram_key,
+                                      jint j_min,
+                                      jint j_max,
+                                      jint j_num_buckets) {
     DCHECK(j_histogram_name);
     DCHECK(j_histogram_key);
+    int64 min = static_cast<int64>(j_min);
+    int64 max = static_cast<int64>(j_max);
+    int num_buckets = static_cast<int>(j_num_buckets);
     HistogramBase* histogram = FindLocked(j_histogram_key);
     if (histogram) {
-      DCHECK(histogram->HasConstructionArguments(histogram_min, histogram_max,
-                                                 histogram_num_buckets));
+      DCHECK(histogram->HasConstructionArguments(min, max, num_buckets));
       return histogram;
     }
 
     std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
-    histogram = Histogram::FactoryGet(histogram_name, histogram_min,
-                                      histogram_max, histogram_num_buckets,
-                                      HistogramBase::kUmaTargetedHistogramFlag);
+    histogram =
+        Histogram::FactoryGet(histogram_name, min, max, num_buckets,
+                              HistogramBase::kUmaTargetedHistogramFlag);
+    return InsertLocked(j_histogram_key, histogram);
+  }
+
+  HistogramBase* SparseHistogram(JNIEnv* env,
+                                 jstring j_histogram_name,
+                                 jint j_histogram_key) {
+    DCHECK(j_histogram_name);
+    DCHECK(j_histogram_key);
+    HistogramBase* histogram = FindLocked(j_histogram_key);
+    if (histogram)
+      return histogram;
+
+    std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
+    histogram = SparseHistogram::FactoryGet(
+        histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
     return InsertLocked(j_histogram_key, histogram);
   }
 
@@ -158,18 +173,33 @@
       ->Add(sample);
 }
 
-void RecordCountHistogram(JNIEnv* env,
-                          jclass clazz,
-                          jstring j_histogram_name,
-                          jint j_histogram_key,
-                          jint j_sample) {
+void RecordCustomCountHistogram(JNIEnv* env,
+                                jclass clazz,
+                                jstring j_histogram_name,
+                                jint j_histogram_key,
+                                jint j_sample,
+                                jint j_min,
+                                jint j_max,
+                                jint j_num_buckets) {
   int sample = static_cast<int>(j_sample);
 
   g_histograms.Get()
-      .CountHistogram(env, j_histogram_name, j_histogram_key)
+      .CustomCountHistogram(env, j_histogram_name, j_histogram_key, j_min,
+                            j_max, j_num_buckets)
       ->Add(sample);
 }
 
+void RecordSparseHistogram(JNIEnv* env,
+                                 jclass clazz,
+                                 jstring j_histogram_name,
+                                 jint j_histogram_key,
+                                 jint j_sample) {
+    int sample = static_cast<int>(j_sample);
+    g_histograms.Get()
+        .SparseHistogram(env, j_histogram_name, j_histogram_key)
+        ->Add(sample);
+}
+
 void RecordCustomTimesHistogramMilliseconds(JNIEnv* env,
                                             jclass clazz,
                                             jstring j_histogram_name,
diff --git a/base/android/record_user_action.cc b/base/android/record_user_action.cc
new file mode 100644
index 0000000..6172f2e
--- /dev/null
+++ b/base/android/record_user_action.cc
@@ -0,0 +1,24 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/record_user_action.h"
+
+#include "base/android/jni_string.h"
+#include "base/metrics/user_metrics.h"
+#include "jni/RecordUserAction_jni.h"
+
+namespace base {
+namespace android {
+
+static void RecordUserAction(JNIEnv* env, jclass clazz, jstring j_action) {
+  RecordComputedAction(ConvertJavaStringToUTF8(env, j_action));
+}
+
+// Register native methods
+bool RegisterRecordUserAction(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/base/android/record_user_action.h b/base/android/record_user_action.h
new file mode 100644
index 0000000..2c2b854
--- /dev/null
+++ b/base/android/record_user_action.h
@@ -0,0 +1,19 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_RECORD_USER_ACTION_H_
+#define BASE_ANDROID_RECORD_USER_ACTION_H_
+
+#include <jni.h>
+
+namespace base {
+namespace android {
+
+// Registers the native methods through jni
+bool RegisterRecordUserAction(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_RECORD_USER_ACTION_H_
diff --git a/base/async_socket_io_handler.h b/base/async_socket_io_handler.h
index bedb00f..a22c29d 100644
--- a/base/async_socket_io_handler.h
+++ b/base/async_socket_io_handler.h
@@ -76,9 +76,9 @@
  private:
 #if defined(OS_WIN)
   // Implementation of IOHandler on Windows.
-  virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
-                             DWORD bytes_transfered,
-                             DWORD error) override;
+  void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
+                     DWORD bytes_transfered,
+                     DWORD error) override;
 #elif defined(OS_POSIX)
   // Implementation of base::MessageLoopForIO::Watcher.
   void OnFileCanWriteWithoutBlocking(int socket) override {}
diff --git a/base/base.gyp b/base/base.gyp
index ac37a89..e9d3e81 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -103,7 +103,9 @@
             }],
           ],
           'dependencies': [
+            'base_java',
             'base_jni_headers',
+            '../build/android/ndk.gyp:cpu_features',
             '../third_party/ashmem/ashmem.gyp:ashmem',
           ],
           'link_settings': {
@@ -114,14 +116,6 @@
           'sources!': [
             'debug/stack_trace_posix.cc',
           ],
-          'includes': [
-            '../build/android/cpufeatures.gypi',
-          ],
-        }],
-        ['OS == "android" and _toolset == "target" and android_webview_build == 0', {
-          'dependencies': [
-            'base_java',
-          ],
         }],
         ['os_bsd==1', {
           'include_dirs': [
@@ -196,6 +190,9 @@
               ],
             },
           ],
+          'dependencies': [
+           'trace_event/etw_manifest/etw_manifest.gyp:etw_manifest',
+          ],
         }],
         ['OS == "mac" or (OS == "ios" and _toolset == "host")', {
           'link_settings': {
@@ -379,24 +376,6 @@
       ],
     },
     {
-      # TODO(pasko): Remove this target when crbug.com/424562 is fixed.
-      # GN: //base:protect_file_posix
-      'target_name': 'protect_file_posix',
-      'conditions': [
-        ['os_posix == 1', {
-          'type': 'static_library',
-          'dependencies': [
-            'base',
-          ],
-          'sources': [
-            'files/protect_file_posix.cc',
-          ],
-        }, {
-          'type': 'none',
-        }],
-      ],
-    },
-    {
       'target_name': 'base_prefs_test_support',
       'type': 'static_library',
       'dependencies': [
@@ -478,7 +457,7 @@
         'callback_unittest.cc',
         'callback_unittest.nc',
         'cancelable_callback_unittest.cc',
-        'chromeos/memory_pressure_observer_chromeos_unittest.cc',
+        'chromeos/memory_pressure_monitor_chromeos_unittest.cc',
         'command_line_unittest.cc',
         'containers/adapters_unittest.cc',
         'containers/hash_tables_unittest.cc',
@@ -498,6 +477,7 @@
         'file_version_info_unittest.cc',
         'files/dir_reader_posix_unittest.cc',
         'files/file_path_unittest.cc',
+        'files/file_path_watcher_unittest.cc',
         'files/file_proxy_unittest.cc',
         'files/file_unittest.cc',
         'files/file_util_proxy_unittest.cc',
@@ -569,6 +549,7 @@
         'metrics/sample_vector_unittest.cc',
         'metrics/sparse_histogram_unittest.cc',
         'metrics/statistics_recorder_unittest.cc',
+        'move_unittest.cc',
         'numerics/safe_numerics_unittest.cc',
         'observer_list_unittest.cc',
         'os_compat_android_unittest.cc',
@@ -637,6 +618,7 @@
         'test/test_pending_task_unittest.cc',
         'test/test_reg_util_win_unittest.cc',
         'test/trace_event_analyzer_unittest.cc',
+        'test/user_action_tester_unittest.cc',
         'threading/non_thread_safe_unittest.cc',
         'threading/platform_thread_unittest.cc',
         'threading/sequenced_worker_pool_unittest.cc',
@@ -762,11 +744,17 @@
             'message_loop/message_pump_glib_unittest.cc',
           ]
         }],
-        ['OS == "linux" and use_allocator!="none"', {
-            'dependencies': [
-              'allocator/allocator.gyp:allocator',
-            ],
-          },
+        ['OS == "linux"', {
+          'dependencies': [
+            'malloc_wrapper',
+          ],
+          'conditions': [
+            ['use_allocator!="none"', {
+              'dependencies': [
+                'allocator/allocator.gyp:allocator',
+              ],
+            }],
+          ]},
         ],
         ['OS == "win"', {
           'sources!': [
@@ -797,14 +785,6 @@
                 '../third_party/icu/icu.gyp:icudata',
               ],
             }],
-            ['incremental_chrome_dll', {
-              'defines': [
-                # Used only to workaround a linker bug, do not use this
-                # otherwise, and don't make it broader scope. See
-                # http://crbug.com/251251.
-                'INCREMENTAL_LINKING',
-              ],
-            }],
           ],
         }, {  # OS != "win"
           'dependencies': [
@@ -924,6 +904,8 @@
         'test/gtest_xml_util.h',
         'test/histogram_tester.cc',
         'test/histogram_tester.h',
+        'test/ios/wait_util.h',
+        'test/ios/wait_util.mm',
         'test/launcher/test_launcher.cc',
         'test/launcher/test_launcher.h',
         'test/launcher/test_result.cc',
@@ -937,6 +919,8 @@
         'test/mock_chrome_application_mac.mm',
         'test/mock_devices_changed_observer.cc',
         'test/mock_devices_changed_observer.h',
+        'test/mock_entropy_provider.cc',
+        'test/mock_entropy_provider.h',
         'test/mock_log.cc',
         'test/mock_log.h',
         'test/multiprocess_test.cc',
@@ -1007,6 +991,8 @@
         'test/trace_event_analyzer.h',
         'test/trace_to_file.cc',
         'test/trace_to_file.h',
+        'test/user_action_tester.cc',
+        'test/user_action_tester.h',
         'test/values_test_util.cc',
         'test/values_test_util.h',
       ],
@@ -1109,6 +1095,7 @@
             'allocator/allocator.gyp:allocator_extension_thunks_win64',
             '../third_party/modp_b64/modp_b64.gyp:modp_b64_win64',
             'third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
+            'trace_event/etw_manifest/etw_manifest.gyp:etw_manifest',
           ],
           # TODO(gregoryd): direct_dependent_settings should be shared with the
           # 32-bit target, but it doesn't work due to a bug in gyp
@@ -1329,6 +1316,20 @@
         },
       ],
     }],
+    ['OS == "linux"', {
+      'targets': [
+        {
+          'target_name': 'malloc_wrapper',
+          'type': 'shared_library',
+          'dependencies': [
+            'base',
+          ],
+          'sources': [
+            'test/malloc_wrapper.cc',
+          ],
+        }
+      ],
+    }],
     ['OS == "android"', {
       'targets': [
         {
@@ -1358,13 +1359,27 @@
             'android/java/src/org/chromium/base/TraceEvent.java',
             'android/java/src/org/chromium/base/library_loader/LibraryLoader.java',
             'android/java/src/org/chromium/base/metrics/RecordHistogram.java',
+            'android/java/src/org/chromium/base/metrics/RecordUserAction.java',
           ],
           'variables': {
             'jni_gen_package': 'base',
           },
+          'dependencies': [
+            'android_runtime_jni_headers',
+          ],
           'includes': [ '../build/jni_generator.gypi' ],
         },
         {
+          # GN: //base:android_runtime_jni_headers
+          'target_name': 'android_runtime_jni_headers',
+          'type': 'none',
+          'variables': {
+            'jni_gen_package': 'base',
+            'input_java_class': 'java/lang/Runtime.class',
+          },
+          'includes': [ '../build/jar_file_jni_generator.gypi' ],
+        },
+        {
           # TODO(GN)
           'target_name': 'base_unittests_jni_headers',
           'type': 'none',
@@ -1412,15 +1427,9 @@
             'base_java_library_process_type',
             'base_java_memory_pressure_level',
             'base_native_libraries_gen',
+            '../third_party/jsr-305/jsr-305.gyp:jsr_305_javalib',
           ],
           'includes': [ '../build/java.gypi' ],
-          'conditions': [
-            ['android_webview_build==0', {
-              'dependencies': [
-                '../third_party/jsr-305/jsr-305.gyp:jsr_305_javalib',
-              ],
-            }]
-          ],
         },
         {
           # GN: //base:base_java_unittest_support
@@ -1474,6 +1483,23 @@
           'includes': [ '../build/java.gypi' ],
         },
         {
+          # GN: //base:base_junit_tests
+          'target_name': 'base_junit_tests',
+          'type': 'none',
+          'dependencies': [
+            'base_java',
+            'base_java_test_support',
+            '../testing/android/junit/junit_test.gyp:junit_test_support',
+          ],
+          'variables': {
+             'main_class': 'org.chromium.testing.local.JunitTestMain',
+             'src_paths': [
+               '../base/android/junit/',
+             ],
+           },
+          'includes': [ '../build/host_jar.gypi' ],
+        },
+        {
           # GN: //base:base_javatests
           'target_name': 'base_javatests',
           'type': 'none',
@@ -1490,25 +1516,18 @@
           # GN: //base/android/linker:chromium_android_linker
           'target_name': 'chromium_android_linker',
           'type': 'shared_library',
-          'conditions': [
-            # Avoid breaking the webview build because it
-            # does not have <(android_ndk_root)/crazy_linker.gyp.
-            # Note that webview never uses the linker anyway.
-            ['android_webview_build == 0', {
-              'sources': [
-                'android/linker/linker_jni.cc',
-              ],
-              # The crazy linker is never instrumented.
-              'cflags!': [
-                '-finstrument-functions',
-              ],
-              'dependencies': [
-                # The NDK contains the crazy_linker here:
-                #   '<(android_ndk_root)/crazy_linker.gyp:crazy_linker'
-                # However, we use our own fork.  See bug 384700.
-                '../third_party/android_crazy_linker/crazy_linker.gyp:crazy_linker',
-              ],
-            }],
+          'sources': [
+            'android/linker/linker_jni.cc',
+          ],
+          # The crazy linker is never instrumented.
+          'cflags!': [
+            '-finstrument-functions',
+          ],
+          'dependencies': [
+            # The NDK contains the crazy_linker here:
+            #   '<(android_ndk_root)/crazy_linker.gyp:crazy_linker'
+            # However, we use our own fork.  See bug 384700.
+            '../third_party/android_crazy_linker/crazy_linker.gyp:crazy_linker',
           ],
         },
         {
diff --git a/base/base.gypi b/base/base.gypi
index 825bca1..bbc3f60 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -45,6 +45,8 @@
           'android/important_file_writer_android.h',
           'android/java_handler_thread.cc',
           'android/java_handler_thread.h',
+          'android/java_runtime.cc',
+          'android/java_runtime.h',
           'android/jni_android.cc',
           'android/jni_android.h',
           'android/jni_array.cc',
@@ -70,6 +72,8 @@
           'android/path_utils.h',
           'android/record_histogram.cc',
           'android/record_histogram.h',
+          'android/record_user_action.cc',
+          'android/record_user_action.h',
           'android/scoped_java_ref.cc',
           'android/scoped_java_ref.h',
           'android/sys_utils.cc',
@@ -122,8 +126,8 @@
           'callback_internal.h',
           'callback_list.h',
           'cancelable_callback.h',
-          'chromeos/memory_pressure_observer_chromeos.cc',
-          'chromeos/memory_pressure_observer_chromeos.h',
+          'chromeos/memory_pressure_monitor_chromeos.cc',
+          'chromeos/memory_pressure_monitor_chromeos.h',
           'command_line.cc',
           'command_line.h',
           'compiler_specific.h',
@@ -223,7 +227,6 @@
           'files/scoped_file.h',
           'files/scoped_temp_dir.cc',
           'files/scoped_temp_dir.h',
-          'float_util.h',
           'format_macros.h',
           'gtest_prod_util.h',
           'guid.cc',
@@ -329,6 +332,8 @@
           'memory/manual_constructor.h',
           'memory/memory_pressure_listener.cc',
           'memory/memory_pressure_listener.h',
+          'memory/memory_pressure_monitor.cc',
+          'memory/memory_pressure_monitor.h',
           'memory/raw_scoped_refptr_mismatch_checker.h',
           'memory/ref_counted.cc',
           'memory/ref_counted.h',
@@ -391,6 +396,7 @@
           'metrics/user_metrics_action.h',
           'move.h',
           'native_library.h',
+          'native_library_ios.mm',
           'native_library_mac.mm',
           'native_library_posix.cc',
           'native_library_win.cc',
@@ -484,6 +490,8 @@
           'process/process_win.cc',
           'profiler/alternate_timer.cc',
           'profiler/alternate_timer.h',
+          'profiler/native_stack_sampler.cc',
+          'profiler/native_stack_sampler.h',
           'profiler/scoped_profile.cc',
           'profiler/scoped_profile.h',
           'profiler/scoped_tracker.cc',
@@ -836,13 +844,6 @@
               ['include', '^threading/platform_thread_linux\\.cc$'],
             ],
           }],
-          ['OS == "android" and <(android_webview_build)==1', {
-            'defines': [
-               # WebView builds as part of the system which already has sincos;
-               # avoid defining it again as it causes a linker warning.
-               'ANDROID_SINCOS_PROVIDED',
-            ],
-          }],
           ['<(chromeos) == 1', {
             'sources!': [
               'power_monitor/power_monitor_device_source_posix.cc',
@@ -876,6 +877,7 @@
               ['include', '^process/.*_ios\.(cc|mm)$'],
               ['include', '^process/memory_stubs\.cc$'],
               ['include', '^process/process_handle_posix\.cc$'],
+              ['include', '^process/process_metrics\\.cc$'],
               ['exclude', '^threading/platform_thread_internal_posix\\.(h|cc)'],
               ['exclude', 'files/file_path_watcher_fsevents.cc'],
               ['exclude', 'files/file_path_watcher_fsevents.h'],
diff --git a/base/base.isolate b/base/base.isolate
index a245819..c7ba651 100644
--- a/base/base.isolate
+++ b/base/base.isolate
@@ -7,6 +7,8 @@
     # itself, virtually all targets using it has to include icu. The only
     # exception is the Windows sandbox (?).
     '../third_party/icu/icu.isolate',
+    # Sanitizer-instrumented third-party libraries (if enabled).
+    '../third_party/instrumented_libraries/instrumented_libraries.isolate',
   ],
   'conditions': [
     ['use_custom_libcxx==1', {
@@ -16,13 +18,6 @@
         ],
       },
     }],
-    ['use_instrumented_libraries==1', {
-      'variables': {
-        'files': [
-          '<(PRODUCT_DIR)/instrumented_libraries/',
-        ],
-      },
-    }],
     ['OS=="mac" and asan==1', {
       'variables': {
         'files': [
diff --git a/base/base_nacl.gyp b/base/base_nacl.gyp
index 90a2893..40005d2 100644
--- a/base/base_nacl.gyp
+++ b/base/base_nacl.gyp
@@ -39,9 +39,6 @@
               '-fno-strict-aliasing',
             ],
           },
-          'dependencies': [
-            '../native_client/tools.gyp:prep_toolchain',
-          ],
         },
         {
           'target_name': 'base_i18n_nacl',
@@ -63,7 +60,6 @@
             ],
           },
           'dependencies': [
-            '../native_client/tools.gyp:prep_toolchain',
             '../third_party/icu/icu_nacl.gyp:icudata_nacl',
             '../third_party/icu/icu_nacl.gyp:icui18n_nacl',
             '../third_party/icu/icu_nacl.gyp:icuuc_nacl',
@@ -113,7 +109,6 @@
             'rand_util_nacl.cc',
           ],
           'dependencies': [
-            '../native_client/tools.gyp:prep_toolchain',
             '../third_party/libevent/libevent_nacl_nonsfi.gyp:event_nacl_nonsfi',
           ],
         },
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate
index e329152..b1c270c 100644
--- a/base/base_unittests.isolate
+++ b/base/base_unittests.isolate
@@ -50,6 +50,13 @@
         'read_only': 1,
       },
     }],
+    ['OS=="linux"', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/lib/libmalloc_wrapper.so',
+        ],
+      },
+    }],
     ['OS=="mac" and asan==1 and fastbuild==0', {
       'variables': {
         'files': [
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index a30b775..f885403 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -778,10 +778,10 @@
 
   copies = 0;
   assigns = 0;
-  DerivedCopyCounter dervied(&copies, &assigns);
+  DerivedCopyCounter derived(&copies, &assigns);
   Callback<void(CopyCounter)> coerce_cb =
       Bind(&VoidPolymorphic1<CopyCounter>);
-  coerce_cb.Run(CopyCounter(dervied));
+  coerce_cb.Run(CopyCounter(derived));
   EXPECT_GE(2, copies);
   EXPECT_EQ(0, assigns);
 }
diff --git a/base/chromeos/memory_pressure_observer_chromeos.cc b/base/chromeos/memory_pressure_monitor_chromeos.cc
similarity index 68%
rename from base/chromeos/memory_pressure_observer_chromeos.cc
rename to base/chromeos/memory_pressure_monitor_chromeos.cc
index 5691eb8..404c515 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.cc
+++ b/base/chromeos/memory_pressure_monitor_chromeos.cc
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/chromeos/memory_pressure_observer_chromeos.h"
+#include "base/chromeos/memory_pressure_monitor_chromeos.h"
+
+#include <fcntl.h>
+#include <sys/select.h>
 
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/posix/eintr_wrapper.h"
 #include "base/process/process_metrics.h"
 #include "base/time/time.h"
 
@@ -26,7 +30,7 @@
 
 // Threshold constants to emit pressure events.
 const int kNormalMemoryPressureModerateThresholdPercent = 60;
-const int kNormalMemoryPressureCriticalThresholdPercent = 90;
+const int kNormalMemoryPressureCriticalThresholdPercent = 95;
 const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
 const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
 
@@ -40,13 +44,18 @@
   NUM_MEMORY_PRESSURE_LEVELS
 };
 
+// This is the file that will exist if low memory notification is available
+// on the device.  Whenever it becomes readable, it signals a low memory
+// condition.
+const char kLowMemFile[] = "/dev/chromeos-low-mem";
+
 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
 // the moderate pressure event.
 int GetModerateMemoryThresholdInPercent(
-    MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
-  return thresholds == MemoryPressureObserverChromeOS::
+    MemoryPressureMonitorChromeOS::MemoryPressureThresholds thresholds) {
+  return thresholds == MemoryPressureMonitorChromeOS::
                            THRESHOLD_AGGRESSIVE_CACHE_DISCARD ||
-         thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
+         thresholds == MemoryPressureMonitorChromeOS::THRESHOLD_AGGRESSIVE
              ? kAggressiveMemoryPressureModerateThresholdPercent
              : kNormalMemoryPressureModerateThresholdPercent;
 }
@@ -54,10 +63,10 @@
 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
 // the critical pressure event.
 int GetCriticalMemoryThresholdInPercent(
-    MemoryPressureObserverChromeOS::MemoryPressureThresholds thresholds) {
-  return thresholds == MemoryPressureObserverChromeOS::
+    MemoryPressureMonitorChromeOS::MemoryPressureThresholds thresholds) {
+  return thresholds == MemoryPressureMonitorChromeOS::
                            THRESHOLD_AGGRESSIVE_TAB_DISCARD ||
-         thresholds == MemoryPressureObserverChromeOS::THRESHOLD_AGGRESSIVE
+         thresholds == MemoryPressureMonitorChromeOS::THRESHOLD_AGGRESSIVE
              ? kAggressiveMemoryPressureCriticalThresholdPercent
              : kNormalMemoryPressureCriticalThresholdPercent;
 }
@@ -74,9 +83,24 @@
              : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
 }
 
+// This function will be called less then once a second. It will check if
+// the kernel has detected a low memory situation.
+bool IsLowMemoryCondition(int file_descriptor) {
+  fd_set fds;
+  struct timeval tv;
+
+  FD_ZERO(&fds);
+  FD_SET(file_descriptor, &fds);
+
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+
+  return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0;
+}
+
 }  // namespace
 
-MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS(
+MemoryPressureMonitorChromeOS::MemoryPressureMonitorChromeOS(
     MemoryPressureThresholds thresholds)
     : current_memory_pressure_level_(
           MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
@@ -85,35 +109,42 @@
           GetModerateMemoryThresholdInPercent(thresholds)),
       critical_pressure_threshold_percent_(
           GetCriticalMemoryThresholdInPercent(thresholds)),
+      low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))),
       weak_ptr_factory_(this) {
   StartObserving();
+  LOG_IF(ERROR, !low_mem_file_.is_valid()) << "Cannot open kernel listener";
 }
 
-MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() {
+MemoryPressureMonitorChromeOS::~MemoryPressureMonitorChromeOS() {
   StopObserving();
 }
 
-void MemoryPressureObserverChromeOS::ScheduleEarlyCheck() {
+void MemoryPressureMonitorChromeOS::ScheduleEarlyCheck() {
   MessageLoop::current()->PostTask(
       FROM_HERE,
-      Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
+      Bind(&MemoryPressureMonitorChromeOS::CheckMemoryPressure,
            weak_ptr_factory_.GetWeakPtr()));
 }
 
-void MemoryPressureObserverChromeOS::StartObserving() {
+MemoryPressureListener::MemoryPressureLevel
+MemoryPressureMonitorChromeOS::GetCurrentPressureLevel() const {
+  return current_memory_pressure_level_;
+}
+
+void MemoryPressureMonitorChromeOS::StartObserving() {
   timer_.Start(FROM_HERE,
                TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
-               Bind(&MemoryPressureObserverChromeOS::
+               Bind(&MemoryPressureMonitorChromeOS::
                         CheckMemoryPressureAndRecordStatistics,
                     weak_ptr_factory_.GetWeakPtr()));
 }
 
-void MemoryPressureObserverChromeOS::StopObserving() {
+void MemoryPressureMonitorChromeOS::StopObserving() {
   // If StartObserving failed, StopObserving will still get called.
   timer_.Stop();
 }
 
-void MemoryPressureObserverChromeOS::CheckMemoryPressureAndRecordStatistics() {
+void MemoryPressureMonitorChromeOS::CheckMemoryPressureAndRecordStatistics() {
   CheckMemoryPressure();
 
   // Record UMA histogram statistics for the current memory pressure level.
@@ -135,13 +166,35 @@
                             NUM_MEMORY_PRESSURE_LEVELS);
 }
 
-void MemoryPressureObserverChromeOS::CheckMemoryPressure() {
+void MemoryPressureMonitorChromeOS::CheckMemoryPressure() {
   MemoryPressureListener::MemoryPressureLevel old_pressure =
       current_memory_pressure_level_;
-  current_memory_pressure_level_ =
-      GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent(),
-                                          moderate_pressure_threshold_percent_,
-                                          critical_pressure_threshold_percent_);
+
+  // If we have the kernel low memory observer, we use it's flag instead of our
+  // own computation (for now). Note that in "simulation mode" it can be null.
+  // TODO(skuhne): We need to add code which makes sure that the kernel and this
+  // computation come to similar results and then remove this override again.
+  // TODO(skuhne): Add some testing framework here to see how close the kernel
+  // and the internal functions are.
+  if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) {
+    current_memory_pressure_level_ =
+        MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
+  } else {
+    current_memory_pressure_level_ = GetMemoryPressureLevelFromFillLevel(
+        GetUsedMemoryInPercent(),
+        moderate_pressure_threshold_percent_,
+        critical_pressure_threshold_percent_);
+
+    // When listening to the kernel, we ignore the reported memory pressure
+    // level from our own computation and reduce critical to moderate.
+    if (low_mem_file_.is_valid() &&
+        current_memory_pressure_level_ ==
+        MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
+      current_memory_pressure_level_ =
+          MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
+    }
+  }
+
   // In case there is no memory pressure we do not notify.
   if (current_memory_pressure_level_ ==
       MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
@@ -171,7 +224,7 @@
 }
 
 // Gets the used ChromeOS memory in percent.
-int MemoryPressureObserverChromeOS::GetUsedMemoryInPercent() {
+int MemoryPressureMonitorChromeOS::GetUsedMemoryInPercent() {
   base::SystemMemoryInfoKB info;
   if (!base::GetSystemMemoryInfo(&info)) {
     VLOG(1) << "Cannot determine the free memory of the system.";
diff --git a/base/chromeos/memory_pressure_observer_chromeos.h b/base/chromeos/memory_pressure_monitor_chromeos.h
similarity index 78%
rename from base/chromeos/memory_pressure_observer_chromeos.h
rename to base/chromeos/memory_pressure_monitor_chromeos.h
index 9af07d4..45855eb 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.h
+++ b/base/chromeos/memory_pressure_monitor_chromeos.h
@@ -2,28 +2,30 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_
-#define BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_
+#ifndef BASE_CHROMEOS_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
+#define BASE_CHROMEOS_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
 
 #include "base/base_export.h"
+#include "base/files/scoped_file.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
+#include "base/memory/memory_pressure_monitor.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
 
 namespace base {
 
-class TestMemoryPressureObserver;
+class TestMemoryPressureMonitor;
 
 ////////////////////////////////////////////////////////////////////////////////
-// MemoryPressureObserverChromeOS
+// MemoryPressureMonitorChromeOS
 //
 // A class to handle the observation of our free memory. It notifies the
 // MemoryPressureListener of memory fill level changes, so that it can take
 // action to reduce memory resources accordingly.
 //
-class BASE_EXPORT MemoryPressureObserverChromeOS {
+class BASE_EXPORT MemoryPressureMonitorChromeOS : public MemoryPressureMonitor {
  public:
   using GetUsedMemoryInPercentCallback = int (*)();
 
@@ -47,8 +49,8 @@
     THRESHOLD_AGGRESSIVE = 4
   };
 
-  explicit MemoryPressureObserverChromeOS(MemoryPressureThresholds thresholds);
-  virtual ~MemoryPressureObserverChromeOS();
+  explicit MemoryPressureMonitorChromeOS(MemoryPressureThresholds thresholds);
+  ~MemoryPressureMonitorChromeOS() override;
 
   // Redo the memory pressure calculation soon and call again if a critical
   // memory pressure prevails. Note that this call will trigger an asynchronous
@@ -56,12 +58,11 @@
   void ScheduleEarlyCheck();
 
   // Get the current memory pressure level.
-  base::MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel() {
-    return current_memory_pressure_level_;
-  }
+  MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel() const
+      override;
 
  private:
-  friend TestMemoryPressureObserver;
+  friend TestMemoryPressureMonitor;
   // Starts observing the memory fill level.
   // Calls to StartObserving should always be matched with calls to
   // StopObserving.
@@ -89,7 +90,7 @@
 
   // A periodic timer to check for resource pressure changes. This will get
   // replaced by a kernel triggered event system (see crbug.com/381196).
-  base::RepeatingTimer<MemoryPressureObserverChromeOS> timer_;
+  base::RepeatingTimer<MemoryPressureMonitorChromeOS> timer_;
 
   // To slow down the amount of moderate pressure event calls, this counter
   // gets used to count the number of events since the last event occured.
@@ -99,11 +100,14 @@
   const int moderate_pressure_threshold_percent_;
   const int critical_pressure_threshold_percent_;
 
-  base::WeakPtrFactory<MemoryPressureObserverChromeOS> weak_ptr_factory_;
+  // File descriptor used to detect low memory condition.
+  ScopedFD low_mem_file_;
 
-  DISALLOW_COPY_AND_ASSIGN(MemoryPressureObserverChromeOS);
+  base::WeakPtrFactory<MemoryPressureMonitorChromeOS> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitorChromeOS);
 };
 
 }  // namespace base
 
-#endif  // BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_
+#endif  // BASE_CHROMEOS_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
diff --git a/base/chromeos/memory_pressure_observer_chromeos_unittest.cc b/base/chromeos/memory_pressure_monitor_chromeos_unittest.cc
similarity index 76%
rename from base/chromeos/memory_pressure_observer_chromeos_unittest.cc
rename to base/chromeos/memory_pressure_monitor_chromeos_unittest.cc
index a227f93..72e00d3 100644
--- a/base/chromeos/memory_pressure_observer_chromeos_unittest.cc
+++ b/base/chromeos/memory_pressure_monitor_chromeos_unittest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
-#include "base/chromeos/memory_pressure_observer_chromeos.h"
+#include "base/chromeos/memory_pressure_monitor_chromeos.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/message_loop/message_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -40,17 +40,17 @@
 
 }  // namespace
 
-class TestMemoryPressureObserver : public MemoryPressureObserverChromeOS {
+class TestMemoryPressureMonitor : public MemoryPressureMonitorChromeOS {
  public:
-  TestMemoryPressureObserver() :
-    MemoryPressureObserverChromeOS(
-        MemoryPressureObserverChromeOS::THRESHOLD_DEFAULT),
+  TestMemoryPressureMonitor() :
+    MemoryPressureMonitorChromeOS(
+        MemoryPressureMonitorChromeOS::THRESHOLD_DEFAULT),
     memory_in_percent_override_(0) {
     // Disable any timers which are going on and set a special memory reporting
     // function.
     StopObserving();
   }
-  ~TestMemoryPressureObserver() override {}
+  ~TestMemoryPressureMonitor() override {}
 
   void SetMemoryInPercentOverride(int percent) {
     memory_in_percent_override_ = percent;
@@ -66,45 +66,45 @@
   }
 
   int memory_in_percent_override_;
-  DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureObserver);
+  DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
 };
 
 // This test tests the various transition states from memory pressure, looking
 // for the correct behavior on event reposting as well as state updates.
-TEST(MemoryPressureObserverChromeOSTest, CheckMemoryPressure) {
+TEST(MemoryPressureMonitorChromeOSTest, CheckMemoryPressure) {
   base::MessageLoopForUI message_loop;
-  scoped_ptr<TestMemoryPressureObserver> observer(
-      new TestMemoryPressureObserver);
+  scoped_ptr<TestMemoryPressureMonitor> monitor(
+      new TestMemoryPressureMonitor);
   scoped_ptr<MemoryPressureListener> listener(
       new MemoryPressureListener(base::Bind(&OnMemoryPressure)));
   // Checking the memory pressure while 0% are used should not produce any
   // events.
-  observer->SetMemoryInPercentOverride(0);
+  monitor->SetMemoryInPercentOverride(0);
   ResetOnMemoryPressureCalled();
 
-  observer->CheckMemoryPressureForTest();
+  monitor->CheckMemoryPressureForTest();
   message_loop.RunUntilIdle();
   EXPECT_FALSE(WasOnMemoryPressureCalled());
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
-            observer->GetCurrentPressureLevel());
+            monitor->GetCurrentPressureLevel());
 
   // Setting the memory level to 80% should produce a moderate pressure level.
-  observer->SetMemoryInPercentOverride(80);
-  observer->CheckMemoryPressureForTest();
+  monitor->SetMemoryInPercentOverride(80);
+  monitor->CheckMemoryPressureForTest();
   message_loop.RunUntilIdle();
   EXPECT_TRUE(WasOnMemoryPressureCalled());
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
-            observer->GetCurrentPressureLevel());
+            monitor->GetCurrentPressureLevel());
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
             on_memory_pressure_level);
 
   // We need to check that the event gets reposted after a while.
   int i = 0;
   for (; i < 100; i++) {
-    observer->CheckMemoryPressureForTest();
+    monitor->CheckMemoryPressureForTest();
     message_loop.RunUntilIdle();
     EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
-              observer->GetCurrentPressureLevel());
+              monitor->GetCurrentPressureLevel());
     if (WasOnMemoryPressureCalled()) {
       EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
                 on_memory_pressure_level);
@@ -116,41 +116,41 @@
   EXPECT_GE(99, i);
 
   // Setting the memory usage to 99% should produce critical levels.
-  observer->SetMemoryInPercentOverride(99);
-  observer->CheckMemoryPressureForTest();
+  monitor->SetMemoryInPercentOverride(99);
+  monitor->CheckMemoryPressureForTest();
   message_loop.RunUntilIdle();
   EXPECT_TRUE(WasOnMemoryPressureCalled());
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
             on_memory_pressure_level);
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
-            observer->GetCurrentPressureLevel());
+            monitor->GetCurrentPressureLevel());
 
   // Calling it again should immediately produce a second call.
-  observer->CheckMemoryPressureForTest();
+  monitor->CheckMemoryPressureForTest();
   message_loop.RunUntilIdle();
   EXPECT_TRUE(WasOnMemoryPressureCalled());
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
             on_memory_pressure_level);
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
-            observer->GetCurrentPressureLevel());
+            monitor->GetCurrentPressureLevel());
 
   // When lowering the pressure again we should not get an event, but the
   // pressure should go back to moderate.
-  observer->SetMemoryInPercentOverride(80);
-  observer->CheckMemoryPressureForTest();
+  monitor->SetMemoryInPercentOverride(80);
+  monitor->CheckMemoryPressureForTest();
   message_loop.RunUntilIdle();
   EXPECT_FALSE(WasOnMemoryPressureCalled());
   EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
-            observer->GetCurrentPressureLevel());
+            monitor->GetCurrentPressureLevel());
 
   // We should need exactly the same amount of calls as before, before the next
   // call comes in.
   int j = 0;
   for (; j < 100; j++) {
-    observer->CheckMemoryPressureForTest();
+    monitor->CheckMemoryPressureForTest();
     message_loop.RunUntilIdle();
     EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
-              observer->GetCurrentPressureLevel());
+              monitor->GetCurrentPressureLevel());
     if (WasOnMemoryPressureCalled()) {
       EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
                 on_memory_pressure_level);
diff --git a/base/command_line.cc b/base/command_line.cc
index d28a4b4..61ff5c1 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -263,7 +263,12 @@
 }
 
 bool CommandLine::HasSwitch(const std::string& switch_string) const {
-  return switches_.find(LowerASCIIOnWindows(switch_string)) != switches_.end();
+  DCHECK_EQ(StringToLowerASCII(switch_string), switch_string);
+  return switches_.find(switch_string) != switches_.end();
+}
+
+bool CommandLine::HasSwitch(const char string_constant[]) const {
+  return HasSwitch(std::string(string_constant));
 }
 
 std::string CommandLine::GetSwitchValueASCII(
diff --git a/base/command_line.h b/base/command_line.h
index 85d924a..439921e 100644
--- a/base/command_line.h
+++ b/base/command_line.h
@@ -142,8 +142,11 @@
   void SetProgram(const FilePath& program);
 
   // Returns true if this command line contains the given switch.
-  // (Switch names are case-insensitive).
+  // Switch names should only be lowercase.
+  // The second override provides an optimized version to avoid inlining the
+  // codegen for the string allocation.
   bool HasSwitch(const std::string& switch_string) const;
+  bool HasSwitch(const char switch_constant[]) const;
 
   // Returns the value associated with the given switch. If the switch has no
   // value or isn't present, this method returns the empty string.
diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc
index e395c85..db1a0b2 100644
--- a/base/command_line_unittest.cc
+++ b/base/command_line_unittest.cc
@@ -60,12 +60,13 @@
             cl.GetProgram().value());
 
   EXPECT_TRUE(cl.HasSwitch("foo"));
-  EXPECT_TRUE(cl.HasSwitch("bAr"));
+#if defined(OS_WIN)
+  EXPECT_TRUE(cl.HasSwitch("bar"));
+#else
+  EXPECT_FALSE(cl.HasSwitch("bar"));
+#endif
   EXPECT_TRUE(cl.HasSwitch("baz"));
   EXPECT_TRUE(cl.HasSwitch("spaetzle"));
-#if defined(OS_WIN)
-  EXPECT_TRUE(cl.HasSwitch("SPAETZLE"));
-#endif
   EXPECT_TRUE(cl.HasSwitch("other-switches"));
   EXPECT_TRUE(cl.HasSwitch("input-translation"));
 
@@ -128,7 +129,6 @@
   EXPECT_TRUE(cl.HasSwitch("bar"));
   EXPECT_TRUE(cl.HasSwitch("baz"));
   EXPECT_TRUE(cl.HasSwitch("spaetzle"));
-  EXPECT_TRUE(cl.HasSwitch("SPAETZLE"));
   EXPECT_TRUE(cl.HasSwitch("other-switches"));
   EXPECT_TRUE(cl.HasSwitch("input-translation"));
   EXPECT_TRUE(cl.HasSwitch("quotes"));
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 034cf06..63297dc 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -128,13 +128,11 @@
 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
 #endif
 
-// Return the byte alignment of the given type (available at compile time).  Use
-// sizeof(type) prior to checking __alignof to workaround Visual C++ bug:
-// http://goo.gl/isH0C
+// Return the byte alignment of the given type (available at compile time).
 // Use like:
 //   ALIGNOF(int32)  // this would be 4
 #if defined(COMPILER_MSVC)
-#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
+#define ALIGNOF(type) __alignof(type)
 #elif defined(COMPILER_GCC)
 #define ALIGNOF(type) __alignof__(type)
 #endif
diff --git a/base/file_version_info_win.h b/base/file_version_info_win.h
index 0e0f271..92d0844 100644
--- a/base/file_version_info_win.h
+++ b/base/file_version_info_win.h
@@ -18,26 +18,26 @@
 class FileVersionInfoWin : public FileVersionInfo {
  public:
   BASE_EXPORT FileVersionInfoWin(void* data, WORD language, WORD code_page);
-  BASE_EXPORT ~FileVersionInfoWin();
+  BASE_EXPORT ~FileVersionInfoWin() override;
 
   // Accessors to the different version properties.
   // Returns an empty string if the property is not found.
-  virtual base::string16 company_name() override;
-  virtual base::string16 company_short_name() override;
-  virtual base::string16 product_name() override;
-  virtual base::string16 product_short_name() override;
-  virtual base::string16 internal_name() override;
-  virtual base::string16 product_version() override;
-  virtual base::string16 private_build() override;
-  virtual base::string16 special_build() override;
-  virtual base::string16 comments() override;
-  virtual base::string16 original_filename() override;
-  virtual base::string16 file_description() override;
-  virtual base::string16 file_version() override;
-  virtual base::string16 legal_copyright() override;
-  virtual base::string16 legal_trademarks() override;
-  virtual base::string16 last_change() override;
-  virtual bool is_official_build() override;
+  base::string16 company_name() override;
+  base::string16 company_short_name() override;
+  base::string16 product_name() override;
+  base::string16 product_short_name() override;
+  base::string16 internal_name() override;
+  base::string16 product_version() override;
+  base::string16 private_build() override;
+  base::string16 special_build() override;
+  base::string16 comments() override;
+  base::string16 original_filename() override;
+  base::string16 file_description() override;
+  base::string16 file_version() override;
+  base::string16 legal_copyright() override;
+  base::string16 legal_trademarks() override;
+  base::string16 last_change() override;
+  bool is_official_build() override;
 
   // Lets you access other properties not covered above.
   BASE_EXPORT bool GetValue(const wchar_t* name, std::wstring* value);
diff --git a/base/files/file.cc b/base/files/file.cc
index a997074..8030bf1 100644
--- a/base/files/file.cc
+++ b/base/files/file.cc
@@ -4,10 +4,8 @@
 
 #include "base/files/file.h"
 #include "base/files/file_path.h"
-
-#if defined(OS_POSIX)
-#include "base/files/file_posix_hooks_internal.h"
-#endif
+#include "base/metrics/histogram.h"
+#include "base/timer/elapsed_timer.h"
 
 namespace base {
 
@@ -42,8 +40,6 @@
       async_(false) {
 #if defined(OS_POSIX)
   DCHECK_GE(platform_file, -1);
-  if (IsValid())
-    ProtectFileDescriptor(platform_file);
 #endif
 }
 
@@ -58,10 +54,6 @@
       error_details_(other.object->error_details()),
       created_(other.object->created()),
       async_(other.object->async_) {
-#if defined(OS_POSIX)
-   if (IsValid())
-     ProtectFileDescriptor(GetPlatformFile());
-#endif
 }
 
 File::~File() {
@@ -86,7 +78,7 @@
     error_details_ = FILE_ERROR_ACCESS_DENIED;
     return;
   }
-  InitializeUnsafe(name, flags);
+  DoInitialize(name, flags);
 }
 #endif
 
@@ -134,4 +126,11 @@
   return "";
 }
 
+bool File::Flush() {
+  ElapsedTimer timer;
+  bool return_value = DoFlush();
+  UMA_HISTOGRAM_TIMES("PlatformFile.FlushTime", timer.Elapsed());
+  return return_value;
+}
+
 }  // namespace base
diff --git a/base/files/file.h b/base/files/file.h
index 13c8a96..89077b4 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -150,13 +150,13 @@
     bool is_symbolic_link;
 
     // The last modified time of a file.
-    base::Time last_modified;
+    Time last_modified;
 
     // The last accessed time of a file.
-    base::Time last_accessed;
+    Time last_accessed;
 
     // The creation time of a file.
-    base::Time creation_time;
+    Time creation_time;
   };
 
   File();
@@ -182,10 +182,6 @@
   // Creates or opens the given file.
   void Initialize(const FilePath& name, uint32 flags);
 
-  // Creates or opens the given file, allowing paths with traversal ('..')
-  // components. Use only with extreme care.
-  void InitializeUnsafe(const FilePath& name, uint32 flags);
-
   bool IsValid() const;
 
   // Returns true if a new file was created (or an old one truncated to zero
@@ -354,6 +350,14 @@
   };
 #endif
 
+  // Creates or opens the given file. Only called if |name| has no traversal
+  // ('..') components.
+  void DoInitialize(const FilePath& name, uint32 flags);
+
+  // TODO(tnagel): Reintegrate into Flush() once histogram isn't needed anymore,
+  // cf. issue 473337.
+  bool DoFlush();
+
   void SetPlatformFile(PlatformFile file);
 
 #if defined(OS_WIN)
diff --git a/base/files/file_path.h b/base/files/file_path.h
index 93f9ec9..5225b12 100644
--- a/base/files/file_path.h
+++ b/base/files/file_path.h
@@ -443,11 +443,9 @@
 #if defined(OS_POSIX)
 #define FILE_PATH_LITERAL(x) x
 #define PRFilePath "s"
-#define PRFilePathLiteral "%s"
 #elif defined(OS_WIN)
 #define FILE_PATH_LITERAL(x) L ## x
 #define PRFilePath "ls"
-#define PRFilePathLiteral L"%ls"
 #endif  // OS_WIN
 
 // Provide a hash function so that hash_sets and maps can contain FilePath
diff --git a/base/files/file_path_watcher.cc b/base/files/file_path_watcher.cc
index b173541..59ae705 100644
--- a/base/files/file_path_watcher.cc
+++ b/base/files/file_path_watcher.cc
@@ -32,7 +32,7 @@
   // FSEvents isn't available on iOS and is broken on OSX 10.6 and earlier.
   // See http://crbug.com/54822#c31
   return mac::IsOSLionOrLater();
-#elif defined(OS_WIN) || defined(OS_LINUX)
+#elif defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)
   return true;
 #else
   return false;
diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc
index f240e33..ef4e6ee 100644
--- a/base/files/file_path_watcher_fsevents.cc
+++ b/base/files/file_path_watcher_fsevents.cc
@@ -75,11 +75,51 @@
   return result;
 }
 
-// The callback passed to FSEventStreamCreate().
-void FSEventsCallback(ConstFSEventStreamRef stream,
-                      void* event_watcher, size_t num_events,
-                      void* event_paths, const FSEventStreamEventFlags flags[],
-                      const FSEventStreamEventId event_ids[]) {
+}  // namespace
+
+FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) {
+}
+
+bool FilePathWatcherFSEvents::Watch(const FilePath& path,
+                                    bool recursive,
+                                    const FilePathWatcher::Callback& callback) {
+  DCHECK(MessageLoopForIO::current());
+  DCHECK(!callback.is_null());
+  DCHECK(callback_.is_null());
+
+  // This class could support non-recursive watches, but that is currently
+  // left to FilePathWatcherKQueue.
+  if (!recursive)
+    return false;
+
+  set_message_loop(MessageLoopProxy::current());
+  callback_ = callback;
+
+  FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
+  g_task_runner.Get().PostTask(
+      FROM_HERE, Bind(&FilePathWatcherFSEvents::StartEventStream, this,
+                      start_event, path));
+  return true;
+}
+
+void FilePathWatcherFSEvents::Cancel() {
+  set_cancelled();
+  callback_.Reset();
+
+  // Switch to the dispatch queue thread to tear down the event stream.
+  g_task_runner.Get().PostTask(
+      FROM_HERE,
+      Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this));
+}
+
+// static
+void FilePathWatcherFSEvents::FSEventsCallback(
+    ConstFSEventStreamRef stream,
+    void* event_watcher,
+    size_t num_events,
+    void* event_paths,
+    const FSEventStreamEventFlags flags[],
+    const FSEventStreamEventId event_ids[]) {
   FilePathWatcherFSEvents* watcher =
       reinterpret_cast<FilePathWatcherFSEvents*>(event_watcher);
   DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
@@ -111,83 +151,51 @@
   watcher->OnFilePathsChanged(paths);
 }
 
-}  // namespace
-
-FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) {
+FilePathWatcherFSEvents::~FilePathWatcherFSEvents() {
+  // This method may be called on either the libdispatch or message_loop()
+  // thread. Checking callback_ on the libdispatch thread here is safe because
+  // it is executing in a task posted by Cancel() which first reset callback_.
+  // PostTask forms a sufficient memory barrier to ensure that the value is
+  // consistent on the target thread.
+  DCHECK(callback_.is_null())
+      << "Cancel() must be called before FilePathWatcher is destroyed.";
 }
 
 void FilePathWatcherFSEvents::OnFilePathsChanged(
     const std::vector<FilePath>& paths) {
-  if (!message_loop()->BelongsToCurrentThread()) {
-    message_loop()->PostTask(
-        FROM_HERE,
-        Bind(&FilePathWatcherFSEvents::OnFilePathsChanged, this, paths));
+  DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
+  DCHECK(!resolved_target_.empty());
+  message_loop()->PostTask(
+      FROM_HERE, Bind(&FilePathWatcherFSEvents::DispatchEvents, this, paths,
+                      target_, resolved_target_));
+}
+
+void FilePathWatcherFSEvents::DispatchEvents(const std::vector<FilePath>& paths,
+                                             const FilePath& target,
+                                             const FilePath& resolved_target) {
+  DCHECK(message_loop()->RunsTasksOnCurrentThread());
+
+  // Don't issue callbacks after Cancel() has been called.
+  if (is_cancelled() || callback_.is_null()) {
     return;
   }
 
-  DCHECK(message_loop()->BelongsToCurrentThread());
-  if (resolved_target_.empty())
-    return;
-
-  for (size_t i = 0; i < paths.size(); i++) {
-    if (resolved_target_.IsParent(paths[i]) || resolved_target_ == paths[i]) {
-      callback_.Run(target_, false);
+  for (const FilePath& path : paths) {
+    if (resolved_target.IsParent(path) || resolved_target == path) {
+      callback_.Run(target, false);
       return;
     }
   }
 }
 
-bool FilePathWatcherFSEvents::Watch(const FilePath& path,
-                                    bool recursive,
-                                    const FilePathWatcher::Callback& callback) {
-  DCHECK(resolved_target_.empty());
-  DCHECK(MessageLoopForIO::current());
-  DCHECK(!callback.is_null());
-
-  // This class could support non-recursive watches, but that is currently
-  // left to FilePathWatcherKQueue.
-  if (!recursive)
-    return false;
-
-  set_message_loop(MessageLoopProxy::current());
-  callback_ = callback;
-  target_ = path;
-
-  FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
-  g_task_runner.Get().PostTask(
-      FROM_HERE,
-      Bind(&FilePathWatcherFSEvents::StartEventStream, this, start_event));
-  return true;
-}
-
-void FilePathWatcherFSEvents::Cancel() {
-  if (callback_.is_null()) {
-    // Watch was never called, so exit.
-    set_cancelled();
-    return;
-  }
-
-  // Switch to the dispatch queue thread if necessary, so we can tear down
-  // the event stream.
-  if (!g_task_runner.Get().RunsTasksOnCurrentThread()) {
-    g_task_runner.Get().PostTask(
-        FROM_HERE,
-        Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this));
-  } else {
-    CancelOnMessageLoopThread();
-  }
-}
-
 void FilePathWatcherFSEvents::CancelOnMessageLoopThread() {
   // For all other implementations, the "message loop thread" is the IO thread,
   // as returned by message_loop(). This implementation, however, needs to
-  // cancel pending work on the Dipatch Queue thread.
+  // cancel pending work on the Dispatch Queue thread.
   DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
 
-  set_cancelled();
   if (fsevent_stream_) {
     DestroyEventStream();
-    callback_.Reset();
     target_.clear();
     resolved_target_.clear();
   }
@@ -199,7 +207,7 @@
 
   // It can happen that the watcher gets canceled while tasks that call this
   // function are still in flight, so abort if this situation is detected.
-  if (is_cancelled() || resolved_target_.empty())
+  if (resolved_target_.empty())
     return;
 
   if (fsevent_stream_)
@@ -230,8 +238,10 @@
   FSEventStreamSetDispatchQueue(fsevent_stream_,
                                 g_task_runner.Get().GetDispatchQueue());
 
-  if (!FSEventStreamStart(fsevent_stream_))
-    message_loop()->PostTask(FROM_HERE, Bind(callback_, target_, true));
+  if (!FSEventStreamStart(fsevent_stream_)) {
+    message_loop()->PostTask(
+        FROM_HERE, Bind(&FilePathWatcherFSEvents::ReportError, this, target_));
+  }
 }
 
 bool FilePathWatcherFSEvents::ResolveTargetPath() {
@@ -239,11 +249,20 @@
   FilePath resolved = ResolvePath(target_).StripTrailingSeparators();
   bool changed = resolved != resolved_target_;
   resolved_target_ = resolved;
-  if (resolved_target_.empty())
-    message_loop()->PostTask(FROM_HERE, Bind(callback_, target_, true));
+  if (resolved_target_.empty()) {
+    message_loop()->PostTask(
+        FROM_HERE, Bind(&FilePathWatcherFSEvents::ReportError, this, target_));
+  }
   return changed;
 }
 
+void FilePathWatcherFSEvents::ReportError(const FilePath& target) {
+  DCHECK(message_loop()->RunsTasksOnCurrentThread());
+  if (!callback_.is_null()) {
+    callback_.Run(target, true);
+  }
+}
+
 void FilePathWatcherFSEvents::DestroyEventStream() {
   FSEventStreamStop(fsevent_stream_);
   FSEventStreamInvalidate(fsevent_stream_);
@@ -251,13 +270,14 @@
   fsevent_stream_ = NULL;
 }
 
-void FilePathWatcherFSEvents::StartEventStream(
-    FSEventStreamEventId start_event) {
+void FilePathWatcherFSEvents::StartEventStream(FSEventStreamEventId start_event,
+                                               const FilePath& path) {
   DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
+  DCHECK(resolved_target_.empty());
+
+  target_ = path;
   ResolveTargetPath();
   UpdateEventStream(start_event);
 }
 
-FilePathWatcherFSEvents::~FilePathWatcherFSEvents() {}
-
 }  // namespace base
diff --git a/base/files/file_path_watcher_fsevents.h b/base/files/file_path_watcher_fsevents.h
index 800c5b4..300aa76 100644
--- a/base/files/file_path_watcher_fsevents.h
+++ b/base/files/file_path_watcher_fsevents.h
@@ -24,9 +24,35 @@
  public:
   FilePathWatcherFSEvents();
 
-  // Called from the FSEvents callback whenever there is a change to the paths.
+  // FilePathWatcher::PlatformDelegate overrides.
+  bool Watch(const FilePath& path,
+             bool recursive,
+             const FilePathWatcher::Callback& callback) override;
+  void Cancel() override;
+
+ private:
+  static void FSEventsCallback(ConstFSEventStreamRef stream,
+                               void* event_watcher,
+                               size_t num_events,
+                               void* event_paths,
+                               const FSEventStreamEventFlags flags[],
+                               const FSEventStreamEventId event_ids[]);
+
+  ~FilePathWatcherFSEvents() override;
+
+  // Called from FSEventsCallback whenever there is a change to the paths.
   void OnFilePathsChanged(const std::vector<FilePath>& paths);
 
+  // Called on the message_loop() thread to dispatch path events. Can't access
+  // target_ and resolved_target_ directly as those are modified on the
+  // libdispatch thread.
+  void DispatchEvents(const std::vector<FilePath>& paths,
+                      const FilePath& target,
+                      const FilePath& resolved_target);
+
+  // Cleans up and stops the event stream.
+  void CancelOnMessageLoopThread() override;
+
   // (Re-)Initialize the event stream to start reporting events from
   // |start_event|.
   void UpdateEventStream(FSEventStreamEventId start_event);
@@ -35,34 +61,29 @@
   // last time it was done.
   bool ResolveTargetPath();
 
-  // FilePathWatcher::PlatformDelegate overrides.
-  bool Watch(const FilePath& path,
-             bool recursive,
-             const FilePathWatcher::Callback& callback) override;
-  void Cancel() override;
-
- private:
-  ~FilePathWatcherFSEvents() override;
+  // Report an error watching the given target.
+  void ReportError(const FilePath& target);
 
   // Destroy the event stream.
   void DestroyEventStream();
 
   // Start watching the FSEventStream.
-  void StartEventStream(FSEventStreamEventId start_event);
-
-  // Cleans up and stops the event stream.
-  void CancelOnMessageLoopThread() override;
+  void StartEventStream(FSEventStreamEventId start_event, const FilePath& path);
 
   // Callback to notify upon changes.
+  // (Only accessed from the message_loop() thread.)
   FilePathWatcher::Callback callback_;
 
   // Target path to watch (passed to callback).
+  // (Only accessed from the libdispatch thread.)
   FilePath target_;
 
   // Target path with all symbolic links resolved.
+  // (Only accessed from the libdispatch thread.)
   FilePath resolved_target_;
 
   // Backend stream we receive event callbacks from (strong reference).
+  // (Only accessed from the libdispatch thread.)
   FSEventStreamRef fsevent_stream_;
 
   DISALLOW_COPY_AND_ASSIGN(FilePathWatcherFSEvents);
diff --git a/base/files/file_path_watcher_stub.cc b/base/files/file_path_watcher_stub.cc
index d7ad206..8138692 100644
--- a/base/files/file_path_watcher_stub.cc
+++ b/base/files/file_path_watcher_stub.cc
@@ -13,18 +13,18 @@
 
 class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
  public:
-  virtual bool Watch(const FilePath& path,
-                     bool recursive,
-                     const FilePathWatcher::Callback& callback) override {
+  bool Watch(const FilePath& path,
+             bool recursive,
+             const FilePathWatcher::Callback& callback) override {
     return false;
   }
 
-  virtual void Cancel() override {}
+  void Cancel() override {}
 
-  virtual void CancelOnMessageLoopThread() override {}
+  void CancelOnMessageLoopThread() override {}
 
  protected:
-  virtual ~FilePathWatcherImpl() {}
+  ~FilePathWatcherImpl() override {}
 };
 
 }  // namespace
diff --git a/base/files/file_path_watcher_browsertest.cc b/base/files/file_path_watcher_unittest.cc
similarity index 93%
rename from base/files/file_path_watcher_browsertest.cc
rename to base/files/file_path_watcher_unittest.cc
index bc7e630..0e1c467 100644
--- a/base/files/file_path_watcher_browsertest.cc
+++ b/base/files/file_path_watcher_unittest.cc
@@ -31,6 +31,10 @@
 #include "base/threading/thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_ANDROID)
+#include "base/android/path_utils.h"
+#endif  // defined(OS_ANDROID)
+
 namespace base {
 
 namespace {
@@ -150,7 +154,17 @@
     // Create a separate file thread in order to test proper thread usage.
     base::Thread::Options options(MessageLoop::TYPE_IO, 0);
     ASSERT_TRUE(file_thread_.StartWithOptions(options));
+#if defined(OS_ANDROID)
+    // Watching files is only permitted when all parent directories are
+    // accessible, which is not the case for the default temp directory
+    // on Android which is under /data/data.  Use /sdcard instead.
+    // TODO(pauljensen): Remove this when crbug.com/475568 is fixed.
+    FilePath parent_dir;
+    ASSERT_TRUE(android::GetExternalStorageDirectory(&parent_dir));
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDirUnderPath(parent_dir));
+#else   // defined(OS_ANDROID)
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+#endif  // defined(OS_ANDROID)
     collector_ = new NotificationCollector();
   }
 
@@ -526,9 +540,16 @@
   ASSERT_TRUE(WriteFile(child_dir_file1, "content"));
   ASSERT_TRUE(WaitForEvents());
 
+// Apps cannot change file attributes on Android in /sdcard as /sdcard uses the
+// "fuse" file system, while /data uses "ext4".  Running these tests in /data
+// would be preferable and allow testing file attributes and symlinks.
+// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
+// the |temp_dir_| in /data.
+#if !defined(OS_ANDROID)
   // Modify "$dir/subdir/subdir_child_dir/child_dir_file1" attributes.
   ASSERT_TRUE(base::MakeFileUnreadable(child_dir_file1));
   ASSERT_TRUE(WaitForEvents());
+#endif
 
   // Delete "$dir/subdir/subdir_file1".
   ASSERT_TRUE(base::DeleteFile(subdir_file1, false));
@@ -541,6 +562,14 @@
 }
 
 #if defined(OS_POSIX)
+#if defined(OS_ANDROID)
+// Apps cannot create symlinks on Android in /sdcard as /sdcard uses the
+// "fuse" file system, while /data uses "ext4".  Running these tests in /data
+// would be preferable and allow testing file attributes and symlinks.
+// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
+// the |temp_dir_| in /data.
+#define RecursiveWithSymLink DISABLED_RecursiveWithSymLink
+#endif  // defined(OS_ANDROID)
 TEST_F(FilePathWatcherTest, RecursiveWithSymLink) {
   if (!FilePathWatcher::RecursiveWatchAvailable())
     return;
@@ -610,6 +639,14 @@
 }
 
 // Verify that changing attributes on a file is caught
+#if defined(OS_ANDROID)
+// Apps cannot change file attributes on Android in /sdcard as /sdcard uses the
+// "fuse" file system, while /data uses "ext4".  Running these tests in /data
+// would be preferable and allow testing file attributes and symlinks.
+// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
+// the |temp_dir_| in /data.
+#define FileAttributesChanged DISABLED_FileAttributesChanged
+#endif  // defined(OS_ANDROID
 TEST_F(FilePathWatcherTest, FileAttributesChanged) {
   ASSERT_TRUE(WriteFile(test_file(), "content"));
   FilePathWatcher watcher;
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
index f6d0029..d7ce524 100644
--- a/base/files/file_path_watcher_win.cc
+++ b/base/files/file_path_watcher_win.cc
@@ -27,21 +27,21 @@
         recursive_watch_(false) {}
 
   // FilePathWatcher::PlatformDelegate overrides.
-  virtual bool Watch(const FilePath& path,
-                     bool recursive,
-                     const FilePathWatcher::Callback& callback) override;
-  virtual void Cancel() override;
+  bool Watch(const FilePath& path,
+             bool recursive,
+             const FilePathWatcher::Callback& callback) override;
+  void Cancel() override;
 
   // Deletion of the FilePathWatcher will call Cancel() to dispose of this
   // object in the right thread. This also observes destruction of the required
   // cleanup thread, in case it quits before Cancel() is called.
-  virtual void WillDestroyCurrentMessageLoop() override;
+  void WillDestroyCurrentMessageLoop() override;
 
   // Callback from MessageLoopForIO.
-  virtual void OnObjectSignaled(HANDLE object) override;
+  void OnObjectSignaled(HANDLE object) override;
 
  private:
-  virtual ~FilePathWatcherImpl() {}
+  ~FilePathWatcherImpl() override {}
 
   // Setup a watch handle for directory |dir|. Set |recursive| to true to watch
   // the directory sub trees. Returns true if no fatal error occurs. |handle|
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc
index 517390f..4c79057 100644
--- a/base/files/file_posix.cc
+++ b/base/files/file_posix.cc
@@ -10,7 +10,6 @@
 #include <unistd.h>
 
 #include "base/files/file_path.h"
-#include "base/files/file_posix_hooks_internal.h"
 #include "base/logging.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/posix/eintr_wrapper.h"
@@ -32,12 +31,12 @@
 
 #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
 static int CallFstat(int fd, stat_wrapper_t *sb) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   return fstat(fd, sb);
 }
 #else
 static int CallFstat(int fd, stat_wrapper_t *sb) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   return fstat64(fd, sb);
 }
 #endif
@@ -53,10 +52,6 @@
   return HANDLE_EINTR(ftruncate(file, length));
 }
 
-static int CallFsync(PlatformFile file) {
-  return HANDLE_EINTR(fsync(file));
-}
-
 static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
 #ifdef __USE_XOPEN2K8
   // futimens should be available, but futimes might not be
@@ -98,11 +93,6 @@
   return 0;
 }
 
-static int CallFsync(PlatformFile file) {
-  NOTIMPLEMENTED();  // NaCl doesn't implement fsync.
-  return 0;
-}
-
 static int CallFutimes(PlatformFile file, const struct timeval times[2]) {
   NOTIMPLEMENTED();  // NaCl doesn't implement futimes.
   return 0;
@@ -167,104 +157,6 @@
                                   Time::kNanosecondsPerMicrosecond);
 }
 
-// Default implementations of Protect/Unprotect hooks defined as weak symbols
-// where possible.
-void ProtectFileDescriptor(int fd) {
-}
-
-void UnprotectFileDescriptor(int fd) {
-}
-
-// NaCl doesn't implement system calls to open files directly.
-#if !defined(OS_NACL)
-// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
-void File::InitializeUnsafe(const FilePath& name, uint32 flags) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(!IsValid());
-
-  int open_flags = 0;
-  if (flags & FLAG_CREATE)
-    open_flags = O_CREAT | O_EXCL;
-
-  created_ = false;
-
-  if (flags & FLAG_CREATE_ALWAYS) {
-    DCHECK(!open_flags);
-    DCHECK(flags & FLAG_WRITE);
-    open_flags = O_CREAT | O_TRUNC;
-  }
-
-  if (flags & FLAG_OPEN_TRUNCATED) {
-    DCHECK(!open_flags);
-    DCHECK(flags & FLAG_WRITE);
-    open_flags = O_TRUNC;
-  }
-
-  if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
-    NOTREACHED();
-    errno = EOPNOTSUPP;
-    error_details_ = FILE_ERROR_FAILED;
-    return;
-  }
-
-  if (flags & FLAG_WRITE && flags & FLAG_READ) {
-    open_flags |= O_RDWR;
-  } else if (flags & FLAG_WRITE) {
-    open_flags |= O_WRONLY;
-  } else if (!(flags & FLAG_READ) &&
-             !(flags & FLAG_WRITE_ATTRIBUTES) &&
-             !(flags & FLAG_APPEND) &&
-             !(flags & FLAG_OPEN_ALWAYS)) {
-    NOTREACHED();
-  }
-
-  if (flags & FLAG_TERMINAL_DEVICE)
-    open_flags |= O_NOCTTY | O_NDELAY;
-
-  if (flags & FLAG_APPEND && flags & FLAG_READ)
-    open_flags |= O_APPEND | O_RDWR;
-  else if (flags & FLAG_APPEND)
-    open_flags |= O_APPEND | O_WRONLY;
-
-  COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
-
-  int mode = S_IRUSR | S_IWUSR;
-#if defined(OS_CHROMEOS)
-  mode |= S_IRGRP | S_IROTH;
-#endif
-
-  int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
-
-  if (flags & FLAG_OPEN_ALWAYS) {
-    if (descriptor < 0) {
-      open_flags |= O_CREAT;
-      if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
-        open_flags |= O_EXCL;   // together with O_CREAT implies O_NOFOLLOW
-
-      descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
-      if (descriptor >= 0)
-        created_ = true;
-    }
-  }
-
-  if (descriptor < 0) {
-    error_details_ = File::OSErrorToFileError(errno);
-    return;
-  }
-
-  if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
-    created_ = true;
-
-  if (flags & FLAG_DELETE_ON_CLOSE)
-    unlink(name.value().c_str());
-
-  async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
-  error_details_ = FILE_OK;
-  file_.reset(descriptor);
-  ProtectFileDescriptor(descriptor);
-}
-#endif  // !defined(OS_NACL)
-
 bool File::IsValid() const {
   return file_.is_valid();
 }
@@ -274,8 +166,6 @@
 }
 
 PlatformFile File::TakePlatformFile() {
-  if (IsValid())
-    UnprotectFileDescriptor(GetPlatformFile());
   return file_.release();
 }
 
@@ -283,13 +173,12 @@
   if (!IsValid())
     return;
 
-  base::ThreadRestrictions::AssertIOAllowed();
-  UnprotectFileDescriptor(GetPlatformFile());
+  ThreadRestrictions::AssertIOAllowed();
   file_.reset();
 }
 
 int64 File::Seek(Whence whence, int64 offset) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
 
 #if defined(OS_ANDROID)
@@ -304,7 +193,7 @@
 }
 
 int File::Read(int64 offset, char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
   if (size < 0)
     return -1;
@@ -324,7 +213,7 @@
 }
 
 int File::ReadAtCurrentPos(char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
   if (size < 0)
     return -1;
@@ -343,14 +232,14 @@
 }
 
 int File::ReadNoBestEffort(int64 offset, char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
 
   return HANDLE_EINTR(pread(file_.get(), data, size, offset));
 }
 
 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
   if (size < 0)
     return -1;
@@ -359,7 +248,7 @@
 }
 
 int File::Write(int64 offset, const char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
 
   if (IsOpenAppend(file_.get()))
     return WriteAtCurrentPos(data, size);
@@ -383,7 +272,7 @@
 }
 
 int File::WriteAtCurrentPos(const char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
   if (size < 0)
     return -1;
@@ -403,7 +292,7 @@
 }
 
 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
   if (size < 0)
     return -1;
@@ -422,19 +311,13 @@
 }
 
 bool File::SetLength(int64 length) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
   return !CallFtruncate(file_.get(), length);
 }
 
-bool File::Flush() {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-  return !CallFsync(file_.get());
-}
-
 bool File::SetTimes(Time last_access_time, Time last_modified_time) {
-  base::ThreadRestrictions::AssertIOAllowed();
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
 
   timeval times[2];
@@ -556,11 +439,111 @@
   ComputeMemoryChecksum(&file_memory_checksum_);
 }
 
+// NaCl doesn't implement system calls to open files directly.
+#if !defined(OS_NACL)
+// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
+void File::DoInitialize(const FilePath& name, uint32 flags) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!IsValid());
+
+  int open_flags = 0;
+  if (flags & FLAG_CREATE)
+    open_flags = O_CREAT | O_EXCL;
+
+  created_ = false;
+
+  if (flags & FLAG_CREATE_ALWAYS) {
+    DCHECK(!open_flags);
+    DCHECK(flags & FLAG_WRITE);
+    open_flags = O_CREAT | O_TRUNC;
+  }
+
+  if (flags & FLAG_OPEN_TRUNCATED) {
+    DCHECK(!open_flags);
+    DCHECK(flags & FLAG_WRITE);
+    open_flags = O_TRUNC;
+  }
+
+  if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
+    NOTREACHED();
+    errno = EOPNOTSUPP;
+    error_details_ = FILE_ERROR_FAILED;
+    return;
+  }
+
+  if (flags & FLAG_WRITE && flags & FLAG_READ) {
+    open_flags |= O_RDWR;
+  } else if (flags & FLAG_WRITE) {
+    open_flags |= O_WRONLY;
+  } else if (!(flags & FLAG_READ) &&
+             !(flags & FLAG_WRITE_ATTRIBUTES) &&
+             !(flags & FLAG_APPEND) &&
+             !(flags & FLAG_OPEN_ALWAYS)) {
+    NOTREACHED();
+  }
+
+  if (flags & FLAG_TERMINAL_DEVICE)
+    open_flags |= O_NOCTTY | O_NDELAY;
+
+  if (flags & FLAG_APPEND && flags & FLAG_READ)
+    open_flags |= O_APPEND | O_RDWR;
+  else if (flags & FLAG_APPEND)
+    open_flags |= O_APPEND | O_WRONLY;
+
+  COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
+
+  int mode = S_IRUSR | S_IWUSR;
+#if defined(OS_CHROMEOS)
+  mode |= S_IRGRP | S_IROTH;
+#endif
+
+  int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
+
+  if (flags & FLAG_OPEN_ALWAYS) {
+    if (descriptor < 0) {
+      open_flags |= O_CREAT;
+      if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
+        open_flags |= O_EXCL;   // together with O_CREAT implies O_NOFOLLOW
+
+      descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
+      if (descriptor >= 0)
+        created_ = true;
+    }
+  }
+
+  if (descriptor < 0) {
+    error_details_ = File::OSErrorToFileError(errno);
+    return;
+  }
+
+  if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
+    created_ = true;
+
+  if (flags & FLAG_DELETE_ON_CLOSE)
+    unlink(name.value().c_str());
+
+  async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
+  error_details_ = FILE_OK;
+  file_.reset(descriptor);
+}
+#endif  // !defined(OS_NACL)
+
+bool File::DoFlush() {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+#if defined(OS_NACL)
+  NOTIMPLEMENTED();  // NaCl doesn't implement fsync.
+  return true;
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+  return !HANDLE_EINTR(fdatasync(file_.get()));
+#else
+  return !HANDLE_EINTR(fsync(file_.get()));
+#endif
+}
+
 void File::SetPlatformFile(PlatformFile file) {
-  CHECK(!file_.is_valid());
+  DCHECK(!file_.is_valid());
   file_.reset(file);
-  if (file_.is_valid())
-    ProtectFileDescriptor(GetPlatformFile());
 }
 
 }  // namespace base
diff --git a/base/files/file_posix_hooks_internal.h b/base/files/file_posix_hooks_internal.h
deleted file mode 100644
index 1137b48..0000000
--- a/base/files/file_posix_hooks_internal.h
+++ /dev/null
@@ -1,31 +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.
-
-#ifndef BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_
-#define BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_
-
-#include "base/base_export.h"
-
-namespace base {
-
-// Define empty hooks for blacklisting file descriptors used in base::File.
-// These functions should be declared 'weak', i.e. the functions declared in
-// a default way would have precedence over the weak ones at link time. This
-// works for both static and dynamic linking.
-// TODO(pasko): Remove these hooks when crbug.com/424562 is fixed.
-//
-// With compilers other than GCC/Clang define strong no-op symbols for
-// simplicity.
-#if defined(COMPILER_GCC)
-#define ATTRIBUTE_WEAK __attribute__ ((weak))
-#else
-#define ATTRIBUTE_WEAK
-#endif
-BASE_EXPORT void ProtectFileDescriptor(int fd) ATTRIBUTE_WEAK;
-BASE_EXPORT void UnprotectFileDescriptor(int fd) ATTRIBUTE_WEAK;
-#undef ATTRIBUTE_WEAK
-
-}  // namespace base
-
-#endif  // BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index dad8edd..b4a64ba 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -57,7 +57,6 @@
 
 namespace base {
 
-#if !defined(OS_NACL_NONSFI)
 namespace {
 
 #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
@@ -80,6 +79,7 @@
 }
 #endif  // !(defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL))
 
+#if !defined(OS_NACL_NONSFI)
 // Helper for NormalizeFilePath(), defined below.
 bool RealPath(const FilePath& path, FilePath* real_path) {
   ThreadRestrictions::AssertIOAllowed();  // For realpath().
@@ -182,9 +182,11 @@
   return result;
 }
 #endif  // defined(OS_LINUX)
+#endif  // !defined(OS_NACL_NONSFI)
 
 }  // namespace
 
+#if !defined(OS_NACL_NONSFI)
 FilePath MakeAbsoluteFilePath(const FilePath& input) {
   ThreadRestrictions::AssertIOAllowed();
   char full_path[PATH_MAX];
@@ -363,6 +365,7 @@
   ThreadRestrictions::AssertIOAllowed();
   return access(path.value().c_str(), W_OK) == 0;
 }
+#endif  // !defined(OS_NACL_NONSFI)
 
 bool DirectoryExists(const FilePath& path) {
   ThreadRestrictions::AssertIOAllowed();
@@ -371,7 +374,6 @@
     return S_ISDIR(file_info.st_mode);
   return false;
 }
-#endif  // !defined(OS_NACL_NONSFI)
 
 bool ReadFromFD(int fd, char* buffer, size_t bytes) {
   size_t total_read = 0;
diff --git a/base/files/file_win.cc b/base/files/file_win.cc
index 9f3033c..200ea29 100644
--- a/base/files/file_win.cc
+++ b/base/files/file_win.cc
@@ -18,8 +18,268 @@
                File::FROM_CURRENT == FILE_CURRENT &&
                File::FROM_END     == FILE_END, whence_matches_system);
 
-void File::InitializeUnsafe(const FilePath& name, uint32 flags) {
-  base::ThreadRestrictions::AssertIOAllowed();
+bool File::IsValid() const {
+  return file_.IsValid();
+}
+
+PlatformFile File::GetPlatformFile() const {
+  return file_.Get();
+}
+
+PlatformFile File::TakePlatformFile() {
+  return file_.Take();
+}
+
+void File::Close() {
+  if (file_.IsValid()) {
+    ThreadRestrictions::AssertIOAllowed();
+    file_.Close();
+  }
+}
+
+int64 File::Seek(Whence whence, int64 offset) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+
+  LARGE_INTEGER distance, res;
+  distance.QuadPart = offset;
+  DWORD move_method = static_cast<DWORD>(whence);
+  if (!SetFilePointerEx(file_.Get(), distance, &res, move_method))
+    return -1;
+  return res.QuadPart;
+}
+
+int File::Read(int64 offset, char* data, int size) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+  DCHECK(!async_);
+  if (size < 0)
+    return -1;
+
+  LARGE_INTEGER offset_li;
+  offset_li.QuadPart = offset;
+
+  OVERLAPPED overlapped = {0};
+  overlapped.Offset = offset_li.LowPart;
+  overlapped.OffsetHigh = offset_li.HighPart;
+
+  DWORD bytes_read;
+  if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped))
+    return bytes_read;
+  if (ERROR_HANDLE_EOF == GetLastError())
+    return 0;
+
+  return -1;
+}
+
+int File::ReadAtCurrentPos(char* data, int size) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+  DCHECK(!async_);
+  if (size < 0)
+    return -1;
+
+  DWORD bytes_read;
+  if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL))
+    return bytes_read;
+  if (ERROR_HANDLE_EOF == GetLastError())
+    return 0;
+
+  return -1;
+}
+
+int File::ReadNoBestEffort(int64 offset, char* data, int size) {
+  return Read(offset, data, size);
+}
+
+int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
+  return ReadAtCurrentPos(data, size);
+}
+
+int File::Write(int64 offset, const char* data, int size) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+  DCHECK(!async_);
+
+  LARGE_INTEGER offset_li;
+  offset_li.QuadPart = offset;
+
+  OVERLAPPED overlapped = {0};
+  overlapped.Offset = offset_li.LowPart;
+  overlapped.OffsetHigh = offset_li.HighPart;
+
+  DWORD bytes_written;
+  if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped))
+    return bytes_written;
+
+  return -1;
+}
+
+int File::WriteAtCurrentPos(const char* data, int size) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+  DCHECK(!async_);
+  if (size < 0)
+    return -1;
+
+  DWORD bytes_written;
+  if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL))
+    return bytes_written;
+
+  return -1;
+}
+
+int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
+  return WriteAtCurrentPos(data, size);
+}
+
+int64 File::GetLength() {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+  LARGE_INTEGER size;
+  if (!::GetFileSizeEx(file_.Get(), &size))
+    return -1;
+
+  return static_cast<int64>(size.QuadPart);
+}
+
+bool File::SetLength(int64 length) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+
+  // Get the current file pointer.
+  LARGE_INTEGER file_pointer;
+  LARGE_INTEGER zero;
+  zero.QuadPart = 0;
+  if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT))
+    return false;
+
+  LARGE_INTEGER length_li;
+  length_li.QuadPart = length;
+  // If length > file size, SetFilePointerEx() should extend the file
+  // with zeroes on all Windows standard file systems (NTFS, FATxx).
+  if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN))
+    return false;
+
+  // Set the new file length and move the file pointer to its old position.
+  // This is consistent with ftruncate()'s behavior, even when the file
+  // pointer points to a location beyond the end of the file.
+  // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not
+  // promised by the interface (nor was promised by PlatformFile). See if this
+  // implementation detail can be removed.
+  return ((::SetEndOfFile(file_.Get()) != FALSE) &&
+          (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) !=
+           FALSE));
+}
+
+bool File::SetTimes(Time last_access_time, Time last_modified_time) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+
+  FILETIME last_access_filetime = last_access_time.ToFileTime();
+  FILETIME last_modified_filetime = last_modified_time.ToFileTime();
+  return (::SetFileTime(file_.Get(), NULL, &last_access_filetime,
+                        &last_modified_filetime) != FALSE);
+}
+
+bool File::GetInfo(Info* info) {
+  ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+
+  BY_HANDLE_FILE_INFORMATION file_info;
+  if (!GetFileInformationByHandle(file_.Get(), &file_info))
+    return false;
+
+  LARGE_INTEGER size;
+  size.HighPart = file_info.nFileSizeHigh;
+  size.LowPart = file_info.nFileSizeLow;
+  info->size = size.QuadPart;
+  info->is_directory =
+      (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+  info->is_symbolic_link = false;  // Windows doesn't have symbolic links.
+  info->last_modified = Time::FromFileTime(file_info.ftLastWriteTime);
+  info->last_accessed = Time::FromFileTime(file_info.ftLastAccessTime);
+  info->creation_time = Time::FromFileTime(file_info.ftCreationTime);
+  return true;
+}
+
+File::Error File::Lock() {
+  DCHECK(IsValid());
+  BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
+  if (!result)
+    return OSErrorToFileError(GetLastError());
+  return FILE_OK;
+}
+
+File::Error File::Unlock() {
+  DCHECK(IsValid());
+  BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
+  if (!result)
+    return OSErrorToFileError(GetLastError());
+  return FILE_OK;
+}
+
+File File::Duplicate() {
+  if (!IsValid())
+    return File();
+
+  HANDLE other_handle = nullptr;
+
+  if (!::DuplicateHandle(GetCurrentProcess(),  // hSourceProcessHandle
+                         GetPlatformFile(),
+                         GetCurrentProcess(),  // hTargetProcessHandle
+                         &other_handle,
+                         0,  // dwDesiredAccess ignored due to SAME_ACCESS
+                         FALSE,  // !bInheritHandle
+                         DUPLICATE_SAME_ACCESS)) {
+    return File(OSErrorToFileError(GetLastError()));
+  }
+
+  File other(other_handle);
+  if (async())
+    other.async_ = true;
+  return other.Pass();
+}
+
+// Static.
+File::Error File::OSErrorToFileError(DWORD last_error) {
+  switch (last_error) {
+    case ERROR_SHARING_VIOLATION:
+      return FILE_ERROR_IN_USE;
+    case ERROR_FILE_EXISTS:
+      return FILE_ERROR_EXISTS;
+    case ERROR_FILE_NOT_FOUND:
+    case ERROR_PATH_NOT_FOUND:
+      return FILE_ERROR_NOT_FOUND;
+    case ERROR_ACCESS_DENIED:
+      return FILE_ERROR_ACCESS_DENIED;
+    case ERROR_TOO_MANY_OPEN_FILES:
+      return FILE_ERROR_TOO_MANY_OPENED;
+    case ERROR_OUTOFMEMORY:
+    case ERROR_NOT_ENOUGH_MEMORY:
+      return FILE_ERROR_NO_MEMORY;
+    case ERROR_HANDLE_DISK_FULL:
+    case ERROR_DISK_FULL:
+    case ERROR_DISK_RESOURCES_EXHAUSTED:
+      return FILE_ERROR_NO_SPACE;
+    case ERROR_USER_MAPPED_FILE:
+      return FILE_ERROR_INVALID_OPERATION;
+    case ERROR_NOT_READY:
+    case ERROR_SECTOR_NOT_FOUND:
+    case ERROR_DEV_NOT_EXIST:
+    case ERROR_IO_DEVICE:
+    case ERROR_FILE_CORRUPT:
+    case ERROR_DISK_CORRUPT:
+      return FILE_ERROR_IO;
+    default:
+      UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows",
+                                  last_error);
+      return FILE_ERROR_FAILED;
+  }
+}
+
+void File::DoInitialize(const FilePath& name, uint32 flags) {
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(!IsValid());
 
   DWORD disposition = 0;
@@ -102,272 +362,12 @@
   }
 }
 
-bool File::IsValid() const {
-  return file_.IsValid();
-}
-
-PlatformFile File::GetPlatformFile() const {
-  return file_.Get();
-}
-
-PlatformFile File::TakePlatformFile() {
-  return file_.Take();
-}
-
-void File::Close() {
-  if (file_.IsValid()) {
-    base::ThreadRestrictions::AssertIOAllowed();
-    file_.Close();
-  }
-}
-
-int64 File::Seek(Whence whence, int64 offset) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-
-  LARGE_INTEGER distance, res;
-  distance.QuadPart = offset;
-  DWORD move_method = static_cast<DWORD>(whence);
-  if (!SetFilePointerEx(file_.Get(), distance, &res, move_method))
-    return -1;
-  return res.QuadPart;
-}
-
-int File::Read(int64 offset, char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-  DCHECK(!async_);
-  if (size < 0)
-    return -1;
-
-  LARGE_INTEGER offset_li;
-  offset_li.QuadPart = offset;
-
-  OVERLAPPED overlapped = {0};
-  overlapped.Offset = offset_li.LowPart;
-  overlapped.OffsetHigh = offset_li.HighPart;
-
-  DWORD bytes_read;
-  if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped))
-    return bytes_read;
-  if (ERROR_HANDLE_EOF == GetLastError())
-    return 0;
-
-  return -1;
-}
-
-int File::ReadAtCurrentPos(char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-  DCHECK(!async_);
-  if (size < 0)
-    return -1;
-
-  DWORD bytes_read;
-  if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL))
-    return bytes_read;
-  if (ERROR_HANDLE_EOF == GetLastError())
-    return 0;
-
-  return -1;
-}
-
-int File::ReadNoBestEffort(int64 offset, char* data, int size) {
-  return Read(offset, data, size);
-}
-
-int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
-  return ReadAtCurrentPos(data, size);
-}
-
-int File::Write(int64 offset, const char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-  DCHECK(!async_);
-
-  LARGE_INTEGER offset_li;
-  offset_li.QuadPart = offset;
-
-  OVERLAPPED overlapped = {0};
-  overlapped.Offset = offset_li.LowPart;
-  overlapped.OffsetHigh = offset_li.HighPart;
-
-  DWORD bytes_written;
-  if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped))
-    return bytes_written;
-
-  return -1;
-}
-
-int File::WriteAtCurrentPos(const char* data, int size) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-  DCHECK(!async_);
-  if (size < 0)
-    return -1;
-
-  DWORD bytes_written;
-  if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL))
-    return bytes_written;
-
-  return -1;
-}
-
-int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
-  return WriteAtCurrentPos(data, size);
-}
-
-int64 File::GetLength() {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-  LARGE_INTEGER size;
-  if (!::GetFileSizeEx(file_.Get(), &size))
-    return -1;
-
-  return static_cast<int64>(size.QuadPart);
-}
-
-bool File::SetLength(int64 length) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-
-  // Get the current file pointer.
-  LARGE_INTEGER file_pointer;
-  LARGE_INTEGER zero;
-  zero.QuadPart = 0;
-  if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT))
-    return false;
-
-  LARGE_INTEGER length_li;
-  length_li.QuadPart = length;
-  // If length > file size, SetFilePointerEx() should extend the file
-  // with zeroes on all Windows standard file systems (NTFS, FATxx).
-  if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN))
-    return false;
-
-  // Set the new file length and move the file pointer to its old position.
-  // This is consistent with ftruncate()'s behavior, even when the file
-  // pointer points to a location beyond the end of the file.
-  // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not
-  // promised by the interface (nor was promised by PlatformFile). See if this
-  // implementation detail can be removed.
-  return ((::SetEndOfFile(file_.Get()) != FALSE) &&
-          (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) !=
-           FALSE));
-}
-
-bool File::Flush() {
-  base::ThreadRestrictions::AssertIOAllowed();
+bool File::DoFlush() {
+  ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
   return ::FlushFileBuffers(file_.Get()) != FALSE;
 }
 
-bool File::SetTimes(Time last_access_time, Time last_modified_time) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-
-  FILETIME last_access_filetime = last_access_time.ToFileTime();
-  FILETIME last_modified_filetime = last_modified_time.ToFileTime();
-  return (::SetFileTime(file_.Get(), NULL, &last_access_filetime,
-                        &last_modified_filetime) != FALSE);
-}
-
-bool File::GetInfo(Info* info) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  DCHECK(IsValid());
-
-  BY_HANDLE_FILE_INFORMATION file_info;
-  if (!GetFileInformationByHandle(file_.Get(), &file_info))
-    return false;
-
-  LARGE_INTEGER size;
-  size.HighPart = file_info.nFileSizeHigh;
-  size.LowPart = file_info.nFileSizeLow;
-  info->size = size.QuadPart;
-  info->is_directory =
-      (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
-  info->is_symbolic_link = false;  // Windows doesn't have symbolic links.
-  info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime);
-  info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime);
-  info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime);
-  return true;
-}
-
-File::Error base::File::Lock() {
-  DCHECK(IsValid());
-  BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
-  if (!result)
-    return OSErrorToFileError(GetLastError());
-  return FILE_OK;
-}
-
-File::Error File::Unlock() {
-  DCHECK(IsValid());
-  BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
-  if (!result)
-    return OSErrorToFileError(GetLastError());
-  return FILE_OK;
-}
-
-File File::Duplicate() {
-  if (!IsValid())
-    return File();
-
-  HANDLE other_handle = nullptr;
-
-  if (!::DuplicateHandle(GetCurrentProcess(),  // hSourceProcessHandle
-                         GetPlatformFile(),
-                         GetCurrentProcess(),  // hTargetProcessHandle
-                         &other_handle,
-                         0,  // dwDesiredAccess ignored due to SAME_ACCESS
-                         FALSE,  // !bInheritHandle
-                         DUPLICATE_SAME_ACCESS)) {
-    return File(OSErrorToFileError(GetLastError()));
-  }
-
-  File other(other_handle);
-  if (async())
-    other.async_ = true;
-  return other.Pass();
-}
-
-// Static.
-File::Error File::OSErrorToFileError(DWORD last_error) {
-  switch (last_error) {
-    case ERROR_SHARING_VIOLATION:
-      return FILE_ERROR_IN_USE;
-    case ERROR_FILE_EXISTS:
-      return FILE_ERROR_EXISTS;
-    case ERROR_FILE_NOT_FOUND:
-    case ERROR_PATH_NOT_FOUND:
-      return FILE_ERROR_NOT_FOUND;
-    case ERROR_ACCESS_DENIED:
-      return FILE_ERROR_ACCESS_DENIED;
-    case ERROR_TOO_MANY_OPEN_FILES:
-      return FILE_ERROR_TOO_MANY_OPENED;
-    case ERROR_OUTOFMEMORY:
-    case ERROR_NOT_ENOUGH_MEMORY:
-      return FILE_ERROR_NO_MEMORY;
-    case ERROR_HANDLE_DISK_FULL:
-    case ERROR_DISK_FULL:
-    case ERROR_DISK_RESOURCES_EXHAUSTED:
-      return FILE_ERROR_NO_SPACE;
-    case ERROR_USER_MAPPED_FILE:
-      return FILE_ERROR_INVALID_OPERATION;
-    case ERROR_NOT_READY:
-    case ERROR_SECTOR_NOT_FOUND:
-    case ERROR_DEV_NOT_EXIST:
-    case ERROR_IO_DEVICE:
-    case ERROR_FILE_CORRUPT:
-    case ERROR_DISK_CORRUPT:
-      return FILE_ERROR_IO;
-    default:
-      UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows",
-                                  last_error);
-      return FILE_ERROR_FAILED;
-  }
-}
-
 void File::SetPlatformFile(PlatformFile file) {
   file_.Set(file);
 }
diff --git a/base/files/protect_file_posix.cc b/base/files/protect_file_posix.cc
deleted file mode 100644
index e4753c4..0000000
--- a/base/files/protect_file_posix.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/containers/hash_tables.h"
-#include "base/files/file.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/synchronization/lock.h"
-
-// These hooks provided for base::File perform additional sanity checks when
-// files are closed. These extra checks are hard to understand and maintain,
-// hence they are temporary. TODO(pasko): Remove these extra checks as soon as
-// crbug.com/424562 is fixed.
-//
-// Background:
-//   1. The browser process crashes if a call to close() provided by the C
-//      library (i.e. close(3)) fails. This is done for security purposes. See
-//      base/files/scoped_file.cc. When a crash like this happens, there is not
-//      enough context in the minidump to triage the problem.
-//   2. base::File provides a good abstraction to prevent closing incorrect
-//      file descriptors or double-closing. Closing non-owned file descriptors
-//      would more likely happen from outside base::File and base::ScopedFD.
-//
-// These hooks intercept base::File operations to 'protect' file handles /
-// descriptors from accidental close(3) by other portions of the code being
-// linked into the browser. Also, this file provides an interceptor for the
-// close(3) itself, and requires to be linked with cooperation of
-// --Wl,--wrap=close (i.e. linker wrapping).
-//
-// Wrapping close(3) on all libraries can lead to confusion, particularly for
-// the libraries that do not use ::base (I am also looking at you,
-// crazy_linker). Instead two hooks are added to base::File, which are
-// implemented as no-op by default. This file should be linked into the Chrome
-// native binary(-ies) for a whitelist of targets where "file descriptor
-// protection" is useful.
-
-// With compilers other than GCC/Clang the wrapper is trivial. This is to avoid
-// overexercising mechanisms for overriding weak symbols.
-#if !defined(COMPILER_GCC)
-extern "C" {
-
-int __real_close(int fd);
-
-BASE_EXPORT int __wrap_close(int fd) {
-  return __real_close(fd);
-}
-
-}  // extern "C"
-
-#else  // defined(COMPILER_GCC)
-
-namespace {
-
-// Protects the |g_protected_fd_set|.
-base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
-
-// Holds the set of all 'protected' file descriptors.
-base::LazyInstance<base::hash_set<int> >::Leaky g_protected_fd_set =
-    LAZY_INSTANCE_INITIALIZER;
-
-bool IsFileDescriptorProtected(int fd) {
-  base::AutoLock lock(*g_lock.Pointer());
-  return g_protected_fd_set.Get().count(fd) != 0;
-}
-
-}  // namespace
-
-namespace base {
-
-BASE_EXPORT void ProtectFileDescriptor(int fd) {
-  base::AutoLock lock(g_lock.Get());
-  CHECK(!g_protected_fd_set.Get().count(fd)) << "fd: " << fd;
-  g_protected_fd_set.Get().insert(fd);
-}
-
-BASE_EXPORT void UnprotectFileDescriptor(int fd) {
-  base::AutoLock lock(*g_lock.Pointer());
-  CHECK(g_protected_fd_set.Get().erase(fd)) << "fd: " << fd;
-}
-
-}  // namespace base
-
-extern "C" {
-
-int __real_close(int fd);
-
-BASE_EXPORT int __wrap_close(int fd) {
-  // The crash happens here if a protected file descriptor was attempted to be
-  // closed without first being unprotected. Unprotection happens only in
-  // base::File. In other words this is an "early crash" as compared to the one
-  // happening in scoped_file.cc.
-  //
-  // Getting an earlier crash provides a more useful stack trace (minidump)
-  // allowing to debug deeper into the thread that freed the wrong resource.
-  CHECK(!IsFileDescriptorProtected(fd)) << "fd: " << fd;
-
-  // Crash by the same reason as in scoped_file.cc.
-  PCHECK(0 == IGNORE_EINTR(__real_close(fd)));
-  return 0;
-}
-
-}  // extern "C"
-
-#endif  // defined(COMPILER_GCC)
diff --git a/base/files/protect_file_posix.gypi b/base/files/protect_file_posix.gypi
deleted file mode 100644
index 017fd87..0000000
--- a/base/files/protect_file_posix.gypi
+++ /dev/null
@@ -1,31 +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.
-
-# Provides sanity-checks and early crashes on some improper use of posix file
-# descriptors. See protect_file_posix.cc for details.
-#
-# Usage:
-#   {
-#     'target_name': 'libsomething',
-#     'type': 'shared_library',  // Do *not* use it for static libraries.
-#     'includes': [
-#       'base/files/protect_file_posix.gypi',
-#     ],
-#     ...
-#   }
-{
-   'conditions': [
-     # In the component build the interceptors have to be declared with
-     # non-hidden visibility, which is not desirable for the release build.
-     # Disable the extra checks for the component build for simplicity.
-     ['component != "shared_library"', {
-       'ldflags': [
-         '-Wl,--wrap=close',
-       ],
-       'dependencies': [
-         '<(DEPTH)/base/base.gyp:protect_file_posix',
-       ],
-     }],
-   ],
-}
diff --git a/base/float_util.h b/base/float_util.h
deleted file mode 100644
index 9027310..0000000
--- a/base/float_util.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-#ifndef BASE_FLOAT_UTIL_H_
-#define BASE_FLOAT_UTIL_H_
-
-#include "build/build_config.h"
-
-#include <float.h>
-
-#include <cmath>
-
-namespace base {
-
-template <typename Float>
-inline bool IsFinite(const Float& number) {
-#if defined(OS_POSIX)
-  return std::isfinite(number) != 0;
-#elif defined(OS_WIN)
-  return _finite(number) != 0;
-#endif
-}
-
-template <typename Float>
-inline bool IsNaN(const Float& number) {
-#if defined(OS_POSIX)
-  return std::isnan(number) != 0;
-#elif defined(OS_WIN)
-  return _isnan(number) != 0;
-#endif
-}
-
-}  // namespace base
-
-#endif  // BASE_FLOAT_UTIL_H_
diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc
index f57bb39..f6e2c29 100644
--- a/base/i18n/file_util_icu.cc
+++ b/base/i18n/file_util_icu.cc
@@ -152,16 +152,15 @@
   collator->setStrength(icu::Collator::TERTIARY);
 
 #if defined(OS_WIN)
-  return CompareString16WithCollator(collator.get(),
-      WideToUTF16(a.value()), WideToUTF16(b.value())) == UCOL_LESS;
+  return CompareString16WithCollator(*collator, WideToUTF16(a.value()),
+                                     WideToUTF16(b.value())) == UCOL_LESS;
 
 #elif defined(OS_POSIX)
   // On linux, the file system encoding is not defined. We assume
   // SysNativeMBToWide takes care of it.
   return CompareString16WithCollator(
-      collator.get(),
-      WideToUTF16(SysNativeMBToWide(a.value().c_str())),
-      WideToUTF16(SysNativeMBToWide(b.value().c_str()))) == UCOL_LESS;
+             *collator, WideToUTF16(SysNativeMBToWide(a.value().c_str())),
+             WideToUTF16(SysNativeMBToWide(b.value().c_str()))) == UCOL_LESS;
 #else
   #error Not implemented on your system
 #endif
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc
index f1fdda7..76eaa62 100644
--- a/base/i18n/icu_util.cc
+++ b/base/i18n/icu_util.cc
@@ -10,6 +10,7 @@
 
 #include <string>
 
+#include "base/debug/alias.h"
 #include "base/files/file_path.h"
 #include "base/files/memory_mapped_file.h"
 #include "base/logging.h"
@@ -48,7 +49,9 @@
 // Assert that we are not called more than once.  Even though calling this
 // function isn't harmful (ICU can handle it), being called twice probably
 // indicates a programming error.
+#if !defined(OS_NACL)
 bool g_called_once = false;
+#endif
 bool g_check_called_once = true;
 #endif
 }
@@ -81,6 +84,7 @@
 #endif
 
 
+#if !defined(OS_NACL)
 bool InitializeICU() {
 #if !defined(NDEBUG)
   DCHECK(!g_check_called_once || !g_called_once);
@@ -127,6 +131,10 @@
 #if defined(OS_WIN)
     // The data file will be in the same directory as the current module.
     bool path_ok = PathService::Get(base::DIR_MODULE, &data_path);
+    wchar_t tmp_buffer[_MAX_PATH] = {0};
+    wcscpy_s(tmp_buffer, data_path.value().c_str());
+    base::debug::Alias(tmp_buffer);
+    CHECK(path_ok);  // TODO(scottmg): http://crbug.com/445616
 #elif defined(OS_ANDROID)
     bool path_ok = PathService::Get(base::DIR_ANDROID_APP_DATA, &data_path);
 #else
@@ -137,6 +145,14 @@
 #endif
     DCHECK(path_ok);
     data_path = data_path.AppendASCII(kIcuDataFileName);
+
+#if defined(OS_WIN)
+    // TODO(scottmg): http://crbug.com/445616
+    wchar_t tmp_buffer2[_MAX_PATH] = {0};
+    wcscpy_s(tmp_buffer2, data_path.value().c_str());
+    base::debug::Alias(tmp_buffer2);
+#endif
+
 #else
     // Assume it is in the framework bundle's Resources directory.
     base::ScopedCFTypeRef<CFStringRef> data_file_name(
@@ -149,15 +165,22 @@
     }
 #endif  // OS check
     if (!mapped_file.Initialize(data_path)) {
+#if defined(OS_WIN)
+      CHECK(false);  // TODO(scottmg): http://crbug.com/445616
+#endif
       LOG(ERROR) << "Couldn't mmap " << data_path.AsUTF8Unsafe();
       return false;
     }
   }
   UErrorCode err = U_ZERO_ERROR;
   udata_setCommonData(const_cast<uint8*>(mapped_file.data()), &err);
+#if defined(OS_WIN)
+  CHECK(err == U_ZERO_ERROR);  // TODO(scottmg): http://crbug.com/445616
+#endif
   return err == U_ZERO_ERROR;
 #endif
 }
+#endif
 
 void AllowMultipleInitializeCallsForTesting() {
 #if !defined(NDEBUG)
diff --git a/base/i18n/icu_util.h b/base/i18n/icu_util.h
index 5094cb0..e9f7c3d 100644
--- a/base/i18n/icu_util.h
+++ b/base/i18n/icu_util.h
@@ -14,9 +14,11 @@
 
 BASE_I18N_EXPORT extern const char kIcuDataFileName[];
 
+#if !defined(OS_NACL)
 // Call this function to load ICU's data tables for the current process.  This
 // function should be called before ICU is used.
 BASE_I18N_EXPORT bool InitializeICU();
+#endif
 
 #if defined(OS_ANDROID)
 // Android uses a file descriptor passed by browser process to initialize ICU
diff --git a/base/i18n/string_compare.cc b/base/i18n/string_compare.cc
index 1ac7284..2851e7d 100644
--- a/base/i18n/string_compare.cc
+++ b/base/i18n/string_compare.cc
@@ -12,12 +12,11 @@
 
 // Compares the character data stored in two different string16 strings by
 // specified Collator instance.
-UCollationResult CompareString16WithCollator(const icu::Collator* collator,
+UCollationResult CompareString16WithCollator(const icu::Collator& collator,
                                              const string16& lhs,
                                              const string16& rhs) {
-  DCHECK(collator);
   UErrorCode error = U_ZERO_ERROR;
-  UCollationResult result = collator->compare(
+  UCollationResult result = collator.compare(
       static_cast<const UChar*>(lhs.c_str()), static_cast<int>(lhs.length()),
       static_cast<const UChar*>(rhs.c_str()), static_cast<int>(rhs.length()),
       error);
diff --git a/base/i18n/string_compare.h b/base/i18n/string_compare.h
index 158c93b..5fcc5fe 100644
--- a/base/i18n/string_compare.h
+++ b/base/i18n/string_compare.h
@@ -17,10 +17,10 @@
 namespace i18n {
 
 // Compares the two strings using the specified collator.
-BASE_I18N_EXPORT UCollationResult CompareString16WithCollator(
-    const icu::Collator* collator,
-    const string16& lhs,
-    const string16& rhs);
+BASE_I18N_EXPORT UCollationResult
+CompareString16WithCollator(const icu::Collator& collator,
+                            const string16& lhs,
+                            const string16& rhs);
 
 }  // namespace i18n
 }  // namespace base
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc
index d42b1a3..e9a27bc 100644
--- a/base/json/json_parser.cc
+++ b/base/json/json_parser.cc
@@ -4,7 +4,8 @@
 
 #include "base/json/json_parser.h"
 
-#include "base/float_util.h"
+#include <cmath>
+
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
@@ -872,7 +873,7 @@
 
   double num_double;
   if (base::StringToDouble(num_string.as_string(), &num_double) &&
-      IsFinite(num_double)) {
+      std::isfinite(num_double)) {
     return new FundamentalValue(num_double);
   }
 
diff --git a/base/json/json_value_converter.h b/base/json/json_value_converter.h
index c4bfe61..f94d46e 100644
--- a/base/json/json_value_converter.h
+++ b/base/json/json_value_converter.h
@@ -123,8 +123,7 @@
         value_converter_(converter) {
   }
 
-  virtual bool ConvertField(
-      const base::Value& value, StructType* dst) const override {
+  bool ConvertField(const base::Value& value, StructType* dst) const override {
     return value_converter_->Convert(value, &(dst->*field_pointer_));
   }
 
@@ -202,8 +201,7 @@
   ValueFieldConverter(ConvertFunc convert_func)
       : convert_func_(convert_func) {}
 
-  virtual bool Convert(const base::Value& value,
-                       FieldType* field) const override {
+  bool Convert(const base::Value& value, FieldType* field) const override {
     return convert_func_(&value, field);
   }
 
@@ -221,8 +219,7 @@
   CustomFieldConverter(ConvertFunc convert_func)
       : convert_func_(convert_func) {}
 
-  virtual bool Convert(const base::Value& value,
-                       FieldType* field) const override {
+  bool Convert(const base::Value& value, FieldType* field) const override {
     std::string string_value;
     return value.GetAsString(&string_value) &&
         convert_func_(string_value, field);
@@ -239,8 +236,7 @@
  public:
   NestedValueConverter() {}
 
-  virtual bool Convert(
-      const base::Value& value, NestedType* field) const override {
+  bool Convert(const base::Value& value, NestedType* field) const override {
     return converter_.Convert(value, field);
   }
 
@@ -254,8 +250,8 @@
  public:
   RepeatedValueConverter() {}
 
-  virtual bool Convert(
-      const base::Value& value, ScopedVector<Element>* field) const override {
+  bool Convert(const base::Value& value,
+               ScopedVector<Element>* field) const override {
     const base::ListValue* list = NULL;
     if (!value.GetAsList(&list)) {
       // The field is not a list.
@@ -290,8 +286,8 @@
  public:
   RepeatedMessageConverter() {}
 
-  virtual bool Convert(const base::Value& value,
-                       ScopedVector<NestedType>* field) const override {
+  bool Convert(const base::Value& value,
+               ScopedVector<NestedType>* field) const override {
     const base::ListValue* list = NULL;
     if (!value.GetAsList(&list))
       return false;
@@ -327,8 +323,8 @@
   RepeatedCustomValueConverter(ConvertFunc convert_func)
       : convert_func_(convert_func) {}
 
-  virtual bool Convert(const base::Value& value,
-                       ScopedVector<NestedType>* field) const override {
+  bool Convert(const base::Value& value,
+               ScopedVector<NestedType>* field) const override {
     const base::ListValue* list = NULL;
     if (!value.GetAsList(&list))
       return false;
diff --git a/base/logging_win.h b/base/logging_win.h
index 38508a3..aa48e22 100644
--- a/base/logging_win.h
+++ b/base/logging_win.h
@@ -61,8 +61,8 @@
 
  protected:
   // Overridden to manipulate the log level on ETW control callbacks.
-  virtual void OnEventsEnabled();
-  virtual void OnEventsDisabled();
+  void OnEventsEnabled() override;
+  void OnEventsDisabled() override;
 
  private:
   LogEventProvider();
diff --git a/base/mac/close_nocancel.cc b/base/mac/close_nocancel.cc
index 134f7ac..8971e73 100644
--- a/base/mac/close_nocancel.cc
+++ b/base/mac/close_nocancel.cc
@@ -28,12 +28,14 @@
 //
 // This file operates by providing a close function with the non-$NOCANCEL
 // symbol name expected for the compilation environment as set by <unistd.h>
-// and <sys/cdefs.h> (the DARWIN_ALIAS_C macro). That function calls the
-// $NOCANCEL variant, which is resolved from libsyscall. By linking with this
-// version of close prior to the libsyscall version, close's implementation is
-// overridden.
+// and <sys/cdefs.h> (the DARWIN_ALIAS_C macro). That name is set by an asm
+// label on the declaration of the close function, so the definition of that
+// function receives that name. The function calls the $NOCANCEL variant, which
+// is resolved from libsyscall. By linking with this version of close prior to
+// the libsyscall version, close's implementation is overridden.
 
 #include <sys/cdefs.h>
+#include <unistd.h>
 
 // If the non-cancelable variants of all system calls have already been
 // chosen, do nothing.
@@ -41,37 +43,26 @@
 
 extern "C" {
 
-#if __DARWIN_UNIX03 && !__DARWIN_ONLY_UNIX_CONFORMANCE
+#if !__DARWIN_ONLY_UNIX_CONFORMANCE
 
-// When there's a choice between UNIX2003 and pre-UNIX2003 and UNIX2003 has
-// been chosen:
-#define close_interface close$UNIX2003
-#define close_implementation close$NOCANCEL$UNIX2003
-
-#elif !__DARWIN_UNIX03 && !__DARWIN_ONLY_UNIX_CONFORMANCE
-
-// When there's a choice between UNIX2003 and pre-UNIX2003 and pre-UNIX2003
-// has been chosen. There's no close$NOCANCEL symbol in this case, so use
-// close$NOCANCEL$UNIX2003 as the implementation. It does the same thing
-// that close$NOCANCEL would do.
-#define close_interface close
+// When there's a choice between UNIX2003 and pre-UNIX2003. There's no
+// close$NOCANCEL symbol in this case, so use close$NOCANCEL$UNIX2003 as the
+// implementation. It does the same thing that close$NOCANCEL would do.
 #define close_implementation close$NOCANCEL$UNIX2003
 
 #else  // __DARWIN_ONLY_UNIX_CONFORMANCE
 
 // When only UNIX2003 is supported:
-#define close_interface close
 #define close_implementation close$NOCANCEL
 
 #endif
 
 int close_implementation(int fd);
 
-int close_interface(int fd) {
+int close(int fd) {
   return close_implementation(fd);
 }
 
-#undef close_interface
 #undef close_implementation
 
 }  // extern "C"
diff --git a/base/md5.cc b/base/md5.cc
index 6227ee6..72c774d 100644
--- a/base/md5.cc
+++ b/base/md5.cc
@@ -23,27 +23,28 @@
 
 #include "base/md5.h"
 
-#include "base/basictypes.h"
+#include <stddef.h>
 
 namespace {
 
 struct Context {
-  uint32 buf[4];
-  uint32 bits[2];
-  unsigned char in[64];
+  uint32_t buf[4];
+  uint32_t bits[2];
+  uint8_t in[64];
 };
 
 /*
  * Note: this code is harmless on little-endian machines.
  */
-void byteReverse(unsigned char *buf, unsigned longs) {
-        uint32 t;
-        do {
-                t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
-                            ((unsigned)buf[1]<<8 | buf[0]);
-                *(uint32 *)buf = t;
-                buf += 4;
-        } while (--longs);
+void byteReverse(uint8_t* buf, unsigned longs) {
+  do {
+    uint32_t temp = static_cast<uint32_t>(
+        static_cast<unsigned>(buf[3]) << 8 |
+        buf[2]) << 16 |
+        (static_cast<unsigned>(buf[1]) << 8 | buf[0]);
+    *reinterpret_cast<uint32_t*>(buf) = temp;
+    buf += 4;
+  } while (--longs);
 }
 
 /* The four core functions - F1 is optimized somewhat */
@@ -56,93 +57,93 @@
 
 /* This is the central step in the MD5 algorithm. */
 #define MD5STEP(f, w, x, y, z, data, s) \
-        ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+  (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
 
 /*
  * The core of the MD5 algorithm, this alters an existing MD5 hash to
  * reflect the addition of 16 longwords of new data.  MD5Update blocks
  * the data and converts bytes into longwords for this routine.
  */
-void MD5Transform(uint32 buf[4], const uint32 in[16]) {
-        register uint32 a, b, c, d;
+void MD5Transform(uint32_t buf[4], const uint32_t in[16]) {
+  uint32_t a, b, c, d;
 
-        a = buf[0];
-        b = buf[1];
-        c = buf[2];
-        d = buf[3];
+  a = buf[0];
+  b = buf[1];
+  c = buf[2];
+  d = buf[3];
 
-        MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
-        MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
-        MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
-        MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
-        MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
-        MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
-        MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
-        MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
-        MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
-        MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
-        MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
-        MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
-        MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
-        MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
-        MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
-        MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
 
-        MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
-        MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
-        MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
-        MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
-        MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
-        MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
-        MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
-        MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
-        MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
-        MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
-        MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
-        MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
-        MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
-        MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
-        MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
-        MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
 
-        MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
-        MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
-        MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
-        MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
-        MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
-        MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
-        MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
-        MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
-        MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
-        MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
-        MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
-        MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
-        MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
-        MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
-        MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
-        MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
 
-        MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
-        MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
-        MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
-        MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
-        MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
-        MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
-        MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
-        MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
-        MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
-        MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
-        MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
-        MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
-        MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
-        MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
-        MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
-        MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
 
-        buf[0] += a;
-        buf[1] += b;
-        buf[2] += c;
-        buf[3] += d;
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
 }
 
 }  // namespace
@@ -154,13 +155,13 @@
  * initialization constants.
  */
 void MD5Init(MD5Context* context) {
-        struct Context *ctx = (struct Context *)context;
-        ctx->buf[0] = 0x67452301;
-        ctx->buf[1] = 0xefcdab89;
-        ctx->buf[2] = 0x98badcfe;
-        ctx->buf[3] = 0x10325476;
-        ctx->bits[0] = 0;
-        ctx->bits[1] = 0;
+  struct Context* ctx = reinterpret_cast<struct Context*>(context);
+  ctx->buf[0] = 0x67452301;
+  ctx->buf[1] = 0xefcdab89;
+  ctx->buf[2] = 0x98badcfe;
+  ctx->buf[3] = 0x10325476;
+  ctx->bits[0] = 0;
+  ctx->bits[1] = 0;
 }
 
 /*
@@ -168,51 +169,49 @@
  * of bytes.
  */
 void MD5Update(MD5Context* context, const StringPiece& data) {
-        const unsigned char* inbuf = (const unsigned char*)data.data();
-        size_t len = data.size();
-        struct Context *ctx = (struct Context *)context;
-        const unsigned char* buf = (const unsigned char*)inbuf;
-        uint32 t;
+  struct Context* ctx = reinterpret_cast<struct Context*>(context);
+  const uint8_t* buf = reinterpret_cast<const uint8_t*>(data.data());
+  size_t len = data.size();
 
-        /* Update bitcount */
+  /* Update bitcount */
 
-        t = ctx->bits[0];
-        if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
-                ctx->bits[1]++; /* Carry from low to high */
-        ctx->bits[1] += static_cast<uint32>(len >> 29);
+  uint32_t t = ctx->bits[0];
+  if ((ctx->bits[0] = t + (static_cast<uint32_t>(len) << 3)) < t)
+    ctx->bits[1]++; /* Carry from low to high */
+  ctx->bits[1] += static_cast<uint32_t>(len >> 29);
 
-        t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
+  t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
 
-        /* Handle any leading odd-sized chunks */
+  /* Handle any leading odd-sized chunks */
 
-        if (t) {
-                unsigned char *p = (unsigned char *)ctx->in + t;
+  if (t) {
+    uint8_t* p = static_cast<uint8_t*>(ctx->in + t);
 
-                t = 64-t;
-                if (len < t) {
-                        memcpy(p, buf, len);
-                        return;
-                }
-                memcpy(p, buf, t);
-                byteReverse(ctx->in, 16);
-                MD5Transform(ctx->buf, (uint32 *)ctx->in);
-                buf += t;
-                len -= t;
-        }
+    t = 64 - t;
+    if (len < t) {
+      memcpy(p, buf, len);
+      return;
+    }
+    memcpy(p, buf, t);
+    byteReverse(ctx->in, 16);
+    MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
+    buf += t;
+    len -= t;
+  }
 
-        /* Process data in 64-byte chunks */
+  /* Process data in 64-byte chunks */
 
-        while (len >= 64) {
-                memcpy(ctx->in, buf, 64);
-                byteReverse(ctx->in, 16);
-                MD5Transform(ctx->buf, (uint32 *)ctx->in);
-                buf += 64;
-                len -= 64;
-        }
+  while (len >= 64) {
+    memcpy(ctx->in, buf, 64);
+    byteReverse(ctx->in, 16);
+    MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
+    buf += 64;
+    len -= 64;
+  }
 
-        /* Handle any remaining bytes of data. */
+  /* Handle any remaining bytes of data. */
 
-        memcpy(ctx->in, buf, len);
+  memcpy(ctx->in, buf, len);
 }
 
 /*
@@ -220,48 +219,46 @@
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
 void MD5Final(MD5Digest* digest, MD5Context* context) {
-        struct Context *ctx = (struct Context *)context;
-        unsigned count;
-        unsigned char *p;
+  struct Context* ctx = reinterpret_cast<struct Context*>(context);
+  unsigned count;
+  uint8_t* p;
 
-        /* Compute number of bytes mod 64 */
-        count = (ctx->bits[0] >> 3) & 0x3F;
+  /* Compute number of bytes mod 64 */
+  count = (ctx->bits[0] >> 3) & 0x3F;
 
-        /* Set the first char of padding to 0x80.  This is safe since there is
-           always at least one byte free */
-        p = ctx->in + count;
-        *p++ = 0x80;
+  /* Set the first char of padding to 0x80.  This is safe since there is
+     always at least one byte free */
+  p = ctx->in + count;
+  *p++ = 0x80;
 
-        /* Bytes of padding needed to make 64 bytes */
-        count = 64 - 1 - count;
+  /* Bytes of padding needed to make 64 bytes */
+  count = 64 - 1 - count;
 
-        /* Pad out to 56 mod 64 */
-        if (count < 8) {
-                /* Two lots of padding:  Pad the first block to 64 bytes */
-                memset(p, 0, count);
-                byteReverse(ctx->in, 16);
-                MD5Transform(ctx->buf, (uint32 *)ctx->in);
+  /* Pad out to 56 mod 64 */
+  if (count < 8) {
+    /* Two lots of padding:  Pad the first block to 64 bytes */
+    memset(p, 0, count);
+    byteReverse(ctx->in, 16);
+    MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
 
-                /* Now fill the next block with 56 bytes */
-                memset(ctx->in, 0, 56);
-        } else {
-                /* Pad block to 56 bytes */
-                memset(p, 0, count-8);
-        }
-        byteReverse(ctx->in, 14);
+    /* Now fill the next block with 56 bytes */
+    memset(ctx->in, 0, 56);
+  } else {
+    /* Pad block to 56 bytes */
+    memset(p, 0, count - 8);
+  }
+  byteReverse(ctx->in, 14);
 
-        /* Append length in bits and transform */
-        memcpy(&ctx->in[14 * sizeof(ctx->bits[0])],
-               &ctx->bits[0],
-               sizeof(ctx->bits[0]));
-        memcpy(&ctx->in[15 * sizeof(ctx->bits[1])],
-               &ctx->bits[1],
-               sizeof(ctx->bits[1]));
+  /* Append length in bits and transform */
+  memcpy(&ctx->in[14 * sizeof(ctx->bits[0])], &ctx->bits[0],
+         sizeof(ctx->bits[0]));
+  memcpy(&ctx->in[15 * sizeof(ctx->bits[1])], &ctx->bits[1],
+         sizeof(ctx->bits[1]));
 
-        MD5Transform(ctx->buf, (uint32 *)ctx->in);
-        byteReverse((unsigned char *)ctx->buf, 4);
-        memcpy(digest->a, ctx->buf, 16);
-        memset(ctx, 0, sizeof(*ctx));    /* In case it's sensitive */
+  MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
+  byteReverse(reinterpret_cast<uint8_t*>(ctx->buf), 4);
+  memcpy(digest->a, ctx->buf, 16);
+  memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
 }
 
 void MD5IntermediateFinal(MD5Digest* digest, const MD5Context* context) {
@@ -278,11 +275,10 @@
   std::string ret;
   ret.resize(32);
 
-  int j = 0;
-  for (int i = 0; i < 16; i ++) {
-    int a = digest.a[i];
-    ret[j++] = zEncode[(a>>4)&0xf];
-    ret[j++] = zEncode[a & 0xf];
+  for (int i = 0, j = 0; i < 16; i++, j += 2) {
+    uint8_t a = digest.a[i];
+    ret[j] = zEncode[(a >> 4) & 0xf];
+    ret[j + 1] = zEncode[a & 0xf];
   }
   return ret;
 }
@@ -290,8 +286,7 @@
 void MD5Sum(const void* data, size_t length, MD5Digest* digest) {
   MD5Context ctx;
   MD5Init(&ctx);
-  MD5Update(&ctx,
-            StringPiece(reinterpret_cast<const char*>(data), length));
+  MD5Update(&ctx, StringPiece(reinterpret_cast<const char*>(data), length));
   MD5Final(digest, &ctx);
 }
 
diff --git a/base/md5.h b/base/md5.h
index 0a87fcf..0b4cbce 100644
--- a/base/md5.h
+++ b/base/md5.h
@@ -5,6 +5,8 @@
 #ifndef BASE_MD5_H_
 #define BASE_MD5_H_
 
+#include <stdint.h>
+
 #include "base/base_export.h"
 #include "base/strings/string_piece.h"
 
@@ -35,17 +37,13 @@
 
 // The output of an MD5 operation.
 struct MD5Digest {
-  unsigned char a[16];
+  uint8_t a[16];
 };
 
 // Used for storing intermediate data during an MD5 computation. Callers
 // should not access the data.
 typedef char MD5Context[88];
 
-// Computes the MD5 sum of the given data buffer with the given length.
-// The given 'digest' structure will be filled with the result data.
-BASE_EXPORT void MD5Sum(const void* data, size_t length, MD5Digest* digest);
-
 // Initializes the given MD5 context structure for subsequent calls to
 // MD5Update().
 BASE_EXPORT void MD5Init(MD5Context* context);
@@ -67,6 +65,10 @@
 // Converts a digest into human-readable hexadecimal.
 BASE_EXPORT std::string MD5DigestToBase16(const MD5Digest& digest);
 
+// Computes the MD5 sum of the given data buffer with the given length.
+// The given 'digest' structure will be filled with the result data.
+BASE_EXPORT void MD5Sum(const void* data, size_t length, MD5Digest* digest);
+
 // Returns the MD5 (in hexadecimal) of a string.
 BASE_EXPORT std::string MD5String(const StringPiece& str);
 
diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn
index a0608e8..bd864ca 100644
--- a/base/memory/BUILD.gn
+++ b/base/memory/BUILD.gn
@@ -16,6 +16,8 @@
     "manual_constructor.h",
     "memory_pressure_listener.cc",
     "memory_pressure_listener.h",
+    "memory_pressure_monitor.cc",
+    "memory_pressure_monitor.h",
     "raw_scoped_refptr_mismatch_checker.h",
     "ref_counted.cc",
     "ref_counted.h",
diff --git a/base/memory/discardable_memory.h b/base/memory/discardable_memory.h
index a0882cc..fc189e7 100644
--- a/base/memory/discardable_memory.h
+++ b/base/memory/discardable_memory.h
@@ -52,8 +52,13 @@
   virtual void Unlock() = 0;
 
   // Returns the memory address held by this object. The object must be locked
-  // before calling this. Otherwise, this will cause a DCHECK error.
-  virtual void* Memory() const = 0;
+  // before calling this.
+  virtual void* data() const = 0;
+
+  // Handy method to simplify calling data() with a reinterpret_cast.
+  template<typename T> T* data_as() const {
+    return reinterpret_cast<T*>(data());
+  }
 };
 
 }  // namespace base
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index 49e93cd..830d6b9 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -325,22 +325,6 @@
   return true;
 }
 
-bool DiscardableSharedMemory::PurgeAndTruncate(Time current_time) {
-  if (!Purge(current_time))
-    return false;
-
-#if defined(OS_POSIX)
-  // Truncate shared memory to size of SharedState.
-  SharedMemoryHandle handle = shared_memory_.handle();
-  if (SharedMemory::IsHandleValid(handle)) {
-    if (HANDLE_EINTR(ftruncate(handle.fd, sizeof(SharedState))) != 0)
-      DPLOG(ERROR) << "ftruncate() failed";
-  }
-#endif
-
-  return true;
-}
-
 bool DiscardableSharedMemory::IsMemoryResident() const {
   DCHECK(shared_memory_.memory());
 
@@ -357,6 +341,26 @@
   mapped_size_ = 0;
 }
 
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+void DiscardableSharedMemory::Shrink() {
+#if defined(OS_POSIX)
+  SharedMemoryHandle handle = shared_memory_.handle();
+  if (!SharedMemory::IsHandleValid(handle))
+    return;
+
+  // Truncate shared memory to size of SharedState.
+  if (HANDLE_EINTR(
+          ftruncate(handle.fd, AlignToPageSize(sizeof(SharedState)))) != 0) {
+    DPLOG(ERROR) << "ftruncate() failed";
+    return;
+  }
+  mapped_size_ = 0;
+#else
+  NOTIMPLEMENTED();
+#endif
+}
+#endif
+
 Time DiscardableSharedMemory::Now() const {
   return Time::Now();
 }
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h
index e3b437c..892d556 100644
--- a/base/memory/discardable_shared_memory.h
+++ b/base/memory/discardable_shared_memory.h
@@ -15,6 +15,12 @@
 #include <set>
 #endif
 
+// Define DISCARDABLE_SHARED_MEMORY_SHRINKING if platform supports shrinking
+// of discardable shared memory segments.
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#define DISCARDABLE_SHARED_MEMORY_SHRINKING
+#endif
+
 namespace base {
 
 // Platform abstraction for discardable shared memory.
@@ -93,12 +99,6 @@
   // each call.
   bool Purge(Time current_time);
 
-  // Purge and release as much memory as possible to the OS.
-  // Note: The amount of memory that can be released to the OS is platform
-  // specific. Best case, all but one page is released. Worst case, nothing
-  // is released.
-  bool PurgeAndTruncate(Time current_time);
-
   // Returns true if memory is still resident.
   bool IsMemoryResident() const;
 
@@ -116,6 +116,12 @@
     return shared_memory_.ShareToProcess(process_handle, new_handle);
   }
 
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+  // Release as much memory as possible to the OS. The change in size will
+  // be reflected by the return value of mapped_size().
+  void Shrink();
+#endif
+
  private:
   // Virtual for tests.
   virtual Time Now() const;
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc
index 74d19a6..ae7235d 100644
--- a/base/memory/discardable_shared_memory_unittest.cc
+++ b/base/memory/discardable_shared_memory_unittest.cc
@@ -311,5 +311,21 @@
   EXPECT_EQ(0u, memory.mapped_size());
 }
 
+#if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
+TEST(DiscardableSharedMemoryTest, Shrink) {
+  const uint32 kDataSize = 1024;
+
+  TestDiscardableSharedMemory memory;
+  bool rv = memory.CreateAndMap(kDataSize);
+  ASSERT_TRUE(rv);
+
+  EXPECT_NE(0u, memory.mapped_size());
+
+  // Mapped size should be 0 after shrinking memory segment.
+  memory.Shrink();
+  EXPECT_EQ(0u, memory.mapped_size());
+}
+#endif
+
 }  // namespace
 }  // namespace base
diff --git a/base/memory/manual_constructor.h b/base/memory/manual_constructor.h
index 9275f73..56081a1 100644
--- a/base/memory/manual_constructor.h
+++ b/base/memory/manual_constructor.h
@@ -18,6 +18,7 @@
 
 #include <stddef.h>
 
+#include "base/compiler_specific.h"
 #include "base/memory/aligned_memory.h"
 
 namespace base {
@@ -33,11 +34,7 @@
   // Support users creating arrays of ManualConstructor<>s.  This ensures that
   // the array itself has the correct alignment.
   static void* operator new[](size_t size) {
-#if defined(COMPILER_MSVC)
-    return AlignedAlloc(size, __alignof(Type));
-#else
-    return AlignedAlloc(size, __alignof__(Type));
-#endif
+    return AlignedAlloc(size, ALIGNOF(Type));
   }
   static void operator delete[](void* mem) {
     AlignedFree(mem);
@@ -56,56 +53,9 @@
   inline Type& operator*() { return *get(); }
   inline const Type& operator*() const { return *get(); }
 
-  // You can pass up to eight constructor arguments as arguments of Init().
-  inline void Init() {
-    new(space_.void_data()) Type;
-  }
-
-  template <typename T1>
-  inline void Init(const T1& p1) {
-    new(space_.void_data()) Type(p1);
-  }
-
-  template <typename T1, typename T2>
-  inline void Init(const T1& p1, const T2& p2) {
-    new(space_.void_data()) Type(p1, p2);
-  }
-
-  template <typename T1, typename T2, typename T3>
-  inline void Init(const T1& p1, const T2& p2, const T3& p3) {
-    new(space_.void_data()) Type(p1, p2, p3);
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4>
-  inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
-    new(space_.void_data()) Type(p1, p2, p3, p4);
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
-                   const T5& p5) {
-    new(space_.void_data()) Type(p1, p2, p3, p4, p5);
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-            typename T6>
-  inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
-                   const T5& p5, const T6& p6) {
-    new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6);
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-            typename T6, typename T7>
-  inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
-                   const T5& p5, const T6& p6, const T7& p7) {
-    new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7);
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-            typename T6, typename T7, typename T8>
-  inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
-                   const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
-    new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7, p8);
+  template <typename... Ts>
+  inline void Init(const Ts&... params) {
+    new(space_.void_data()) Type(params...);
   }
 
   inline void Destroy() {
@@ -113,11 +63,7 @@
   }
 
  private:
-#if defined(COMPILER_MSVC)
-  AlignedMemory<sizeof(Type), __alignof(Type)> space_;
-#else
-  AlignedMemory<sizeof(Type), __alignof__(Type)> space_;
-#endif
+  AlignedMemory<sizeof(Type), ALIGNOF(Type)> space_;
 };
 
 }  // namespace base
diff --git a/base/memory/memory_pressure_monitor.cc b/base/memory/memory_pressure_monitor.cc
new file mode 100644
index 0000000..00633f1
--- /dev/null
+++ b/base/memory/memory_pressure_monitor.cc
@@ -0,0 +1,31 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/memory_pressure_monitor.h"
+
+#include "base/logging.h"
+
+namespace base {
+namespace {
+
+MemoryPressureMonitor* g_monitor = nullptr;
+
+}  // namespace
+
+MemoryPressureMonitor::MemoryPressureMonitor() {
+  DCHECK(!g_monitor);
+  g_monitor = this;
+}
+
+MemoryPressureMonitor::~MemoryPressureMonitor() {
+  DCHECK(g_monitor);
+  g_monitor = nullptr;
+}
+
+// static
+MemoryPressureMonitor* MemoryPressureMonitor::Get() {
+  return g_monitor;
+}
+
+}  // namespace base
diff --git a/base/memory/memory_pressure_monitor.h b/base/memory/memory_pressure_monitor.h
new file mode 100644
index 0000000..9aeeaca
--- /dev/null
+++ b/base/memory/memory_pressure_monitor.h
@@ -0,0 +1,39 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
+#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
+
+#include "base/base_export.h"
+#include "base/memory/memory_pressure_listener.h"
+
+namespace base {
+
+// Declares the interface for a MemoryPressureMonitor. There are multiple
+// OS specific implementations of this class. An instance of the memory
+// pressure observer is created at the process level, tracks memory usage, and
+// pushes memory state change notifications to the static function
+// base::MemoryPressureListener::NotifyMemoryPressure. This is turn notifies
+// all MemoryPressureListener instances via a callback.
+class BASE_EXPORT MemoryPressureMonitor {
+ public:
+  using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
+
+  // Return the singleton MemoryPressureMonitor.
+  static MemoryPressureMonitor* Get();
+
+  // Returns the currently observed memory pressure.
+  virtual MemoryPressureLevel GetCurrentPressureLevel() const = 0;
+
+ protected:
+  MemoryPressureMonitor();
+  virtual ~MemoryPressureMonitor();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor);
+};
+
+}  // namespace base
+
+#endif  // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
index 219437e..5f94b4c 100644
--- a/base/memory/ref_counted.h
+++ b/base/memory/ref_counted.h
@@ -14,6 +14,7 @@
 #ifndef NDEBUG
 #include "base/logging.h"
 #endif
+#include "base/move.h"
 #include "base/threading/thread_collision_warner.h"
 #include "build/build_config.h"
 
@@ -264,6 +265,7 @@
 //
 template <class T>
 class scoped_refptr {
+  TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_refptr)
  public:
   typedef T element_type;
 
@@ -286,6 +288,11 @@
       AddRef(ptr_);
   }
 
+  template <typename U>
+  scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
+    r.ptr_ = nullptr;
+  }
+
   ~scoped_refptr() {
     if (ptr_)
       Release(ptr_);
@@ -323,6 +330,17 @@
     return *this = r.get();
   }
 
+  scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
+    scoped_refptr<T>(r.Pass()).swap(*this);
+    return *this;
+  }
+
+  template <typename U>
+  scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
+    scoped_refptr<T>(r.Pass()).swap(*this);
+    return *this;
+  }
+
   void swap(T** pp) {
     T* p = ptr_;
     ptr_ = *pp;
@@ -334,6 +352,8 @@
   }
 
  private:
+  template <typename U> friend class scoped_refptr;
+
   // Allow scoped_refptr<T> to be used in boolean expressions, but not
   // implicitly convertible to a real bool (which is dangerous).
   //
diff --git a/base/memory/ref_counted_delete_on_message_loop.h b/base/memory/ref_counted_delete_on_message_loop.h
index 7b898ac..139a1ed 100644
--- a/base/memory/ref_counted_delete_on_message_loop.h
+++ b/base/memory/ref_counted_delete_on_message_loop.h
@@ -8,7 +8,9 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+// TODO(ricea): Remove the following include once all callers have been fixed.
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
 
 namespace base {
 
@@ -18,7 +20,7 @@
 // Sample usage:
 // class Foo : public RefCountedDeleteOnMessageLoop<Foo> {
 //
-//   Foo(const scoped_refptr<MessageLoopProxy>& loop)
+//   Foo(const scoped_refptr<SingleThreadTaskRunner>& loop)
 //       : RefCountedDeleteOnMessageLoop<Foo>(loop) {
 //     ...
 //   }
@@ -33,9 +35,14 @@
 template <class T>
 class RefCountedDeleteOnMessageLoop : public subtle::RefCountedThreadSafeBase {
  public:
+  // This constructor will accept a MessageL00pProxy object, but new code should
+  // prefer a SingleThreadTaskRunner. A SingleThreadTaskRunner for the
+  // MessageLoop on the current thread can be acquired by calling
+  // MessageLoop::current()->task_runner().
   RefCountedDeleteOnMessageLoop(
-      const scoped_refptr<MessageLoopProxy>& proxy) : proxy_(proxy) {
-    DCHECK(proxy_.get());
+      const scoped_refptr<SingleThreadTaskRunner>& task_runner)
+      : task_runner_(task_runner) {
+    DCHECK(task_runner_.get());
   }
 
   void AddRef() const {
@@ -53,13 +60,13 @@
 
   void DestructOnMessageLoop() const {
     const T* t = static_cast<const T*>(this);
-    if (proxy_->BelongsToCurrentThread())
+    if (task_runner_->BelongsToCurrentThread())
       delete t;
     else
-      proxy_->DeleteSoon(FROM_HERE, t);
+      task_runner_->DeleteSoon(FROM_HERE, t);
   }
 
-  scoped_refptr<MessageLoopProxy> proxy_;
+  scoped_refptr<SingleThreadTaskRunner> task_runner_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(RefCountedDeleteOnMessageLoop);
diff --git a/base/memory/ref_counted_unittest.cc b/base/memory/ref_counted_unittest.cc
index f75cd38..6f8e599 100644
--- a/base/memory/ref_counted_unittest.cc
+++ b/base/memory/ref_counted_unittest.cc
@@ -40,19 +40,71 @@
 
   static bool was_destroyed() { return was_destroyed_; }
 
-  void SelfDestruct() { self_ptr_ = NULL; }
+  static void reset_was_destroyed() { was_destroyed_ = false; }
+
+  scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
 
  private:
   friend class base::RefCounted<ScopedRefPtrToSelf>;
   ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
 
   static bool was_destroyed_;
-
-  scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
 };
 
 bool ScopedRefPtrToSelf::was_destroyed_ = false;
 
+class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
+ public:
+  ScopedRefPtrCountBase() { ++constructor_count_; }
+
+  static int constructor_count() { return constructor_count_; }
+
+  static int destructor_count() { return destructor_count_; }
+
+  static void reset_count() {
+    constructor_count_ = 0;
+    destructor_count_ = 0;
+  }
+
+ protected:
+  virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
+
+ private:
+  friend class base::RefCounted<ScopedRefPtrCountBase>;
+
+  static int constructor_count_;
+  static int destructor_count_;
+};
+
+int ScopedRefPtrCountBase::constructor_count_ = 0;
+int ScopedRefPtrCountBase::destructor_count_ = 0;
+
+class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
+ public:
+  ScopedRefPtrCountDerived() { ++constructor_count_; }
+
+  static int constructor_count() { return constructor_count_; }
+
+  static int destructor_count() { return destructor_count_; }
+
+  static void reset_count() {
+    constructor_count_ = 0;
+    destructor_count_ = 0;
+  }
+
+ protected:
+  ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
+
+ private:
+  friend class base::RefCounted<ScopedRefPtrCountDerived>;
+
+  static int constructor_count_;
+  static int destructor_count_;
+};
+
+int ScopedRefPtrCountDerived::constructor_count_ = 0;
+int ScopedRefPtrCountDerived::destructor_count_ = 0;
+
 }  // end namespace
 
 TEST(RefCountedUnitTest, TestSelfAssignment) {
@@ -66,10 +118,24 @@
   CheckDerivedMemberAccess check;
 }
 
-TEST(RefCountedUnitTest, ScopedRefPtrToSelf) {
+TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
+  ScopedRefPtrToSelf::reset_was_destroyed();
+
   ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
   EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
-  check->SelfDestruct();
+  check->self_ptr_ = nullptr;
+  EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
+}
+
+TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
+  ScopedRefPtrToSelf::reset_was_destroyed();
+
+  ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
+  EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
+  // Releasing |check->self_ptr_| will delete |check|.
+  // The move assignment operator must assign |check->self_ptr_| first then
+  // release |check->self_ptr_|.
+  check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
   EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
 }
 
@@ -113,3 +179,284 @@
   EXPECT_EQ(p1, p2);
   EXPECT_EQ(p2, p1);
 }
+
+TEST(RefCountedUnitTest, SelfMoveAssignment) {
+  ScopedRefPtrCountBase::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p(raw);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    p = p.Pass();
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+    EXPECT_EQ(raw, p.get());
+
+    // p goes out of scope.
+  }
+  EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignment1) {
+  ScopedRefPtrCountBase::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    {
+      scoped_refptr<ScopedRefPtrCountBase> p2;
+
+      p2 = p1.Pass();
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(nullptr, p1.get());
+      EXPECT_EQ(raw, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignment2) {
+  ScopedRefPtrCountBase::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p1;
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    {
+      scoped_refptr<ScopedRefPtrCountBase> p2(raw);
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+      p1 = p2.Pass();
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(raw, p1.get());
+      EXPECT_EQ(nullptr, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
+  ScopedRefPtrCountBase::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    {
+      scoped_refptr<ScopedRefPtrCountBase> p2(p1);
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+      p1 = p2.Pass();
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(raw, p1.get());
+      EXPECT_EQ(nullptr, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
+  ScopedRefPtrCountBase::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    {
+      scoped_refptr<ScopedRefPtrCountBase> p2(p1);
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+      p2 = p1.Pass();
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(nullptr, p1.get());
+      EXPECT_EQ(raw, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
+  ScopedRefPtrCountBase::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    {
+      ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
+      scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
+      EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+      p1 = p2.Pass();
+      EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(raw2, p1.get());
+      EXPECT_EQ(nullptr, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveAssignmentDerived) {
+  ScopedRefPtrCountBase::reset_count();
+  ScopedRefPtrCountDerived::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+    {
+      ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
+      scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
+      EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+      p1 = p2.Pass();
+      EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+      EXPECT_EQ(raw2, p1.get());
+      EXPECT_EQ(nullptr, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveConstructor) {
+  ScopedRefPtrCountBase::reset_count();
+
+  {
+    ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
+    scoped_refptr<ScopedRefPtrCountBase> p1(raw);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+
+    {
+      scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(nullptr, p1.get());
+      EXPECT_EQ(raw, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+}
+
+TEST(RefCountedUnitTest, MoveConstructorDerived) {
+  ScopedRefPtrCountBase::reset_count();
+  ScopedRefPtrCountDerived::reset_count();
+
+  {
+    ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
+    scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+    EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+
+    {
+      scoped_refptr<ScopedRefPtrCountBase> p2(p1.Pass());
+      EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
+      EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+      EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
+      EXPECT_EQ(nullptr, p1.get());
+      EXPECT_EQ(raw1, p2.get());
+
+      // p2 goes out of scope.
+    }
+    EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+    EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+
+    // p1 goes out of scope.
+  }
+  EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
+  EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
+}
+
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc
index 6e5a4d8..6fe5706 100644
--- a/base/memory/shared_memory_unittest.cc
+++ b/base/memory/shared_memory_unittest.cc
@@ -101,10 +101,10 @@
 class MultipleLockThread : public PlatformThread::Delegate {
  public:
   explicit MultipleLockThread(int id) : id_(id) {}
-  virtual ~MultipleLockThread() {}
+  ~MultipleLockThread() override {}
 
   // PlatformThread::Delegate interface.
-  virtual void ThreadMain() override {
+  void ThreadMain() override {
     const uint32 kDataSize = sizeof(int);
     SharedMemoryHandle handle = NULL;
     {
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index ccf79c0..ddde6bb 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -425,7 +425,7 @@
  public:
   DispatcherImpl() : dispatch_count_(0) {}
 
-  virtual uint32_t Dispatch(const NativeEvent& msg) override {
+  uint32_t Dispatch(const NativeEvent& msg) override {
     ::TranslateMessage(&msg);
     ::DispatchMessage(&msg);
     // Do not count WM_TIMER since it is not what we post and it will cause
@@ -489,8 +489,9 @@
  public:
   TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
 
-  virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
-                             DWORD bytes_transfered, DWORD error);
+  void OnIOCompleted(MessageLoopForIO::IOContext* context,
+                     DWORD bytes_transfered,
+                     DWORD error) override;
 
   void Init();
   void WaitForIO();
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc
index d52025a..b5b1fb7 100644
--- a/base/message_loop/message_pump_libevent.cc
+++ b/base/message_loop/message_pump_libevent.cc
@@ -15,6 +15,7 @@
 #include "base/observer_list.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
 #include "third_party/libevent/event.h"
 
 #if defined(OS_MACOSX)
@@ -274,6 +275,9 @@
         delayed_work_time_ = TimeTicks();
       }
     }
+
+    if (!keep_running_)
+      break;
   }
 }
 
@@ -341,6 +345,8 @@
   WeakPtr<FileDescriptorWatcher> controller =
       static_cast<FileDescriptorWatcher*>(context)->weak_factory_.GetWeakPtr();
   DCHECK(controller.get());
+  TRACE_EVENT1("toplevel", "MessagePumpLibevent::OnLibeventNotification",
+               "fd", fd);
 
   MessagePumpLibevent* pump = controller->pump();
   pump->processed_io_events_ = true;
diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc
index 1058ee8..65d7217 100644
--- a/base/message_loop/message_pump_libevent_unittest.cc
+++ b/base/message_loop/message_pump_libevent_unittest.cc
@@ -7,9 +7,14 @@
 #include <unistd.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_util.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/synchronization/waitable_event_watcher.h"
 #include "base/threading/thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libevent/event.h"
@@ -19,7 +24,7 @@
 class MessagePumpLibeventTest : public testing::Test {
  protected:
   MessagePumpLibeventTest()
-      : ui_loop_(MessageLoop::TYPE_UI),
+      : ui_loop_(new MessageLoop(MessageLoop::TYPE_UI)),
         io_thread_("MessagePumpLibeventTestIOThread") {}
   ~MessagePumpLibeventTest() override {}
 
@@ -38,7 +43,6 @@
       PLOG(ERROR) << "close";
   }
 
-  MessageLoop* ui_loop() { return &ui_loop_; }
   MessageLoopForIO* io_loop() const {
     return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
   }
@@ -50,9 +54,9 @@
   }
 
   int pipefds_[2];
+  scoped_ptr<MessageLoop> ui_loop_;
 
  private:
-  MessageLoop ui_loop_;
   Thread io_thread_;
 };
 
@@ -194,6 +198,69 @@
   OnLibeventNotification(pump.get(), &watcher);
 }
 
+void FatalClosure() {
+  FAIL() << "Reached fatal closure.";
+}
+
+class QuitWatcher : public BaseWatcher {
+ public:
+  QuitWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller,
+              RunLoop* run_loop)
+      : BaseWatcher(controller), run_loop_(run_loop) {}
+  ~QuitWatcher() override {}
+
+  void OnFileCanReadWithoutBlocking(int /* fd */) override {
+    // Post a fatal closure to the MessageLoop before we quit it.
+    MessageLoop::current()->PostTask(FROM_HERE, Bind(&FatalClosure));
+
+    // Now quit the MessageLoop.
+    run_loop_->Quit();
+  }
+
+ private:
+  RunLoop* run_loop_;  // weak
+};
+
+void WriteFDWrapper(const int fd,
+                    const char* buf,
+                    int size,
+                    WaitableEvent* event) {
+  ASSERT_TRUE(WriteFileDescriptor(fd, buf, size));
+}
+
+// Tests that MessagePumpLibevent quits immediately when it is quit from
+// libevent's event_base_loop().
+TEST_F(MessagePumpLibeventTest, QuitWatcher) {
+  // Delete the old MessageLoop so that we can manage our own one here.
+  ui_loop_.reset();
+
+  MessagePumpLibevent* pump = new MessagePumpLibevent;  // owned by |loop|.
+  MessageLoop loop(make_scoped_ptr(pump));
+  RunLoop run_loop;
+  MessagePumpLibevent::FileDescriptorWatcher controller;
+  QuitWatcher delegate(&controller, &run_loop);
+  WaitableEvent event(false /* manual_reset */, false /* initially_signaled */);
+  WaitableEventWatcher watcher;
+
+  // Tell the pump to watch the pipe.
+  pump->WatchFileDescriptor(pipefds_[0], false, MessagePumpLibevent::WATCH_READ,
+                            &controller, &delegate);
+
+  // Make the IO thread wait for |event| before writing to pipefds[1].
+  const char buf = 0;
+  const WaitableEventWatcher::EventCallback write_fd_task =
+      Bind(&WriteFDWrapper, pipefds_[1], &buf, 1);
+  io_loop()->PostTask(FROM_HERE,
+                      Bind(IgnoreResult(&WaitableEventWatcher::StartWatching),
+                           Unretained(&watcher), &event, write_fd_task));
+
+  // Queue |event| to signal on |loop|.
+  loop.PostTask(FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&event)));
+
+  // Now run the MessageLoop.
+  run_loop.Run();
+}
+
 }  // namespace
 
 }  // namespace base
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc
index 8226495..27b47e1 100644
--- a/base/message_loop/message_pump_win.cc
+++ b/base/message_loop/message_pump_win.cc
@@ -53,6 +53,10 @@
   state_ = previous_state;
 }
 
+void MessagePumpWin::Run(Delegate* delegate) {
+  RunWithDispatcher(delegate, NULL);
+}
+
 void MessagePumpWin::Quit() {
   DCHECK(state_);
   state_->should_quit = true;
@@ -472,6 +476,9 @@
   DCHECK(port_.IsValid());
 }
 
+MessagePumpForIO::~MessagePumpForIO() {
+}
+
 void MessagePumpForIO::ScheduleWork() {
   if (InterlockedExchange(&have_work_, 1))
     return;  // Someone else continued the pumping.
diff --git a/base/message_loop/message_pump_win.h b/base/message_loop/message_pump_win.h
index b257317..00f1287 100644
--- a/base/message_loop/message_pump_win.h
+++ b/base/message_loop/message_pump_win.h
@@ -25,14 +25,13 @@
 class BASE_EXPORT MessagePumpWin : public MessagePump {
  public:
   MessagePumpWin() : have_work_(0), state_(NULL) {}
-  virtual ~MessagePumpWin() {}
 
   // Like MessagePump::Run, but MSG objects are routed through dispatcher.
   void RunWithDispatcher(Delegate* delegate, MessagePumpDispatcher* dispatcher);
 
   // MessagePump methods:
-  virtual void Run(Delegate* delegate) { RunWithDispatcher(delegate, NULL); }
-  virtual void Quit();
+  void Run(Delegate* delegate) override;
+  void Quit() override;
 
  protected:
   struct RunState {
@@ -115,18 +114,18 @@
   static const int kMessageFilterCode = 0x5001;
 
   MessagePumpForUI();
-  virtual ~MessagePumpForUI();
+  ~MessagePumpForUI() override;
 
   // MessagePump methods:
-  virtual void ScheduleWork();
-  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
+  void ScheduleWork() override;
+  void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
 
  private:
   static LRESULT CALLBACK WndProcThunk(HWND window_handle,
                                        UINT message,
                                        WPARAM wparam,
                                        LPARAM lparam);
-  virtual void DoRunLoop();
+  void DoRunLoop() override;
   void InitMessageWnd();
   void WaitForWork();
   void HandleWorkMessage();
@@ -267,11 +266,11 @@
   };
 
   MessagePumpForIO();
-  virtual ~MessagePumpForIO() {}
+  ~MessagePumpForIO() override;
 
   // MessagePump methods:
-  virtual void ScheduleWork();
-  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
+  void ScheduleWork() override;
+  void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
 
   // Register the handler to be used when asynchronous IO for the given file
   // completes. The registration persists as long as |file_handle| is valid, so
@@ -311,7 +310,7 @@
     bool has_valid_io_context;
   };
 
-  virtual void DoRunLoop();
+  void DoRunLoop() override;
   void WaitForWork();
   bool MatchCompletedIOItem(IOHandler* filter, IOItem* item);
   bool GetIOItem(DWORD timeout, IOItem* item);
diff --git a/base/metrics/BUILD.gn b/base/metrics/BUILD.gn
index 0202637..845ac4f 100644
--- a/base/metrics/BUILD.gn
+++ b/base/metrics/BUILD.gn
@@ -12,8 +12,8 @@
     "histogram.h",
     "histogram_base.cc",
     "histogram_base.h",
-    "histogram_delta_serialization.",
     "histogram_delta_serialization.cc",
+    "histogram_delta_serialization.h",
     "histogram_flattener.h",
     "histogram_macros.h",
     "histogram_samples.cc",
diff --git a/base/move.h b/base/move.h
index 06f3f32..87dc52d 100644
--- a/base/move.h
+++ b/base/move.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/compiler_specific.h"
-
 #ifndef BASE_MOVE_H_
 #define BASE_MOVE_H_
 
+#include "base/compiler_specific.h"
+
 // Macro with the boilerplate that makes a type move-only in C++03.
 //
 // USAGE
@@ -219,11 +219,16 @@
 
 #define MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \
  private: \
-  type(type&); \
-  void operator=(type&); \
+  type(const type&); \
+  void operator=(const type&); \
  public: \
   type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \
   typedef void MoveOnlyTypeForCPP03; \
  private:
 
+#define TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \
+ public: \
+  type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \
+ private:
+
 #endif  // BASE_MOVE_H_
diff --git a/base/move_unittest.cc b/base/move_unittest.cc
new file mode 100644
index 0000000..1f4ce84
--- /dev/null
+++ b/base/move_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/move.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class MoveOnly {
+  MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(MoveOnly)
+
+ public:
+  MoveOnly() {}
+
+  MoveOnly(MoveOnly&& other) {}
+  MoveOnly& operator=(MoveOnly&& other) { return *this; }
+};
+
+class Container {
+ public:
+  Container() = default;
+  Container(const Container& other) = default;
+  Container& operator=(const Container& other) = default;
+
+  Container(Container&& other) { value_ = other.value_.Pass(); }
+
+  Container& operator=(Container&& other) {
+    value_ = other.value_.Pass();
+    return *this;
+  }
+
+ private:
+  MoveOnly value_;
+};
+
+Container GetContainerRvalue() {
+  Container x;
+  return x;
+}
+
+TEST(MoveTest, CopyableContainerCanBeMoved) {
+  // Container should be move-constructible and move-assignable.
+  Container y = GetContainerRvalue();
+  y = GetContainerRvalue();
+}
+
+}  // namespace
diff --git a/base/native_library_ios.mm b/base/native_library_ios.mm
new file mode 100644
index 0000000..030c171
--- /dev/null
+++ b/base/native_library_ios.mm
@@ -0,0 +1,40 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/native_library.h"
+
+#include "base/logging.h"
+
+namespace base {
+
+std::string NativeLibraryLoadError::ToString() const {
+  return message;
+}
+
+// static
+NativeLibrary LoadNativeLibrary(const base::FilePath& library_path,
+                                NativeLibraryLoadError* error) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+// static
+void UnloadNativeLibrary(NativeLibrary library) {
+  NOTIMPLEMENTED();
+  DCHECK(!library);
+}
+
+// static
+void* GetFunctionPointerFromNativeLibrary(NativeLibrary library,
+                                          const char* name) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+// static
+string16 GetNativeLibraryName(const string16& name) {
+  return name;
+}
+
+}  // namespace base
diff --git a/base/observer_list.h b/base/observer_list.h
index f7b9267..9ea344d 100644
--- a/base/observer_list.h
+++ b/base/observer_list.h
@@ -143,17 +143,18 @@
 template <class ObserverType>
 ObserverType* ObserverListBase<ObserverType>::Iterator::GetNext() {
   if (!list_.get())
-    return NULL;
+    return nullptr;
   ListType& observers = list_->observers_;
   // Advance if the current element is null
   size_t max_index = std::min(max_index_, observers.size());
   while (index_ < max_index && !observers[index_])
     ++index_;
-  return index_ < max_index ? observers[index_++] : NULL;
+  return index_ < max_index ? observers[index_++] : nullptr;
 }
 
 template <class ObserverType>
 void ObserverListBase<ObserverType>::AddObserver(ObserverType* obs) {
+  DCHECK(obs);
   if (std::find(observers_.begin(), observers_.end(), obs)
       != observers_.end()) {
     NOTREACHED() << "Observers can only be added once!";
@@ -164,11 +165,12 @@
 
 template <class ObserverType>
 void ObserverListBase<ObserverType>::RemoveObserver(ObserverType* obs) {
+  DCHECK(obs);
   typename ListType::iterator it =
     std::find(observers_.begin(), observers_.end(), obs);
   if (it != observers_.end()) {
     if (notify_depth_) {
-      *it = 0;
+      *it = nullptr;
     } else {
       observers_.erase(it);
     }
@@ -190,7 +192,7 @@
   if (notify_depth_) {
     for (typename ListType::iterator it = observers_.begin();
       it != observers_.end(); ++it) {
-      *it = 0;
+      *it = nullptr;
     }
   } else {
     observers_.clear();
@@ -200,8 +202,8 @@
 template <class ObserverType>
 void ObserverListBase<ObserverType>::Compact() {
   observers_.erase(
-      std::remove(observers_.begin(), observers_.end(),
-                  static_cast<ObserverType*>(NULL)), observers_.end());
+      std::remove(observers_.begin(), observers_.end(), nullptr),
+      observers_.end());
 }
 
 template <class ObserverType, bool check_empty = false>
@@ -233,7 +235,7 @@
       ObserverListBase<ObserverType>::Iterator it_inside_observer_macro( \
           &observer_list);                                               \
       ObserverType* obs;                                                 \
-      while ((obs = it_inside_observer_macro.GetNext()) != NULL)         \
+      while ((obs = it_inside_observer_macro.GetNext()) != nullptr)         \
         obs->func;                                                       \
     }                                                                    \
   } while (0)
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h
index 46ce880..5205a5a 100644
--- a/base/observer_list_threadsafe.h
+++ b/base/observer_list_threadsafe.h
@@ -111,7 +111,7 @@
     if (!base::MessageLoop::current())
       return;
 
-    ObserverList<ObserverType>* list = NULL;
+    ObserverList<ObserverType>* list = nullptr;
     base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
     {
       base::AutoLock lock(list_lock_);
@@ -128,8 +128,8 @@
   // If the observer to be removed is in the list, RemoveObserver MUST
   // be called from the same thread which called AddObserver.
   void RemoveObserver(ObserverType* obs) {
-    ObserverListContext* context = NULL;
-    ObserverList<ObserverType>* list = NULL;
+    ObserverListContext* context = nullptr;
+    ObserverList<ObserverType>* list = nullptr;
     base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
     {
       base::AutoLock lock(list_lock_);
@@ -230,7 +230,7 @@
     {
       typename ObserverList<ObserverType>::Iterator it(&context->list);
       ObserverType* obs;
-      while ((obs = it.GetNext()) != NULL)
+      while ((obs = it.GetNext()) != nullptr)
         method.Run(obs);
     }
 
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc
index 636aa83..ea916b1 100644
--- a/base/observer_list_unittest.cc
+++ b/base/observer_list_unittest.cc
@@ -71,7 +71,7 @@
         adder(1) {
   }
 
-  virtual void Observe(int x) override {
+  void Observe(int x) override {
     if (!added) {
       added = true;
       observer_list->AddObserver(&adder);
@@ -94,7 +94,7 @@
  public:
   AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify)
       : list_(list),
-        loop_(NULL),
+        loop_(nullptr),
         in_list_(false),
         start_(Time::Now()),
         count_observes_(0),
diff --git a/base/prefs/pref_member.h b/base/prefs/pref_member.h
index 078be95..9b140d1 100644
--- a/base/prefs/pref_member.h
+++ b/base/prefs/pref_member.h
@@ -264,9 +264,9 @@
     }
 
    protected:
-    virtual ~Internal() {}
+    ~Internal() override {}
 
-    virtual BASE_PREFS_EXPORT bool UpdateValueInternal(
+    BASE_PREFS_EXPORT bool UpdateValueInternal(
         const base::Value& value) const override;
 
     // We cache the value of the pref so we don't have to keep walking the pref
@@ -277,8 +277,8 @@
     DISALLOW_COPY_AND_ASSIGN(Internal);
   };
 
-  virtual Internal* internal() const override { return internal_.get(); }
-  virtual void CreateInternal() const override { internal_ = new Internal(); }
+  Internal* internal() const override { return internal_.get(); }
+  void CreateInternal() const override { internal_ = new Internal(); }
 
   // This method is used to do the actual sync with pref of the specified type.
   void BASE_PREFS_EXPORT UpdatePref(const ValueType& value);
diff --git a/base/prefs/pref_registry.cc b/base/prefs/pref_registry.cc
index 69f0494..74f4b52 100644
--- a/base/prefs/pref_registry.cc
+++ b/base/prefs/pref_registry.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/prefs/default_pref_store.h"
 #include "base/prefs/pref_store.h"
+#include "base/stl_util.h"
 #include "base/values.h"
 
 PrefRegistry::PrefRegistry()
@@ -16,6 +17,13 @@
 PrefRegistry::~PrefRegistry() {
 }
 
+uint32 PrefRegistry::GetRegistrationFlags(const std::string& pref_name) const {
+  const auto& it = registration_flags_.find(pref_name);
+  if (it == registration_flags_.end())
+    return NO_REGISTRATION_FLAGS;
+  return it->second;
+}
+
 scoped_refptr<PrefStore> PrefRegistry::defaults() {
   return defaults_.get();
 }
@@ -41,13 +49,18 @@
 }
 
 void PrefRegistry::RegisterPreference(const std::string& path,
-                                      base::Value* default_value) {
+                                      base::Value* default_value,
+                                      uint32 flags) {
   base::Value::Type orig_type = default_value->GetType();
   DCHECK(orig_type != base::Value::TYPE_NULL &&
          orig_type != base::Value::TYPE_BINARY) <<
          "invalid preference type: " << orig_type;
   DCHECK(!defaults_->GetValue(path, NULL)) <<
       "Trying to register a previously registered pref: " << path;
+  DCHECK(!ContainsKey(registration_flags_, path)) <<
+      "Trying to register a previously registered pref: " << path;
 
   defaults_->SetDefaultValue(path, make_scoped_ptr(default_value));
+  if (flags != NO_REGISTRATION_FLAGS)
+    registration_flags_[path] = flags;
 }
diff --git a/base/prefs/pref_registry.h b/base/prefs/pref_registry.h
index a500b6e..cc5804e 100644
--- a/base/prefs/pref_registry.h
+++ b/base/prefs/pref_registry.h
@@ -5,6 +5,7 @@
 #ifndef BASE_PREFS_PREF_REGISTRY_H_
 #define BASE_PREFS_PREF_REGISTRY_H_
 
+#include "base/containers/hash_tables.h"
 #include "base/memory/ref_counted.h"
 #include "base/prefs/base_prefs_export.h"
 #include "base/prefs/pref_value_map.h"
@@ -27,10 +28,26 @@
 // also work, but this is being deprecated.
 class BASE_PREFS_EXPORT PrefRegistry : public base::RefCounted<PrefRegistry> {
  public:
+  // Registration flags that can be specified which impact how the pref will
+  // behave or be stored. This will be passed in a bitmask when the pref is
+  // registered. Subclasses of PrefRegistry can specify their own flags. Care
+  // must be taken to ensure none of these overlap with the flags below.
+  enum PrefRegistrationFlags {
+    // No flags are specified.
+    NO_REGISTRATION_FLAGS = 0,
+
+    // The first 8 bits are reserved for subclasses of PrefRegistry to use.
+  };
+
   typedef PrefValueMap::const_iterator const_iterator;
+  typedef base::hash_map<std::string, uint32> PrefRegistrationFlagsMap;
 
   PrefRegistry();
 
+  // Retrieve the set of registration flags for the given preference. The return
+  // value is a bitmask of PrefRegistrationFlags.
+  uint32 GetRegistrationFlags(const std::string& pref_name) const;
+
   // Gets the registered defaults.
   scoped_refptr<PrefStore> defaults();
 
@@ -47,11 +64,17 @@
   friend class base::RefCounted<PrefRegistry>;
   virtual ~PrefRegistry();
 
-  // Used by subclasses to register a default value for a preference.
-  void RegisterPreference(const std::string& path, base::Value* default_value);
+  // Used by subclasses to register a default value and registration flags for
+  // a preference. |flags| is a bitmask of |PrefRegistrationFlags|.
+  void RegisterPreference(const std::string& path,
+                          base::Value* default_value,
+                          uint32 flags);
 
   scoped_refptr<DefaultPrefStore> defaults_;
 
+  // A map of pref name to a bitmask of PrefRegistrationFlags.
+  PrefRegistrationFlagsMap registration_flags_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(PrefRegistry);
 };
diff --git a/base/prefs/pref_registry_simple.cc b/base/prefs/pref_registry_simple.cc
index fa679dc..93c2686 100644
--- a/base/prefs/pref_registry_simple.cc
+++ b/base/prefs/pref_registry_simple.cc
@@ -16,51 +16,146 @@
 
 void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
                                              bool default_value) {
-  RegisterPreference(path, new base::FundamentalValue(default_value));
+  RegisterPrefAndNotify(path, new base::FundamentalValue(default_value),
+                        NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterIntegerPref(const std::string& path,
                                              int default_value) {
-  RegisterPreference(path, new base::FundamentalValue(default_value));
+  RegisterPrefAndNotify(path, new base::FundamentalValue(default_value),
+                        NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterDoublePref(const std::string& path,
                                             double default_value) {
-  RegisterPreference(path, new base::FundamentalValue(default_value));
+  RegisterPrefAndNotify(path, new base::FundamentalValue(default_value),
+                        NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterStringPref(const std::string& path,
                                             const std::string& default_value) {
-  RegisterPreference(path, new base::StringValue(default_value));
+  RegisterPrefAndNotify(path, new base::StringValue(default_value),
+                        NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterFilePathPref(
     const std::string& path,
     const base::FilePath& default_value) {
-  RegisterPreference(path, new base::StringValue(default_value.value()));
+  RegisterPrefAndNotify(path, new base::StringValue(default_value.value()),
+                        NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterListPref(const std::string& path) {
-  RegisterPreference(path, new base::ListValue());
+  RegisterPrefAndNotify(path, new base::ListValue(), NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterListPref(const std::string& path,
                                           base::ListValue* default_value) {
-  RegisterPreference(path, default_value);
+  RegisterPrefAndNotify(path, default_value, NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path) {
-  RegisterPreference(path, new base::DictionaryValue());
+  RegisterPrefAndNotify(path, new base::DictionaryValue(),
+                        NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterDictionaryPref(
     const std::string& path,
     base::DictionaryValue* default_value) {
-  RegisterPreference(path, default_value);
+  RegisterPrefAndNotify(path, default_value, NO_REGISTRATION_FLAGS);
 }
 
 void PrefRegistrySimple::RegisterInt64Pref(const std::string& path,
                                            int64 default_value) {
-  RegisterPreference(
-      path, new base::StringValue(base::Int64ToString(default_value)));
+  RegisterPrefAndNotify(
+      path, new base::StringValue(base::Int64ToString(default_value)),
+      NO_REGISTRATION_FLAGS);
+}
+
+void PrefRegistrySimple::RegisterUint64Pref(const std::string& path,
+                                            uint64 default_value) {
+  RegisterPrefAndNotify(
+      path, new base::StringValue(base::Uint64ToString(default_value)),
+      NO_REGISTRATION_FLAGS);
+}
+
+void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
+                                             bool default_value,
+                                             uint32 flags) {
+  RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterIntegerPref(const std::string& path,
+                                             int default_value,
+                                             uint32 flags) {
+  RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterDoublePref(const std::string& path,
+                                            double default_value,
+                                            uint32 flags) {
+  RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterStringPref(const std::string& path,
+                                            const std::string& default_value,
+                                            uint32 flags) {
+  RegisterPrefAndNotify(path, new base::StringValue(default_value), flags);
+}
+
+void PrefRegistrySimple::RegisterFilePathPref(
+    const std::string& path,
+    const base::FilePath& default_value,
+    uint32 flags) {
+  RegisterPrefAndNotify(path, new base::StringValue(default_value.value()),
+                        flags);
+}
+
+void PrefRegistrySimple::RegisterListPref(const std::string& path,
+                                          uint32 flags) {
+  RegisterPrefAndNotify(path, new base::ListValue(), flags);
+}
+
+void PrefRegistrySimple::RegisterListPref(const std::string& path,
+                                          base::ListValue* default_value,
+                                          uint32 flags) {
+  RegisterPrefAndNotify(path, default_value, flags);
+}
+
+void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path,
+                                                uint32 flags) {
+  RegisterPrefAndNotify(path, new base::DictionaryValue(), flags);
+}
+
+void PrefRegistrySimple::RegisterDictionaryPref(
+    const std::string& path,
+    base::DictionaryValue* default_value,
+    uint32 flags) {
+  RegisterPrefAndNotify(path, default_value, flags);
+}
+
+void PrefRegistrySimple::RegisterInt64Pref(const std::string& path,
+                                           int64 default_value,
+                                           uint32 flags) {
+  RegisterPrefAndNotify(
+      path, new base::StringValue(base::Int64ToString(default_value)), flags);
+}
+
+void PrefRegistrySimple::RegisterUint64Pref(const std::string& path,
+                                            uint64 default_value,
+                                            uint32 flags) {
+  RegisterPrefAndNotify(
+      path, new base::StringValue(base::Uint64ToString(default_value)), flags);
+}
+
+void PrefRegistrySimple::OnPrefRegistered(const std::string& path,
+                                          base::Value* default_value,
+                                          uint32 flags) {
+}
+
+void PrefRegistrySimple::RegisterPrefAndNotify(const std::string& path,
+                                               base::Value* default_value,
+                                               uint32 flags) {
+  RegisterPreference(path, default_value, flags);
+  OnPrefRegistered(path, default_value, flags);
 }
diff --git a/base/prefs/pref_registry_simple.h b/base/prefs/pref_registry_simple.h
index 73ae216..6b69e30 100644
--- a/base/prefs/pref_registry_simple.h
+++ b/base/prefs/pref_registry_simple.h
@@ -35,9 +35,48 @@
   void RegisterDictionaryPref(const std::string& path,
                               base::DictionaryValue* default_value);
   void RegisterInt64Pref(const std::string& path, int64 default_value);
+  void RegisterUint64Pref(const std::string&, uint64 default_value);
+
+  // Versions of registration functions that accept PrefRegistrationFlags.
+  // |flags| is a bitmask of PrefRegistrationFlags.
+  void RegisterBooleanPref(const std::string&,
+                           bool default_value,
+                           uint32 flags);
+  void RegisterIntegerPref(const std::string&, int default_value, uint32 flags);
+  void RegisterDoublePref(const std::string&,
+                          double default_value,
+                          uint32 flags);
+  void RegisterStringPref(const std::string&,
+                          const std::string& default_value,
+                          uint32 flags);
+  void RegisterFilePathPref(const std::string&,
+                            const base::FilePath& default_value,
+                            uint32 flags);
+  void RegisterListPref(const std::string&, uint32 flags);
+  void RegisterDictionaryPref(const std::string&, uint32 flags);
+  void RegisterListPref(const std::string&,
+                        base::ListValue* default_value,
+                        uint32 flags);
+  void RegisterDictionaryPref(const std::string&,
+                              base::DictionaryValue* default_value,
+                              uint32 flags);
+  void RegisterInt64Pref(const std::string&, int64 default_value, uint32 flags);
+  void RegisterUint64Pref(const std::string&,
+                          uint64 default_value,
+                          uint32 flags);
+
+ protected:
+  ~PrefRegistrySimple() override;
+
+  // Allows subclasses to hook into pref registration.
+  virtual void OnPrefRegistered(const std::string&,
+                                base::Value* default_value,
+                                uint32 flags);
 
  private:
-  ~PrefRegistrySimple() override;
+  void RegisterPrefAndNotify(const std::string&,
+                             base::Value* default_value,
+                             uint32 flags);
 
   DISALLOW_COPY_AND_ASSIGN(PrefRegistrySimple);
 };
diff --git a/base/prefs/pref_value_map.cc b/base/prefs/pref_value_map.cc
index cafc1d8..5f2dc50 100644
--- a/base/prefs/pref_value_map.cc
+++ b/base/prefs/pref_value_map.cc
@@ -4,6 +4,8 @@
 
 #include "base/prefs/pref_value_map.h"
 
+#include <map>
+
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/stl_util.h"
@@ -18,51 +20,49 @@
 bool PrefValueMap::GetValue(const std::string& key,
                             const base::Value** value) const {
   const Map::const_iterator entry = prefs_.find(key);
-  if (entry != prefs_.end()) {
-    if (value)
-      *value = entry->second;
-    return true;
-  }
+  if (entry == prefs_.end())
+    return false;
 
-  return false;
+  if (value)
+    *value = entry->second;
+  return true;
 }
 
 bool PrefValueMap::GetValue(const std::string& key, base::Value** value) {
   const Map::const_iterator entry = prefs_.find(key);
-  if (entry != prefs_.end()) {
-    if (value)
-      *value = entry->second;
-    return true;
-  }
+  if (entry == prefs_.end())
+    return false;
 
-  return false;
+  if (value)
+    *value = entry->second;
+  return true;
 }
 
 bool PrefValueMap::SetValue(const std::string& key, base::Value* value) {
   DCHECK(value);
+  auto result = prefs_.insert(std::make_pair(key, value));
+  if (result.second)
+    return true;
+
   scoped_ptr<base::Value> value_ptr(value);
-  const Map::iterator entry = prefs_.find(key);
-  if (entry != prefs_.end()) {
-    if (base::Value::Equals(entry->second, value))
-      return false;
-    delete entry->second;
-    entry->second = value_ptr.release();
-  } else {
-    prefs_[key] = value_ptr.release();
-  }
+  const Map::iterator& entry = result.first;
+  if (base::Value::Equals(entry->second, value))
+    return false;
+
+  delete entry->second;
+  entry->second = value_ptr.release();
 
   return true;
 }
 
 bool PrefValueMap::RemoveValue(const std::string& key) {
   const Map::iterator entry = prefs_.find(key);
-  if (entry != prefs_.end()) {
-    delete entry->second;
-    prefs_.erase(entry);
-    return true;
-  }
+  if (entry == prefs_.end())
+    return false;
 
-  return false;
+  delete entry->second;
+  prefs_.erase(entry);
+  return true;
 }
 
 void PrefValueMap::Clear() {
@@ -91,7 +91,7 @@
 
 bool PrefValueMap::GetBoolean(const std::string& key,
                               bool* value) const {
-  const base::Value* stored_value = NULL;
+  const base::Value* stored_value = nullptr;
   return GetValue(key, &stored_value) && stored_value->GetAsBoolean(value);
 }
 
@@ -101,7 +101,7 @@
 
 bool PrefValueMap::GetString(const std::string& key,
                              std::string* value) const {
-  const base::Value* stored_value = NULL;
+  const base::Value* stored_value = nullptr;
   return GetValue(key, &stored_value) && stored_value->GetAsString(value);
 }
 
@@ -111,7 +111,7 @@
 }
 
 bool PrefValueMap::GetInteger(const std::string& key, int* value) const {
-  const base::Value* stored_value = NULL;
+  const base::Value* stored_value = nullptr;
   return GetValue(key, &stored_value) && stored_value->GetAsInteger(value);
 }
 
@@ -128,10 +128,15 @@
     std::vector<std::string>* differing_keys) const {
   differing_keys->clear();
 
+  // Put everything into ordered maps.
+  std::map<std::string, base::Value*> this_prefs(prefs_.begin(), prefs_.end());
+  std::map<std::string, base::Value*> other_prefs(other->prefs_.begin(),
+                                                  other->prefs_.end());
+
   // Walk over the maps in lockstep, adding everything that is different.
-  Map::const_iterator this_pref(prefs_.begin());
-  Map::const_iterator other_pref(other->prefs_.begin());
-  while (this_pref != prefs_.end() && other_pref != other->prefs_.end()) {
+  auto this_pref(this_prefs.begin());
+  auto other_pref(other_prefs.begin());
+  while (this_pref != this_prefs.end() && other_pref != other_prefs.end()) {
     const int diff = this_pref->first.compare(other_pref->first);
     if (diff == 0) {
       if (!this_pref->second->Equals(other_pref->second))
@@ -148,8 +153,8 @@
   }
 
   // Add the remaining entries.
-  for ( ; this_pref != prefs_.end(); ++this_pref)
+  for ( ; this_pref != this_prefs.end(); ++this_pref)
       differing_keys->push_back(this_pref->first);
-  for ( ; other_pref != other->prefs_.end(); ++other_pref)
+  for ( ; other_pref != other_prefs.end(); ++other_pref)
       differing_keys->push_back(other_pref->first);
 }
diff --git a/base/prefs/pref_value_map.h b/base/prefs/pref_value_map.h
index 2db18ab..12b30c6 100644
--- a/base/prefs/pref_value_map.h
+++ b/base/prefs/pref_value_map.h
@@ -5,11 +5,11 @@
 #ifndef BASE_PREFS_PREF_VALUE_MAP_H_
 #define BASE_PREFS_PREF_VALUE_MAP_H_
 
-#include <map>
 #include <string>
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
 #include "base/prefs/base_prefs_export.h"
 
 namespace base {
@@ -19,8 +19,9 @@
 // A generic string to value map used by the PrefStore implementations.
 class BASE_PREFS_EXPORT PrefValueMap {
  public:
-  typedef std::map<std::string, base::Value*>::iterator iterator;
-  typedef std::map<std::string, base::Value*>::const_iterator const_iterator;
+  using Map = base::hash_map<std::string, base::Value*>;
+  using iterator = Map::iterator;
+  using const_iterator = Map::const_iterator;
 
   PrefValueMap();
   virtual ~PrefValueMap();
@@ -81,8 +82,6 @@
                         std::vector<std::string>* differing_keys) const;
 
  private:
-  typedef std::map<std::string, base::Value*> Map;
-
   Map prefs_;
 
   DISALLOW_COPY_AND_ASSIGN(PrefValueMap);
diff --git a/base/process/kill.cc b/base/process/kill.cc
index a647d96..5d8ba6a 100644
--- a/base/process/kill.cc
+++ b/base/process/kill.cc
@@ -15,7 +15,7 @@
   NamedProcessIterator iter(executable_name, filter);
   while (const ProcessEntry* entry = iter.NextProcessEntry()) {
     Process process = Process::Open(entry->pid());
-    result &= KillProcess(process.Handle(), exit_code, true);
+    result &= process.Terminate(exit_code, true);
   }
   return result;
 }
diff --git a/base/process/kill.h b/base/process/kill.h
index df0d95e..af00b03 100644
--- a/base/process/kill.h
+++ b/base/process/kill.h
@@ -45,12 +45,6 @@
                                int exit_code,
                                const ProcessFilter* filter);
 
-// Attempts to kill the process identified by the given process
-// entry structure, giving it the specified exit code. If |wait| is true, wait
-// for the process to be actually terminated before returning.
-// Returns true if this is successful, false otherwise.
-BASE_EXPORT bool KillProcess(ProcessHandle process, int exit_code, bool wait);
-
 #if defined(OS_POSIX)
 // Attempts to kill the process group identified by |process_group_id|. Returns
 // true on success.
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc
index 298486b..0e303c6 100644
--- a/base/process/kill_posix.cc
+++ b/base/process/kill_posix.cc
@@ -15,7 +15,6 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/process_iterator.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/platform_thread.h"
 
 namespace base {
@@ -69,61 +68,6 @@
 }  // namespace
 
 #if !defined(OS_NACL_NONSFI)
-// Attempts to kill the process identified by the given process
-// entry structure.  Ignores specified exit_code; posix can't force that.
-// Returns true if this is successful, false otherwise.
-bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
-  DCHECK_GT(process_id, 1) << " tried to kill invalid process_id";
-  if (process_id <= 1)
-    return false;
-  bool result = kill(process_id, SIGTERM) == 0;
-  if (result && wait) {
-    int tries = 60;
-
-    if (RunningOnValgrind()) {
-      // Wait for some extra time when running under Valgrind since the child
-      // processes may take some time doing leak checking.
-      tries *= 2;
-    }
-
-    unsigned sleep_ms = 4;
-
-    // The process may not end immediately due to pending I/O
-    bool exited = false;
-    while (tries-- > 0) {
-      pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
-      if (pid == process_id) {
-        exited = true;
-        break;
-      }
-      if (pid == -1) {
-        if (errno == ECHILD) {
-          // The wait may fail with ECHILD if another process also waited for
-          // the same pid, causing the process state to get cleaned up.
-          exited = true;
-          break;
-        }
-        DPLOG(ERROR) << "Error waiting for process " << process_id;
-      }
-
-      usleep(sleep_ms * 1000);
-      const unsigned kMaxSleepMs = 1000;
-      if (sleep_ms < kMaxSleepMs)
-        sleep_ms *= 2;
-    }
-
-    // If we're waiting and the child hasn't died by now, force it
-    // with a SIGKILL.
-    if (!exited)
-      result = kill(process_id, SIGKILL) == 0;
-  }
-
-  if (!result)
-    DPLOG(ERROR) << "Unable to terminate process " << process_id;
-
-  return result;
-}
-
 bool KillProcessGroup(ProcessHandle process_group_id) {
   bool result = kill(-1 * process_group_id, SIGKILL) == 0;
   if (!result)
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index 3c93047..0da3a26 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -38,12 +38,12 @@
 class TimerExpiredTask : public win::ObjectWatcher::Delegate {
  public:
   explicit TimerExpiredTask(Process process);
-  ~TimerExpiredTask();
+  ~TimerExpiredTask() override;
 
   void TimedOut();
 
   // MessageLoop::Watcher -----------------------------------------------------
-  virtual void OnObjectSignaled(HANDLE object);
+  void OnObjectSignaled(HANDLE object) override;
 
  private:
   void KillProcess();
@@ -81,7 +81,7 @@
   // terminates.  We just care that it eventually terminates, and that's what
   // TerminateProcess should do for us. Don't check for the result code since
   // it fails quite often. This should be investigated eventually.
-  base::KillProcess(process_.Handle(), kProcessKilledExitCode, false);
+  process_.Terminate(kProcessKilledExitCode, false);
 
   // Now, just cleanup as if the process exited normally.
   OnObjectSignaled(process_.Handle());
@@ -89,18 +89,6 @@
 
 }  // namespace
 
-bool KillProcess(ProcessHandle process, int exit_code, bool wait) {
-  bool result = (TerminateProcess(process, exit_code) != FALSE);
-  if (result && wait) {
-    // The process may not end immediately due to pending I/O
-    if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000))
-      DPLOG(ERROR) << "Error waiting for process exit";
-  } else if (!result) {
-    DPLOG(ERROR) << "Unable to terminate process";
-  }
-  return result;
-}
-
 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
   DWORD tmp_exit_code = 0;
 
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc
index c2bd295..ebc19b8 100644
--- a/base/process/launch_win.cc
+++ b/base/process/launch_win.cc
@@ -219,7 +219,8 @@
     if (0 == AssignProcessToJobObject(options.job_handle,
                                       process_info.process_handle())) {
       DLOG(ERROR) << "Could not AssignProcessToObject.";
-      KillProcess(process_info.process_handle(), kProcessKilledExitCode, true);
+      Process scoped_process(process_info.TakeProcessHandle());
+      scoped_process.Terminate(kProcessKilledExitCode, true);
       return Process();
     }
 
diff --git a/base/process/memory.cc b/base/process/memory.cc
index 8542dc5..133a72a 100644
--- a/base/process/memory.cc
+++ b/base/process/memory.cc
@@ -2,10 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/debug/alias.h"
+#include "base/logging.h"
 #include "base/process/memory.h"
 
 namespace base {
 
+namespace {
+
+// Breakpad server classifies base::`anonymous namespace'::OnNoMemory as
+// out-of-memory crash.
+NOINLINE void OnNoMemory(size_t size) {
+  size_t tmp_size = size;
+  base::debug::Alias(&tmp_size);
+  LOG(FATAL) << "Out of memory. size=" << tmp_size;
+}
+
+}  // namespace
+
+void TerminateBecauseOutOfMemory(size_t size) {
+  OnNoMemory(size);
+}
+
 // Defined in memory_mac.mm for Mac.
 #if !defined(OS_MACOSX)
 
diff --git a/base/process/memory.h b/base/process/memory.h
index 100d9c7..da27151 100644
--- a/base/process/memory.h
+++ b/base/process/memory.h
@@ -39,6 +39,10 @@
 // Turns on process termination if memory runs out.
 BASE_EXPORT void EnableTerminationOnOutOfMemory();
 
+// Terminates process. Should be called only for out of memory errors.
+// Crash reporting classifies such crashes as OOM.
+BASE_EXPORT void TerminateBecauseOutOfMemory(size_t size);
+
 #if defined(OS_WIN)
 // Returns the module handle to which an address belongs. The reference count
 // of the module is not incremented.
diff --git a/base/process/memory_mac.mm b/base/process/memory_mac.mm
index 0f0414b..4d719f8 100644
--- a/base/process/memory_mac.mm
+++ b/base/process/memory_mac.mm
@@ -131,7 +131,7 @@
                         size_t size) {
   void* result = g_old_malloc(zone, size);
   if (!result && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   return result;
 }
 
@@ -140,7 +140,7 @@
                         size_t size) {
   void* result = g_old_calloc(zone, num_items, size);
   if (!result && num_items && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(num_items * size);
   return result;
 }
 
@@ -148,7 +148,7 @@
                         size_t size) {
   void* result = g_old_valloc(zone, size);
   if (!result && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   return result;
 }
 
@@ -162,7 +162,7 @@
                          size_t size) {
   void* result = g_old_realloc(zone, ptr, size);
   if (!result && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   return result;
 }
 
@@ -175,7 +175,7 @@
   // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ).
   if (!result && size && alignment >= sizeof(void*) &&
       (alignment & (alignment - 1)) == 0) {
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   }
   return result;
 }
@@ -184,7 +184,7 @@
                                   size_t size) {
   void* result = g_old_malloc_purgeable(zone, size);
   if (!result && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   return result;
 }
 
@@ -193,7 +193,7 @@
                                   size_t size) {
   void* result = g_old_calloc_purgeable(zone, num_items, size);
   if (!result && num_items && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(num_items * size);
   return result;
 }
 
@@ -201,7 +201,7 @@
                                   size_t size) {
   void* result = g_old_valloc_purgeable(zone, size);
   if (!result && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   return result;
 }
 
@@ -215,7 +215,7 @@
                                    size_t size) {
   void* result = g_old_realloc_purgeable(zone, ptr, size);
   if (!result && size)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   return result;
 }
 
@@ -228,7 +228,7 @@
   // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ).
   if (!result && size && alignment >= sizeof(void*)
       && (alignment & (alignment - 1)) == 0) {
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(size);
   }
   return result;
 }
@@ -238,7 +238,7 @@
 // === C++ operator new ===
 
 void oom_killer_new() {
-  debug::BreakDebugger();
+  TerminateBecauseOutOfMemory(0);
 }
 
 #if !defined(ADDRESS_SANITIZER)
@@ -277,7 +277,7 @@
                                             void* info) {
   void* result = g_old_cfallocator_system_default(alloc_size, hint, info);
   if (!result)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(alloc_size);
   return result;
 }
 
@@ -286,7 +286,7 @@
                                     void* info) {
   void* result = g_old_cfallocator_malloc(alloc_size, hint, info);
   if (!result)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(alloc_size);
   return result;
 }
 
@@ -295,7 +295,7 @@
                                          void* info) {
   void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info);
   if (!result)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(alloc_size);
   return result;
 }
 
@@ -310,7 +310,7 @@
 {
   id result = g_old_allocWithZone(self, _cmd, zone);
   if (!result)
-    debug::BreakDebugger();
+    TerminateBecauseOutOfMemory(0);
   return result;
 }
 
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc
index 5904de2..0276b49 100644
--- a/base/process/memory_unittest.cc
+++ b/base/process/memory_unittest.cc
@@ -26,6 +26,7 @@
 #endif
 #if defined(OS_LINUX)
 #include <malloc.h>
+#include "base/test/malloc_wrapper.h"
 #endif
 
 #if defined(OS_WIN)
@@ -105,37 +106,6 @@
 // test suite setup and does not need to be done again, else mach_override
 // will fail.
 
-#if !defined(ADDRESS_SANITIZER)
-// The following code tests the system implementation of malloc() thus no need
-// to test it under AddressSanitizer.
-TEST(ProcessMemoryTest, MacMallocFailureDoesNotTerminate) {
-#if ARCH_CPU_32_BITS
-  // The Mavericks malloc library changed in a way which breaks the tricks used
-  // to implement EnableTerminationOnOutOfMemory() with UncheckedMalloc() under
-  // 32-bit.  Under 64-bit the oom_killer code handles this.
-  if (base::mac::IsOSMavericksOrLater())
-    return;
-#endif
-
-  // Test that ENOMEM doesn't crash via CrMallocErrorBreak two ways: the exit
-  // code and lack of the error string. The number of bytes is one less than
-  // MALLOC_ABSOLUTE_MAX_SIZE, more than which the system early-returns NULL and
-  // does not call through malloc_error_break(). See the comment at
-  // EnableTerminationOnOutOfMemory() for more information.
-  void* buf = NULL;
-  ASSERT_EXIT(
-      {
-        base::EnableTerminationOnOutOfMemory();
-
-        buf = malloc(std::numeric_limits<size_t>::max() - (2 * PAGE_SIZE) - 1);
-      },
-      testing::KilledBySignal(SIGTRAP),
-      "\\*\\*\\* error: can't allocate region.*\\n?.*");
-
-  base::debug::Alias(buf);
-}
-#endif  // !defined(ADDRESS_SANITIZER)
-
 TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
   // Assert that freeing an unallocated pointer will crash the process.
   char buf[9];
@@ -157,11 +127,12 @@
 #endif  // defined(OS_MACOSX)
 
 // Android doesn't implement set_new_handler, so we can't use the
-// OutOfMemoryTest cases.
-// OpenBSD does not support these tests either.
+// OutOfMemoryTest cases. OpenBSD does not support these tests either.
+// Don't test these on ASan/TSan/MSan configurations: only test the real
+// allocator.
 // TODO(vandebo) make this work on Windows too.
-#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
-    !defined(OS_WIN)
+#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN) && \
+    !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
 
 #if defined(USE_TCMALLOC)
 extern "C" {
@@ -169,6 +140,10 @@
 }
 #endif  // defined(USE_TCMALLOC)
 
+namespace {
+const char *kOomRegex = "Out of memory";
+}  // namespace
+
 class OutOfMemoryTest : public testing::Test {
  public:
   OutOfMemoryTest()
@@ -207,42 +182,42 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = operator new(test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, NewArray) {
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = new char[test_size_];
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, Malloc) {
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = malloc(test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, Realloc) {
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = realloc(NULL, test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, Calloc) {
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = calloc(1024, test_size_ / 1024L);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, Valloc) {
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = valloc(test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 #if defined(OS_LINUX)
@@ -252,7 +227,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = pvalloc(test_size_);
-    }, "");
+    }, kOomRegex);
 }
 #endif  // PVALLOC_AVAILABLE == 1
 
@@ -260,18 +235,16 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = memalign(4, test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) {
   // This tests that the run-time symbol resolution is overriding malloc for
-  // shared libraries (including libc itself) as well as for our code.
-  std::string format = base::StringPrintf("%%%zud", test_size_);
-  char *value = NULL;
+  // shared libraries as well as for our code.
   ASSERT_DEATH({
-      SetUpInDeathAssert();
-      EXPECT_EQ(-1, asprintf(&value, format.c_str(), 0));
-    }, "");
+    SetUpInDeathAssert();
+    value_ = MallocWrapper(test_size_);
+  }, kOomRegex);
 }
 #endif  // OS_LINUX
 
@@ -284,7 +257,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       EXPECT_EQ(ENOMEM, posix_memalign(&value_, 8, test_size_));
-    }, "");
+    }, kOomRegex);
 }
 #endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
 
@@ -297,7 +270,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = malloc_zone_malloc(zone, test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) {
@@ -305,7 +278,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = malloc_zone_realloc(zone, NULL, test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, CallocPurgeable) {
@@ -313,7 +286,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, VallocPurgeable) {
@@ -321,7 +294,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = malloc_zone_valloc(zone, test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) {
@@ -329,7 +302,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       value_ = malloc_zone_memalign(zone, 8, test_size_);
-    }, "");
+    }, kOomRegex);
 }
 
 // Since these allocation functions take a signed size, it's possible that
@@ -344,7 +317,7 @@
       SetUpInDeathAssert();
       while ((value_ =
               base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {}
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) {
@@ -352,7 +325,7 @@
       SetUpInDeathAssert();
       while ((value_ =
               base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {}
-    }, "");
+    }, kOomRegex);
 }
 
 TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) {
@@ -360,7 +333,7 @@
       SetUpInDeathAssert();
       while ((value_ =
               base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {}
-    }, "");
+    }, kOomRegex);
 }
 
 #if !defined(ARCH_CPU_64_BITS)
@@ -372,7 +345,7 @@
   ASSERT_DEATH({
       SetUpInDeathAssert();
       while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {}
-    }, "");
+    }, kOomRegex);
 }
 
 #endif  // !ARCH_CPU_64_BITS
@@ -442,4 +415,5 @@
   EXPECT_TRUE(value_ == NULL);
 }
 #endif  // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-#endif  // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN)
+#endif  // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN) &&
+        // !defined(ADDRESS_SANITIZER)
diff --git a/base/process/process.h b/base/process/process.h
index 045f870..808baeb 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -41,7 +41,7 @@
   Process(RValue other);
 
   // The destructor does not terminate the process.
-  ~Process() {}
+  ~Process();
 
   // Move operator= for C++03 move emulation of this type.
   Process& operator=(RValue other);
@@ -91,12 +91,12 @@
   // Close the process handle. This will not terminate the process.
   void Close();
 
-  // Terminates the process with extreme prejudice. The given |result_code| will
+  // Terminates the process with extreme prejudice. The given |exit_code| will
   // be the exit code of the process. If |wait| is true, this method will wait
   // for up to one minute for the process to actually terminate.
   // Returns true if the process terminates within the allowed time.
-  // NOTE: On POSIX |result_code| is ignored.
-  bool Terminate(int result_code, bool wait) const;
+  // NOTE: On POSIX |exit_code| is ignored.
+  bool Terminate(int exit_code, bool wait) const;
 
   // Waits for the process to exit. Returns true on success.
   // On POSIX, if the process has been signaled then |exit_code| is set to -1.
diff --git a/base/process/process_metrics_ios.cc b/base/process/process_metrics_ios.cc
index 9ae838d..07f2c8d 100644
--- a/base/process/process_metrics_ios.cc
+++ b/base/process/process_metrics_ios.cc
@@ -6,6 +6,8 @@
 
 #include <mach/task.h>
 
+#include "base/logging.h"
+
 namespace base {
 
 namespace {
@@ -30,6 +32,11 @@
   return new ProcessMetrics(process);
 }
 
+double ProcessMetrics::GetCPUUsage() {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
 size_t ProcessMetrics::GetPagefileUsage() const {
   task_basic_info_64 task_info_data;
   if (!GetTaskInfo(&task_info_data))
@@ -69,4 +76,10 @@
   return getpagesize();
 }
 
+// Bytes committed by the system.
+size_t GetSystemCommitCharge() {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
 }  // namespace base
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index dd37236..2d54c4c 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -669,13 +669,13 @@
   }
 
 #if defined(OS_CHROMEOS)
-  // Report on Chrome OS GEM object graphics memory. /var/run/debugfs_gpu is a
+  // Report on Chrome OS GEM object graphics memory. /run/debugfs_gpu is a
   // bind mount into /sys/kernel/debug and synchronously reading the in-memory
   // files in /sys is fast.
 #if defined(ARCH_CPU_ARM_FAMILY)
-  FilePath geminfo_file("/var/run/debugfs_gpu/exynos_gem_objects");
+  FilePath geminfo_file("/run/debugfs_gpu/exynos_gem_objects");
 #else
-  FilePath geminfo_file("/var/run/debugfs_gpu/i915_gem_objects");
+  FilePath geminfo_file("/run/debugfs_gpu/i915_gem_objects");
 #endif
   std::string geminfo_data;
   meminfo->gem_objects = -1;
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index a083123..a7d16f8 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/kill.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 
 #if defined(OS_MACOSX)
 #include <sys/event.h>
@@ -210,6 +211,9 @@
 Process::Process(ProcessHandle handle) : process_(handle) {
 }
 
+Process::~Process() {
+}
+
 Process::Process(RValue other)
     : process_(other.object->process_) {
   other.object->Close();
@@ -287,14 +291,59 @@
   // end up w/ a zombie when it does finally exit.
 }
 
-bool Process::Terminate(int result_code, bool wait) const {
+#if !defined(OS_NACL_NONSFI)
+bool Process::Terminate(int exit_code, bool wait) const {
   // result_code isn't supportable.
   DCHECK(IsValid());
-  // We don't wait here. It's the responsibility of other code to reap the
-  // child.
-  // TODO(rvargas) crbug/417532: Move the implementation here.
-  return KillProcess(process_, result_code, wait);
+  DCHECK_GT(process_, 1);
+  bool result = kill(process_, SIGTERM) == 0;
+  if (result && wait) {
+    int tries = 60;
+
+    if (RunningOnValgrind()) {
+      // Wait for some extra time when running under Valgrind since the child
+      // processes may take some time doing leak checking.
+      tries *= 2;
+    }
+
+    unsigned sleep_ms = 4;
+
+    // The process may not end immediately due to pending I/O
+    bool exited = false;
+    while (tries-- > 0) {
+      pid_t pid = HANDLE_EINTR(waitpid(process_, NULL, WNOHANG));
+      if (pid == process_) {
+        exited = true;
+        break;
+      }
+      if (pid == -1) {
+        if (errno == ECHILD) {
+          // The wait may fail with ECHILD if another process also waited for
+          // the same pid, causing the process state to get cleaned up.
+          exited = true;
+          break;
+        }
+        DPLOG(ERROR) << "Error waiting for process " << process_;
+      }
+
+      usleep(sleep_ms * 1000);
+      const unsigned kMaxSleepMs = 1000;
+      if (sleep_ms < kMaxSleepMs)
+        sleep_ms *= 2;
+    }
+
+    // If we're waiting and the child hasn't died by now, force it
+    // with a SIGKILL.
+    if (!exited)
+      result = kill(process_, SIGKILL) == 0;
+  }
+
+  if (!result)
+    DPLOG(ERROR) << "Unable to terminate process " << process_;
+
+  return result;
 }
+#endif  // !defined(OS_NACL_NONSFI)
 
 bool Process::WaitForExit(int* exit_code) {
   return WaitForExitWithTimeout(TimeDelta::Max(), exit_code);
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index d72dd49..0d312a3 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -32,6 +32,9 @@
   other.object->Close();
 }
 
+Process::~Process() {
+}
+
 Process& Process::operator=(RValue other) {
   if (this != other.object) {
     process_.Set(other.object->process_.Take());
@@ -123,10 +126,17 @@
   process_.Close();
 }
 
-bool Process::Terminate(int result_code, bool wait) const {
+bool Process::Terminate(int exit_code, bool wait) const {
   DCHECK(IsValid());
-  // TODO(rvargas) crbug/417532: Move the implementation here.
-  return KillProcess(Handle(), result_code, wait);
+  bool result = (::TerminateProcess(Handle(), exit_code) != FALSE);
+  if (result && wait) {
+    // The process may not end immediately due to pending I/O
+    if (::WaitForSingleObject(Handle(), 60 * 1000) != WAIT_OBJECT_0)
+      DPLOG(ERROR) << "Error waiting for process exit";
+  } else if (!result) {
+    DPLOG(ERROR) << "Unable to terminate process";
+  }
+  return result;
 }
 
 bool Process::WaitForExit(int* exit_code) {
diff --git a/base/profiler/native_stack_sampler.cc b/base/profiler/native_stack_sampler.cc
new file mode 100644
index 0000000..8b4731b
--- /dev/null
+++ b/base/profiler/native_stack_sampler.cc
@@ -0,0 +1,13 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/profiler/native_stack_sampler.h"
+
+namespace base {
+
+NativeStackSampler::NativeStackSampler() {}
+
+NativeStackSampler::~NativeStackSampler() {}
+
+}  // namespace base
diff --git a/base/profiler/native_stack_sampler.h b/base/profiler/native_stack_sampler.h
new file mode 100644
index 0000000..bc170dc
--- /dev/null
+++ b/base/profiler/native_stack_sampler.h
@@ -0,0 +1,50 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
+#define BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/profiler/stack_sampling_profiler.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+// NativeStackSampler is an implementation detail of StackSamplingProfiler. It
+// abstracts the native implementation required to record a stack sample for a
+// given thread.
+class NativeStackSampler {
+ public:
+  virtual ~NativeStackSampler();
+
+  // Creates a stack sampler that records samples for |thread_handle|. Returns
+  // null if this platform does not support stack sampling.
+  static scoped_ptr<NativeStackSampler> Create(PlatformThreadId thread_id);
+
+  // The following functions are all called on the SamplingThread (not the
+  // thread being sampled).
+
+  // Notifies the sampler that we're starting to record a new profile. Modules
+  // shared across samples in the profile should be recorded in |modules|.
+  virtual void ProfileRecordingStarting(
+      std::vector<StackSamplingProfiler::Module>* modules) = 0;
+
+  // Records a stack sample to |sample|.
+  virtual void RecordStackSample(StackSamplingProfiler::Sample* sample) = 0;
+
+  // Notifies the sampler that we've stopped recording the current
+  // profile.
+  virtual void ProfileRecordingStopped() = 0;
+
+ protected:
+  NativeStackSampler();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NativeStackSampler);
+};
+
+}  // namespace base
+
+#endif  // BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
+
diff --git a/base/profiler/scoped_profile.h b/base/profiler/scoped_profile.h
index c1e2830..6b0c800 100644
--- a/base/profiler/scoped_profile.h
+++ b/base/profiler/scoped_profile.h
@@ -30,6 +30,14 @@
       FROM_HERE_WITH_EXPLICIT_FUNCTION(#dispatch_function_name),           \
       ::tracked_objects::ScopedProfile::ENABLED)
 
+// Same as TRACK_RUN_IN_THIS_SCOPED_REGION except that there's an extra param
+// which is concatenated with the function name for better filtering.
+#define TRACK_SCOPED_REGION(category_name, dispatch_function_name)         \
+  ::tracked_objects::ScopedProfile LINE_BASED_VARIABLE_NAME_FOR_PROFILING( \
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(                                    \
+          "[" category_name "]" dispatch_function_name),                   \
+      ::tracked_objects::ScopedProfile::ENABLED)
+
 namespace tracked_objects {
 class Births;
 
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
index 57b7b35..9da6628 100644
--- a/base/profiler/stack_sampling_profiler.cc
+++ b/base/profiler/stack_sampling_profiler.cc
@@ -9,114 +9,144 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/singleton.h"
+#include "base/profiler/native_stack_sampler.h"
 #include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
 #include "base/timer/elapsed_timer.h"
 
-template <typename T> struct DefaultSingletonTraits;
-
 namespace base {
 
+// DefaultProfileProcessor ----------------------------------------------------
+
 namespace {
 
-// Thread-safe singleton class that stores collected profiles waiting to be
-// processed.
-class PendingProfiles {
+// Singleton class responsible for providing the default processing for profiles
+// (i.e. for profiles generated by profilers without their own completed
+// callback).
+class DefaultProfileProcessor {
  public:
-  PendingProfiles();
-  ~PendingProfiles();
+  using CompletedCallback = StackSamplingProfiler::CompletedCallback;
 
-  static PendingProfiles* GetInstance();
+  ~DefaultProfileProcessor();
 
-  // Appends |profiles|. This function is thread safe.
-  void PutProfiles(const std::vector<StackSamplingProfiler::Profile>& profiles);
-  // Gets the pending profiles into *|profiles|. This function is thread safe.
-  void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles);
+  static DefaultProfileProcessor* GetInstance();
+
+  // Sets the callback to use for processing profiles captured without a
+  // per-profiler completed callback. Pending completed profiles are stored in
+  // this object until a non-null callback is provided here. This function is
+  // thread-safe.
+  void SetCompletedCallback(CompletedCallback callback);
+
+  // Processes |profiles|. This function is thread safe.
+  void ProcessProfiles(
+      const StackSamplingProfiler::CallStackProfiles& profiles);
 
  private:
-  Lock profiles_lock_;
-  std::vector<StackSamplingProfiler::Profile> profiles_;
+  friend struct DefaultSingletonTraits<DefaultProfileProcessor>;
 
-  DISALLOW_COPY_AND_ASSIGN(PendingProfiles);
+  DefaultProfileProcessor();
+
+  // Copies the pending profiles from |profiles_| into |profiles|, and clears
+  // |profiles_|. This function may be called on any thread.
+  void GetAndClearPendingProfiles(
+      StackSamplingProfiler::CallStackProfiles* profiles);
+
+  // Gets the current completed callback, with proper locking.
+  CompletedCallback GetCompletedCallback() const;
+
+  mutable Lock callback_lock_;
+  CompletedCallback default_completed_callback_;
+
+  Lock profiles_lock_;
+  StackSamplingProfiler::CallStackProfiles profiles_;
+
+  DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor);
 };
 
-PendingProfiles::PendingProfiles() {}
-
-PendingProfiles::~PendingProfiles() {}
+DefaultProfileProcessor::~DefaultProfileProcessor() {}
 
 // static
-PendingProfiles* PendingProfiles::GetInstance() {
-  return Singleton<PendingProfiles>::get();
+DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() {
+  return Singleton<DefaultProfileProcessor>::get();
 }
 
-void PendingProfiles::PutProfiles(
-    const std::vector<StackSamplingProfiler::Profile>& profiles) {
-  AutoLock scoped_lock(profiles_lock_);
-  profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
+void DefaultProfileProcessor::SetCompletedCallback(CompletedCallback callback) {
+  {
+    AutoLock scoped_lock(callback_lock_);
+    default_completed_callback_ = callback;
+  }
+
+  if (!callback.is_null()) {
+    // Provide any pending profiles to the callback immediately.
+    StackSamplingProfiler::CallStackProfiles profiles;
+    GetAndClearPendingProfiles(&profiles);
+    if (!profiles.empty())
+      callback.Run(profiles);
+  }
 }
 
-void PendingProfiles::GetProfiles(
-    std::vector<StackSamplingProfiler::Profile>* profiles) {
+void DefaultProfileProcessor::ProcessProfiles(
+    const StackSamplingProfiler::CallStackProfiles& profiles) {
+  CompletedCallback callback = GetCompletedCallback();
+
+  // Store pending profiles if we don't have a valid callback.
+  if (!callback.is_null()) {
+    callback.Run(profiles);
+  } else {
+    AutoLock scoped_lock(profiles_lock_);
+    profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
+  }
+}
+
+DefaultProfileProcessor::DefaultProfileProcessor() {}
+
+void DefaultProfileProcessor::GetAndClearPendingProfiles(
+    StackSamplingProfiler::CallStackProfiles* profiles) {
   profiles->clear();
 
   AutoLock scoped_lock(profiles_lock_);
   profiles_.swap(*profiles);
 }
+
+DefaultProfileProcessor::CompletedCallback
+DefaultProfileProcessor::GetCompletedCallback() const {
+  AutoLock scoped_lock(callback_lock_);
+  return default_completed_callback_;
+}
+
 }  // namespace
 
+// StackSamplingProfiler::Module ----------------------------------------------
+
 StackSamplingProfiler::Module::Module() : base_address(nullptr) {}
+StackSamplingProfiler::Module::Module(const void* base_address,
+                                      const std::string& id,
+                                      const FilePath& filename)
+    : base_address(base_address), id(id), filename(filename) {}
 
 StackSamplingProfiler::Module::~Module() {}
 
-StackSamplingProfiler::Frame::Frame()
-    : instruction_pointer(nullptr),
-      module_index(-1) {}
+// StackSamplingProfiler::Frame -----------------------------------------------
+
+StackSamplingProfiler::Frame::Frame(const void* instruction_pointer,
+                                    size_t module_index)
+    : instruction_pointer(instruction_pointer),
+      module_index(module_index) {}
 
 StackSamplingProfiler::Frame::~Frame() {}
 
-StackSamplingProfiler::Profile::Profile() : preserve_sample_ordering(false) {}
+// StackSamplingProfiler::CallStackProfile ------------------------------------
 
-StackSamplingProfiler::Profile::~Profile() {}
+StackSamplingProfiler::CallStackProfile::CallStackProfile()
+    : preserve_sample_ordering(false), user_data(0) {}
 
-class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate {
- public:
-  // Samples stacks using |native_sampler|. When complete, invokes
-  // |profiles_callback| with the collected profiles. |profiles_callback| must
-  // be thread-safe and may consume the contents of the vector.
-  SamplingThread(
-      scoped_ptr<NativeStackSampler> native_sampler,
-      const SamplingParams& params,
-      Callback<void(const std::vector<Profile>&)> completed_callback);
-  ~SamplingThread() override;
+StackSamplingProfiler::CallStackProfile::~CallStackProfile() {}
 
-  // Implementation of PlatformThread::Delegate:
-  void ThreadMain() override;
-
-  void Stop();
-
- private:
-  // Collects a profile from a single burst. Returns true if the profile was
-  // collected, or false if collection was stopped before it completed.
-  bool CollectProfile(Profile* profile, TimeDelta* elapsed_time);
-  // Collects profiles from all bursts, or until the sampling is stopped. If
-  // stopped before complete, |profiles| will contains only full bursts.
-  void CollectProfiles(std::vector<Profile>* profiles);
-
-  scoped_ptr<NativeStackSampler> native_sampler_;
-
-  const SamplingParams params_;
-
-  WaitableEvent stop_event_;
-
-  Callback<void(const std::vector<Profile>&)> completed_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(SamplingThread);
-};
+// StackSamplingProfiler::SamplingThread --------------------------------------
 
 StackSamplingProfiler::SamplingThread::SamplingThread(
     scoped_ptr<NativeStackSampler> native_sampler,
     const SamplingParams& params,
-    Callback<void(const std::vector<Profile>&)> completed_callback)
+    CompletedCallback completed_callback)
     : native_sampler_(native_sampler.Pass()),
       params_(params),
       stop_event_(false, false),
@@ -128,61 +158,79 @@
 void StackSamplingProfiler::SamplingThread::ThreadMain() {
   PlatformThread::SetName("Chrome_SamplingProfilerThread");
 
-  std::vector<Profile> profiles;
+  CallStackProfiles profiles;
   CollectProfiles(&profiles);
   completed_callback_.Run(profiles);
 }
 
+// Depending on how long the sampling takes and the length of the sampling
+// interval, a burst of samples could take arbitrarily longer than
+// samples_per_burst * sampling_interval. In this case, we (somewhat
+// arbitrarily) honor the number of samples requested rather than strictly
+// adhering to the sampling intervals. Once we have established users for the
+// StackSamplingProfiler and the collected data to judge, we may go the other
+// way or make this behavior configurable.
 bool StackSamplingProfiler::SamplingThread::CollectProfile(
-    Profile* profile,
+    CallStackProfile* profile,
     TimeDelta* elapsed_time) {
   ElapsedTimer profile_timer;
-  Profile current_profile;
-  native_sampler_->ProfileRecordingStarting(&current_profile);
+  CallStackProfile current_profile;
+  native_sampler_->ProfileRecordingStarting(&current_profile.modules);
   current_profile.sampling_period = params_.sampling_interval;
-  bool stopped_early = false;
+  bool burst_completed = true;
+  TimeDelta previous_elapsed_sample_time;
   for (int i = 0; i < params_.samples_per_burst; ++i) {
-    ElapsedTimer sample_timer;
-    current_profile.samples.push_back(Sample());
-    native_sampler_->RecordStackSample(&current_profile.samples.back());
-    TimeDelta elapsed_sample_time = sample_timer.Elapsed();
-    if (i != params_.samples_per_burst - 1) {
+    if (i != 0) {
+      // Always wait, even if for 0 seconds, so we can observe a signal on
+      // stop_event_.
       if (stop_event_.TimedWait(
-              std::max(params_.sampling_interval - elapsed_sample_time,
+              std::max(params_.sampling_interval - previous_elapsed_sample_time,
                        TimeDelta()))) {
-        stopped_early = true;
+        burst_completed = false;
         break;
       }
     }
+    ElapsedTimer sample_timer;
+    current_profile.samples.push_back(Sample());
+    native_sampler_->RecordStackSample(&current_profile.samples.back());
+    previous_elapsed_sample_time = sample_timer.Elapsed();
   }
 
   *elapsed_time = profile_timer.Elapsed();
   current_profile.profile_duration = *elapsed_time;
+  current_profile.preserve_sample_ordering = params_.preserve_sample_ordering;
+  current_profile.user_data = params_.user_data;
   native_sampler_->ProfileRecordingStopped();
 
-  if (!stopped_early)
+  if (burst_completed)
     *profile = current_profile;
 
-  return !stopped_early;
+  return burst_completed;
 }
 
+// In an analogous manner to CollectProfile() and samples exceeding the expected
+// total sampling time, bursts may also exceed the burst_interval. We adopt the
+// same wait-and-see approach here.
 void StackSamplingProfiler::SamplingThread::CollectProfiles(
-    std::vector<Profile>* profiles) {
+    CallStackProfiles* profiles) {
   if (stop_event_.TimedWait(params_.initial_delay))
     return;
 
+  TimeDelta previous_elapsed_profile_time;
   for (int i = 0; i < params_.bursts; ++i) {
-    Profile profile;
-    TimeDelta elapsed_profile_time;
-    if (CollectProfile(&profile, &elapsed_profile_time))
-      profiles->push_back(profile);
-    else
-      return;
+    if (i != 0) {
+      // Always wait, even if for 0 seconds, so we can observe a signal on
+      // stop_event_.
+      if (stop_event_.TimedWait(
+              std::max(params_.burst_interval - previous_elapsed_profile_time,
+                       TimeDelta())))
+        return;
+    }
 
-    if (stop_event_.TimedWait(
-            std::max(params_.burst_interval - elapsed_profile_time,
-                     TimeDelta())))
+    CallStackProfile profile;
+    if (!CollectProfile(&profile, &previous_elapsed_profile_time))
       return;
+    profiles->push_back(profile);
   }
 }
 
@@ -190,14 +238,7 @@
   stop_event_.Signal();
 }
 
-void StackSamplingProfiler::SamplingThreadDeleter::operator()(
-    SamplingThread* thread) const {
-  delete thread;
-}
-
-StackSamplingProfiler::NativeStackSampler::NativeStackSampler() {}
-
-StackSamplingProfiler::NativeStackSampler::~NativeStackSampler() {}
+// StackSamplingProfiler ------------------------------------------------------
 
 StackSamplingProfiler::SamplingParams::SamplingParams()
     : initial_delay(TimeDelta::FromMilliseconds(0)),
@@ -205,29 +246,40 @@
       burst_interval(TimeDelta::FromMilliseconds(10000)),
       samples_per_burst(300),
       sampling_interval(TimeDelta::FromMilliseconds(100)),
-      preserve_sample_ordering(false) {
+      preserve_sample_ordering(false),
+      user_data(0) {
 }
 
 StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
                                              const SamplingParams& params)
     : thread_id_(thread_id), params_(params) {}
 
-StackSamplingProfiler::~StackSamplingProfiler() {}
+StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
+                                             const SamplingParams& params,
+                                             CompletedCallback callback)
+    : thread_id_(thread_id), params_(params), completed_callback_(callback) {}
+
+StackSamplingProfiler::~StackSamplingProfiler() {
+  Stop();
+  if (!sampling_thread_handle_.is_null())
+    PlatformThread::Join(sampling_thread_handle_);
+}
 
 void StackSamplingProfiler::Start() {
-  native_sampler_ = NativeStackSampler::Create(thread_id_);
-  if (!native_sampler_)
+  scoped_ptr<NativeStackSampler> native_sampler =
+      NativeStackSampler::Create(thread_id_);
+  if (!native_sampler)
     return;
 
+  CompletedCallback callback =
+      !completed_callback_.is_null() ? completed_callback_ :
+      Bind(&DefaultProfileProcessor::ProcessProfiles,
+           Unretained(DefaultProfileProcessor::GetInstance()));
   sampling_thread_.reset(
-      new SamplingThread(
-          native_sampler_.Pass(), params_,
-          (custom_completed_callback_.is_null() ?
-           Bind(&PendingProfiles::PutProfiles,
-                Unretained(PendingProfiles::GetInstance())) :
-           custom_completed_callback_)));
-  if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get()))
-    LOG(ERROR) << "failed to create thread";
+      new SamplingThread(native_sampler.Pass(), params_, callback));
+  if (!PlatformThread::Create(0, sampling_thread_.get(),
+                              &sampling_thread_handle_))
+    sampling_thread_.reset();
 }
 
 void StackSamplingProfiler::Stop() {
@@ -236,14 +288,12 @@
 }
 
 // static
-void StackSamplingProfiler::GetPendingProfiles(std::vector<Profile>* profiles) {
-  PendingProfiles::GetInstance()->GetProfiles(profiles);
+void StackSamplingProfiler::SetDefaultCompletedCallback(
+    CompletedCallback callback) {
+  DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback);
 }
 
-void StackSamplingProfiler::SetCustomCompletedCallback(
-    Callback<void(const std::vector<Profile>&)> callback) {
-  custom_completed_callback_ = callback;
-}
+// StackSamplingProfiler::Frame global functions ------------------------------
 
 bool operator==(const StackSamplingProfiler::Frame &a,
                 const StackSamplingProfiler::Frame &b) {
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h
index 8d7671e..9d52f27 100644
--- a/base/profiler/stack_sampling_profiler.h
+++ b/base/profiler/stack_sampling_profiler.h
@@ -13,17 +13,20 @@
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
 
 namespace base {
 
+class NativeStackSampler;
+
 // StackSamplingProfiler periodically stops a thread to sample its stack, for
 // the purpose of collecting information about which code paths are
 // executing. This information is used in aggregate by UMA to identify hot
 // and/or janky code paths.
 //
-// Sample StackStackSamplingProfiler usage:
+// Sample StackSamplingProfiler usage:
 //
 //   // Create and customize params as desired.
 //   base::StackStackSamplingProfiler::SamplingParams params;
@@ -31,32 +34,47 @@
 //   base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
 //       params);
 //
-//   // To process the profiles within Chrome rather than via UMA, set a custom
-//   // completed callback:
-//   base::Callback<void(const std::vector<Profile>&)>
+//   // Or, to process the profiles within Chrome rather than via UMA, use a
+//   // custom completed callback:
+//   base::StackStackSamplingProfiler::CompletedCallback
 //       thread_safe_callback = ...;
-//   profiler.SetCustomCompletedCallback(thread_safe_callback);
+//   base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
+//       params, thread_safe_callback);
 //
 //   profiler.Start();
 //   // ... work being done on the target thread here ...
 //   profiler.Stop();  // optional, stops collection before complete per params
 //
-// When all profiles are complete or the profiler is stopped, if the custom
-// completed callback was set it will be called from the profiler thread with
-// the completed profiles. If no callback was set, the profiles are stored
-// internally and retrieved for UMA through
-// GetPendingProfiles(). GetPendingProfiles() should never be called by other
-// code; to retrieve profiles for in-process processing, set a completed
-// callback.
+// The default SamplingParams causes stacks to be recorded in a single burst at
+// a 10Hz interval for a total of 30 seconds. All of these parameters may be
+// altered as desired.
+//
+// When all call stack profiles are complete or the profiler is stopped, if the
+// custom completed callback was set it is called from a thread created by the
+// profiler with the completed profiles. A profile is considered complete if all
+// requested samples were recorded for the profile (i.e. it was not stopped
+// prematurely).  If no callback was set, the default completed callback will be
+// called with the profiles. It is expected that the the default completed
+// callback is set by the metrics system to allow profiles to be provided via
+// UMA.
+//
+// The results of the profiling are passed to the completed callback and consist
+// of a vector of CallStackProfiles. Each CallStackProfile corresponds to a
+// burst as specified in SamplingParams and contains a set of Samples and
+// Modules. One Sample corresponds to a single recorded stack, and the Modules
+// record those modules associated with the recorded stack frames.
 class BASE_EXPORT StackSamplingProfiler {
  public:
   // Module represents the module (DLL or exe) corresponding to a stack frame.
   struct BASE_EXPORT Module {
     Module();
+    Module(const void* base_address, const std::string& id,
+           const FilePath& filename);
     ~Module();
 
     // Points to the base address of the module.
     const void* base_address;
+
     // An opaque binary string that uniquely identifies a particular program
     // version with high probability. This is parsed from headers of the loaded
     // module.
@@ -65,68 +83,53 @@
     // On Windows:
     //   GUID + AGE in the debug image headers of a module.
     std::string id;
+
     // The filename of the module.
     FilePath filename;
   };
 
   // Frame represents an individual sampled stack frame with module information.
   struct BASE_EXPORT Frame {
-    Frame();
+    // Identifies an unknown module.
+    static const size_t kUnknownModuleIndex = static_cast<size_t>(-1);
+
+    Frame(const void* instruction_pointer, size_t module_index);
     ~Frame();
 
     // The sampled instruction pointer within the function.
     const void* instruction_pointer;
-    // Index of the module in the array of modules. We don't represent module
-    // state directly here to save space.
-    int module_index;
+
+    // Index of the module in CallStackProfile::modules. We don't represent
+    // module state directly here to save space.
+    size_t module_index;
   };
 
   // Sample represents a set of stack frames.
   using Sample = std::vector<Frame>;
 
-  // Profile represents a set of samples.
-  struct BASE_EXPORT Profile {
-    Profile();
-    ~Profile();
+  // CallStackProfile represents a set of samples.
+  struct BASE_EXPORT CallStackProfile {
+    CallStackProfile();
+    ~CallStackProfile();
 
     std::vector<Module> modules;
     std::vector<Sample> samples;
+
     // Duration of this profile.
     TimeDelta profile_duration;
+
     // Time between samples.
     TimeDelta sampling_period;
+
     // True if sample ordering is important and should be preserved if and when
     // this profile is compressed and processed.
     bool preserve_sample_ordering;
+
+    // User data associated with this profile.
+    uintptr_t user_data;
   };
 
-  // NativeStackSampler abstracts the native implementation required to record a
-  // stack sample for a given thread.
-  class NativeStackSampler {
-   public:
-    virtual ~NativeStackSampler();
-
-    // Create a stack sampler that records samples for |thread_handle|. Returns
-    // null if this platform does not support stack sampling.
-    static scoped_ptr<NativeStackSampler> Create(PlatformThreadId thread_id);
-
-    // Notify the sampler that we're starting to record a new profile. This
-    // function is called on the SamplingThread.
-    virtual void ProfileRecordingStarting(Profile* profile) = 0;
-
-    // Record a stack sample. This function is called on the SamplingThread.
-    virtual void RecordStackSample(Sample* sample) = 0;
-
-    // Notify the sampler that we've stopped recording the current profile. This
-    // function is called on the SamplingThread.
-    virtual void ProfileRecordingStopped() = 0;
-
-   protected:
-    NativeStackSampler();
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(NativeStackSampler);
-  };
+  using CallStackProfiles = std::vector<CallStackProfile>;
 
   // Represents parameters that configure the sampling.
   struct BASE_EXPORT SamplingParams {
@@ -134,51 +137,106 @@
 
     // Time to delay before first samples are taken. Defaults to 0.
     TimeDelta initial_delay;
+
     // Number of sampling bursts to perform. Defaults to 1.
     int bursts;
+
     // Interval between sampling bursts. This is the desired duration from the
     // start of one burst to the start of the next burst. Defaults to 10s.
     TimeDelta burst_interval;
+
     // Number of samples to record per burst. Defaults to 300.
     int samples_per_burst;
+
     // Interval between samples during a sampling burst. This is the desired
-    // duration from the start of one burst to the start of the next
-    // burst. Defaults to 100ms.
+    // duration from the start of one sample to the start of the next
+    // sample. Defaults to 100ms.
     TimeDelta sampling_interval;
+
     // True if sample ordering is important and should be preserved if and when
     // this profile is compressed and processed. Defaults to false.
     bool preserve_sample_ordering;
+
+    // User data associated with this profile.
+    uintptr_t user_data;
   };
 
+  // The callback type used to collect completed profiles.
+  //
+  // IMPORTANT NOTE: the callback is invoked on a thread the profiler
+  // constructs, rather than on the thread used to construct the profiler and
+  // set the callback, and thus the callback must be callable on any thread. For
+  // threads with message loops that create StackSamplingProfilers, posting a
+  // task to the message loop with a copy of the profiles is the recommended
+  // thread-safe callback implementation.
+  using CompletedCallback = Callback<void(const CallStackProfiles&)>;
+
+  // Creates a profiler that sends completed profiles to the default completed
+  // callback.
   StackSamplingProfiler(PlatformThreadId thread_id,
                         const SamplingParams& params);
+  // Creates a profiler that sends completed profiles to |completed_callback|.
+  StackSamplingProfiler(PlatformThreadId thread_id,
+                        const SamplingParams& params,
+                        CompletedCallback callback);
   ~StackSamplingProfiler();
 
   // Initializes the profiler and starts sampling.
   void Start();
+
   // Stops the profiler and any ongoing sampling. Calling this function is
-  // optional; if not invoked profiling will terminate when all the profiling
-  // bursts specified in the SamplingParams are completed.
+  // optional; if not invoked profiling terminates when all the profiling bursts
+  // specified in the SamplingParams are completed.
   void Stop();
 
-  // Gets the pending profiles into *|profiles| and clears the internal
-  // storage. This function is thread safe.
+  // Sets a callback to process profiles collected by profiler instances without
+  // a completed callback. Profiles are queued internally until a non-null
+  // callback is provided to this function,
   //
-  // ***This is intended for use only by UMA.*** Callers who want to process the
-  // collected profiles should use SetCustomCompletedCallback.
-  static void GetPendingProfiles(std::vector<Profile>* profiles);
-
-  // By default, collected profiles are stored internally and can be retrieved
-  // by GetPendingProfiles. If a callback is provided via this function,
-  // however, it will be called with the collected profiles instead. Note that
-  // this call to the callback occurs *on the profiler thread*.
-  void SetCustomCompletedCallback(
-      Callback<void(const std::vector<Profile>&)> callback);
+  // The callback is typically called on a thread created by the profiler.  If
+  // completed profiles are queued when set, however, it will also be called
+  // immediately on the calling thread.
+  static void SetDefaultCompletedCallback(CompletedCallback callback);
 
  private:
-  class SamplingThread;
-  struct SamplingThreadDeleter {
-    void operator() (SamplingThread* thread) const;
+  // SamplingThread is a separate thread used to suspend and sample stacks from
+  // the target thread.
+  class SamplingThread : public PlatformThread::Delegate {
+   public:
+    // Samples stacks using |native_sampler|. When complete, invokes
+    // |completed_callback| with the collected call stack profiles.
+    // |completed_callback| must be callable on any thread.
+    SamplingThread(scoped_ptr<NativeStackSampler> native_sampler,
+                   const SamplingParams& params,
+                   CompletedCallback completed_callback);
+    ~SamplingThread() override;
+
+    // PlatformThread::Delegate:
+    void ThreadMain() override;
+
+    void Stop();
+
+   private:
+    // Collects a call stack profile from a single burst. Returns true if the
+    // profile was collected, or false if collection was stopped before it
+    // completed.
+    bool CollectProfile(CallStackProfile* profile, TimeDelta* elapsed_time);
+
+    // Collects call stack profiles from all bursts, or until the sampling is
+    // stopped. If stopped before complete, |call_stack_profiles| will contain
+    // only full bursts.
+    void CollectProfiles(CallStackProfiles* profiles);
+
+    scoped_ptr<NativeStackSampler> native_sampler_;
+    const SamplingParams params_;
+
+    // If Stop() is called, it signals this event to force the sampling to
+    // terminate before all the samples specified in |params_| are collected.
+    WaitableEvent stop_event_;
+
+    const CompletedCallback completed_callback_;
+
+    DISALLOW_COPY_AND_ASSIGN(SamplingThread);
   };
 
   // The thread whose stack will be sampled.
@@ -186,18 +244,18 @@
 
   const SamplingParams params_;
 
-  scoped_ptr<SamplingThread, SamplingThreadDeleter> sampling_thread_;
-  scoped_ptr<NativeStackSampler> native_sampler_;
+  scoped_ptr<SamplingThread> sampling_thread_;
+  PlatformThreadHandle sampling_thread_handle_;
 
-  Callback<void(const std::vector<Profile>&)> custom_completed_callback_;
+  const CompletedCallback completed_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(StackSamplingProfiler);
 };
 
-// Defined to allow equality check of Samples.
+// The metrics provider code wants to put Samples in a map and compare them,
+// which requires us to define a few operators.
 BASE_EXPORT bool operator==(const StackSamplingProfiler::Frame& a,
                             const StackSamplingProfiler::Frame& b);
-// Defined to allow ordering of Samples.
 BASE_EXPORT bool operator<(const StackSamplingProfiler::Frame& a,
                            const StackSamplingProfiler::Frame& b);
 
diff --git a/base/profiler/stack_sampling_profiler_posix.cc b/base/profiler/stack_sampling_profiler_posix.cc
index 6a44d7e..bce37e1 100644
--- a/base/profiler/stack_sampling_profiler_posix.cc
+++ b/base/profiler/stack_sampling_profiler_posix.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/profiler/stack_sampling_profiler.h"
+#include "base/profiler/native_stack_sampler.h"
 
 namespace base {
 
-scoped_ptr<StackSamplingProfiler::NativeStackSampler>
-StackSamplingProfiler::NativeStackSampler::Create(PlatformThreadId thread_id) {
+scoped_ptr<NativeStackSampler> NativeStackSampler::Create(
+    PlatformThreadId thread_id) {
   return scoped_ptr<NativeStackSampler>();
 }
 
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc
index ad9e926..5ade15a 100644
--- a/base/profiler/stack_sampling_profiler_unittest.cc
+++ b/base/profiler/stack_sampling_profiler_unittest.cc
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <sstream>
-
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/path_service.h"
 #include "base/profiler/stack_sampling_profiler.h"
+#include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
@@ -15,30 +14,37 @@
 
 namespace base {
 
+using SamplingParams = StackSamplingProfiler::SamplingParams;
 using Frame = StackSamplingProfiler::Frame;
 using Module = StackSamplingProfiler::Module;
 using Sample = StackSamplingProfiler::Sample;
-using Profile = StackSamplingProfiler::Profile;
+using CallStackProfile = StackSamplingProfiler::CallStackProfile;
+using CallStackProfiles = StackSamplingProfiler::CallStackProfiles;
 
 namespace {
+
 // A thread to target for profiling, whose stack is guaranteed to contain
 // SignalAndWaitUntilSignaled() when coordinated with the main thread.
 class TargetThread : public PlatformThread::Delegate {
  public:
   TargetThread();
 
-  // Implementation of PlatformThread::Delegate:
+  // PlatformThread::Delegate:
   void ThreadMain() override;
 
-  // Wait for the thread to have started and be executing in
+  // Waits for the thread to have started and be executing in
   // SignalAndWaitUntilSignaled().
   void WaitForThreadStart();
-  // Allow the thread to return from SignalAndWaitUntilSignaled() and finish
+
+  // Allows the thread to return from SignalAndWaitUntilSignaled() and finish
   // execution.
   void SignalThreadToFinish();
 
   // This function is guaranteed to be executing between calls to
-  // WaitForThreadStart() and SignalThreadToFinish().
+  // WaitForThreadStart() and SignalThreadToFinish(). This function is static so
+  // that we can get a straightforward address for it in one of the tests below,
+  // rather than dealing with the complexity of a member function pointer
+  // representation.
   static void SignalAndWaitUntilSignaled(WaitableEvent* thread_started_event,
                                          WaitableEvent* finish_event);
 
@@ -81,49 +87,105 @@
   ALLOW_UNUSED_LOCAL(x);
 }
 
+// Called on the profiler thread when complete, to collect profiles.
+void SaveProfiles(CallStackProfiles* profiles,
+                  const CallStackProfiles& pending_profiles) {
+  *profiles = pending_profiles;
+}
+
 // Called on the profiler thread when complete. Collects profiles produced by
 // the profiler, and signals an event to allow the main thread to know that that
 // the profiler is done.
-void SaveProfilesAndSignalEvent(std::vector<Profile>* profiles,
+void SaveProfilesAndSignalEvent(CallStackProfiles* profiles,
                                 WaitableEvent* event,
-                                const std::vector<Profile>& pending_profiles) {
+                                const CallStackProfiles& pending_profiles) {
   *profiles = pending_profiles;
   event->Signal();
 }
 
-// Captures profiles as specified by |params| on the TargetThread, and returns
-// them in |profiles|. Waits up to |profiler_wait_time| for the profiler to
-// complete.
-void CaptureProfiles(const StackSamplingProfiler::SamplingParams& params,
-                     std::vector<Profile>* profiles,
-                     TimeDelta profiler_wait_time) {
+// Executes the function with the target thread running and executing within
+// SignalAndWaitUntilSignaled(). Performs all necessary target thread startup
+// and shutdown work before and afterward.
+template <class Function>
+void WithTargetThread(Function function) {
   TargetThread target_thread;
   PlatformThreadHandle target_thread_handle;
   EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle));
 
   target_thread.WaitForThreadStart();
 
-  WaitableEvent sampling_thread_completed(true, false);
-  profiles->clear();
-  StackSamplingProfiler profiler(target_thread.id(), params);
-  profiler.SetCustomCompletedCallback(
-      Bind(&SaveProfilesAndSignalEvent, Unretained(profiles),
-           Unretained(&sampling_thread_completed)));
-  profiler.Start();
-  sampling_thread_completed.TimedWait(profiler_wait_time);
-  profiler.Stop();
-  sampling_thread_completed.Wait();
+  function(target_thread.id());
 
   target_thread.SignalThreadToFinish();
 
   PlatformThread::Join(target_thread_handle);
 }
 
+// Captures profiles as specified by |params| on the TargetThread, and returns
+// them in |profiles|. Waits up to |profiler_wait_time| for the profiler to
+// complete.
+void CaptureProfilesWithObjectCallback(const SamplingParams& params,
+                                       CallStackProfiles* profiles,
+                                       TimeDelta profiler_wait_time) {
+  profiles->clear();
+
+  WithTargetThread([&params, profiles, profiler_wait_time](
+      PlatformThreadId target_thread_id) {
+    WaitableEvent sampling_thread_completed(true, false);
+    const StackSamplingProfiler::CompletedCallback callback =
+        Bind(&SaveProfilesAndSignalEvent, Unretained(profiles),
+             Unretained(&sampling_thread_completed));
+    StackSamplingProfiler profiler(target_thread_id, params, callback);
+    profiler.Start();
+    sampling_thread_completed.TimedWait(profiler_wait_time);
+    profiler.Stop();
+    sampling_thread_completed.Wait();
+  });
+}
+
+// Captures profiles as specified by |params| on the TargetThread, and returns
+// them in |profiles|. Uses the default callback rather than a per-object
+// callback.
+void CaptureProfilesWithDefaultCallback(const SamplingParams& params,
+                                        CallStackProfiles* profiles) {
+  profiles->clear();
+
+  WithTargetThread([&params, profiles](PlatformThreadId target_thread_id) {
+    WaitableEvent sampling_thread_completed(false, false);
+    StackSamplingProfiler::SetDefaultCompletedCallback(
+        Bind(&SaveProfilesAndSignalEvent, Unretained(profiles),
+             Unretained(&sampling_thread_completed)));
+
+    StackSamplingProfiler profiler(target_thread_id, params);
+    profiler.Start();
+    sampling_thread_completed.Wait();
+
+    StackSamplingProfiler::SetDefaultCompletedCallback(
+        StackSamplingProfiler::CompletedCallback());
+  });
+}
+
+// Runs the profiler with |params| on the TargetThread, with no default or
+// per-object callback.
+void RunProfilerWithNoCallback(const SamplingParams& params,
+                               TimeDelta profiler_wait_time) {
+  WithTargetThread([&params, profiler_wait_time](
+      PlatformThreadId target_thread_id) {
+    StackSamplingProfiler profiler(target_thread_id, params);
+    profiler.Start();
+    // Since we don't specify a callback, we don't have a synchronization
+    // mechanism with the sampling thread. Just sleep instead.
+    PlatformThread::Sleep(profiler_wait_time);
+    profiler.Stop();
+  });
+}
+
 // If this executable was linked with /INCREMENTAL (the default for non-official
 // debug and release builds on Windows), function addresses do not correspond to
 // function code itself, but instead to instructions in the Incremental Link
-// Table that jump to the functions. Check for a jump instruction and if present
-// do a little decompilation to find the function's actual starting address.
+// Table that jump to the functions. Checks for a jump instruction and if
+// present does a little decompilation to find the function's actual starting
+// address.
 const void* MaybeFixupFunctionAddressForILT(const void* function_address) {
 #if defined(_WIN64)
   const unsigned char* opcode =
@@ -131,10 +193,10 @@
   if (*opcode == 0xe9) {
     // This is a relative jump instruction. Assume we're in the ILT and compute
     // the function start address from the instruction offset.
-    const unsigned char* offset = opcode + 1;
-    const unsigned char* next_instruction = opcode + 5;
-    return next_instruction +
-        static_cast<int64>(*reinterpret_cast<const int32*>(offset));
+    const int32* offset = reinterpret_cast<const int32*>(opcode + 1);
+    const unsigned char* next_instruction =
+        reinterpret_cast<const unsigned char*>(offset + 1);
+    return next_instruction + *offset;
   }
 #endif
   return function_address;
@@ -150,11 +212,9 @@
     int function_size) {
   function_address = MaybeFixupFunctionAddressForILT(function_address);
   for (auto it = sample.begin(); it != sample.end(); ++it) {
-    if ((reinterpret_cast<const unsigned char*>(it->instruction_pointer) >=
-         reinterpret_cast<const unsigned char*>(function_address)) &&
-        (reinterpret_cast<const unsigned char*>(it->instruction_pointer) <
-         (reinterpret_cast<const unsigned char*>(function_address) +
-          function_size)))
+    if ((it->instruction_pointer >= function_address) &&
+        (it->instruction_pointer <
+         (static_cast<const unsigned char*>(function_address) + function_size)))
       return it;
   }
   return sample.end();
@@ -164,56 +224,60 @@
 std::string FormatSampleForDiagnosticOutput(
     const Sample& sample,
     const std::vector<Module>& modules) {
-  std::ostringstream stream;
+  std::string output;
   for (const Frame& frame: sample) {
-    stream << frame.instruction_pointer << " "
-           << modules[frame.module_index].filename.value() << std::endl;
+    output += StringPrintf(
+        "0x%p %s\n", frame.instruction_pointer,
+        modules[frame.module_index].filename.AsUTF8Unsafe().c_str());
   }
-  return stream.str();
+  return output;
 }
 
 // Returns a duration that is longer than the test timeout. We would use
 // TimeDelta::Max() but https://crbug.com/465948.
 TimeDelta AVeryLongTimeDelta() { return TimeDelta::FromDays(1); }
+
 }  // namespace
 
 
 // The tests below are enabled for Win x64 only, pending implementation of the
 // tested functionality on other platforms/architectures.
 
-// Checks that the basic expected information is present in a sampled profile.
+// Checks that the basic expected information is present in a sampled call stack
+// profile.
 #if defined(_WIN64)
 #define MAYBE_Basic Basic
 #else
 #define MAYBE_Basic DISABLED_Basic
 #endif
 TEST(StackSamplingProfilerTest, MAYBE_Basic) {
-  StackSamplingProfiler::SamplingParams params;
-  params.initial_delay = params.burst_interval = params.sampling_interval =
-      TimeDelta::FromMilliseconds(0);
-  params.bursts = 1;
+  SamplingParams params;
+  params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.samples_per_burst = 1;
+  params.user_data = 100;
+  params.preserve_sample_ordering = true;
 
-  std::vector<Profile> profiles;
-  CaptureProfiles(params, &profiles, AVeryLongTimeDelta());
+  std::vector<CallStackProfile> profiles;
+  CaptureProfilesWithObjectCallback(params, &profiles, AVeryLongTimeDelta());
 
   // Check that the profile and samples sizes are correct, and the module
   // indices are in range.
-
   ASSERT_EQ(1u, profiles.size());
-  const Profile& profile = profiles[0];
+  const CallStackProfile& profile = profiles[0];
   ASSERT_EQ(1u, profile.samples.size());
   EXPECT_EQ(params.sampling_interval, profile.sampling_period);
   const Sample& sample = profile.samples[0];
   for (const auto& frame : sample) {
-    ASSERT_GE(frame.module_index, 0);
-    ASSERT_LT(frame.module_index, static_cast<int>(profile.modules.size()));
+    ASSERT_GE(frame.module_index, 0u);
+    ASSERT_LT(frame.module_index, profile.modules.size());
   }
+  EXPECT_EQ(100u, profile.user_data);
+  EXPECT_EQ(true, profile.preserve_sample_ordering);
 
   // Check that the stack contains a frame for
   // TargetThread::SignalAndWaitUntilSignaled() and that the frame has this
   // executable's module.
-
+  //
   // Since we don't have a good way to know the function size, use 100 bytes as
   // a reasonable window to locate the instruction pointer.
   Sample::const_iterator loc = FindFirstFrameWithinFunction(
@@ -225,80 +289,76 @@
       << MaybeFixupFunctionAddressForILT(
           reinterpret_cast<const void*>(
               &TargetThread::SignalAndWaitUntilSignaled))
-      << " was not found in stack:" << std::endl
+      << " was not found in stack:\n"
       << FormatSampleForDiagnosticOutput(sample, profile.modules);
-
   FilePath executable_path;
-  bool got_executable_path = PathService::Get(FILE_EXE, &executable_path);
-  EXPECT_TRUE(got_executable_path);
+  EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path));
   EXPECT_EQ(executable_path, profile.modules[loc->module_index].filename);
 }
 
 // Checks that the expected number of profiles and samples are present in the
-// profiles produced.
+// call stack profiles produced.
 #if defined(_WIN64)
 #define MAYBE_MultipleProfilesAndSamples MultipleProfilesAndSamples
 #else
 #define MAYBE_MultipleProfilesAndSamples DISABLED_MultipleProfilesAndSamples
 #endif
 TEST(StackSamplingProfilerTest, MAYBE_MultipleProfilesAndSamples) {
-  StackSamplingProfiler::SamplingParams params;
-  params.initial_delay = params.burst_interval = params.sampling_interval =
+  SamplingParams params;
+  params.burst_interval = params.sampling_interval =
       TimeDelta::FromMilliseconds(0);
   params.bursts = 2;
   params.samples_per_burst = 3;
 
-  std::vector<Profile> profiles;
-  CaptureProfiles(params, &profiles, AVeryLongTimeDelta());
+  std::vector<CallStackProfile> profiles;
+  CaptureProfilesWithObjectCallback(params, &profiles, AVeryLongTimeDelta());
 
   ASSERT_EQ(2u, profiles.size());
   EXPECT_EQ(3u, profiles[0].samples.size());
   EXPECT_EQ(3u, profiles[1].samples.size());
 }
 
-// Checks that no profiles are captured if the profiling is stopped during the
-// initial delay.
+// Checks that no call stack profiles are captured if the profiling is stopped
+// during the initial delay.
 #if defined(_WIN64)
 #define MAYBE_StopDuringInitialDelay StopDuringInitialDelay
 #else
 #define MAYBE_StopDuringInitialDelay DISABLED_StopDuringInitialDelay
 #endif
 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInitialDelay) {
-  StackSamplingProfiler::SamplingParams params;
-  params.burst_interval = params.sampling_interval =
-      TimeDelta::FromMilliseconds(0);
+  SamplingParams params;
   params.initial_delay = TimeDelta::FromSeconds(60);
-  params.bursts = params.samples_per_burst = 1;
 
-  std::vector<Profile> profiles;
-  CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(0));
+  std::vector<CallStackProfile> profiles;
+  CaptureProfilesWithObjectCallback(params, &profiles,
+                                    TimeDelta::FromMilliseconds(0));
 
   EXPECT_TRUE(profiles.empty());
 }
 
-// Checks that the single completed profile is captured if the profiling is
-// stopped between bursts.
+// Checks that the single completed call stack profile is captured if the
+// profiling is stopped between bursts.
 #if defined(_WIN64)
 #define MAYBE_StopDuringInterBurstInterval StopDuringInterBurstInterval
 #else
 #define MAYBE_StopDuringInterBurstInterval DISABLED_StopDuringInterBurstInterval
 #endif
 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterBurstInterval) {
-  StackSamplingProfiler::SamplingParams params;
-  params.initial_delay = params.sampling_interval =
-      TimeDelta::FromMilliseconds(0);
+  SamplingParams params;
+  params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.burst_interval = TimeDelta::FromSeconds(60);
   params.bursts = 2;
   params.samples_per_burst = 1;
 
-  std::vector<Profile> profiles;
-  CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(50));
+  std::vector<CallStackProfile> profiles;
+  CaptureProfilesWithObjectCallback(params, &profiles,
+                                    TimeDelta::FromMilliseconds(50));
 
   ASSERT_EQ(1u, profiles.size());
   EXPECT_EQ(1u, profiles[0].samples.size());
 }
 
-// Checks that only completed profiles are captured.
+// Checks that only completed call stack profiles are captured.
 #if defined(_WIN64)
 #define MAYBE_StopDuringInterSampleInterval StopDuringInterSampleInterval
 #else
@@ -306,16 +366,80 @@
   DISABLED_StopDuringInterSampleInterval
 #endif
 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterSampleInterval) {
-  StackSamplingProfiler::SamplingParams params;
-  params.initial_delay = params.burst_interval = TimeDelta::FromMilliseconds(0);
+  SamplingParams params;
   params.sampling_interval = TimeDelta::FromSeconds(60);
-  params.bursts = 1;
   params.samples_per_burst = 2;
 
-  std::vector<Profile> profiles;
-  CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(50));
+  std::vector<CallStackProfile> profiles;
+  CaptureProfilesWithObjectCallback(params, &profiles,
+                                    TimeDelta::FromMilliseconds(50));
 
   EXPECT_TRUE(profiles.empty());
 }
 
-}  // namespace tracked_objects
+// Checks that profiles are captured via the default completed callback.
+#if defined(_WIN64)
+#define MAYBE_DefaultCallback DefaultCallback
+#else
+#define MAYBE_DefaultCallback DISABLED_DefaultCallback
+#endif
+TEST(StackSamplingProfilerTest, MAYBE_DefaultCallback) {
+  SamplingParams params;
+  params.samples_per_burst = 1;
+
+  CallStackProfiles profiles;
+  CaptureProfilesWithDefaultCallback(params, &profiles);
+
+  EXPECT_EQ(1u, profiles.size());
+  EXPECT_EQ(1u, profiles[0].samples.size());
+}
+
+// Checks that profiles are queued until a default callback is set, then
+// delivered.
+#if defined(_WIN64)
+#define MAYBE_ProfilesQueuedWithNoCallback ProfilesQueuedWithNoCallback
+#else
+#define MAYBE_ProfilesQueuedWithNoCallback DISABLED_ProfilesQueuedWithNoCallback
+#endif
+TEST(StackSamplingProfilerTest, MAYBE_ProfilesQueuedWithNoCallback) {
+  SamplingParams params;
+  params.samples_per_burst = 1;
+
+  RunProfilerWithNoCallback(params, TimeDelta::FromMilliseconds(50));
+
+  CallStackProfiles profiles;
+  // This should immediately call SaveProfiles on this thread.
+  StackSamplingProfiler::SetDefaultCompletedCallback(
+      Bind(&SaveProfiles, Unretained(&profiles)));
+  EXPECT_EQ(1u, profiles.size());
+  EXPECT_EQ(1u, profiles[0].samples.size());
+  StackSamplingProfiler::SetDefaultCompletedCallback(
+      StackSamplingProfiler::CompletedCallback());
+}
+
+// Checks that we can destroy the profiler while profiling.
+#if defined(_WIN64)
+#define MAYBE_DestroyProfilerWhileProfiling DestroyProfilerWhileProfiling
+#else
+#define MAYBE_DestroyProfilerWhileProfiling \
+  DISABLED_DestroyProfilerWhileProfiling
+#endif
+TEST(StackSamplingProfilerTest, MAYBE_DestroyProfilerWhileProfiling) {
+  SamplingParams params;
+  params.sampling_interval = TimeDelta::FromMilliseconds(10);
+
+  CallStackProfiles profiles;
+  WithTargetThread([&params, &profiles](PlatformThreadId target_thread_id) {
+    scoped_ptr<StackSamplingProfiler> profiler;
+    profiler.reset(new StackSamplingProfiler(
+        target_thread_id, params, Bind(&SaveProfiles, Unretained(&profiles))));
+    profiler->Start();
+    profiler.reset();
+
+    // Wait longer than a sample interval to catch any use-after-free actions by
+    // the profiler thread.
+    PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
+  });
+}
+
+}  // namespace base
diff --git a/base/profiler/stack_sampling_profiler_win.cc b/base/profiler/stack_sampling_profiler_win.cc
index ba46cf0..1ccd134 100644
--- a/base/profiler/stack_sampling_profiler_win.cc
+++ b/base/profiler/stack_sampling_profiler_win.cc
@@ -2,14 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/profiler/stack_sampling_profiler.h"
-
-#include <dbghelp.h>
-#include <map>
-#include <utility>
+#include <objbase.h>
 #include <windows.h>
 
+#include <map>
+#include <utility>
+
 #include "base/logging.h"
+#include "base/profiler/native_stack_sampler.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/win/pe_image.h"
 #include "base/win/scoped_handle.h"
@@ -18,38 +21,7 @@
 
 namespace {
 
-class NativeStackSamplerWin : public StackSamplingProfiler::NativeStackSampler {
- public:
-  explicit NativeStackSamplerWin(win::ScopedHandle thread_handle);
-  ~NativeStackSamplerWin() override;
-
-  // StackSamplingProfiler::NativeStackSampler:
-  void ProfileRecordingStarting(
-      StackSamplingProfiler::Profile* profile) override;
-  void RecordStackSample(StackSamplingProfiler::Sample* sample) override;
-  void ProfileRecordingStopped() override;
-
- private:
-  static bool GetModuleInfo(HMODULE module,
-                            StackSamplingProfiler::Module* module_info);
-
-  void CopyToSample(const void* const instruction_pointers[],
-                    const HMODULE modules[],
-                    int stack_depth,
-                    StackSamplingProfiler::Sample* sample,
-                    std::vector<StackSamplingProfiler::Module>* module_infos);
-
-  win::ScopedHandle thread_handle_;
-  // Weak. Points to the profile being recorded between
-  // ProfileRecordingStarting() and ProfileRecordingStopped().
-  StackSamplingProfiler::Profile* current_profile_;
-  // Maps a module to the module's index within current_profile_->modules.
-  std::map<HMODULE, int> profile_module_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
-};
-
-// Walk the stack represented by |context| from the current frame downwards,
+// Walks the stack represented by |context| from the current frame downwards,
 // recording the instruction pointers for each frame in |instruction_pointers|.
 int RecordStack(CONTEXT* context,
                 int max_stack_size,
@@ -58,69 +30,104 @@
 #ifdef _WIN64
   *last_frame_is_unknown_function = false;
 
-  IMAGEHLP_SYMBOL64 sym;
-  sym.SizeOfStruct = sizeof(sym);
-  sym.MaxNameLength = 0;
-
-  for (int i = 0; i < max_stack_size; ++i) {
+  int i = 0;
+  for (; (i < max_stack_size) && context->Rip; ++i) {
     // Try to look up unwind metadata for the current function.
     ULONG64 image_base;
     PRUNTIME_FUNCTION runtime_function =
         RtlLookupFunctionEntry(context->Rip, &image_base, nullptr);
 
-    instruction_pointers[i] = reinterpret_cast<void*>(context->Rip);
+    instruction_pointers[i] = reinterpret_cast<const void*>(context->Rip);
 
     if (runtime_function) {
       KNONVOLATILE_CONTEXT_POINTERS nvcontext = {0};
       void* handler_data;
       ULONG64 establisher_frame;
       RtlVirtualUnwind(0, image_base, context->Rip, runtime_function, context,
-          &handler_data, &establisher_frame, &nvcontext);
+                       &handler_data, &establisher_frame, &nvcontext);
     } else {
-      // If we don't have a RUNTIME_FUNCTION, then we've encountered
-      // a leaf function.  Adjust the stack appropriately.
-      context->Rip = *reinterpret_cast<PDWORD64>(context->Rsp);
-      context->Rsp += 8;
-      *last_frame_is_unknown_function = true;
-    }
-
-    if (!context->Rip)
+      // If we don't have a RUNTIME_FUNCTION, then in theory this should be a
+      // leaf function whose frame contains only a return address, at
+      // RSP. However, crash data also indicates that some third party libraries
+      // do not provide RUNTIME_FUNCTION information for non-leaf functions. We
+      // could manually unwind the stack in the former case, but attempting to
+      // do so in the latter case would produce wrong results and likely crash,
+      // so just bail out.
+      //
+      // Ad hoc runs with instrumentation show that ~5% of stack traces end with
+      // a valid leaf function. To avoid selectively omitting these traces it
+      // makes sense to ultimately try to distinguish these two cases and
+      // selectively unwind the stack for legitimate leaf functions. For the
+      // purposes of avoiding crashes though, just ignore them all for now.
       return i;
+    }
   }
-  return max_stack_size;
+  return i;
 #else
   return 0;
 #endif
 }
 
-// Fills in |modules| corresponding to the pointers to code in |addresses|. The
-// modules are returned with reference counts incremented should be freed with
-// FreeModules.
-void FindModulesForAddresses(const void* const addresses[], HMODULE modules[],
-                             int stack_depth,
+// Fills in |module_handles| corresponding to the pointers to code in
+// |addresses|. The module handles are returned with reference counts
+// incremented and should be freed with FreeModuleHandles. See note in
+// SuspendThreadAndRecordStack for why |addresses| and |module_handles| are
+// arrays.
+void FindModuleHandlesForAddresses(const void* const addresses[],
+                             HMODULE module_handles[], int stack_depth,
                              bool last_frame_is_unknown_function) {
-  const int module_frames = last_frame_is_unknown_function ? stack_depth - 1 :
-      stack_depth;
+  const int module_frames =
+      last_frame_is_unknown_function ? stack_depth - 1 : stack_depth;
   for (int i = 0; i < module_frames; ++i) {
-    HMODULE module = NULL;
+    HMODULE module_handle = NULL;
     if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
                           reinterpret_cast<LPCTSTR>(addresses[i]),
-                          &module)) {
-      // HMODULE is the base address of the module.
-      DCHECK_LT(reinterpret_cast<const void*>(module), addresses[i]);
-      modules[i] = module;
+                          &module_handle)) {
+      // HMODULE actually represents the base address of the module, so we can
+      // use it directly as an address.
+      DCHECK_LE(reinterpret_cast<const void*>(module_handle), addresses[i]);
+      module_handles[i] = module_handle;
     }
   }
 }
 
-// Free the modules returned by FindModulesForAddresses.
-void FreeModules(int stack_depth, HMODULE modules[]) {
+// Frees the modules handles returned by FindModuleHandlesForAddresses. See note
+// in SuspendThreadAndRecordStack for why |module_handles| is an array.
+void FreeModuleHandles(int stack_depth, HMODULE module_handles[]) {
   for (int i = 0; i < stack_depth; ++i) {
-    if (modules[i])
-      ::FreeLibrary(modules[i]);
+    if (module_handles[i])
+      ::FreeLibrary(module_handles[i]);
   }
 }
 
+// Gets the unique build ID for a module. Windows build IDs are created by a
+// concatenation of a GUID and AGE fields found in the headers of a module. The
+// GUID is stored in the first 16 bytes and the AGE is stored in the last 4
+// bytes. Returns the empty string if the function fails to get the build ID.
+//
+// Example:
+// dumpbin chrome.exe /headers | find "Format:"
+//   ... Format: RSDS, {16B2A428-1DED-442E-9A36-FCE8CBD29726}, 10, ...
+//
+// The resulting buildID string of this instance of chrome.exe is
+// "16B2A4281DED442E9A36FCE8CBD2972610".
+//
+// Note that the AGE field is encoded in decimal, not hex.
+std::string GetBuildIDForModule(HMODULE module_handle) {
+  GUID guid;
+  DWORD age;
+  win::PEImage(module_handle).GetDebugId(&guid, &age);
+  const int kGUIDSize = 39;
+  std::wstring build_id;
+  int result =
+      ::StringFromGUID2(guid, WriteInto(&build_id, kGUIDSize), kGUIDSize);
+  if (result != kGUIDSize)
+    return std::string();
+  RemoveChars(build_id, L"{}-", &build_id);
+  build_id += StringPrintf(L"%d", age);
+  return WideToUTF8(build_id);
+}
+
 // Disables priority boost on a thread for the lifetime of the object.
 class ScopedDisablePriorityBoost {
  public:
@@ -141,185 +148,210 @@
       boost_state_was_disabled_(false) {
   got_previous_boost_state_ =
       ::GetThreadPriorityBoost(thread_handle_, &boost_state_was_disabled_);
-  if (got_previous_boost_state_ && !boost_state_was_disabled_) {
-    // Confusingly, TRUE disables priority boost ...
+  if (got_previous_boost_state_) {
+    // Confusingly, TRUE disables priority boost.
     ::SetThreadPriorityBoost(thread_handle_, TRUE);
   }
 }
 
 ScopedDisablePriorityBoost::~ScopedDisablePriorityBoost() {
-  if (got_previous_boost_state_ && !boost_state_was_disabled_) {
-    // ... and FALSE enables priority boost.
-    ::SetThreadPriorityBoost(thread_handle_, FALSE);
-  }
+  if (got_previous_boost_state_)
+    ::SetThreadPriorityBoost(thread_handle_, boost_state_was_disabled_);
 }
 
 // Suspends the thread with |thread_handle|, records the stack into
 // |instruction_pointers|, then resumes the thread. Returns the size of the
 // stack.
+//
+// IMPORTANT NOTE: No heap allocations may occur between SuspendThread and
+// ResumeThread. Otherwise this code can deadlock on heap locks acquired by the
+// target thread before it was suspended. This is why we pass instruction
+// pointers and module handles as preallocated arrays rather than vectors, since
+// vectors make it too easy to subtly allocate memory.
 int SuspendThreadAndRecordStack(HANDLE thread_handle, int max_stack_size,
                                 const void* instruction_pointers[],
                                 bool* last_frame_is_unknown_function) {
-#if defined(_WIN64)
-  if (RtlVirtualUnwind == nullptr || RtlLookupFunctionEntry == nullptr)
+  if (::SuspendThread(thread_handle) == -1)
     return 0;
-#endif
 
-  if (::SuspendThread(thread_handle) == -1) {
-    LOG(ERROR) << "SuspendThread failed: " << GetLastError();
-    return 0;
-  }
-
+  int stack_depth = 0;
   CONTEXT thread_context = {0};
   thread_context.ContextFlags = CONTEXT_FULL;
-  if (!::GetThreadContext(thread_handle, &thread_context)) {
-    LOG(ERROR) << "GetThreadContext failed: " << GetLastError();
+  if (::GetThreadContext(thread_handle, &thread_context)) {
+    stack_depth = RecordStack(&thread_context, max_stack_size,
+                              instruction_pointers,
+                              last_frame_is_unknown_function);
   }
 
-  int stack_depth = RecordStack(&thread_context, max_stack_size,
-                                instruction_pointers,
-                                last_frame_is_unknown_function);
-
-  {
-    ScopedDisablePriorityBoost disable_priority_boost(thread_handle);
-    if (::ResumeThread(thread_handle) == -1)
-      LOG(ERROR) << "ResumeThread failed: " << GetLastError();
-  }
+  // Disable the priority boost that the thread would otherwise receive on
+  // resume. We do this to avoid artificially altering the dynamics of the
+  // executing application any more than we already are by suspending and
+  // resuming the thread.
+  //
+  // Note that this can racily disable a priority boost that otherwise would
+  // have been given to the thread, if the thread is waiting on other wait
+  // conditions at the time of SuspendThread and those conditions are satisfied
+  // before priority boost is reenabled. The measured length of this window is
+  // ~100us, so this should occur fairly rarely.
+  ScopedDisablePriorityBoost disable_priority_boost(thread_handle);
+  bool resume_thread_succeeded = ::ResumeThread(thread_handle) != -1;
+  CHECK(resume_thread_succeeded) << "ResumeThread failed: " << GetLastError();
 
   return stack_depth;
 }
 
-}  // namespace
+class NativeStackSamplerWin : public NativeStackSampler {
+ public:
+  explicit NativeStackSamplerWin(win::ScopedHandle thread_handle);
+  ~NativeStackSamplerWin() override;
 
-scoped_ptr<StackSamplingProfiler::NativeStackSampler>
-StackSamplingProfiler::NativeStackSampler::Create(PlatformThreadId thread_id) {
-#if _WIN64
-  // Get the thread's handle.
-  HANDLE thread_handle = ::OpenThread(
-      THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
-      FALSE,
-      thread_id);
-  DCHECK(thread_handle) << "OpenThread failed";
+  // StackSamplingProfiler::NativeStackSampler:
+  void ProfileRecordingStarting(
+      std::vector<StackSamplingProfiler::Module>* modules) override;
+  void RecordStackSample(StackSamplingProfiler::Sample* sample) override;
+  void ProfileRecordingStopped() override;
 
-  return scoped_ptr<NativeStackSampler>(new NativeStackSamplerWin(
-      win::ScopedHandle(thread_handle)));
-#else
-  return scoped_ptr<NativeStackSampler>();
-#endif
-}
+ private:
+  // Attempts to query the module filename, base address, and id for
+  // |module_handle|, and store them in |module|. Returns true if it succeeded.
+  static bool GetModuleForHandle(HMODULE module_handle,
+                                 StackSamplingProfiler::Module* module);
+
+  // Gets the index for the Module corresponding to |module_handle| in
+  // |modules|, adding it if it's not already present. Returns
+  // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be
+  // determined for |module|.
+  size_t GetModuleIndex(HMODULE module_handle,
+                        std::vector<StackSamplingProfiler::Module>* modules);
+
+  // Copies the stack information represented by |instruction_pointers| into
+  // |sample| and |modules|.
+  void CopyToSample(const void* const instruction_pointers[],
+                    const HMODULE module_handles[],
+                    int stack_depth,
+                    StackSamplingProfiler::Sample* sample,
+                    std::vector<StackSamplingProfiler::Module>* modules);
+
+  win::ScopedHandle thread_handle_;
+  // Weak. Points to the modules associated with the profile being recorded
+  // between ProfileRecordingStarting() and ProfileRecordingStopped().
+  std::vector<StackSamplingProfiler::Module>* current_modules_;
+  // Maps a module handle to the corresponding Module's index within
+  // current_modules_.
+  std::map<HMODULE, size_t> profile_module_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
+};
 
 NativeStackSamplerWin::NativeStackSamplerWin(win::ScopedHandle thread_handle)
     : thread_handle_(thread_handle.Take()) {
-#ifdef _WIN64
-  if (RtlVirtualUnwind == nullptr && RtlLookupFunctionEntry == nullptr) {
-    const HMODULE nt_dll_handle = ::GetModuleHandle(L"ntdll.dll");
-    // This should always be non-null, but handle just in case.
-    if (nt_dll_handle) {
-      reinterpret_cast<void*&>(RtlVirtualUnwind) =
-          ::GetProcAddress(nt_dll_handle, "RtlVirtualUnwind");
-      reinterpret_cast<void*&>(RtlLookupFunctionEntry) =
-          ::GetProcAddress(nt_dll_handle, "RtlLookupFunctionEntry");
-    }
-  }
-#endif
 }
 
 NativeStackSamplerWin::~NativeStackSamplerWin() {
 }
 
 void NativeStackSamplerWin::ProfileRecordingStarting(
-    StackSamplingProfiler::Profile* profile) {
-  current_profile_ = profile;
+    std::vector<StackSamplingProfiler::Module>* modules) {
+  current_modules_ = modules;
   profile_module_index_.clear();
 }
 
 void NativeStackSamplerWin::RecordStackSample(
     StackSamplingProfiler::Sample* sample) {
-  DCHECK(current_profile_);
+  DCHECK(current_modules_);
 
   const int max_stack_size = 64;
   const void* instruction_pointers[max_stack_size] = {0};
-  HMODULE modules[max_stack_size] = {0};
+  HMODULE module_handles[max_stack_size] = {0};
 
   bool last_frame_is_unknown_function = false;
   int stack_depth = SuspendThreadAndRecordStack(
       thread_handle_.Get(), max_stack_size, instruction_pointers,
       &last_frame_is_unknown_function);
-  FindModulesForAddresses(instruction_pointers, modules, stack_depth,
-                          last_frame_is_unknown_function);
-  CopyToSample(instruction_pointers, modules, stack_depth, sample,
-               &current_profile_->modules);
-  FreeModules(stack_depth, modules);
+  FindModuleHandlesForAddresses(instruction_pointers, module_handles,
+                                stack_depth, last_frame_is_unknown_function);
+  CopyToSample(instruction_pointers, module_handles, stack_depth, sample,
+               current_modules_);
+  FreeModuleHandles(stack_depth, module_handles);
 }
 
 void NativeStackSamplerWin::ProfileRecordingStopped() {
-  current_profile_ = nullptr;
+  current_modules_ = nullptr;
 }
 
 // static
-bool NativeStackSamplerWin::GetModuleInfo(
-    HMODULE module,
-    StackSamplingProfiler::Module* module_info) {
+bool NativeStackSamplerWin::GetModuleForHandle(
+    HMODULE module_handle,
+    StackSamplingProfiler::Module* module) {
   wchar_t module_name[MAX_PATH];
   DWORD result_length =
-      GetModuleFileName(module, module_name, arraysize(module_name));
+      GetModuleFileName(module_handle, module_name, arraysize(module_name));
   if (result_length == 0)
     return false;
 
-  module_info->filename = base::FilePath(module_name);
+  module->filename = base::FilePath(module_name);
 
-  module_info->base_address = reinterpret_cast<const void*>(module);
+  module->base_address = reinterpret_cast<const void*>(module_handle);
 
-  GUID guid;
-  DWORD age;
-  win::PEImage(module).GetDebugId(&guid, &age);
-  module_info->id.insert(module_info->id.end(),
-                         reinterpret_cast<char*>(&guid),
-                         reinterpret_cast<char*>(&guid + 1));
-  module_info->id.insert(module_info->id.end(),
-                         reinterpret_cast<char*>(&age),
-                         reinterpret_cast<char*>(&age + 1));
+  module->id = GetBuildIDForModule(module_handle);
+  if (module->id.empty())
+    return false;
 
   return true;
 }
 
+size_t NativeStackSamplerWin::GetModuleIndex(
+    HMODULE module_handle,
+    std::vector<StackSamplingProfiler::Module>* modules) {
+  if (!module_handle)
+    return StackSamplingProfiler::Frame::kUnknownModuleIndex;
+
+  auto loc = profile_module_index_.find(module_handle);
+  if (loc == profile_module_index_.end()) {
+    StackSamplingProfiler::Module module;
+    if (!GetModuleForHandle(module_handle, &module))
+      return StackSamplingProfiler::Frame::kUnknownModuleIndex;
+    modules->push_back(module);
+    loc = profile_module_index_.insert(std::make_pair(
+        module_handle, modules->size() - 1)).first;
+  }
+
+  return loc->second;
+}
+
 void NativeStackSamplerWin::CopyToSample(
     const void* const instruction_pointers[],
-    const HMODULE modules[],
+    const HMODULE module_handles[],
     int stack_depth,
     StackSamplingProfiler::Sample* sample,
-    std::vector<StackSamplingProfiler::Module>* module_infos) {
+    std::vector<StackSamplingProfiler::Module>* module) {
   sample->clear();
   sample->reserve(stack_depth);
 
   for (int i = 0; i < stack_depth; ++i) {
-    sample->push_back(StackSamplingProfiler::Frame());
-    StackSamplingProfiler::Frame& frame = sample->back();
-
-    frame.instruction_pointer = instruction_pointers[i];
-
-    // Record an invalid module index if we don't have a valid module.
-    if (!modules[i]) {
-      frame.module_index = -1;
-      continue;
-    }
-
-    auto loc = profile_module_index_.find(modules[i]);
-    if (loc == profile_module_index_.end()) {
-      StackSamplingProfiler::Module module_info;
-      // Record an invalid module index if we have a module but can't find
-      // information on it.
-      if (!GetModuleInfo(modules[i], &module_info)) {
-        frame.module_index = -1;
-        continue;
-      }
-      module_infos->push_back(module_info);
-      loc = profile_module_index_.insert(std::make_pair(
-          modules[i], static_cast<int>(module_infos->size() - 1))).first;
-    }
-
-    frame.module_index = loc->second;
+    sample->push_back(StackSamplingProfiler::Frame(
+        instruction_pointers[i],
+        GetModuleIndex(module_handles[i], module)));
   }
 }
 
+}  // namespace
+
+scoped_ptr<NativeStackSampler> NativeStackSampler::Create(
+    PlatformThreadId thread_id) {
+#if _WIN64
+  // Get the thread's handle.
+  HANDLE thread_handle = ::OpenThread(
+      THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
+      FALSE,
+      thread_id);
+
+  if (thread_handle) {
+    return scoped_ptr<NativeStackSampler>(new NativeStackSamplerWin(
+        win::ScopedHandle(thread_handle)));
+  }
+#endif
+  return scoped_ptr<NativeStackSampler>();
+}
+
 }  // namespace base
diff --git a/base/security_unittest.cc b/base/security_unittest.cc
index f4c60a7..07ba6f5 100644
--- a/base/security_unittest.cc
+++ b/base/security_unittest.cc
@@ -69,7 +69,7 @@
 // We also use it so that the compiler doesn't discard certain return values
 // as something we don't need (see the comment with calloc below).
 template <typename Type>
-Type HideValueFromCompiler(volatile Type value) {
+NOINLINE Type HideValueFromCompiler(volatile Type value) {
 #if defined(__GNUC__)
   // In a GCC compatible compiler (GCC or Clang), make this compiler barrier
   // more robust than merely using "volatile".
@@ -293,8 +293,8 @@
   scoped_ptr<char, base::FreeDeleter> array_pointer(
       static_cast<char*>(calloc(nmemb, size)));
   // We need the call to HideValueFromCompiler(): we have seen LLVM
-  // optimize away the call to calloc() entirely and assume
-  // the pointer to not be NULL.
+  // optimize away the call to calloc() entirely and assume the pointer to not
+  // be NULL.
   return HideValueFromCompiler(array_pointer.get()) == NULL;
 }
 
diff --git a/base/stl_util.h b/base/stl_util.h
index 89a53b0..e937d2f 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -90,6 +90,14 @@
   }
 }
 
+// Counts the number of instances of val in a container.
+template <typename Container, typename T>
+typename std::iterator_traits<
+    typename Container::const_iterator>::difference_type
+STLCount(const Container& container, const T& val) {
+  return std::count(container.begin(), container.end(), val);
+}
+
 // To treat a possibly-empty vector as an array, use these functions.
 // If you know the array will never be empty, you can use &*v.begin()
 // directly, but that is undefined behaviour if |v| is empty.
@@ -195,6 +203,14 @@
   return collection.find(key) != collection.end();
 }
 
+// Test to see if a collection like a vector contains a particular value.
+// Returns true if the value is in the collection.
+template <typename Collection, typename Value>
+bool ContainsValue(const Collection& collection, const Value& value) {
+  return std::find(collection.begin(), collection.end(), value) !=
+      collection.end();
+}
+
 namespace base {
 
 // Returns true if the container is sorted.
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc
index 692f300..88a6236 100644
--- a/base/strings/string_split.cc
+++ b/base/strings/string_split.cc
@@ -6,7 +6,6 @@
 
 #include "base/logging.h"
 #include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/third_party/icu/icu_utf.h"
 
 namespace base {
@@ -193,7 +192,6 @@
 void SplitStringDontTrim(const std::string& str,
                          char c,
                          std::vector<std::string>* r) {
-  DCHECK(IsStringUTF8(str));
 #if CHAR_MIN < 0
   DCHECK_GE(c, 0);
 #endif
diff --git a/base/sync_socket.h b/base/sync_socket.h
index 4da9d3b..36d6bc1 100644
--- a/base/sync_socket.h
+++ b/base/sync_socket.h
@@ -124,11 +124,11 @@
   // and there isn't a way to cancel a blocking synchronous Read that is
   // supported on <Vista. So, for Windows only, we override these
   // SyncSocket methods in order to support shutting down the 'socket'.
-  virtual bool Close() override;
-  virtual size_t Receive(void* buffer, size_t length) override;
-  virtual size_t ReceiveWithTimeout(void* buffer,
-                                    size_t length,
-                                    TimeDelta timeout) override;
+  bool Close() override;
+  size_t Receive(void* buffer, size_t length) override;
+  size_t ReceiveWithTimeout(void* buffer,
+                            size_t length,
+                            TimeDelta timeout) override;
 #endif
 
   // Send() is overridden to catch cases where the remote end is not responding
diff --git a/base/synchronization/cancellation_flag.cc b/base/synchronization/cancellation_flag.cc
index ad3b551..ca5c0a8 100644
--- a/base/synchronization/cancellation_flag.cc
+++ b/base/synchronization/cancellation_flag.cc
@@ -19,4 +19,8 @@
   return base::subtle::Acquire_Load(&flag_) != 0;
 }
 
+void CancellationFlag::UnsafeResetForTesting() {
+  base::subtle::Release_Store(&flag_, 0);
+}
+
 }  // namespace base
diff --git a/base/synchronization/cancellation_flag.h b/base/synchronization/cancellation_flag.h
index 51a4def..0f0f08e 100644
--- a/base/synchronization/cancellation_flag.h
+++ b/base/synchronization/cancellation_flag.h
@@ -29,6 +29,11 @@
   void Set();
   bool IsSet() const;  // Returns true iff the flag was set.
 
+  // For subtle reasons that may be different on different architectures,
+  // a different thread testing IsSet() may erroneously read 'true' after
+  // this method has been called.
+  void UnsafeResetForTesting();
+
  private:
   base::subtle::Atomic32 flag_;
 #if !defined(NDEBUG)
diff --git a/base/synchronization/condition_variable_win.cc b/base/synchronization/condition_variable_win.cc
index 6dc4831..5f165c8 100644
--- a/base/synchronization/condition_variable_win.cc
+++ b/base/synchronization/condition_variable_win.cc
@@ -72,12 +72,12 @@
 class WinVistaCondVar: public ConditionVarImpl {
  public:
   WinVistaCondVar(Lock* user_lock);
-  ~WinVistaCondVar() {};
+  ~WinVistaCondVar() override {}
   // Overridden from ConditionVarImpl.
-  virtual void Wait() override;
-  virtual void TimedWait(const TimeDelta& max_time) override;
-  virtual void Broadcast() override;
-  virtual void Signal() override;
+  void Wait() override;
+  void TimedWait(const TimeDelta& max_time) override;
+  void Broadcast() override;
+  void Signal() override;
 
  private:
   base::Lock& user_lock_;
@@ -127,12 +127,12 @@
 class WinXPCondVar : public ConditionVarImpl {
  public:
   WinXPCondVar(Lock* user_lock);
-  ~WinXPCondVar();
+  ~WinXPCondVar() override;
   // Overridden from ConditionVarImpl.
-  virtual void Wait() override;
-  virtual void TimedWait(const TimeDelta& max_time) override;
-  virtual void Broadcast() override;
-  virtual void Signal() override;
+  void Wait() override;
+  void TimedWait(const TimeDelta& max_time) override;
+  void Broadcast() override;
+  void Signal() override;
 
   // Define Event class that is used to form circularly linked lists.
   // The list container is an element with NULL as its handle_ value.
diff --git a/base/synchronization/waitable_event_unittest.cc b/base/synchronization/waitable_event_unittest.cc
index abba935..be56cf1 100644
--- a/base/synchronization/waitable_event_unittest.cc
+++ b/base/synchronization/waitable_event_unittest.cc
@@ -73,29 +73,27 @@
 
 class WaitableEventSignaler : public PlatformThread::Delegate {
  public:
-  WaitableEventSignaler(double seconds, WaitableEvent* ev)
-      : seconds_(seconds),
-        ev_(ev) {
+  WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
+      : delay_(delay),
+        event_(event) {
   }
 
   void ThreadMain() override {
-    PlatformThread::Sleep(TimeDelta::FromSecondsD(seconds_));
-    ev_->Signal();
+    PlatformThread::Sleep(delay_);
+    event_->Signal();
   }
 
  private:
-  const double seconds_;
-  WaitableEvent *const ev_;
+  const TimeDelta delay_;
+  WaitableEvent* event_;
 };
 
+// Tests that a WaitableEvent can be safely deleted when |Wait| is done without
+// additional synchronization.
 TEST(WaitableEventTest, WaitAndDelete) {
-  // This test tests that if a WaitableEvent can be safely deleted
-  // when |Wait| is done without additional synchrnization.
-  // If this test crashes, it is a bug.
-
   WaitableEvent* ev = new WaitableEvent(false, false);
 
-  WaitableEventSignaler signaler(0.01, ev);
+  WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
   PlatformThreadHandle thread;
   PlatformThread::Create(0, &signaler, &thread);
 
@@ -105,16 +103,14 @@
   PlatformThread::Join(thread);
 }
 
+// Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
+// without additional synchronization.
 TEST(WaitableEventTest, WaitMany) {
-  // This test tests that if a WaitableEvent can be safely deleted
-  // when |WaitMany| is done without additional synchrnization.
-  // If this test crashes, it is a bug.
-
   WaitableEvent* ev[5];
   for (unsigned i = 0; i < 5; ++i)
     ev[i] = new WaitableEvent(false, false);
 
-  WaitableEventSignaler signaler(0.01, ev[2]);
+  WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
   PlatformThreadHandle thread;
   PlatformThread::Create(0, &signaler, &thread);
 
@@ -127,4 +123,28 @@
   EXPECT_EQ(2u, index);
 }
 
+// Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
+// a timeout of 0. (crbug.com/465948)
+#if defined(OS_POSIX)
+// crbug.com/465948 not fixed yet.
+#define MAYBE_TimedWait DISABLED_TimedWait
+#else
+#define MAYBE_TimedWait TimedWait
+#endif
+TEST(WaitableEventTest, MAYBE_TimedWait) {
+  WaitableEvent* ev = new WaitableEvent(false, false);
+
+  TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
+  WaitableEventSignaler signaler(thread_delay, ev);
+  PlatformThreadHandle thread;
+  TimeTicks start = TimeTicks::Now();
+  PlatformThread::Create(0, &signaler, &thread);
+
+  ev->TimedWait(TimeDelta::Max());
+  EXPECT_GE(TimeTicks::Now() - start, thread_delay);
+  delete ev;
+
+  PlatformThread::Join(thread);
+}
+
 }  // namespace base
diff --git a/base/synchronization/waitable_event_watcher.h b/base/synchronization/waitable_event_watcher.h
index d4d8e77..eb51eff 100644
--- a/base/synchronization/waitable_event_watcher.h
+++ b/base/synchronization/waitable_event_watcher.h
@@ -92,7 +92,7 @@
 
  private:
 #if defined(OS_WIN)
-  virtual void OnObjectSignaled(HANDLE h) override;
+  void OnObjectSignaled(HANDLE h) override;
   win::ObjectWatcher watcher_;
 #else
   // Implementation of MessageLoop::DestructionObserver
diff --git a/base/synchronization/waitable_event_win.cc b/base/synchronization/waitable_event_win.cc
index 770c582..4db5627 100644
--- a/base/synchronization/waitable_event_win.cc
+++ b/base/synchronization/waitable_event_win.cc
@@ -4,10 +4,10 @@
 
 #include "base/synchronization/waitable_event.h"
 
-#include <math.h>
 #include <windows.h>
 
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 
@@ -37,7 +37,7 @@
 }
 
 bool WaitableEvent::IsSignaled() {
-  return TimedWait(TimeDelta::FromMilliseconds(0));
+  return TimedWait(TimeDelta());
 }
 
 void WaitableEvent::Wait() {
@@ -50,13 +50,13 @@
 
 bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
   base::ThreadRestrictions::AssertWaitAllowed();
-  DCHECK(max_time >= TimeDelta::FromMicroseconds(0));
-  // Be careful here.  TimeDelta has a precision of microseconds, but this API
-  // is in milliseconds.  If there are 5.5ms left, should the delay be 5 or 6?
-  // It should be 6 to avoid returning too early.
-  double timeout = ceil(max_time.InMillisecondsF());
-  DWORD result = WaitForSingleObject(handle_.Get(),
-                                     static_cast<DWORD>(timeout));
+  DCHECK_GE(max_time, TimeDelta());
+  // Truncate the timeout to milliseconds. The API specifies that this method
+  // can return in less than |max_time| (when returning false), as the argument
+  // is the maximum time that a caller is willing to wait.
+  DWORD timeout = saturated_cast<DWORD>(max_time.InMilliseconds());
+
+  DWORD result = WaitForSingleObject(handle_.Get(), timeout);
   switch (result) {
     case WAIT_OBJECT_0:
       return true;
diff --git a/base/sys_info.h b/base/sys_info.h
index d3476d9..654d694 100644
--- a/base/sys_info.h
+++ b/base/sys_info.h
@@ -48,10 +48,6 @@
   // or -1 on failure.
   static int64 AmountOfFreeDiskSpace(const FilePath& path);
 
-  // Determine whether the device that services |path| has a seek penalty.
-  // Returns false if it couldn't be determined (e.g., |path| doesn't exist).
-  static bool HasSeekPenalty(const FilePath& path, bool* has_seek_penalty);
-
   // Returns system uptime in milliseconds.
   static int64 Uptime();
 
@@ -98,7 +94,7 @@
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
   // Returns the maximum SysV shared memory segment size, or zero if there is no
   // limit.
-  static size_t MaxSharedMemorySize();
+  static uint64 MaxSharedMemorySize();
 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
 
 #if defined(OS_CHROMEOS)
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc
index 0f2abc5..245097f 100644
--- a/base/sys_info_android.cc
+++ b/base/sys_info_android.cc
@@ -155,12 +155,6 @@
 
 namespace base {
 
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  // Find a case where this is incorrect and dbeam@ will buy you a beer.
-  *has_seek_penalty = false;
-  return true;
-}
-
 std::string SysInfo::OperatingSystemName() {
   return "Android";
 }
diff --git a/base/sys_info_chromeos.cc b/base/sys_info_chromeos.cc
index 2a5f5d7..ef5f1fe 100644
--- a/base/sys_info_chromeos.cc
+++ b/base/sys_info_chromeos.cc
@@ -169,11 +169,6 @@
 
 }  // namespace
 
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  // TODO(dbeam): implement. Can we just use boards/models?
-  return false;
-}
-
 // static
 void SysInfo::OperatingSystemVersionNumbers(int32* major_version,
                                             int32* minor_version,
diff --git a/base/sys_info_freebsd.cc b/base/sys_info_freebsd.cc
index 338f1cd..515b59d 100644
--- a/base/sys_info_freebsd.cc
+++ b/base/sys_info_freebsd.cc
@@ -22,19 +22,15 @@
   return static_cast<int64>(pages) * page_size;
 }
 
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  return false;
-}
-
 // static
-size_t SysInfo::MaxSharedMemorySize() {
+uint64 SysInfo::MaxSharedMemorySize() {
   size_t limit;
   size_t size = sizeof(limit);
   if (sysctlbyname("kern.ipc.shmmax", &limit, &size, NULL, 0) < 0) {
     NOTREACHED();
     return 0;
   }
-  return limit;
+  return static_cast<uint64>(limit);
 }
 
 }  // namespace base
diff --git a/base/sys_info_ios.mm b/base/sys_info_ios.mm
index 324bef6..49d618c 100644
--- a/base/sys_info_ios.mm
+++ b/base/sys_info_ios.mm
@@ -16,12 +16,6 @@
 
 namespace base {
 
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  // Find a case where this is incorrect and dbeam@ will buy you a beer.
-  *has_seek_penalty = false;
-  return true;
-}
-
 // static
 std::string SysInfo::OperatingSystemName() {
   static dispatch_once_t get_system_name_once;
diff --git a/base/sys_info_linux.cc b/base/sys_info_linux.cc
index 401d55c..1bbfe9c 100644
--- a/base/sys_info_linux.cc
+++ b/base/sys_info_linux.cc
@@ -9,6 +9,7 @@
 #include "base/files/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/sys_info_internal.h"
 
@@ -28,7 +29,7 @@
   return AmountOfMemory(_SC_PHYS_PAGES);
 }
 
-size_t MaxSharedMemorySize() {
+uint64 MaxSharedMemorySize() {
   std::string contents;
   base::ReadFileToString(base::FilePath("/proc/sys/kernel/shmmax"), &contents);
   DCHECK(!contents.empty());
@@ -40,18 +41,15 @@
   if (!base::StringToUint64(contents, &limit)) {
     limit = 0;
   }
-  if (limit > std::numeric_limits<size_t>::max()) {
-    limit = 0;
-  }
   DCHECK_GT(limit, 0u);
-  return static_cast<size_t>(limit);
+  return limit;
 }
 
 base::LazyInstance<
     base::internal::LazySysInfoValue<int64, AmountOfPhysicalMemory> >::Leaky
     g_lazy_physical_memory = LAZY_INSTANCE_INITIALIZER;
 base::LazyInstance<
-    base::internal::LazySysInfoValue<size_t, MaxSharedMemorySize> >::Leaky
+    base::internal::LazySysInfoValue<uint64, MaxSharedMemorySize> >::Leaky
     g_lazy_max_shared_memory = LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
@@ -68,15 +66,8 @@
   return g_lazy_physical_memory.Get().value();
 }
 
-#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  // TODO(dbeam): implement.
-  return false;
-}
-#endif
-
 // static
-size_t SysInfo::MaxSharedMemorySize() {
+uint64 SysInfo::MaxSharedMemorySize() {
   return g_lazy_max_shared_memory.Get().value();
 }
 
diff --git a/base/sys_info_mac.cc b/base/sys_info_mac.cc
index 8635088..18df624 100644
--- a/base/sys_info_mac.cc
+++ b/base/sys_info_mac.cc
@@ -76,11 +76,6 @@
       vm_info.free_count - vm_info.speculative_count) * PAGE_SIZE;
 }
 
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  // TODO(dbeam): implement.
-  return false;
-}
-
 // static
 std::string SysInfo::CPUModelName() {
   char name[256];
diff --git a/base/sys_info_openbsd.cc b/base/sys_info_openbsd.cc
index 68d2ea1..595291b 100644
--- a/base/sys_info_openbsd.cc
+++ b/base/sys_info_openbsd.cc
@@ -48,12 +48,8 @@
   return AmountOfMemory(_SC_AVPHYS_PAGES);
 }
 
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  return false;
-}
-
 // static
-size_t SysInfo::MaxSharedMemorySize() {
+uint64 SysInfo::MaxSharedMemorySize() {
   int mib[] = { CTL_KERN, KERN_SHMINFO, KERN_SHMINFO_SHMMAX };
   size_t limit;
   size_t size = sizeof(limit);
@@ -61,7 +57,7 @@
     NOTREACHED();
     return 0;
   }
-  return limit;
+  return static_cast<uint64>(limit);
 }
 
 // static
diff --git a/base/sys_info_unittest.cc b/base/sys_info_unittest.cc
index da47861..15ae098 100644
--- a/base/sys_info_unittest.cc
+++ b/base/sys_info_unittest.cc
@@ -41,13 +41,6 @@
             << tmp_path.value();
 }
 
-TEST_F(SysInfoTest, HasSeekPenalty) {
-  FilePath tmp_path;
-  ASSERT_TRUE(base::GetTempDir(&tmp_path));
-  bool unused;
-  base::SysInfo::HasSeekPenalty(tmp_path, &unused);
-}
-
 #if defined(OS_WIN) || defined(OS_MACOSX)
 TEST_F(SysInfoTest, OperatingSystemVersionNumbers) {
   int32 os_major_version = -1;
diff --git a/base/sys_info_win.cc b/base/sys_info_win.cc
index 817992c..c8314c7 100644
--- a/base/sys_info_win.cc
+++ b/base/sys_info_win.cc
@@ -1,13 +1,11 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/sys_info.h"
 
 #include <windows.h>
-#include <winioctl.h>
 
-#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
@@ -65,44 +63,6 @@
   return rv < 0 ? kint64max : rv;
 }
 
-bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) {
-  ThreadRestrictions::AssertIOAllowed();
-
-  DCHECK(path.IsAbsolute());
-  DCHECK(has_seek_penalty);
-
-  // TODO(dbeam): Vista, XP support.
-  if (win::GetVersion() < win::VERSION_WIN7)
-    return false;
-
-  std::vector<FilePath::StringType> components;
-  path.GetComponents(&components);
-
-  File drive(FilePath(L"\\\\.\\" + components[0]), File::FLAG_OPEN);
-  if (!drive.IsValid())
-    return false;
-
-  STORAGE_PROPERTY_QUERY query = {};
-  query.QueryType = PropertyStandardQuery;
-  query.PropertyId = StorageDeviceSeekPenaltyProperty;
-
-  DEVICE_SEEK_PENALTY_DESCRIPTOR result;
-  DWORD bytes_returned;
-
-  BOOL success = DeviceIoControl(drive.GetPlatformFile(),
-                                 IOCTL_STORAGE_QUERY_PROPERTY,
-                                 &query, sizeof(query),
-                                 &result, sizeof(result),
-                                 &bytes_returned,
-                                 NULL);
-  if (success == FALSE || bytes_returned < sizeof(result))
-    return false;
-
-  *has_seek_penalty = result.IncursSeekPenalty != FALSE;
-  return true;
-}
-
-// static
 std::string SysInfo::OperatingSystemName() {
   return "Windows NT";
 }
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index c4356cb..91456db 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -50,6 +50,8 @@
     "mock_chrome_application_mac.mm",
     "mock_devices_changed_observer.cc",
     "mock_devices_changed_observer.h",
+    "mock_entropy_provider.cc",
+    "mock_entropy_provider.h",
     "mock_log.cc",
     "mock_log.h",
     "multiprocess_test.cc",
@@ -116,6 +118,8 @@
     "trace_event_analyzer.h",
     "trace_to_file.cc",
     "trace_to_file.h",
+    "user_action_tester.cc",
+    "user_action_tester.h",
     "values_test_util.cc",
     "values_test_util.h",
   ]
@@ -183,6 +187,18 @@
   ]
 }
 
+if (is_linux) {
+  shared_library("malloc_wrapper") {
+    testonly = true
+    sources = [
+      "malloc_wrapper.cc",
+    ]
+    deps = [
+      "//base",
+    ]
+  }
+}
+
 if (is_android) {
   generate_jni("base_unittests_jni_headers") {
     sources = [
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java b/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
index ca6e73b..8765def 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
@@ -29,12 +29,12 @@
         Writer writer = null;
         try {
             writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
-            writer.write("<html><meta charset=\"UTF-8\" />" +
-                         "<head><title>" + title + "</title></head>" +
-                         "<body>" +
-                         (body != null ? body : "") +
-                         "</body>" +
-                         "</html>");
+            writer.write("<html><meta charset=\"UTF-8\" />"
+                    + "     <head><title>" + title + "</title></head>"
+                    + "     <body>"
+                    + (body != null ? body : "")
+                    + "     </body>"
+                    + "   </html>");
         } finally {
             if (writer != null) {
                 writer.close();
@@ -61,8 +61,8 @@
         try {
             File f = new File(fileName);
             if (f.length() > sizeLimit) {
-                throw new IOException("File " + fileName + " length " + f.length() +
-                        " exceeds limit " + sizeLimit);
+                throw new IOException("File " + fileName + " length " + f.length()
+                        + " exceeds limit " + sizeLimit);
             }
             char[] buffer = new char[(int) f.length()];
             reader = new InputStreamReader(new FileInputStream(f), "UTF-8");
diff --git a/base/test/gtest_xml_util.h b/base/test/gtest_xml_util.h
index f832cde..9ff2406 100644
--- a/base/test/gtest_xml_util.h
+++ b/base/test/gtest_xml_util.h
@@ -21,17 +21,17 @@
 class XmlUnitTestResultPrinter : public testing::EmptyTestEventListener {
  public:
   XmlUnitTestResultPrinter();
-  virtual ~XmlUnitTestResultPrinter();
+  ~XmlUnitTestResultPrinter() override;
 
   // Must be called before adding as a listener. Returns true on success.
   bool Initialize(const FilePath& output_file_path) WARN_UNUSED_RESULT;
 
  private:
   // testing::EmptyTestEventListener:
-  virtual void OnTestCaseStart(const testing::TestCase& test_case) override;
-  virtual void OnTestStart(const testing::TestInfo& test_info) override;
-  virtual void OnTestEnd(const testing::TestInfo& test_info) override;
-  virtual void OnTestCaseEnd(const testing::TestCase& test_case) override;
+  void OnTestCaseStart(const testing::TestCase& test_case) override;
+  void OnTestStart(const testing::TestInfo& test_info) override;
+  void OnTestEnd(const testing::TestInfo& test_info) override;
+  void OnTestCaseEnd(const testing::TestCase& test_case) override;
 
   FILE* output_file_;
 
diff --git a/base/test/ios/OWNERS b/base/test/ios/OWNERS
new file mode 100644
index 0000000..1b3348e
--- /dev/null
+++ b/base/test/ios/OWNERS
@@ -0,0 +1,2 @@
+rohitrao@chromium.org
+stuartmorgan@chromium.org
diff --git a/base/test/ios/wait_util.h b/base/test/ios/wait_util.h
new file mode 100644
index 0000000..01c6fe7
--- /dev/null
+++ b/base/test/ios/wait_util.h
@@ -0,0 +1,49 @@
+// 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.
+
+#ifndef BASE_TEST_IOS_WAIT_UTIL_H_
+#define BASE_TEST_IOS_WAIT_UTIL_H_
+
+#include "base/ios/block_types.h"
+#include "base/time/time.h"
+
+namespace base {
+
+class MessageLoop;
+
+namespace test {
+namespace ios {
+
+// Returns the time spent in running |action| plus waiting until |condition| is
+// met.
+// Performs |action| and then spins run loop and runs the |message_loop| until
+// |condition| block returns true.
+// |action| may be nil if no action needs to be performed before the wait loop.
+// |message_loop| can be null if there is no need to spin the message loop.
+// |condition| may be nil if there is no condition to wait for: the run loop
+// will spin until timeout is reached.
+// |timeout| parameter sets the maximum wait time. If |timeout| is zero,
+// a reasonable default will be used.
+TimeDelta TimeUntilCondition(ProceduralBlock action,
+                             ConditionBlock condition,
+                             MessageLoop* message_loop,
+                             TimeDelta timeout);
+
+// Waits until |condition| is met. A |message_loop| to spin and a |timeout| can
+// be optionally passed; if |timeout| is zero, a reasonable default will be
+// used.
+void WaitUntilCondition(ConditionBlock condition,
+                        MessageLoop* message_loop,
+                        TimeDelta timeout);
+void WaitUntilCondition(ConditionBlock condition);
+
+// Lets the run loop of the current thread process other messages
+// within the given maximum delay.
+void SpinRunLoopWithMaxDelay(TimeDelta max_delay);
+
+}  // namespace ios
+}  // namespace test
+}  // namespace base
+
+#endif  // BASE_TEST_IOS_WAIT_UTIL_H_
diff --git a/base/test/ios/wait_util.mm b/base/test/ios/wait_util.mm
new file mode 100644
index 0000000..e8b3a0f
--- /dev/null
+++ b/base/test/ios/wait_util.mm
@@ -0,0 +1,62 @@
+// 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 "base/test/ios/wait_util.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/message_loop/message_loop.h"
+#include "base/test/test_timeouts.h"
+#include "base/timer/elapsed_timer.h"
+
+namespace base {
+namespace test {
+namespace ios {
+
+TimeDelta TimeUntilCondition(ProceduralBlock action,
+                             ConditionBlock condition,
+                             MessageLoop* message_loop,
+                             TimeDelta timeout) {
+  ElapsedTimer timer;
+  if (action)
+    action();
+  if (timeout == TimeDelta())
+    timeout = TestTimeouts::action_timeout();
+  const TimeDelta spin_delay(TimeDelta::FromMilliseconds(10));
+  while (timer.Elapsed() < timeout && (!condition || !condition())) {
+    SpinRunLoopWithMaxDelay(spin_delay);
+    if (message_loop) {
+      message_loop->RunUntilIdle();
+    }
+  }
+  TimeDelta elapsed = timer.Elapsed();
+  // If DCHECK is ever hit, check if |action| is doing something that is
+  // taking an unreasonably long time, or if |condition| does not come
+  // true quickly enough. Increase |timeout| only if necessary.
+  DCHECK(!condition || condition());
+  return elapsed;
+}
+
+void WaitUntilCondition(ConditionBlock condition,
+                        MessageLoop* message_loop,
+                        TimeDelta timeout) {
+  TimeUntilCondition(nil, condition, message_loop, timeout);
+}
+
+void WaitUntilCondition(ConditionBlock condition) {
+  WaitUntilCondition(condition, nullptr, TimeDelta());
+}
+
+void SpinRunLoopWithMaxDelay(TimeDelta max_delay) {
+  scoped_nsobject<NSDate> beforeDate(
+      [[NSDate alloc] initWithTimeIntervalSinceNow:max_delay.InSecondsF()]);
+  [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
+                           beforeDate:beforeDate];
+}
+
+}  // namespace ios
+}  // namespace test
+}  // namespace base
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index 1d48060..521f69c 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -150,7 +150,7 @@
     KillSpawnedTestProcesses();
 
     // The signal would normally kill the process, so exit now.
-    exit(1);
+    _exit(1);
   }
 
   void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
@@ -310,7 +310,7 @@
     exit_code = -1;  // Set a non-zero exit code to signal a failure.
 
     // Ensure that the process terminates.
-    KillProcess(process.Handle(), -1, true);
+    process.Terminate(-1, true);
   }
 
   {
@@ -570,7 +570,7 @@
   }
   if (print_snippet) {
     std::vector<std::string> snippet_lines;
-    SplitString(result.output_snippet, '\n', &snippet_lines);
+    SplitStringDontTrim(result.output_snippet, '\n', &snippet_lines);
     if (snippet_lines.size() > kOutputSnippetLinesLimit) {
       size_t truncated_size = snippet_lines.size() - kOutputSnippetLinesLimit;
       snippet_lines.erase(
diff --git a/base/test/malloc_wrapper.cc b/base/test/malloc_wrapper.cc
new file mode 100644
index 0000000..eb280a3
--- /dev/null
+++ b/base/test/malloc_wrapper.cc
@@ -0,0 +1,11 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "malloc_wrapper.h"
+
+#include <stdlib.h>
+
+void* MallocWrapper(size_t size) {
+  return malloc(size);
+}
diff --git a/base/test/malloc_wrapper.h b/base/test/malloc_wrapper.h
new file mode 100644
index 0000000..0fa7dbb
--- /dev/null
+++ b/base/test/malloc_wrapper.h
@@ -0,0 +1,21 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TEST_MALLOC_WRAPPER_H_
+#define BASE_TEST_MALLOC_WRAPPER_H_
+
+#include "base/basictypes.h"
+
+// BASE_EXPORT depends on COMPONENT_BUILD.
+// This will always be a separate shared library, so don't use BASE_EXPORT here.
+#if defined(WIN32)
+#define MALLOC_WRAPPER_EXPORT __declspec(dllexport)
+#else
+#define MALLOC_WRAPPER_EXPORT __attribute__((visibility("default")))
+#endif  // defined(WIN32)
+
+// Calls malloc directly.
+MALLOC_WRAPPER_EXPORT void* MallocWrapper(size_t size);
+
+#endif  // BASE_TEST_MALLOC_WRAPPER_H_
diff --git a/base/test/mock_entropy_provider.cc b/base/test/mock_entropy_provider.cc
new file mode 100644
index 0000000..75186a5
--- /dev/null
+++ b/base/test/mock_entropy_provider.cc
@@ -0,0 +1,16 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/mock_entropy_provider.h"
+
+namespace base {
+
+MockEntropyProvider::~MockEntropyProvider() {}
+
+double MockEntropyProvider::GetEntropyForTrial(
+    const std::string& trial_name, uint32 randomization_seed) const {
+  return 0.5;
+}
+
+}  // namespace base
diff --git a/base/test/mock_entropy_provider.h b/base/test/mock_entropy_provider.h
new file mode 100644
index 0000000..c55bea6
--- /dev/null
+++ b/base/test/mock_entropy_provider.h
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TEST_MOCK_ENTROPY_PROVIDER_H_
+#define BASE_TEST_MOCK_ENTROPY_PROVIDER_H_
+
+#include "base/metrics/field_trial.h"
+
+namespace base {
+
+class MockEntropyProvider : public base::FieldTrial::EntropyProvider {
+ public:
+  ~MockEntropyProvider() override;
+
+  // base::FieldTrial::EntropyProvider:
+  double GetEntropyForTrial(const std::string& trial_name,
+                            uint32 randomization_seed) const override;
+};
+
+}  // namespace base
+
+#endif  // BASE_TEST_MOCK_ENTROPY_PROVIDER_H_
diff --git a/base/test/sequenced_worker_pool_owner.cc b/base/test/sequenced_worker_pool_owner.cc
index f6a0d01..4486323 100644
--- a/base/test/sequenced_worker_pool_owner.cc
+++ b/base/test/sequenced_worker_pool_owner.cc
@@ -43,6 +43,9 @@
 void SequencedWorkerPoolOwner::WillWaitForShutdown() {
   if (!will_wait_for_shutdown_callback_.is_null()) {
     will_wait_for_shutdown_callback_.Run();
+
+    // Release the reference to the callback to prevent retain cycles.
+    will_wait_for_shutdown_callback_ = Closure();
   }
 }
 
diff --git a/base/test/test_discardable_memory_allocator.cc b/base/test/test_discardable_memory_allocator.cc
index cb2cccf..23d529c 100644
--- a/base/test/test_discardable_memory_allocator.cc
+++ b/base/test/test_discardable_memory_allocator.cc
@@ -13,15 +13,15 @@
 
 class DiscardableMemoryImpl : public DiscardableMemory {
  public:
-  explicit DiscardableMemoryImpl(size_t size) : memory_(new uint8_t[size]) {}
+  explicit DiscardableMemoryImpl(size_t size) : data_(new uint8_t[size]) {}
 
   // Overridden from DiscardableMemory:
   bool Lock() override { return false; }
   void Unlock() override {}
-  void* Memory() const override { return memory_.get(); }
+  void* data() const override { return data_.get(); }
 
  private:
-  scoped_ptr<uint8_t[]> memory_;
+  scoped_ptr<uint8_t[]> data_;
 };
 
 }  // namespace
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc
index 8cc2e6d..f2e18a3 100644
--- a/base/test/test_mock_time_task_runner.cc
+++ b/base/test/test_mock_time_task_runner.cc
@@ -67,15 +67,55 @@
 
 }  // namespace
 
+// TestMockTimeTaskRunner::TestOrderedPendingTask -----------------------------
+
+// Subclass of TestPendingTask which has a strictly monotonically increasing ID
+// for every task, so that tasks posted with the same 'time to run' can be run
+// in the order of being posted.
+struct TestMockTimeTaskRunner::TestOrderedPendingTask
+    : public base::TestPendingTask {
+  TestOrderedPendingTask();
+  TestOrderedPendingTask(const tracked_objects::Location& location,
+                         const Closure& task,
+                         TimeTicks post_time,
+                         TimeDelta delay,
+                         size_t ordinal,
+                         TestNestability nestability);
+  ~TestOrderedPendingTask();
+
+  size_t ordinal;
+};
+
+TestMockTimeTaskRunner::TestOrderedPendingTask::TestOrderedPendingTask()
+    : ordinal(0) {
+}
+
+TestMockTimeTaskRunner::TestOrderedPendingTask::TestOrderedPendingTask(
+    const tracked_objects::Location& location,
+    const Closure& task,
+    TimeTicks post_time,
+    TimeDelta delay,
+    size_t ordinal,
+    TestNestability nestability)
+    : base::TestPendingTask(location, task, post_time, delay, nestability),
+      ordinal(ordinal) {
+}
+
+TestMockTimeTaskRunner::TestOrderedPendingTask::~TestOrderedPendingTask() {
+}
+
 // TestMockTimeTaskRunner -----------------------------------------------------
 
 bool TestMockTimeTaskRunner::TemporalOrder::operator()(
-    const TestPendingTask& first_task,
-    const TestPendingTask& second_task) const {
+    const TestOrderedPendingTask& first_task,
+    const TestOrderedPendingTask& second_task) const {
+  if (first_task.GetTimeToRun() == second_task.GetTimeToRun())
+    return first_task.ordinal > second_task.ordinal;
   return first_task.GetTimeToRun() > second_task.GetTimeToRun();
 }
 
-TestMockTimeTaskRunner::TestMockTimeTaskRunner() : now_(Time::UnixEpoch()) {
+TestMockTimeTaskRunner::TestMockTimeTaskRunner()
+    : now_(Time::UnixEpoch()), next_task_ordinal_(0) {
 }
 
 TestMockTimeTaskRunner::~TestMockTimeTaskRunner() {
@@ -152,8 +192,9 @@
     const Closure& task,
     TimeDelta delay) {
   AutoLock scoped_lock(tasks_lock_);
-  tasks_.push(TestPendingTask(from_here, task, now_ticks_, delay,
-                              TestPendingTask::NESTABLE));
+  tasks_.push(TestOrderedPendingTask(from_here, task, now_ticks_, delay,
+                                     next_task_ordinal_++,
+                                     TestPendingTask::NESTABLE));
   return true;
 }
 
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index 705af10..6319e0c 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -112,15 +112,17 @@
   virtual void OnAfterTaskRun();
 
  private:
+  struct TestOrderedPendingTask;
+
   // Predicate that defines a strict weak temporal ordering of tasks.
   class TemporalOrder {
    public:
-    bool operator()(const TestPendingTask& first_task,
-                    const TestPendingTask& second_task) const;
+    bool operator()(const TestOrderedPendingTask& first_task,
+                    const TestOrderedPendingTask& second_task) const;
   };
 
-  typedef std::priority_queue<TestPendingTask,
-                              std::vector<TestPendingTask>,
+  typedef std::priority_queue<TestOrderedPendingTask,
+                              std::vector<TestOrderedPendingTask>,
                               TemporalOrder> TaskPriorityQueue;
 
   // Core of the implementation for all flavors of fast-forward methods. Given a
@@ -148,6 +150,11 @@
   // Temporally ordered heap of pending tasks. Must only be accessed while the
   // |tasks_lock_| is held.
   TaskPriorityQueue tasks_;
+
+  // The ordinal to use for the next task. Must only be accessed while the
+  // |tasks_lock_| is held.
+  size_t next_task_ordinal_;
+
   Lock tasks_lock_;
 
   DISALLOW_COPY_AND_ASSIGN(TestMockTimeTaskRunner);
diff --git a/base/test/test_reg_util_win_unittest.cc b/base/test/test_reg_util_win_unittest.cc
index 11abe5d..216d58e 100644
--- a/base/test/test_reg_util_win_unittest.cc
+++ b/base/test/test_reg_util_win_unittest.cc
@@ -32,7 +32,7 @@
     key.DeleteKey(kTestKeyPath);
   }
 
-  virtual ~RegistryOverrideManagerTest() {
+  ~RegistryOverrideManagerTest() override {
     base::win::RegKey key(HKEY_CURRENT_USER);
     key.DeleteKey(fake_test_key_root_.c_str());
   }
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index d40dd98..ee135e5 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -55,7 +55,7 @@
 
 class MaybeTestDisabler : public testing::EmptyTestEventListener {
  public:
-  virtual void OnTestStart(const testing::TestInfo& test_info) override {
+  void OnTestStart(const testing::TestInfo& test_info) override {
     ASSERT_FALSE(TestSuite::IsMarkedMaybe(test_info))
         << "Probably the OS #ifdefs don't include all of the necessary "
            "platforms.\nPlease ensure that no tests have the MAYBE_ prefix "
@@ -69,11 +69,11 @@
       : old_command_line_(base::CommandLine::NO_PROGRAM) {
   }
 
-  virtual void OnTestStart(const testing::TestInfo& test_info) override {
+  void OnTestStart(const testing::TestInfo& test_info) override {
     old_command_line_ = *base::CommandLine::ForCurrentProcess();
   }
 
-  virtual void OnTestEnd(const testing::TestInfo& test_info) override {
+  void OnTestEnd(const testing::TestInfo& test_info) override {
     *base::CommandLine::ForCurrentProcess() = old_command_line_;
   }
 
diff --git a/base/test/user_action_tester.cc b/base/test/user_action_tester.cc
new file mode 100644
index 0000000..3fdab12
--- /dev/null
+++ b/base/test/user_action_tester.cc
@@ -0,0 +1,35 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/user_action_tester.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+
+namespace base {
+
+UserActionTester::UserActionTester()
+    : action_callback_(
+          base::Bind(&UserActionTester::OnUserAction, base::Unretained(this))) {
+  base::AddActionCallback(action_callback_);
+}
+
+UserActionTester::~UserActionTester() {
+  base::RemoveActionCallback(action_callback_);
+}
+
+int UserActionTester::GetActionCount(const std::string& user_action) const {
+  UserActionCountMap::const_iterator iter = count_map_.find(user_action);
+  return iter == count_map_.end() ? 0 : iter->second;
+}
+
+void UserActionTester::ResetCounts() {
+  count_map_.clear();
+}
+
+void UserActionTester::OnUserAction(const std::string& user_action) {
+  ++(count_map_[user_action]);
+}
+
+}  // namespace base
diff --git a/base/test/user_action_tester.h b/base/test/user_action_tester.h
new file mode 100644
index 0000000..6b0efc5
--- /dev/null
+++ b/base/test/user_action_tester.h
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TEST_USER_ACTION_TESTER_H_
+#define BASE_TEST_USER_ACTION_TESTER_H_
+
+#include <map>
+#include <string>
+
+#include "base/metrics/user_metrics.h"
+
+namespace base {
+
+// This class observes and collects user action notifications that are sent
+// by the tests, so that they can be examined afterwards for correctness.
+// Note: This class is NOT thread-safe.
+class UserActionTester {
+ public:
+  UserActionTester();
+  ~UserActionTester();
+
+  // Returns the number of times the given |user_action| occurred.
+  int GetActionCount(const std::string& user_action) const;
+
+  // Resets all user action counts to 0.
+  void ResetCounts();
+
+ private:
+  typedef std::map<std::string, int> UserActionCountMap;
+
+  // The callback that is notified when a user actions occurs.
+  void OnUserAction(const std::string& user_action);
+
+  // A map that tracks the number of times a user action has occurred.
+  UserActionCountMap count_map_;
+
+  // The callback that is added to the global action callback list.
+  base::ActionCallback action_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(UserActionTester);
+};
+
+}  // namespace base
+
+#endif  // BASE_TEST_USER_ACTION_TESTER_H_
diff --git a/base/test/user_action_tester_unittest.cc b/base/test/user_action_tester_unittest.cc
new file mode 100644
index 0000000..a51849f
--- /dev/null
+++ b/base/test/user_action_tester_unittest.cc
@@ -0,0 +1,86 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/user_action_tester.h"
+
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+const char kUserAction1[] = "user.action.1";
+const char kUserAction2[] = "user.action.2";
+const char kUserAction3[] = "user.action.3";
+
+// Record an action and cause all ActionCallback observers to be notified.
+void RecordAction(const char user_action[]) {
+  base::RecordAction(base::UserMetricsAction(user_action));
+}
+
+}  // namespace
+
+// Verify user action counts are zero initially.
+TEST(UserActionTesterTest, GetActionCountWhenNoActionsHaveBeenRecorded) {
+  UserActionTester user_action_tester;
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction1));
+}
+
+// Verify user action counts are tracked properly.
+TEST(UserActionTesterTest, GetActionCountWhenActionsHaveBeenRecorded) {
+  UserActionTester user_action_tester;
+
+  RecordAction(kUserAction1);
+  RecordAction(kUserAction2);
+  RecordAction(kUserAction2);
+
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
+  EXPECT_EQ(2, user_action_tester.GetActionCount(kUserAction2));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction3));
+}
+
+// Verify no seg faults occur when resetting action counts when none have been
+// recorded.
+TEST(UserActionTesterTest, ResetCountsWhenNoActionsHaveBeenRecorded) {
+  UserActionTester user_action_tester;
+  user_action_tester.ResetCounts();
+}
+
+// Verify user action counts are set to zero on a ResetCounts.
+TEST(UserActionTesterTest, ResetCountsWhenActionsHaveBeenRecorded) {
+  UserActionTester user_action_tester;
+
+  RecordAction(kUserAction1);
+  RecordAction(kUserAction1);
+  RecordAction(kUserAction2);
+  user_action_tester.ResetCounts();
+
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction1));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction2));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction3));
+}
+
+// Verify the UserActionsTester is notified when base::RecordAction is called.
+TEST(UserActionTesterTest, VerifyUserActionTesterListensForUserActions) {
+  UserActionTester user_action_tester;
+
+  base::RecordAction(base::UserMetricsAction(kUserAction1));
+
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
+}
+
+// Verify the UserActionsTester is notified when base::RecordComputedAction is
+// called.
+TEST(UserActionTesterTest,
+     VerifyUserActionTesterListensForComputedUserActions) {
+  UserActionTester user_action_tester;
+
+  base::RecordComputedAction(kUserAction1);
+
+  EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
+}
+
+}  // namespace base
diff --git a/base/third_party/nspr/BUILD.gn b/base/third_party/nspr/BUILD.gn
deleted file mode 100644
index 034f37b..0000000
--- a/base/third_party/nspr/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 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.
-
-source_set("nspr") {
-  visibility = [ "//base/*" ]
-
-  sources = [
-    "prtime.cc",
-    "prtime.h",
-  ]
-
-  # In GYP this project is part of base, so it uses the base implementation
-  # define. TODO(brettw) rename this define.
-  configs += [ "//base:base_implementation" ]
-
-  if (is_android && !is_debug) {
-    configs -= [ "//build/config/compiler:optimize" ]
-    configs += [ "//build/config/compiler:optimize_max" ]
-  }
-}
diff --git a/base/third_party/xdg_mime/README.chromium b/base/third_party/xdg_mime/README.chromium
index 29d239a..95f3a96 100644
--- a/base/third_party/xdg_mime/README.chromium
+++ b/base/third_party/xdg_mime/README.chromium
@@ -7,5 +7,7 @@
 @ 2cdd8d36d7930d5a594587286cb1949ff62f7027 on 2012/08/06.
 
 In addition, we have the following patch(es):
-- compile.patch: small tweaks to make the code compile.
-- Added a LICENSE file.
+  - compile.patch: small tweaks to make the code compile.
+  - free_pointer_later.patch: small patch that fixes potential crash in
+      xdg_mime_get_mime_type_for_file() - use of pointer after being freed.
+  - Added a LICENSE file.
diff --git a/base/third_party/xdg_mime/free_pointer_later.patch b/base/third_party/xdg_mime/free_pointer_later.patch
new file mode 100644
index 0000000..7668761
--- /dev/null
+++ b/base/third_party/xdg_mime/free_pointer_later.patch
@@ -0,0 +1,22 @@
+diff --git a/base/third_party/xdg_mime/xdgmime.c b/base/third_party/xdg_mime/xdgmime.c
+index c7b16bb..6dc58c2 100644
+--- a/base/third_party/xdg_mime/xdgmime.c
++++ b/base/third_party/xdg_mime/xdgmime.c
+@@ -558,13 +558,13 @@ xdg_mime_get_mime_type_for_file (const char  *file_name,
+   mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read, NULL,
+ 					   mime_types, n);
+ 
+-  free (data);
+   fclose (file);
+ 
+-  if (mime_type)
+-    return mime_type;
++  if (!mime_type)
++    mime_type = _xdg_binary_or_text_fallback(data, bytes_read);
+ 
+-  return _xdg_binary_or_text_fallback(data, bytes_read);
++  free (data);
++  return mime_type;
+ }
+ 
+ const char *
diff --git a/base/third_party/xdg_mime/xdgmime.c b/base/third_party/xdg_mime/xdgmime.c
index c7b16bb..6dc58c2 100644
--- a/base/third_party/xdg_mime/xdgmime.c
+++ b/base/third_party/xdg_mime/xdgmime.c
@@ -558,13 +558,13 @@
   mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read, NULL,
 					   mime_types, n);
 
-  free (data);
   fclose (file);
 
-  if (mime_type)
-    return mime_type;
+  if (!mime_type)
+    mime_type = _xdg_binary_or_text_fallback(data, bytes_read);
 
-  return _xdg_binary_or_text_fallback(data, bytes_read);
+  free (data);
+  return mime_type;
 }
 
 const char *
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h
index 2874314..653961d 100644
--- a/base/threading/platform_thread.h
+++ b/base/threading/platform_thread.h
@@ -110,15 +110,17 @@
 
 const PlatformThreadId kInvalidThreadId(0);
 
-// Valid values for SetThreadPriority()
-enum ThreadPriority{
-  kThreadPriority_Normal,
-  // Suitable for low-latency, glitch-resistant audio.
-  kThreadPriority_RealtimeAudio,
-  // Suitable for threads which generate data for the display (at ~60Hz).
-  kThreadPriority_Display,
+// Valid values for SetThreadPriority(), listed in increasing order of
+// importance.
+enum class ThreadPriority {
   // Suitable for threads that shouldn't disrupt high priority work.
-  kThreadPriority_Background
+  BACKGROUND,
+  // Default priority level.
+  NORMAL,
+  // Suitable for threads which generate data for the display (at ~60Hz).
+  DISPLAY,
+  // Suitable for low-latency, glitch-resistant audio.
+  REALTIME_AUDIO,
 };
 
 // A namespace for low-level thread functions.
@@ -141,7 +143,10 @@
   // we're on the right thread quickly.
   static PlatformThreadRef CurrentRef();
 
-  // Get the current handle.
+  // Get the handle representing the current thread. On Windows, this is a
+  // pseudo handle constant which will always represent the thread using it and
+  // hence should not be shared with other threads nor be used to differentiate
+  // the current thread from another.
   static PlatformThreadHandle CurrentHandle();
 
   // Yield the current thread so another thread can be scheduled.
@@ -171,9 +176,7 @@
 
   // CreateWithPriority() does the same thing as Create() except the priority of
   // the thread is set based on |priority|.  Can be used in place of Create()
-  // followed by SetThreadPriority().  SetThreadPriority() has not been
-  // implemented on the Linux platform yet, this is the only way to get a high
-  // priority thread on Linux.
+  // followed by SetThreadPriority().
   static bool CreateWithPriority(size_t stack_size, Delegate* delegate,
                                  PlatformThreadHandle* thread_handle,
                                  ThreadPriority priority);
@@ -191,6 +194,8 @@
   static void SetThreadPriority(PlatformThreadHandle handle,
                                 ThreadPriority priority);
 
+  static ThreadPriority GetThreadPriority(PlatformThreadHandle handle);
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
 };
diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc
index aab4c19..a31f659 100644
--- a/base/threading/platform_thread_android.cc
+++ b/base/threading/platform_thread_android.cc
@@ -38,17 +38,17 @@
 // We use -6 for display, but we may want to split this into urgent (-8) and
 // non-urgent (-4).
 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
-    {kThreadPriority_RealtimeAudio, -16},
-    {kThreadPriority_Background, 10},
-    {kThreadPriority_Normal, 0},
-    {kThreadPriority_Display, -6},
+    {ThreadPriority::BACKGROUND, 10},
+    {ThreadPriority::NORMAL, 0},
+    {ThreadPriority::DISPLAY, -6},
+    {ThreadPriority::REALTIME_AUDIO, -16},
 };
 
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
-                                        ThreadPriority priority) {
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority priority) {
   // On Android, we set the Audio priority through JNI as Audio priority
   // will also allow the process to run while it is backgrounded.
-  if (priority == kThreadPriority_RealtimeAudio) {
+  if (priority == ThreadPriority::REALTIME_AUDIO) {
     JNIEnv* env = base::android::AttachCurrentThread();
     Java_ThreadUtils_setThreadPriorityAudio(env, PlatformThread::CurrentId());
     return true;
@@ -56,6 +56,12 @@
   return false;
 }
 
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority* priority) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
 }  // namespace internal
 
 void PlatformThread::SetName(const char* name) {
@@ -83,7 +89,7 @@
   // Threads on linux/android may inherit their priority from the thread
   // where they were created. This sets all new threads to the default.
   PlatformThread::SetThreadPriority(PlatformThread::CurrentHandle(),
-                                    kThreadPriority_Normal);
+                                    ThreadPriority::NORMAL);
 }
 
 void TerminateOnThread() {
diff --git a/base/threading/platform_thread_freebsd.cc b/base/threading/platform_thread_freebsd.cc
index a163f65..7ba4eed 100644
--- a/base/threading/platform_thread_freebsd.cc
+++ b/base/threading/platform_thread_freebsd.cc
@@ -30,22 +30,42 @@
 }  // namespace
 
 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
-  { kThreadPriority_RealtimeAudio, -10 },
-  { kThreadPriority_Background, 10 },
-  { kThreadPriority_Normal, 0 },
-  { kThreadPriority_Display, -6 },
+    {ThreadPriority::BACKGROUND, 10},
+    {ThreadPriority::NORMAL, 0},
+    {ThreadPriority::DISPLAY, -6},
+    {ThreadPriority::REALTIME_AUDIO, -10},
 }
 
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
-                                        ThreadPriority priority) {
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority priority) {
 #if !defined(OS_NACL)
-  return priority == kThreadPriority_RealtimeAudio &&
+  // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+  // of |handle|. http://crbug.com/468793.
+  return priority == ThreadPriority::REALTIME_AUDIO &&
          pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0;
 #else
   return false;
 #endif
 }
 
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority* priority) {
+#if !defined(OS_NACL)
+  // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+  // of |handle|. http://crbug.com/468793.
+  int maybe_sched_rr = 0;
+  struct sched_param maybe_realtime_prio = {0};
+  if (pthread_getschedparam(pthread_self(), &maybe_sched_rr,
+                            &maybe_realtime_prio) == 0 &&
+      maybe_sched_rr == SCHED_RR &&
+      maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) {
+    *priority = ThreadPriority::REALTIME_AUDIO;
+    return true;
+  }
+#endif
+  return false;
+}
+
 }  // namespace internal
 
 // static
diff --git a/base/threading/platform_thread_internal_posix.cc b/base/threading/platform_thread_internal_posix.cc
index 7e6604b..9af0204 100644
--- a/base/threading/platform_thread_internal_posix.cc
+++ b/base/threading/platform_thread_internal_posix.cc
@@ -20,6 +20,16 @@
   return 0;
 }
 
+ThreadPriority NiceValueToThreadPriority(int nice_value) {
+  for (const ThreadPriorityToNiceValuePair& pair :
+       kThreadPriorityToNiceValueMap) {
+    if (pair.nice_value == nice_value)
+      return pair.priority;
+  }
+  NOTREACHED() << "Unknown nice value";
+  return ThreadPriority::NORMAL;
+}
+
 }  // namespace internal
 
 }  // namespace base
diff --git a/base/threading/platform_thread_internal_posix.h b/base/threading/platform_thread_internal_posix.h
index 1ae968f..62006ce 100644
--- a/base/threading/platform_thread_internal_posix.h
+++ b/base/threading/platform_thread_internal_posix.h
@@ -21,12 +21,22 @@
 // implementation of kThreadPriorityToNiceValueMap.
 int ThreadPriorityToNiceValue(ThreadPriority priority);
 
+// Returns the ThreadPrioirty matching |nice_value| based on the platform-
+// specific implementation of kThreadPriorityToNiceValueMap.
+ThreadPriority NiceValueToThreadPriority(int nice_value);
+
 // Allows platform specific tweaks to the generic POSIX solution for
 // SetThreadPriority. Returns true if the platform-specific implementation
 // handled this |priority| change, false if the generic implementation should
 // instead proceed.
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
-                                        ThreadPriority priority);
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority priority);
+
+// Returns true if there is a platform-specific ThreadPriority set on |handle|
+// (and returns the actual ThreadPriority via |priority|). Returns false
+// otherwise, leaving |priority| untouched.
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority* priority);
 
 }  // namespace internal
 
diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc
index 623a3de..b72fb5b 100644
--- a/base/threading/platform_thread_linux.cc
+++ b/base/threading/platform_thread_linux.cc
@@ -31,22 +31,42 @@
 }  // namespace
 
 const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
-    {kThreadPriority_RealtimeAudio, -10},
-    {kThreadPriority_Background, 10},
-    {kThreadPriority_Normal, 0},
-    {kThreadPriority_Display, -6},
+    {ThreadPriority::BACKGROUND, 10},
+    {ThreadPriority::NORMAL, 0},
+    {ThreadPriority::DISPLAY, -6},
+    {ThreadPriority::REALTIME_AUDIO, -10},
 };
 
-bool HandleSetThreadPriorityForPlatform(PlatformThreadHandle handle,
-                                        ThreadPriority priority) {
+bool SetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority priority) {
 #if !defined(OS_NACL)
-  return priority == kThreadPriority_RealtimeAudio &&
+  // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+  // of |handle|. http://crbug.com/468793.
+  return priority == ThreadPriority::REALTIME_AUDIO  &&
          pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0;
 #else
   return false;
 #endif
 }
 
+bool GetThreadPriorityForPlatform(PlatformThreadHandle handle,
+                                  ThreadPriority* priority) {
+#if !defined(OS_NACL)
+  int maybe_sched_rr = 0;
+  struct sched_param maybe_realtime_prio = {0};
+  // TODO(gab): Assess the correctness of using |pthread_self()| below instead
+  // of |handle|. http://crbug.com/468793.
+  if (pthread_getschedparam(pthread_self(), &maybe_sched_rr,
+                            &maybe_realtime_prio) == 0 &&
+      maybe_sched_rr == SCHED_RR &&
+      maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) {
+    *priority = ThreadPriority::REALTIME_AUDIO;
+    return true;
+  }
+#endif
+  return false;
+}
+
 }  // namespace internal
 
 // static
diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm
index 147e625..fd40d79 100644
--- a/base/threading/platform_thread_mac.mm
+++ b/base/threading/platform_thread_mac.mm
@@ -161,10 +161,10 @@
   mach_port_t mach_thread_id = pthread_mach_thread_np(handle.handle_);
 
   switch (priority) {
-    case kThreadPriority_Normal:
+    case ThreadPriority::NORMAL:
       SetPriorityNormal(mach_thread_id);
       break;
-    case kThreadPriority_RealtimeAudio:
+    case ThreadPriority::REALTIME_AUDIO:
       SetPriorityRealtimeAudio(mach_thread_id);
       break;
     default:
@@ -173,6 +173,12 @@
   }
 }
 
+// static
+ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) {
+  NOTIMPLEMENTED();
+  return ThreadPriority::NORMAL;
+}
+
 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
 #if defined(OS_IOS)
   return 0;
diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc
index 5c5023b..3dbdc98 100644
--- a/base/threading/platform_thread_posix.cc
+++ b/base/threading/platform_thread_posix.cc
@@ -39,7 +39,7 @@
   ThreadParams()
       : delegate(NULL),
         joinable(false),
-        priority(kThreadPriority_Normal),
+        priority(ThreadPriority::NORMAL),
         handle(NULL),
         handle_set(false, false) {
   }
@@ -59,7 +59,7 @@
   if (!thread_params->joinable)
     base::ThreadRestrictions::SetSingletonAllowed(false);
 
-  if (thread_params->priority != kThreadPriority_Normal) {
+  if (thread_params->priority != ThreadPriority::NORMAL) {
     PlatformThread::SetThreadPriority(PlatformThread::CurrentHandle(),
                                       thread_params->priority);
   }
@@ -201,7 +201,7 @@
                             PlatformThreadHandle* thread_handle) {
   base::ThreadRestrictions::ScopedAllowWait allow_wait;
   return CreateThread(stack_size, true /* joinable thread */,
-                      delegate, thread_handle, kThreadPriority_Normal);
+                      delegate, thread_handle, ThreadPriority::NORMAL);
 }
 
 // static
@@ -219,7 +219,7 @@
 
   base::ThreadRestrictions::ScopedAllowWait allow_wait;
   bool result = CreateThread(stack_size, false /* non-joinable thread */,
-                             delegate, &unused, kThreadPriority_Normal);
+                             delegate, &unused, ThreadPriority::NORMAL);
   return result;
 }
 
@@ -232,13 +232,16 @@
   CHECK_EQ(0, pthread_join(thread_handle.handle_, NULL));
 }
 
-// Mac has its own SetThreadPriority() implementation.
+// Mac has its own Set/GetThreadPriority() implementations.
 #if !defined(OS_MACOSX)
+
 // static
 void PlatformThread::SetThreadPriority(PlatformThreadHandle handle,
                                        ThreadPriority priority) {
-#if !defined(OS_NACL)
-  if (internal::HandleSetThreadPriorityForPlatform(handle, priority))
+#if defined(OS_NACL)
+  NOTIMPLEMENTED();
+#else
+  if (internal::SetThreadPriorityForPlatform(handle, priority))
     return;
 
   // setpriority(2) should change the whole thread group's (i.e. process)
@@ -255,8 +258,38 @@
     DVPLOG(1) << "Failed to set nice value of thread (" << handle.id_ << ") to "
               << nice_setting;
   }
+#endif  // defined(OS_NACL)
+}
+
+// static
+ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) {
+#if defined(OS_NACL)
+  NOTIMPLEMENTED();
+  return ThreadPriority::NORMAL;
+#else
+  // Mirrors SetThreadPriority()'s implementation.
+  ThreadPriority platform_specific_priority;
+  if (internal::GetThreadPriorityForPlatform(handle,
+                                             &platform_specific_priority)) {
+    return platform_specific_priority;
+  }
+
+  DCHECK_NE(handle.id_, kInvalidThreadId);
+  const PlatformThreadId current_id = PlatformThread::CurrentId();
+  // Need to clear errno before calling getpriority():
+  // http://man7.org/linux/man-pages/man2/getpriority.2.html
+  errno = 0;
+  int nice_value =
+      getpriority(PRIO_PROCESS, handle.id_ == current_id ? 0 : handle.id_);
+  if (errno != 0) {
+    DVPLOG(1) << "Failed to get nice value of thread (" << handle.id_ << ")";
+    return ThreadPriority::NORMAL;
+  }
+
+  return internal::NiceValueToThreadPriority(nice_value);
 #endif  // !defined(OS_NACL)
 }
+
 #endif  // !defined(OS_MACOSX)
 
 }  // namespace base
diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc
index 21260e5..c4b3d5d 100644
--- a/base/threading/platform_thread_unittest.cc
+++ b/base/threading/platform_thread_unittest.cc
@@ -3,10 +3,15 @@
 // found in the LICENSE file.
 
 #include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
-
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
 namespace base {
 
 // Trivial tests that thread runs and doesn't crash on create and join ---------
@@ -51,26 +56,59 @@
 
 // Tests of basic thread functions ---------------------------------------------
 
-class FunctionTestThread : public TrivialThread {
+class FunctionTestThread : public PlatformThread::Delegate {
  public:
-  FunctionTestThread() : thread_id_(0) {}
+  FunctionTestThread()
+      : thread_id_(kInvalidThreadId),
+        thread_started_(true, false),
+        terminate_thread_(true, false),
+        done_(false) {}
+  ~FunctionTestThread() override {
+    EXPECT_TRUE(terminate_thread_.IsSignaled())
+        << "Need to mark thread for termination and join the underlying thread "
+        << "before destroying a FunctionTestThread as it owns the "
+        << "WaitableEvent blocking the underlying thread's main.";
+  }
 
+  // Grabs |thread_id_|, signals |thread_started_|, and then waits for
+  // |terminate_thread_| to be signaled before exiting.
   void ThreadMain() override {
     thread_id_ = PlatformThread::CurrentId();
-    PlatformThread::YieldCurrentThread();
-    PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
+    EXPECT_NE(thread_id_, kInvalidThreadId);
 
     // Make sure that the thread ID is the same across calls.
     EXPECT_EQ(thread_id_, PlatformThread::CurrentId());
 
-    TrivialThread::ThreadMain();
+    thread_started_.Signal();
+
+    terminate_thread_.Wait();
+
+    done_ = true;
   }
 
-  PlatformThreadId thread_id() const { return thread_id_; }
+  PlatformThreadId thread_id() const {
+    EXPECT_TRUE(thread_started_.IsSignaled()) << "Thread ID still unknown";
+    return thread_id_;
+  }
+
+  bool IsRunning() const {
+    return thread_started_.IsSignaled() && !done_;
+  }
+
+  // Blocks until this thread is started.
+  void WaitForThreadStart() { thread_started_.Wait(); }
+
+  // Mark this thread for termination (callers must then join this thread to be
+  // guaranteed of termination).
+  void MarkForTermination() { terminate_thread_.Signal(); }
 
  private:
   PlatformThreadId thread_id_;
 
+  mutable WaitableEvent thread_started_;
+  WaitableEvent terminate_thread_;
+  bool done_;
+
   DISALLOW_COPY_AND_ASSIGN(FunctionTestThread);
 };
 
@@ -80,12 +118,16 @@
   FunctionTestThread thread;
   PlatformThreadHandle handle;
 
-  ASSERT_FALSE(thread.did_run());
+  ASSERT_FALSE(thread.IsRunning());
   ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
-  PlatformThread::Join(handle);
-  ASSERT_TRUE(thread.did_run());
+  thread.WaitForThreadStart();
+  ASSERT_TRUE(thread.IsRunning());
   EXPECT_NE(thread.thread_id(), main_thread_id);
 
+  thread.MarkForTermination();
+  PlatformThread::Join(handle);
+  ASSERT_FALSE(thread.IsRunning());
+
   // Make sure that the thread ID is the same across calls.
   EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
 }
@@ -97,13 +139,15 @@
   PlatformThreadHandle handle[arraysize(thread)];
 
   for (size_t n = 0; n < arraysize(thread); n++)
-    ASSERT_FALSE(thread[n].did_run());
+    ASSERT_FALSE(thread[n].IsRunning());
+
   for (size_t n = 0; n < arraysize(thread); n++)
     ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
   for (size_t n = 0; n < arraysize(thread); n++)
-    PlatformThread::Join(handle[n]);
+    thread[n].WaitForThreadStart();
+
   for (size_t n = 0; n < arraysize(thread); n++) {
-    ASSERT_TRUE(thread[n].did_run());
+    ASSERT_TRUE(thread[n].IsRunning());
     EXPECT_NE(thread[n].thread_id(), main_thread_id);
 
     // Make sure no two threads get the same ID.
@@ -112,8 +156,120 @@
     }
   }
 
+  for (size_t n = 0; n < arraysize(thread); n++)
+    thread[n].MarkForTermination();
+  for (size_t n = 0; n < arraysize(thread); n++)
+    PlatformThread::Join(handle[n]);
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_FALSE(thread[n].IsRunning());
+
   // Make sure that the thread ID is the same across calls.
   EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
 }
 
+namespace {
+
+const ThreadPriority kThreadPriorityTestValues[] = {
+// Disable non-normal priority toggling on POSIX as it appears to be broken
+// (http://crbug.com/468793). This is prefered to disabling the tests altogether
+// on POSIX as it at least provides coverage for running this code under
+// "normal" priority.
+#if !defined(OS_POSIX)
+    ThreadPriority::DISPLAY,
+    ThreadPriority::REALTIME_AUDIO,
+    // Keep BACKGROUND second to last to test backgrounding from other
+    // priorities.
+    ThreadPriority::BACKGROUND,
+#endif  // !defined(OS_POSIX)
+    // Keep NORMAL last to test unbackgrounding.
+    ThreadPriority::NORMAL
+};
+
+}  // namespace
+
+// Test changing another thread's priority.
+// NOTE: This test is partially disabled on POSIX, see note above and
+// http://crbug.com/468793.
+TEST(PlatformThreadTest, ThreadPriorityOtherThread) {
+  PlatformThreadHandle current_handle(PlatformThread::CurrentHandle());
+
+  // Confirm that the current thread's priority is as expected.
+  EXPECT_EQ(ThreadPriority::NORMAL,
+            PlatformThread::GetThreadPriority(current_handle));
+
+  // Create a test thread.
+  FunctionTestThread thread;
+  PlatformThreadHandle handle;
+  ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+  thread.WaitForThreadStart();
+  EXPECT_NE(thread.thread_id(), kInvalidThreadId);
+  EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId());
+
+  // New threads should get normal priority by default.
+  EXPECT_EQ(ThreadPriority::NORMAL, PlatformThread::GetThreadPriority(handle));
+
+  // Toggle each supported priority on the test thread and confirm it only
+  // affects it (and not the current thread).
+  for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) {
+    SCOPED_TRACE(i);
+
+    // Alter and verify the test thread's priority.
+    PlatformThread::SetThreadPriority(handle, kThreadPriorityTestValues[i]);
+    EXPECT_EQ(kThreadPriorityTestValues[i],
+              PlatformThread::GetThreadPriority(handle));
+
+    // Make sure the current thread was otherwise unaffected.
+    EXPECT_EQ(ThreadPriority::NORMAL,
+              PlatformThread::GetThreadPriority(current_handle));
+  }
+
+  thread.MarkForTermination();
+  PlatformThread::Join(handle);
+}
+
+// Test changing the current thread's priority (which has different semantics on
+// some platforms).
+// NOTE: This test is partially disabled on POSIX, see note above and
+// http://crbug.com/468793.
+TEST(PlatformThreadTest, ThreadPriorityCurrentThread) {
+  PlatformThreadHandle current_handle(PlatformThread::CurrentHandle());
+
+  // Confirm that the current thread's priority is as expected.
+  EXPECT_EQ(ThreadPriority::NORMAL,
+            PlatformThread::GetThreadPriority(current_handle));
+
+  // Create a test thread for verification purposes only.
+  FunctionTestThread thread;
+  PlatformThreadHandle handle;
+  ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+  thread.WaitForThreadStart();
+  EXPECT_NE(thread.thread_id(), kInvalidThreadId);
+  EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId());
+
+  // Confirm that the new thread's priority is as expected.
+  EXPECT_EQ(ThreadPriority::NORMAL, PlatformThread::GetThreadPriority(handle));
+
+  // Toggle each supported priority on the current thread and confirm it only
+  // affects it (and not the test thread).
+  for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) {
+    SCOPED_TRACE(i);
+
+    // Alter and verify the current thread's priority.
+    PlatformThread::SetThreadPriority(current_handle,
+                                      kThreadPriorityTestValues[i]);
+    EXPECT_EQ(kThreadPriorityTestValues[i],
+              PlatformThread::GetThreadPriority(current_handle));
+
+    // Make sure the test thread was otherwise unaffected.
+    EXPECT_EQ(ThreadPriority::NORMAL,
+              PlatformThread::GetThreadPriority(handle));
+  }
+
+  // Restore current thread priority for follow-up tests.
+  PlatformThread::SetThreadPriority(current_handle, ThreadPriority::NORMAL);
+
+  thread.MarkForTermination();
+  PlatformThread::Join(handle);
+}
+
 }  // namespace base
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc
index 3df3719..b9f7a56 100644
--- a/base/threading/platform_thread_win.cc
+++ b/base/threading/platform_thread_win.cc
@@ -126,18 +126,17 @@
 
 // static
 PlatformThreadId PlatformThread::CurrentId() {
-  return GetCurrentThreadId();
+  return ::GetCurrentThreadId();
 }
 
 // static
 PlatformThreadRef PlatformThread::CurrentRef() {
-  return PlatformThreadRef(GetCurrentThreadId());
+  return PlatformThreadRef(::GetCurrentThreadId());
 }
 
 // static
 PlatformThreadHandle PlatformThread::CurrentHandle() {
-  NOTIMPLEMENTED(); // See OpenThread()
-  return PlatformThreadHandle();
+  return PlatformThreadHandle(::GetCurrentThread());
 }
 
 // static
@@ -234,17 +233,56 @@
 // static
 void PlatformThread::SetThreadPriority(PlatformThreadHandle handle,
                                        ThreadPriority priority) {
+  DCHECK(!handle.is_null());
+
+  int desired_priority = THREAD_PRIORITY_ERROR_RETURN;
   switch (priority) {
-    case kThreadPriority_Normal:
-      ::SetThreadPriority(handle.handle_, THREAD_PRIORITY_NORMAL);
+    case ThreadPriority::BACKGROUND:
+      desired_priority = THREAD_PRIORITY_LOWEST;
       break;
-    case kThreadPriority_RealtimeAudio:
-      ::SetThreadPriority(handle.handle_, THREAD_PRIORITY_TIME_CRITICAL);
+    case ThreadPriority::NORMAL:
+      desired_priority = THREAD_PRIORITY_NORMAL;
+      break;
+    case ThreadPriority::DISPLAY:
+      desired_priority = THREAD_PRIORITY_ABOVE_NORMAL;
+      break;
+    case ThreadPriority::REALTIME_AUDIO:
+      desired_priority = THREAD_PRIORITY_TIME_CRITICAL;
       break;
     default:
       NOTREACHED() << "Unknown priority.";
       break;
   }
+  DCHECK_NE(desired_priority, THREAD_PRIORITY_ERROR_RETURN);
+
+#ifndef NDEBUG
+  const BOOL success =
+#endif
+      ::SetThreadPriority(handle.handle_, desired_priority);
+  DPLOG_IF(ERROR, !success) << "Failed to set thread priority to "
+                            << desired_priority;
+}
+
+// static
+ThreadPriority PlatformThread::GetThreadPriority(PlatformThreadHandle handle) {
+  DCHECK(!handle.is_null());
+
+  int priority = ::GetThreadPriority(handle.handle_);
+  switch (priority) {
+    case THREAD_PRIORITY_LOWEST:
+      return ThreadPriority::BACKGROUND;
+    case THREAD_PRIORITY_NORMAL:
+      return ThreadPriority::NORMAL;
+    case THREAD_PRIORITY_ABOVE_NORMAL:
+      return ThreadPriority::DISPLAY;
+    case THREAD_PRIORITY_TIME_CRITICAL:
+      return ThreadPriority::REALTIME_AUDIO;
+    case THREAD_PRIORITY_ERROR_RETURN:
+      DPCHECK(false) << "GetThreadPriority error";  // Falls through.
+    default:
+      NOTREACHED() << "Unexpected priority: " << priority;
+      return ThreadPriority::NORMAL;
+  }
 }
 
 }  // namespace base
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 52b178b..6f4a248 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -239,24 +239,41 @@
   // SimpleThread implementation. This actually runs the background thread.
   void Run() override;
 
+  // Indicates that a task is about to be run. The parameters provide
+  // additional metainformation about the task being run.
   void set_running_task_info(SequenceToken token,
                              WorkerShutdown shutdown_behavior) {
-    running_sequence_ = token;
-    running_shutdown_behavior_ = shutdown_behavior;
+    is_processing_task_ = true;
+    task_sequence_token_ = token;
+    task_shutdown_behavior_ = shutdown_behavior;
   }
 
-  SequenceToken running_sequence() const {
-    return running_sequence_;
+  // Indicates that the task has finished running.
+  void reset_running_task_info() { is_processing_task_ = false; }
+
+  // Whether the worker is processing a task.
+  bool is_processing_task() { return is_processing_task_; }
+
+  SequenceToken task_sequence_token() const {
+    DCHECK(is_processing_task_);
+    return task_sequence_token_;
   }
 
-  WorkerShutdown running_shutdown_behavior() const {
-    return running_shutdown_behavior_;
+  WorkerShutdown task_shutdown_behavior() const {
+    DCHECK(is_processing_task_);
+    return task_shutdown_behavior_;
   }
 
  private:
   scoped_refptr<SequencedWorkerPool> worker_pool_;
-  SequenceToken running_sequence_;
-  WorkerShutdown running_shutdown_behavior_;
+  // The sequence token of the task being processed. Only valid when
+  // is_processing_task_ is true.
+  SequenceToken task_sequence_token_;
+  // The shutdown behavior of the task being processed. Only valid when
+  // is_processing_task_ is true.
+  WorkerShutdown task_shutdown_behavior_;
+  // Whether the Worker is processing a task.
+  bool is_processing_task_;
 
   DISALLOW_COPY_AND_ASSIGN(Worker);
 };
@@ -326,11 +343,6 @@
   // Called from within the lock, this returns the next sequence task number.
   int64 LockedGetNextSequenceTaskNumber();
 
-  // Called from within the lock, returns the shutdown behavior of the task
-  // running on the currently executing worker thread. If invoked from a thread
-  // that is not one of the workers, returns CONTINUE_ON_SHUTDOWN.
-  WorkerShutdown LockedCurrentThreadShutdownBehavior() const;
-
   // Gets new task. There are 3 cases depending on the return value:
   //
   // 1) If the return value is |GET_WORK_FOUND|, |task| is filled in and should
@@ -483,7 +495,8 @@
     const std::string& prefix)
     : SimpleThread(prefix + StringPrintf("Worker%d", thread_number)),
       worker_pool_(worker_pool),
-      running_shutdown_behavior_(CONTINUE_ON_SHUTDOWN) {
+      task_shutdown_behavior_(BLOCK_SHUTDOWN),
+      is_processing_task_(false) {
   Start();
 }
 
@@ -497,7 +510,7 @@
 
   // Store a pointer to the running sequence in thread local storage for
   // static function access.
-  g_lazy_tls_ptr.Get().Set(&running_sequence_);
+  g_lazy_tls_ptr.Get().Set(&task_sequence_token_);
 
   // Just jump back to the Inner object to run the thread, since it has all the
   // tracking information and queues. It might be more natural to implement
@@ -583,10 +596,19 @@
   {
     AutoLock lock(lock_);
     if (shutdown_called_) {
-      if (shutdown_behavior != BLOCK_SHUTDOWN ||
-          LockedCurrentThreadShutdownBehavior() == CONTINUE_ON_SHUTDOWN) {
+      // Don't allow a new task to be posted if it doesn't block shutdown.
+      if (shutdown_behavior != BLOCK_SHUTDOWN)
+        return false;
+
+      // If the current thread is running a task, and that task doesn't block
+      // shutdown, then it shouldn't be allowed to post any more tasks.
+      ThreadMap::const_iterator found =
+          threads_.find(PlatformThread::CurrentId());
+      if (found != threads_.end() && found->second->is_processing_task() &&
+          found->second->task_shutdown_behavior() != BLOCK_SHUTDOWN) {
         return false;
       }
+
       if (max_blocking_tasks_after_shutdown_ <= 0) {
         DLOG(WARNING) << "BLOCK_SHUTDOWN task disallowed";
         return false;
@@ -635,7 +657,8 @@
   ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
   if (found == threads_.end())
     return false;
-  return sequence_token.Equals(found->second->running_sequence());
+  return found->second->is_processing_task() &&
+         sequence_token.Equals(found->second->task_sequence_token());
 }
 
 // See https://code.google.com/p/chromium/issues/detail?id=168415
@@ -765,13 +788,12 @@
 
           // Make sure our task is erased outside the lock for the
           // same reason we do this with delete_these_oustide_lock.
-          // Also, do it before calling set_running_task_info() so
+          // Also, do it before calling reset_running_task_info() so
           // that sequence-checking from within the task's destructor
           // still works.
           task.task = Closure();
 
-          this_worker->set_running_task_info(
-              SequenceToken(), CONTINUE_ON_SHUTDOWN);
+          this_worker->reset_running_task_info();
         }
         DidRunWorkerTask(task);  // Must be done inside the lock.
       } else if (cleanup_state_ == CLEANUP_RUNNING) {
@@ -904,15 +926,6 @@
   return next_sequence_task_number_++;
 }
 
-SequencedWorkerPool::WorkerShutdown
-SequencedWorkerPool::Inner::LockedCurrentThreadShutdownBehavior() const {
-  lock_.AssertAcquired();
-  ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
-  if (found == threads_.end())
-    return CONTINUE_ON_SHUTDOWN;
-  return found->second->running_shutdown_behavior();
-}
-
 SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
     SequencedTask* task,
     TimeDelta* wait_time,
diff --git a/base/threading/sequenced_worker_pool.h b/base/threading/sequenced_worker_pool.h
index 63c6204..0b6c5f9 100644
--- a/base/threading/sequenced_worker_pool.h
+++ b/base/threading/sequenced_worker_pool.h
@@ -320,12 +320,10 @@
   // Must be called from the same thread this object was constructed on.
   void Shutdown() { Shutdown(0); }
 
-  // A variant that allows an arbitrary number of new blocking tasks to
-  // be posted during shutdown from within tasks that execute during shutdown.
-  // Only tasks designated as BLOCKING_SHUTDOWN will be allowed, and only if
-  // posted by tasks that are not designated as CONTINUE_ON_SHUTDOWN. Once
+  // A variant that allows an arbitrary number of new blocking tasks to be
+  // posted during shutdown. The tasks cannot be posted within the execution
+  // context of tasks whose shutdown behavior is not BLOCKING_SHUTDOWN. Once
   // the limit is reached, subsequent calls to post task fail in all cases.
-  //
   // Must be called from the same thread this object was constructed on.
   void Shutdown(int max_new_blocking_tasks_after_shutdown);
 
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc
index 5d0880c..c12156e 100644
--- a/base/threading/sequenced_worker_pool_unittest.cc
+++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -159,6 +159,16 @@
         FROM_HERE, reposting_task, SequencedWorkerPool::BLOCK_SHUTDOWN);
   }
 
+  void PostBlockingTaskThenUnblockThreads(
+      const scoped_refptr<SequencedWorkerPool>& pool,
+      ThreadBlocker* blocker,
+      size_t threads_to_wake) {
+    Closure arbitrary_task = base::Bind(&TestTracker::FastTask, this, 0);
+    pool->PostWorkerTaskWithShutdownBehavior(
+        FROM_HERE, arbitrary_task, SequencedWorkerPool::BLOCK_SHUTDOWN);
+    blocker->Unblock(threads_to_wake);
+  }
+
   // Waits until the given number of tasks have started executing.
   void WaitUntilTasksBlocked(size_t count) {
     {
@@ -287,7 +297,7 @@
 
 // Checks that the given number of entries are in the tasks to complete of
 // the given tracker, and then signals the given event the given number of
-// times. This is used to wakt up blocked background threads before blocking
+// times. This is used to wake up blocked background threads before blocking
 // on shutdown.
 void EnsureTasksToCompleteCountAndUnblock(scoped_refptr<TestTracker> tracker,
                                           size_t expected_tasks_to_complete,
@@ -583,6 +593,34 @@
   tracker()->ClearCompleteSequence();
 }
 
+// Tests that blocking tasks can still be posted during shutdown, as long as
+// the task is not being posted within the context of a running task.
+TEST_F(SequencedWorkerPoolTest,
+       AllowsBlockingTasksDuringShutdownOutsideOfRunningTask) {
+  EnsureAllWorkersCreated();
+  ThreadBlocker blocker;
+
+  // Start tasks to take all the threads and block them.
+  const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads);
+  for (int i = 0; i < kNumBlockTasks; ++i) {
+    EXPECT_TRUE(pool()->PostWorkerTask(
+        FROM_HERE,
+        base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker)));
+  }
+  tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
+
+  // Setup to open the floodgates from within Shutdown().
+  SetWillWaitForShutdownCallback(
+      base::Bind(&TestTracker::PostBlockingTaskThenUnblockThreads,
+                 scoped_refptr<TestTracker>(tracker()), pool(), &blocker,
+                 kNumWorkerThreads));
+  pool()->Shutdown(kNumWorkerThreads + 1);
+
+  // Ensure that the correct number of tasks actually got run.
+  tracker()->WaitUntilTasksComplete(static_cast<size_t>(kNumWorkerThreads + 1));
+  tracker()->ClearCompleteSequence();
+}
+
 // Tests that unrun tasks are discarded properly according to their shutdown
 // mode.
 TEST_F(SequencedWorkerPoolTest, DiscardOnShutdown) {
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index ea5b174..d42ba4d 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -95,11 +95,6 @@
 }
 
 bool Thread::StartWithOptions(const Options& options) {
-  // TODO(eroman): Remove once crbug.com/465458 is solved.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-        "465458 base::Thread::StartWithOptions"));
-
   DCHECK(!message_loop_);
 #if defined(OS_WIN)
   DCHECK((com_status_ != STA) ||
@@ -117,7 +112,7 @@
     return false;
   }
 
-  // TODO(eroman): Remove once crbug.com/465458 is solved.
+  // TODO(kinuko): Remove once crbug.com/465458 is solved.
   tracked_objects::ScopedTracker tracking_profile_wait(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
           "465458 base::Thread::StartWithOptions (Wait)"));
diff --git a/base/threading/thread_local_storage_unittest.cc b/base/threading/thread_local_storage_unittest.cc
index b53f577..bcc1d1b 100644
--- a/base/threading/thread_local_storage_unittest.cc
+++ b/base/threading/thread_local_storage_unittest.cc
@@ -79,17 +79,16 @@
   EXPECT_EQ(value, 123);
 }
 
-#if defined(THREAD_SANITIZER) ||                    \
-    (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && \
-     defined(INCREMENTAL_LINKING))
+#if defined(THREAD_SANITIZER) || \
+    (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && !defined(NDEBUG))
 // Do not run the test under ThreadSanitizer. Because this test iterates its
 // own TSD destructor for the maximum possible number of times, TSan can't jump
 // in after the last destructor invocation, therefore the destructor remains
 // unsynchronized with the following users of the same TSD slot. This results
 // in race reports between the destructor and functions in other tests.
 //
-// It is disabled on Win x64 with incremental linking pending resolution of
-// http://crbug.com/251251.
+// It is disabled on Win x64 with incremental linking (i.e. "Debug") pending
+// resolution of http://crbug.com/251251.
 #define MAYBE_TLSDestructors DISABLED_TLSDestructors
 #else
 #define MAYBE_TLSDestructors TLSDestructors
diff --git a/base/threading/thread_local_unittest.cc b/base/threading/thread_local_unittest.cc
index 8dc7cd2..e94c1db 100644
--- a/base/threading/thread_local_unittest.cc
+++ b/base/threading/thread_local_unittest.cc
@@ -14,7 +14,7 @@
 
 class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate {
  public:
-  typedef base::ThreadLocalPointer<ThreadLocalTesterBase> TLPType;
+  typedef base::ThreadLocalPointer<char> TLPType;
 
   ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done)
       : tlp_(tlp),
@@ -35,7 +35,7 @@
   }
   ~SetThreadLocal() override {}
 
-  void set_value(ThreadLocalTesterBase* val) { val_ = val; }
+  void set_value(char* val) { val_ = val; }
 
   void Run() override {
     DCHECK(!done_->IsSignaled());
@@ -44,7 +44,7 @@
   }
 
  private:
-  ThreadLocalTesterBase* val_;
+  char* val_;
 };
 
 class GetThreadLocal : public ThreadLocalTesterBase {
@@ -55,7 +55,7 @@
   }
   ~GetThreadLocal() override {}
 
-  void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; }
+  void set_ptr(char** ptr) { ptr_ = ptr; }
 
   void Run() override {
     DCHECK(!done_->IsSignaled());
@@ -64,7 +64,7 @@
   }
 
  private:
-  ThreadLocalTesterBase** ptr_;
+  char** ptr_;
 };
 
 }  // namespace
@@ -77,12 +77,11 @@
   tp1.Start();
   tp2.Start();
 
-  base::ThreadLocalPointer<ThreadLocalTesterBase> tlp;
+  base::ThreadLocalPointer<char> tlp;
 
-  static ThreadLocalTesterBase* const kBogusPointer =
-      reinterpret_cast<ThreadLocalTesterBase*>(0x1234);
+  static char* const kBogusPointer = reinterpret_cast<char*>(0x1234);
 
-  ThreadLocalTesterBase* tls_val;
+  char* tls_val;
   base::WaitableEvent done(true, false);
 
   GetThreadLocal getter(&tlp, &done);
@@ -93,13 +92,13 @@
   done.Reset();
   tp1.AddWork(&getter);
   done.Wait();
-  EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
+  EXPECT_EQ(static_cast<char*>(NULL), tls_val);
 
   tls_val = kBogusPointer;
   done.Reset();
   tp2.AddWork(&getter);
   done.Wait();
-  EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
+  EXPECT_EQ(static_cast<char*>(NULL), tls_val);
 
 
   SetThreadLocal setter(&tlp, &done);
@@ -121,7 +120,7 @@
   done.Reset();
   tp2.AddWork(&getter);
   done.Wait();
-  EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
+  EXPECT_EQ(static_cast<char*>(NULL), tls_val);
 
   // Set thread 2 to kBogusPointer + 1.
   setter.set_value(kBogusPointer + 1);
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc
index b94f942..a08cc5b 100644
--- a/base/threading/thread_perftest.cc
+++ b/base/threading/thread_perftest.cc
@@ -174,12 +174,12 @@
 template <typename WaitableEventType>
 class EventPerfTest : public ThreadPerfTest {
  public:
-  virtual void Init() override {
+  void Init() override {
     for (size_t i = 0; i < threads_.size(); i++)
       events_.push_back(new WaitableEventType(false, false));
   }
 
-  virtual void Reset() override { events_.clear(); }
+  void Reset() override { events_.clear(); }
 
   void WaitAndSignalOnThread(size_t event) {
     size_t next_event = (event + 1) % events_.size();
@@ -195,7 +195,7 @@
       FinishMeasurement();
   }
 
-  virtual void PingPong(int hops) override {
+  void PingPong(int hops) override {
     remaining_hops_ = hops;
     for (size_t i = 0; i < threads_.size(); i++) {
       threads_[i]->message_loop_proxy()->PostTask(
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 75d8925..54f50eb 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -42,6 +42,7 @@
 class NestedMessagePumpAndroid;
 class RenderWidgetResizeHelper;
 class ScopedAllowWaitForAndroidLayoutTests;
+class ScopedAllowWaitForDebugURL;
 class TextInputClientMac;
 }  // namespace content
 namespace dbus {
@@ -175,6 +176,7 @@
   friend class content::NestedMessagePumpAndroid;
   friend class content::RenderWidgetResizeHelper;
   friend class content::ScopedAllowWaitForAndroidLayoutTests;
+  friend class content::ScopedAllowWaitForDebugURL;
   friend class ::HistogramSynchronizer;
   friend class ::ScopedAllowWaitForLegacyWebViewApi;
   friend class cc::CompletionEvent;
diff --git a/base/time/time.cc b/base/time/time.cc
index 321323b..bf6c998 100644
--- a/base/time/time.cc
+++ b/base/time/time.cc
@@ -4,12 +4,12 @@
 
 #include "base/time/time.h"
 
+#include <cmath>
 #include <ios>
 #include <limits>
 #include <ostream>
 #include <sstream>
 
-#include "base/float_util.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
@@ -161,7 +161,7 @@
 
 // static
 Time Time::FromDoubleT(double dt) {
-  if (dt == 0 || IsNaN(dt))
+  if (dt == 0 || std::isnan(dt))
     return Time();  // Preserve 0 so we can tell it doesn't exist.
   if (dt == std::numeric_limits<double>::infinity())
     return Max();
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn
index 479a918..4f3819d 100644
--- a/base/trace_event/BUILD.gn
+++ b/base/trace_event/BUILD.gn
@@ -4,13 +4,19 @@
 
 source_set("trace_event") {
   sources = [
-    "memory_allocator_attributes.h",
+    "java_heap_dump_provider_android.cc",
+    "java_heap_dump_provider_android.h",
+    "memory_allocator_attributes_type_info.cc",
+    "memory_allocator_attributes_type_info.h",
     "memory_allocator_dump.cc",
     "memory_allocator_dump.h",
     "memory_dump_manager.cc",
     "memory_dump_manager.h",
     "memory_dump_provider.cc",
     "memory_dump_provider.h",
+    "memory_dump_request_args.h",
+    "memory_dump_session_state.cc",
+    "memory_dump_session_state.h",
     "process_memory_dump.cc",
     "process_memory_dump.h",
     "process_memory_maps.cc",
@@ -25,6 +31,8 @@
     "trace_event_android.cc",
     "trace_event_argument.cc",
     "trace_event_argument.h",
+    "trace_event_etw_export_win.cc",
+    "trace_event_etw_export_win.h",
     "trace_event_impl.cc",
     "trace_event_impl.h",
     "trace_event_impl_constants.cc",
@@ -36,6 +44,8 @@
     "trace_event_system_stats_monitor.h",
     "trace_event_win.cc",
     "trace_event_win.h",
+    "winheap_dump_provider_win.cc",
+    "winheap_dump_provider_win.h",
   ]
 
   if (is_nacl) {
@@ -45,6 +55,13 @@
     ]
   }
 
+  if (is_linux || is_android) {
+    sources += [
+      "malloc_dump_provider.cc",
+      "malloc_dump_provider.h",
+    ]
+  }
+
   configs += [ "//base:base_implementation" ]
 
   deps = [
@@ -55,6 +72,10 @@
     "//base/third_party/dynamic_annotations",
   ]
 
+  if (is_win) {
+    deps += [ "//base/trace_event/etw_manifest:chrome_events_win" ]
+  }
+
   allow_circular_includes_from = [
     "//base/debug",
     "//base/memory",
@@ -67,6 +88,7 @@
 source_set("trace_event_unittests") {
   testonly = true
   sources = [
+    "memory_allocator_attributes_type_info_unittest.cc",
     "memory_allocator_dump_unittest.cc",
     "memory_dump_manager_unittest.cc",
     "process_memory_maps_dump_provider_unittest.cc",
@@ -77,6 +99,7 @@
     "trace_event_system_stats_monitor_unittest.cc",
     "trace_event_unittest.cc",
     "trace_event_win_unittest.cc",
+    "winheap_dump_provider_win_unittest.cc",
   ]
 
   deps = [
diff --git a/base/trace_event/OWNERS b/base/trace_event/OWNERS
index 3932776..aa1d675 100644
--- a/base/trace_event/OWNERS
+++ b/base/trace_event/OWNERS
@@ -1,3 +1,4 @@
 nduca@chromium.org
 dsinclair@chromium.org
+primiano@chromium.org
 per-file trace_event_android.cc=wangxianzhu@chromium.org
diff --git a/base/trace_event/etw_manifest/BUILD.gn b/base/trace_event/etw_manifest/BUILD.gn
new file mode 100644
index 0000000..07cf80e
--- /dev/null
+++ b/base/trace_event/etw_manifest/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(is_win, "This only runs on Windows.")
+
+# Makes the .h/.rc files from the .man file.
+action("chrome_events_win") {
+  visibility = [
+    "//base/trace_event/*",
+    "//chrome:main_dll",
+  ]
+  script = "build/message_compiler.py"
+
+  sources = [
+    "chrome_events_win.man",
+  ]
+
+  outputs = [
+    "$target_gen_dir/chrome_events_win.h",
+    "$target_gen_dir/chrome_events_win.rc",
+  ]
+
+  args = [
+    # Where to put the header.
+    "-h",
+    rebase_path("$target_gen_dir", root_build_dir),
+
+    # Where to put the .rc file.
+    "-r",
+    rebase_path("$target_gen_dir", root_build_dir),
+
+    # Generate the user-mode code.
+    "-um",
+    rebase_path("chrome_events_win.man", root_build_dir),
+  ]
+}
diff --git a/base/trace_event/etw_manifest/BUILD/message_compiler.py b/base/trace_event/etw_manifest/BUILD/message_compiler.py
new file mode 100644
index 0000000..be5927d
--- /dev/null
+++ b/base/trace_event/etw_manifest/BUILD/message_compiler.py
@@ -0,0 +1,16 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Runs the Microsoft Message Compiler (mc.exe). This Python adapter is for the
+# GN build, which can only run Python and not native binaries.
+
+import subprocess
+import sys
+
+# mc writes to stderr, so this explicily redirects to stdout and eats it.
+try:
+  subprocess.check_output(["mc.exe"] + sys.argv[1:], stderr=subprocess.STDOUT)
+except subprocess.CalledProcessError as e:
+  print e.output
+  sys.exit(e.returncode)
diff --git a/base/trace_event/etw_manifest/chrome_events_win.man b/base/trace_event/etw_manifest/chrome_events_win.man
new file mode 100644
index 0000000..10a8ddf
--- /dev/null
+++ b/base/trace_event/etw_manifest/chrome_events_win.man
@@ -0,0 +1,84 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes'?>
+<instrumentationManifest
+    xmlns="http://schemas.microsoft.com/win/2004/08/events"
+    xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd"
+    >
+  <instrumentation>
+    <events>
+      <provider
+          guid="{D2D578D9-2936-45B6-A09f-30E32715F42D}"
+          messageFileName="chrome.dll"
+          name="Chrome"
+          resourceFileName="chrome.dll"
+          symbol="CHROME"
+          >
+        <channels>
+          <importChannel
+              chid="SYSTEM"
+              name="System"
+              />
+        </channels>
+        <templates>
+          <template tid="tid_chrome_event">
+            <data
+                inType="win:AnsiString"
+                name="Name"
+                />
+            <data
+                inType="win:AnsiString"
+                name="Phase"
+                />
+            <data
+                inType="win:AnsiString"
+                name="Arg Name 1"
+                />
+            <data
+                inType="win:AnsiString"
+                name="Arg Value 1"
+                />
+            <data
+                inType="win:AnsiString"
+                name="Arg Name 2"
+                />
+            <data
+                inType="win:AnsiString"
+                name="Arg Value 2"
+                />
+            <data
+                inType="win:AnsiString"
+                name="Arg Name 3"
+                />
+            <data
+                inType="win:AnsiString"
+                name="Arg Value 3"
+                />
+          </template>
+        </templates>
+        <events>
+          <event
+              channel="SYSTEM"
+              level="win:Informational"
+              message="$(string.ChromeEvent.EventMessage)"
+              opcode="win:Info"
+              symbol="ChromeEvent"
+              template="tid_chrome_event"
+              value="1"
+              />
+        </events>
+      </provider>
+    </events>
+  </instrumentation>
+  <localization xmlns="http://schemas.microsoft.com/win/2004/08/events">
+    <resources culture="en-US">
+      <stringTable>
+        <string
+            id="ChromeEvent.EventMessage"
+            value="Chrome Event: %1 (%2)"
+            />
+      </stringTable>
+    </resources>
+  </localization>
+</instrumentationManifest>
diff --git a/base/trace_event/etw_manifest/etw_manifest.gyp b/base/trace_event/etw_manifest/etw_manifest.gyp
new file mode 100644
index 0000000..b0a8712
--- /dev/null
+++ b/base/trace_event/etw_manifest/etw_manifest.gyp
@@ -0,0 +1,39 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'targets': [
+    {
+      # GN version: //base/trace_event/etw_manifest/BUILD.gn
+      'target_name': 'etw_manifest',
+      'type': 'static_library',
+      'conditions': [
+        ['OS=="win"', {
+          'sources': [
+            'chrome_events_win.man',
+          ],
+          'variables': {
+            'man_output_dir': '<(SHARED_INTERMEDIATE_DIR)/base/trace_event/etw_manifest',
+          },
+          'rules': [{
+            # Rule to run the message compiler.
+            'rule_name': 'message_compiler',
+            'extension': 'man',
+            'outputs': [
+              '<(man_output_dir)/chrome_events_win.h',
+              '<(man_output_dir)/chrome_events_win.rc',
+            ],
+            'action': [
+              'mc.exe',
+              '-h', '<(man_output_dir)',
+              '-r', '<(man_output_dir)/.',
+              '-um',
+              '<(RULE_INPUT_PATH)',
+            ],
+            'message': 'Running message compiler on <(RULE_INPUT_PATH)',
+          }],
+        }],
+      ],
+    }
+  ]
+}
diff --git a/base/trace_event/java_heap_dump_provider_android.cc b/base/trace_event/java_heap_dump_provider_android.cc
new file mode 100644
index 0000000..aa193ab
--- /dev/null
+++ b/base/trace_event/java_heap_dump_provider_android.cc
@@ -0,0 +1,53 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/java_heap_dump_provider_android.h"
+
+#include "base/android/java_runtime.h"
+#include "base/trace_event/process_memory_dump.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+
+const char kDumperFriendlyName[] = "JavaHeap";
+const char kDumperName[] = "java_heap";
+
+}  // namespace
+
+// static
+JavaHeapDumpProvider* JavaHeapDumpProvider::GetInstance() {
+  return Singleton<JavaHeapDumpProvider,
+                   LeakySingletonTraits<JavaHeapDumpProvider>>::get();
+}
+
+JavaHeapDumpProvider::JavaHeapDumpProvider() {
+}
+
+JavaHeapDumpProvider::~JavaHeapDumpProvider() {
+}
+
+// Called at trace dump point time. Creates a snapshot with the memory counters
+// for the current process.
+bool JavaHeapDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+  MemoryAllocatorDump* dump =
+      pmd->CreateAllocatorDump(kDumperName, MemoryAllocatorDump::kRootHeap);
+
+  // These numbers come from java.lang.Runtime stats.
+  long total_heap_size = 0;
+  long free_heap_size = 0;
+  android::JavaRuntime::GetMemoryUsage(&total_heap_size, &free_heap_size);
+  dump->set_physical_size_in_bytes(total_heap_size);
+  dump->set_allocated_objects_count(0);
+  dump->set_allocated_objects_size_in_bytes(total_heap_size - free_heap_size);
+  return true;
+}
+
+const char* JavaHeapDumpProvider::GetFriendlyName() const {
+  return kDumperFriendlyName;
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/trace_event/java_heap_dump_provider_android.h b/base/trace_event/java_heap_dump_provider_android.h
new file mode 100644
index 0000000..8280751
--- /dev/null
+++ b/base/trace_event/java_heap_dump_provider_android.h
@@ -0,0 +1,35 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
+#define BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
+
+#include "base/memory/singleton.h"
+#include "base/trace_event/memory_dump_provider.h"
+
+namespace base {
+namespace trace_event {
+
+// Dump provider which collects process-wide memory stats.
+class JavaHeapDumpProvider : public MemoryDumpProvider {
+ public:
+  static JavaHeapDumpProvider* GetInstance();
+
+  // MemoryDumpProvider implementation.
+  bool DumpInto(ProcessMemoryDump* pmd) override;
+  const char* GetFriendlyName() const override;
+
+ private:
+  friend struct DefaultSingletonTraits<JavaHeapDumpProvider>;
+
+  JavaHeapDumpProvider();
+  ~JavaHeapDumpProvider() override;
+
+  DISALLOW_COPY_AND_ASSIGN(JavaHeapDumpProvider);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
diff --git a/base/trace_event/malloc_dump_provider.cc b/base/trace_event/malloc_dump_provider.cc
new file mode 100644
index 0000000..7d9931c
--- /dev/null
+++ b/base/trace_event/malloc_dump_provider.cc
@@ -0,0 +1,64 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/malloc_dump_provider.h"
+
+#include <malloc.h>
+
+#include "base/trace_event/process_memory_dump.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+
+const char kDumperFriendlyName[] = "Malloc";
+
+}  // namespace
+
+// static
+MallocDumpProvider* MallocDumpProvider::GetInstance() {
+  return Singleton<MallocDumpProvider,
+                   LeakySingletonTraits<MallocDumpProvider>>::get();
+}
+
+MallocDumpProvider::MallocDumpProvider() {
+}
+
+MallocDumpProvider::~MallocDumpProvider() {
+}
+
+// Called at trace dump point time. Creates a snapshot the memory counters for
+// the current process.
+bool MallocDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+  struct mallinfo info = mallinfo();
+  DCHECK_GE(info.arena + info.hblkhd, info.uordblks);
+
+  MemoryAllocatorDump* dump =
+      pmd->CreateAllocatorDump("malloc", MemoryAllocatorDump::kRootHeap);
+  if (!dump)
+    return false;
+
+  // When the system allocator is implemented by tcmalloc, the total physical
+  // size is given by |arena| and |hblkhd| is 0. In case of Android's jemalloc
+  // |arena| is 0 and the outer pages size is reported by |hblkhd|. In case of
+  // dlmalloc the total is given by |arena| + |hblkhd|.
+  // For more details see link: http://goo.gl/fMR8lF.
+  dump->set_physical_size_in_bytes(info.arena + info.hblkhd);
+
+  // mallinfo doesn't support any allocated object count.
+  dump->set_allocated_objects_count(0);
+
+  // Total allocated space is given by |uordblks|.
+  dump->set_allocated_objects_size_in_bytes(info.uordblks);
+
+  return true;
+}
+
+const char* MallocDumpProvider::GetFriendlyName() const {
+  return kDumperFriendlyName;
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/trace_event/malloc_dump_provider.h b/base/trace_event/malloc_dump_provider.h
new file mode 100644
index 0000000..b6f6973
--- /dev/null
+++ b/base/trace_event/malloc_dump_provider.h
@@ -0,0 +1,37 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
+#define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
+
+#include <istream>
+
+#include "base/memory/singleton.h"
+#include "base/trace_event/memory_dump_provider.h"
+
+namespace base {
+namespace trace_event {
+
+// Dump provider which collects process-wide memory stats.
+class BASE_EXPORT MallocDumpProvider : public MemoryDumpProvider {
+ public:
+  static MallocDumpProvider* GetInstance();
+
+  // MemoryDumpProvider implementation.
+  bool DumpInto(ProcessMemoryDump* pmd) override;
+  const char* GetFriendlyName() const override;
+
+ private:
+  friend struct DefaultSingletonTraits<MallocDumpProvider>;
+
+  MallocDumpProvider();
+  ~MallocDumpProvider() override;
+
+  DISALLOW_COPY_AND_ASSIGN(MallocDumpProvider);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
diff --git a/base/trace_event/memory_allocator_attributes.h b/base/trace_event/memory_allocator_attributes.h
deleted file mode 100644
index efae9de..0000000
--- a/base/trace_event/memory_allocator_attributes.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_
-#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/containers/hash_tables.h"
-
-namespace base {
-namespace trace_event {
-
-struct BASE_EXPORT MemoryAllocatorDeclaredAttribute {
-  std::string name;
-
-  // Refer to src/tools/perf/unit-info.json for the semantic of the type.
-  std::string type;
-};
-
-using MemoryAllocatorDeclaredAttributes =
-    hash_map<std::string, MemoryAllocatorDeclaredAttribute>;
-
-}  // namespace trace_event
-}  // namespace base
-
-#endif  // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_
diff --git a/base/trace_event/memory_allocator_attributes_type_info.cc b/base/trace_event/memory_allocator_attributes_type_info.cc
new file mode 100644
index 0000000..7d1e61c
--- /dev/null
+++ b/base/trace_event/memory_allocator_attributes_type_info.cc
@@ -0,0 +1,61 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+base::LazyInstance<const std::string> kNotFound = LAZY_INSTANCE_INITIALIZER;
+
+std::string GetKey(const std::string& allocator_name,
+                   const std::string& attribute_name) {
+  return allocator_name + "/" + attribute_name;
+}
+}  // namespace
+
+MemoryAllocatorAttributesTypeInfo::MemoryAllocatorAttributesTypeInfo() {
+}
+
+MemoryAllocatorAttributesTypeInfo::~MemoryAllocatorAttributesTypeInfo() {
+}
+
+const std::string& MemoryAllocatorAttributesTypeInfo::Get(
+    const std::string& allocator_name,
+    const std::string& attribute_name) const {
+  auto it = type_info_map_.find(GetKey(allocator_name, attribute_name));
+  if (it == type_info_map_.end())
+    return kNotFound.Get();
+  return it->second;
+}
+
+void MemoryAllocatorAttributesTypeInfo::Set(const std::string& allocator_name,
+                                            const std::string& attribute_name,
+                                            const std::string& attribute_type) {
+  std::string key = GetKey(allocator_name, attribute_name);
+  DCHECK_EQ(0u, type_info_map_.count(key));
+  type_info_map_[key] = attribute_type;
+}
+
+bool MemoryAllocatorAttributesTypeInfo::Exists(
+    const std::string& allocator_name,
+    const std::string& attribute_name) const {
+  return type_info_map_.count(GetKey(allocator_name, attribute_name)) == 1;
+}
+
+void MemoryAllocatorAttributesTypeInfo::Update(
+    const MemoryAllocatorAttributesTypeInfo& other) {
+  for (auto it = other.type_info_map_.begin();
+       it != other.type_info_map_.end(); ++it) {
+    bool no_duplicates = type_info_map_.insert(*it).second;
+    DCHECK(no_duplicates) << "Duplicated allocator attribute " << it->first;
+  }
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/trace_event/memory_allocator_attributes_type_info.h b/base/trace_event/memory_allocator_attributes_type_info.h
new file mode 100644
index 0000000..c3986ae
--- /dev/null
+++ b/base/trace_event/memory_allocator_attributes_type_info.h
@@ -0,0 +1,49 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_TYPE_INFO_H_
+#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_TYPE_INFO_H_
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/containers/hash_tables.h"
+
+namespace base {
+namespace trace_event {
+
+// A dictionary of "allocator_name/attribute_name" -> "attribute_type" which
+// supports merging and enforces duplicate checking.
+class BASE_EXPORT MemoryAllocatorAttributesTypeInfo {
+ public:
+  MemoryAllocatorAttributesTypeInfo();
+  ~MemoryAllocatorAttributesTypeInfo();
+
+  // Returns the attribute type, or an empty string if not found.
+  const std::string& Get(const std::string& allocator_name,
+                         const std::string& attribute_name) const;
+
+  // Refer to tools/perf/unit-info.json for the semantics of |attribute_type|.
+  void Set(const std::string& allocator_name,
+           const std::string& attribute_name,
+           const std::string& attribute_type);
+
+  // Checks whether a given {allocator_name, attribute_name} declaration exists.
+  bool Exists(const std::string& allocator_name,
+              const std::string& attribute_name) const;
+
+  // Merges the attribute types declared in |other| into this.
+  void Update(const MemoryAllocatorAttributesTypeInfo& other);
+
+ private:
+  // "allocator_name/attribute_name" -> attribute_type.
+  hash_map<std::string, std::string> type_info_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorAttributesTypeInfo);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_TYPE_INFO_H_
diff --git a/base/trace_event/memory_allocator_attributes_type_info_unittest.cc b/base/trace_event/memory_allocator_attributes_type_info_unittest.cc
new file mode 100644
index 0000000..5f69fae
--- /dev/null
+++ b/base/trace_event/memory_allocator_attributes_type_info_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace trace_event {
+
+TEST(MemoryAllocatorAttributesTypeInfoTest, BasicTest) {
+  MemoryAllocatorAttributesTypeInfo attrs;
+  EXPECT_EQ("", attrs.Get("non_existing_alloc", "non_existing_attr"));
+
+  attrs.Set("alloc", "attr", "type");
+  EXPECT_TRUE(attrs.Exists("alloc", "attr"));
+  EXPECT_FALSE(attrs.Exists("alloc", "foo"));
+  EXPECT_FALSE(attrs.Exists("foo", "attr"));
+  EXPECT_EQ("type", attrs.Get("alloc", "attr"));
+
+  attrs.Set("alloc2", "attr", "type2");
+  EXPECT_TRUE(attrs.Exists("alloc2", "attr"));
+  EXPECT_FALSE(attrs.Exists("alloc2", "foo"));
+  EXPECT_EQ("type", attrs.Get("alloc", "attr"));
+  EXPECT_EQ("type2", attrs.Get("alloc2", "attr"));
+
+  MemoryAllocatorAttributesTypeInfo other_attrs;
+  other_attrs.Set("other_alloc", "other_attr", "other_type");
+  other_attrs.Set("other_alloc", "attr", "other_type2");
+  other_attrs.Set("other_alloc_2", "other_attr", "other_type");
+  other_attrs.Set("other_alloc_2", "attr", "other_type3");
+
+  // Check the merging logic.
+  attrs.Update(other_attrs);
+  EXPECT_EQ("other_type", attrs.Get("other_alloc", "other_attr"));
+  EXPECT_EQ("other_type2", attrs.Get("other_alloc", "attr"));
+  EXPECT_EQ("other_type", attrs.Get("other_alloc_2", "other_attr"));
+  EXPECT_EQ("other_type3", attrs.Get("other_alloc_2", "attr"));
+  EXPECT_EQ("type", attrs.Get("alloc", "attr"));
+  EXPECT_EQ("type2", attrs.Get("alloc2", "attr"));
+  EXPECT_FALSE(other_attrs.Exists("alloc", "attr"));
+  EXPECT_FALSE(other_attrs.Exists("alloc2", "attr"));
+}
+
+// DEATH tests are not supported in Android / iOS.
+#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
+TEST(MemoryAllocatorAttributesTypeInfoTest, DuplicatesDeathTest) {
+  MemoryAllocatorAttributesTypeInfo attrs;
+  attrs.Set("alloc", "attr", "type");
+  MemoryAllocatorAttributesTypeInfo conflicting_attrs;
+  conflicting_attrs.Set("alloc", "attr", "type2");
+  ASSERT_DEATH(attrs.Set("alloc", "attr", "other_type"), "");
+  ASSERT_DEATH(attrs.Update(conflicting_attrs), "");
+}
+#endif
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc
index 604af7a..1d2fb3f 100644
--- a/base/trace_event/memory_allocator_dump.cc
+++ b/base/trace_event/memory_allocator_dump.cc
@@ -6,85 +6,122 @@
 
 #include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
-#include "base/trace_event/memory_allocator_attributes.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "base/values.h"
 
 namespace base {
 namespace trace_event {
 
-MemoryAllocatorDump::MemoryAllocatorDump(const std::string& name,
-                                         MemoryAllocatorDump* parent)
-    : name_(name),
-      parent_(parent),
+// static
+const char MemoryAllocatorDump::kRootHeap[] = "";
+
+// static
+std::string MemoryAllocatorDump::GetAbsoluteName(
+    const std::string& allocator_name,
+    const std::string& heap_name) {
+  return allocator_name + (heap_name == kRootHeap ? "" : "/" + heap_name);
+}
+
+MemoryAllocatorDump::MemoryAllocatorDump(const std::string& allocator_name,
+                                         const std::string& heap_name,
+                                         ProcessMemoryDump* process_memory_dump)
+    : allocator_name_(allocator_name),
+      heap_name_(heap_name),
+      process_memory_dump_(process_memory_dump),
       physical_size_in_bytes_(0),
       allocated_objects_count_(0),
       allocated_objects_size_in_bytes_(0) {
-  // Dots are not allowed in the name as the underlying base::DictionaryValue
+  // The allocator name cannot be empty or contain slash separators.
+  DCHECK(!allocator_name.empty());
+  DCHECK_EQ(std::string::npos, allocator_name.find_first_of('/'));
+
+  // The heap_name can be empty and contain slash separator, but not
+  // leading or trailing ones.
+  DCHECK(heap_name.empty() ||
+         (heap_name[0] != '/' && *heap_name.rbegin() != '/'));
+
+  // Dots are not allowed anywhere as the underlying base::DictionaryValue
   // would treat them magically and split in sub-nodes, which is not intended.
-  DCHECK_EQ(std::string::npos, name.find_first_of('.'));
+  DCHECK_EQ(std::string::npos, allocator_name.find_first_of('.'));
+  DCHECK_EQ(std::string::npos, heap_name.find_first_of('.'));
 }
 
 MemoryAllocatorDump::~MemoryAllocatorDump() {
 }
 
-void MemoryAllocatorDump::SetExtraAttribute(const std::string& name,
-                                            int value) {
-  extra_attributes_.SetInteger(name, value);
+void MemoryAllocatorDump::SetAttribute(const std::string& name, int value) {
+  DCHECK(GetAttributesTypeInfo().Exists(allocator_name_, name))
+      << "attribute '" << name << "' not declared."
+      << "See MemoryDumpProvider.DeclareAllocatorAttribute()";
+  attributes_values_.SetInteger(name, value);
 }
 
-int MemoryAllocatorDump::GetExtraIntegerAttribute(
-    const std::string& name) const {
-  bool res;
+std::string MemoryAllocatorDump::GetAbsoluteName() const {
+  return GetAbsoluteName(allocator_name_, heap_name_);
+}
+
+int MemoryAllocatorDump::GetIntegerAttribute(const std::string& name) const {
   int value = -1;
-  res = extra_attributes_.GetInteger(name, &value);
-  DCHECK(res) << "Allocator attribute '" << name << "' not found";
+  bool res = attributes_values_.GetInteger(name, &value);
+  DCHECK(res) << "Attribute '" << name << "' not found";
   return value;
 }
 
 void MemoryAllocatorDump::AsValueInto(TracedValue* value) const {
   static const char kHexFmt[] = "%" PRIx64;
 
-  value->BeginDictionary(name_.c_str());
+  value->BeginDictionary(GetAbsoluteName().c_str());
+  value->BeginDictionary("attrs");
 
-  value->SetString("parent", parent_ ? parent_->name_ : "");
-  value->SetString("physical_size_in_bytes",
-                   StringPrintf(kHexFmt, physical_size_in_bytes_));
-  value->SetString("allocated_objects_count",
-                   StringPrintf(kHexFmt, allocated_objects_count_));
-  value->SetString("allocated_objects_size_in_bytes",
+  // TODO(primiano): these hard-coded types are temporary to transition to the
+  // new generalized attribute format. This code will be refactored by the end
+  // of May 2015.
+  value->BeginDictionary("outer_size");
+  value->SetString("type", "scalar");
+  value->SetString("units", "bytes");
+  value->SetString("value", StringPrintf(kHexFmt, physical_size_in_bytes_));
+  value->EndDictionary();
+
+  value->BeginDictionary("inner_size");
+  value->SetString("type", "scalar");
+  value->SetString("units", "bytes");
+  value->SetString("value",
                    StringPrintf(kHexFmt, allocated_objects_size_in_bytes_));
+  value->EndDictionary();
+
+  value->BeginDictionary("objects_count");
+  value->SetString("type", "scalar");
+  value->SetString("units", "objects");
+  value->SetString("value", StringPrintf(kHexFmt, allocated_objects_count_));
+  value->EndDictionary();
 
   // Copy all the extra attributes.
-  const MemoryDumpProvider* mdp =
-      MemoryDumpManager::GetInstance()->dump_provider_currently_active();
-  const MemoryAllocatorDeclaredAttributes& extra_attributes_types =
-      mdp->allocator_attributes();
-
-  value->BeginDictionary("args");
-  for (DictionaryValue::Iterator it(extra_attributes_); !it.IsAtEnd();
+  for (DictionaryValue::Iterator it(attributes_values_); !it.IsAtEnd();
        it.Advance()) {
     const std::string& attr_name = it.key();
     const Value& attr_value = it.value();
     value->BeginDictionary(attr_name.c_str());
     value->SetValue("value", attr_value.DeepCopy());
 
-    auto attr_it = extra_attributes_types.find(attr_name);
-    DCHECK(attr_it != extra_attributes_types.end())
-        << "Allocator attribute " << attr_name
-        << " not declared for the dumper " << mdp->GetFriendlyName();
-
-    // TODO(primiano): the "type" should be dumped just once, not repeated on
-    // on every event. The ability of doing so depends on crbug.com/466121.
-    value->SetString("type", attr_it->second.type);
+    const std::string& attr_type =
+        GetAttributesTypeInfo().Get(allocator_name_, attr_name);
+    DCHECK(!attr_type.empty());
+    value->SetString("type", "scalar");
+    value->SetString("units", attr_type);
 
     value->EndDictionary();  // "arg_name": { "type": "...", "value": "..." }
   }
-  value->EndDictionary();  // "args": {}
 
-  value->EndDictionary();  // "allocator name": {}
+  value->EndDictionary();  // "attrs": { ... }
+  value->EndDictionary();  // "allocator_name/heap_subheap": { ... }
+}
+
+const MemoryAllocatorAttributesTypeInfo&
+MemoryAllocatorDump::GetAttributesTypeInfo() const {
+  return process_memory_dump_->session_state()->allocators_attributes_type_info;
 }
 
 }  // namespace trace_event
diff --git a/base/trace_event/memory_allocator_dump.h b/base/trace_event/memory_allocator_dump.h
index 4d7293e..1c786ab 100644
--- a/base/trace_event/memory_allocator_dump.h
+++ b/base/trace_event/memory_allocator_dump.h
@@ -8,34 +8,45 @@
 #include "base/base_export.h"
 #include "base/basictypes.h"
 #include "base/logging.h"
-#include "base/trace_event/memory_allocator_attributes.h"
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
 #include "base/values.h"
 
 namespace base {
 namespace trace_event {
 
 class MemoryDumpManager;
+class ProcessMemoryDump;
 class TracedValue;
 
 // Data model for user-land memory allocator dumps.
 class BASE_EXPORT MemoryAllocatorDump {
  public:
-  MemoryAllocatorDump(const std::string& name, MemoryAllocatorDump* parent);
+  // Returns the absolute name for a given (|allocator_name|,|heap_name|) tuple.
+  static std::string GetAbsoluteName(const std::string& allocator_name,
+                                     const std::string& heap_name);
+
+  // Use as argument for |heap_name| when the allocator has only one root heap.
+  static const char kRootHeap[];
+
+  // MemoryAllocatorDump is owned by ProcessMemoryDump.
+  MemoryAllocatorDump(const std::string& allocator_name,
+                      const std::string& heap_name,
+                      ProcessMemoryDump* process_memory_dump);
   ~MemoryAllocatorDump();
 
-  const std::string& name() const { return name_; }
-  const MemoryAllocatorDump* parent() const { return parent_; }
+  // Name of the allocator, a plain string with no separators (e.g, "malloc").
+  const std::string& allocator_name() const { return allocator_name_; }
 
-  void set_physical_size_in_bytes(uint64 value) {
-    physical_size_in_bytes_ = value;
-  }
-  uint64 physical_size_in_bytes() const { return physical_size_in_bytes_; }
+  // Name of the heap being dumped, either: "heap", "heap/subheap" or kRootHeap
+  // if the allocator has just one root heap.
+  const std::string& heap_name() const { return heap_name_; }
 
-  void set_allocated_objects_count(uint64 value) {
-    allocated_objects_count_ = value;
-  }
-  uint64 allocated_objects_count() const { return allocated_objects_count_; }
+  // Absolute name, unique within the scope of an entire ProcessMemoryDump.
+  // In practice this is "allocator_name/heap/subheap".
+  std::string GetAbsoluteName() const;
 
+  // Inner size: Bytes requested by clients of the allocator, without accounting
+  // for any metadata or allocator-specific bookeeping structs.
   void set_allocated_objects_size_in_bytes(uint64 value) {
     allocated_objects_size_in_bytes_ = value;
   }
@@ -43,19 +54,46 @@
     return allocated_objects_size_in_bytes_;
   }
 
-  void SetExtraAttribute(const std::string& name, int value);
-  int GetExtraIntegerAttribute(const std::string& name) const;
+  // Outer size: bytes requested to the system to handle all the allocations,
+  // including any allocator-internal metadata / bookeeping structs. For
+  // instance, in the case of an allocator which gets pages to the system via
+  // mmap() or similar, this is the number of requested pages * 4k.
+  void set_physical_size_in_bytes(uint64 value) {
+    physical_size_in_bytes_ = value;
+  }
+  uint64 physical_size_in_bytes() const { return physical_size_in_bytes_; }
+
+  // Number of objects allocated, if known, or 0 if not available.
+  void set_allocated_objects_count(uint64 value) {
+    allocated_objects_count_ = value;
+  }
+  uint64 allocated_objects_count() const { return allocated_objects_count_; }
+
+  // Get/Set extra attributes. The attributes name must have been previously
+  // declared through MemoryDumpProvider.DeclareAllocatorAttribute().
+  void SetAttribute(const std::string& name, int value);
+  int GetIntegerAttribute(const std::string& name) const;
 
   // Called at trace generation time to populate the TracedValue.
   void AsValueInto(TracedValue* value) const;
 
+  // Get the ProcessMemoryDump instance that owns this.
+  ProcessMemoryDump* process_memory_dump() const {
+    return process_memory_dump_;
+  }
+
+  // Retrieves the map of allocator attributes types, which is shared by all
+  // MemoryAllocatorDump(s) across all ProcessMemoryDump(s) per tracing session.
+  const MemoryAllocatorAttributesTypeInfo& GetAttributesTypeInfo() const;
+
  private:
-  const std::string name_;
-  MemoryAllocatorDump* const parent_;  // Not owned.
+  const std::string allocator_name_;
+  const std::string heap_name_;
+  ProcessMemoryDump* const process_memory_dump_;  // Not owned (PMD owns this).
   uint64 physical_size_in_bytes_;
   uint64 allocated_objects_count_;
   uint64 allocated_objects_size_in_bytes_;
-  DictionaryValue extra_attributes_;
+  DictionaryValue attributes_values_;
 
   DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorDump);
 };
diff --git a/base/trace_event/memory_allocator_dump_unittest.cc b/base/trace_event/memory_allocator_dump_unittest.cc
index 8c14560..110a25d 100644
--- a/base/trace_event/memory_allocator_dump_unittest.cc
+++ b/base/trace_event/memory_allocator_dump_unittest.cc
@@ -5,89 +5,110 @@
 #include "base/trace_event/memory_allocator_dump.h"
 
 #include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/memory_dump_session_state.h"
 #include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/trace_event_argument.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
 namespace trace_event {
 
 namespace {
+
 class FakeMemoryAllocatorDumpProvider : public MemoryDumpProvider {
  public:
   FakeMemoryAllocatorDumpProvider() {
-    DeclareAllocatorAttribute({"attr1", "count"});
-    DeclareAllocatorAttribute({"attr2", "bytes"});
+    DeclareAllocatorAttribute("foobar_allocator", "attr1", "count");
+    DeclareAllocatorAttribute("foobar_allocator", "attr2", "bytes");
   }
 
   bool DumpInto(ProcessMemoryDump* pmd) override {
-    MemoryAllocatorDump* mad_foo = pmd->CreateAllocatorDump("foo");
-    mad_foo->set_physical_size_in_bytes(4096);
-    mad_foo->set_allocated_objects_count(42);
-    mad_foo->set_allocated_objects_size_in_bytes(1000);
-    mad_foo->SetExtraAttribute("attr1", 1234);
-    mad_foo->SetExtraAttribute("attr2", 99);
+    MemoryAllocatorDump* root_heap = pmd->CreateAllocatorDump(
+        "foobar_allocator", MemoryAllocatorDump::kRootHeap);
+    root_heap->set_physical_size_in_bytes(4096);
+    root_heap->set_allocated_objects_count(42);
+    root_heap->set_allocated_objects_size_in_bytes(1000);
+    root_heap->SetAttribute("attr1", 1234);
+    root_heap->SetAttribute("attr2", 99);
 
-    MemoryAllocatorDump* mad_bar = pmd->CreateAllocatorDump("foo/bar", mad_foo);
-    mad_bar->set_physical_size_in_bytes(1);
-    mad_bar->set_allocated_objects_count(2);
-    mad_bar->set_allocated_objects_size_in_bytes(3);
+    MemoryAllocatorDump* sub_heap =
+        pmd->CreateAllocatorDump("foobar_allocator", "sub_heap");
+    sub_heap->set_physical_size_in_bytes(1);
+    sub_heap->set_allocated_objects_count(2);
+    sub_heap->set_allocated_objects_size_in_bytes(3);
 
-    pmd->CreateAllocatorDump("baz");
-    // Leave the rest of |baz| deliberately uninitialized, to check that
+    pmd->CreateAllocatorDump("foobar_allocator", "sub_heap/empty");
+    // Leave the rest of sub heap deliberately uninitialized, to check that
     // CreateAllocatorDump returns a properly zero-initialized object.
 
     return true;
   }
 
-  const char* GetFriendlyName() const override { return "mock_allocator"; }
+  const char* GetFriendlyName() const override { return "FooBar Allocator"; }
 };
 }  // namespace
 
 TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) {
   FakeMemoryAllocatorDumpProvider fmadp;
-  ProcessMemoryDump pmd;
+  ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
+  pmd.session_state()->allocators_attributes_type_info.Update(
+      fmadp.allocator_attributes_type_info());
 
   fmadp.DumpInto(&pmd);
 
   ASSERT_EQ(3u, pmd.allocator_dumps().size());
 
-  const MemoryAllocatorDump* mad_foo = pmd.GetAllocatorDump("foo");
-  ASSERT_NE(nullptr, mad_foo);
-  EXPECT_EQ("foo", mad_foo->name());
-  ASSERT_EQ(nullptr, mad_foo->parent());
-  EXPECT_EQ(4096u, mad_foo->physical_size_in_bytes());
-  EXPECT_EQ(42u, mad_foo->allocated_objects_count());
-  EXPECT_EQ(1000u, mad_foo->allocated_objects_size_in_bytes());
+  const MemoryAllocatorDump* root_heap =
+      pmd.GetAllocatorDump("foobar_allocator", MemoryAllocatorDump::kRootHeap);
+  ASSERT_NE(nullptr, root_heap);
+  EXPECT_EQ("foobar_allocator", root_heap->allocator_name());
+  EXPECT_EQ("", root_heap->heap_name());
+  EXPECT_NE("", root_heap->GetAbsoluteName());
+  EXPECT_EQ(4096u, root_heap->physical_size_in_bytes());
+  EXPECT_EQ(42u, root_heap->allocated_objects_count());
+  EXPECT_EQ(1000u, root_heap->allocated_objects_size_in_bytes());
 
-  // Check the extra attributes of |mad_foo|.
-  EXPECT_EQ(1234, mad_foo->GetExtraIntegerAttribute("attr1"));
-  EXPECT_EQ(99, mad_foo->GetExtraIntegerAttribute("attr2"));
+  // Check the extra attributes of |root_heap|.
+  EXPECT_EQ(1234, root_heap->GetIntegerAttribute("attr1"));
+  EXPECT_EQ(99, root_heap->GetIntegerAttribute("attr2"));
 
-  const MemoryAllocatorDump* mad_bar = pmd.GetAllocatorDump("foo/bar");
-  ASSERT_NE(nullptr, mad_bar);
-  EXPECT_EQ("foo/bar", mad_bar->name());
-  ASSERT_EQ(mad_foo, mad_bar->parent());
-  EXPECT_EQ(1u, mad_bar->physical_size_in_bytes());
-  EXPECT_EQ(2u, mad_bar->allocated_objects_count());
-  EXPECT_EQ(3u, mad_bar->allocated_objects_size_in_bytes());
+  const MemoryAllocatorDump* sub_heap =
+      pmd.GetAllocatorDump("foobar_allocator", "sub_heap");
+  ASSERT_NE(nullptr, sub_heap);
+  EXPECT_EQ("foobar_allocator", sub_heap->allocator_name());
+  EXPECT_EQ("sub_heap", sub_heap->heap_name());
+  EXPECT_NE("", sub_heap->GetAbsoluteName());
+  EXPECT_EQ(1u, sub_heap->physical_size_in_bytes());
+  EXPECT_EQ(2u, sub_heap->allocated_objects_count());
+  EXPECT_EQ(3u, sub_heap->allocated_objects_size_in_bytes());
 
-  const MemoryAllocatorDump* mad_baz = pmd.GetAllocatorDump("baz");
-  ASSERT_NE(nullptr, mad_baz);
-  EXPECT_EQ("baz", mad_baz->name());
-  ASSERT_EQ(nullptr, mad_baz->parent());
-  EXPECT_EQ(0u, mad_baz->physical_size_in_bytes());
-  EXPECT_EQ(0u, mad_baz->allocated_objects_count());
-  EXPECT_EQ(0u, mad_baz->allocated_objects_size_in_bytes());
+  const MemoryAllocatorDump* empty_sub_heap =
+      pmd.GetAllocatorDump("foobar_allocator", "sub_heap/empty");
+  ASSERT_NE(nullptr, empty_sub_heap);
+  EXPECT_EQ("foobar_allocator", empty_sub_heap->allocator_name());
+  EXPECT_EQ("sub_heap/empty", empty_sub_heap->heap_name());
+  EXPECT_NE("", sub_heap->GetAbsoluteName());
+  EXPECT_EQ(0u, empty_sub_heap->physical_size_in_bytes());
+  EXPECT_EQ(0u, empty_sub_heap->allocated_objects_count());
+  EXPECT_EQ(0u, empty_sub_heap->allocated_objects_size_in_bytes());
+
+  // Check that the AsValueInfo doesn't hit any DCHECK.
+  scoped_refptr<TracedValue> traced_value(new TracedValue());
+  pmd.AsValueInto(traced_value.get());
 }
 
 // DEATH tests are not supported in Android / iOS.
 #if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
 TEST(MemoryAllocatorDumpTest, ForbidDuplicatesDeathTest) {
   FakeMemoryAllocatorDumpProvider fmadp;
-  ProcessMemoryDump pmd;
-  pmd.CreateAllocatorDump("dump_1");
-  pmd.CreateAllocatorDump("dump_2");
-  ASSERT_DEATH(pmd.CreateAllocatorDump("dump_1"), "");
+  ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
+  pmd.CreateAllocatorDump("foo_allocator", MemoryAllocatorDump::kRootHeap);
+  pmd.CreateAllocatorDump("bar_allocator", "heap");
+  ASSERT_DEATH(
+      pmd.CreateAllocatorDump("foo_allocator", MemoryAllocatorDump::kRootHeap),
+      "");
+  ASSERT_DEATH(pmd.CreateAllocatorDump("bar_allocator", "heap"), "");
+  ASSERT_DEATH(pmd.CreateAllocatorDump("", "must_have_allocator_name"), "");
 }
 #endif
 
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 0ec5d19..859e8e0 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -9,41 +9,123 @@
 #include "base/atomic_sequence_num.h"
 #include "base/compiler_specific.h"
 #include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/memory_dump_session_state.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "base/trace_event/trace_event_argument.h"
 
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+#include "base/trace_event/malloc_dump_provider.h"
+#include "base/trace_event/process_memory_maps_dump_provider.h"
+#include "base/trace_event/process_memory_totals_dump_provider.h"
+#elif defined(OS_WIN)
+#include "base/trace_event/winheap_dump_provider_win.h"
+#endif
+
 namespace base {
 namespace trace_event {
 
 namespace {
 
+// TODO(primiano): this should be smarter and should do something similar to
+// trace event synthetic delays.
+const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra");
+
 MemoryDumpManager* g_instance_for_testing = nullptr;
+const int kDumpIntervalSeconds = 2;
 const int kTraceEventNumArgs = 1;
 const char* kTraceEventArgNames[] = {"dumps"};
 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
 StaticAtomicSequenceNumber g_next_guid;
 
-const char* DumpPointTypeToString(const DumpPointType& dump_point_type) {
-  switch (dump_point_type) {
-    case DumpPointType::TASK_BEGIN:
+const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) {
+  switch (dump_type) {
+    case MemoryDumpType::TASK_BEGIN:
       return "TASK_BEGIN";
-    case DumpPointType::TASK_END:
+    case MemoryDumpType::TASK_END:
       return "TASK_END";
-    case DumpPointType::PERIODIC_INTERVAL:
+    case MemoryDumpType::PERIODIC_INTERVAL:
       return "PERIODIC_INTERVAL";
-    case DumpPointType::EXPLICITLY_TRIGGERED:
+    case MemoryDumpType::EXPLICITLY_TRIGGERED:
       return "EXPLICITLY_TRIGGERED";
   }
   NOTREACHED();
   return "UNKNOWN";
 }
 
+// Internal class used to hold details about ProcessMemoryDump requests for the
+// current process.
+// TODO(primiano): In the upcoming CLs, ProcessMemoryDump will become async.
+// and this class will be used to convey more details across PostTask()s.
+class ProcessMemoryDumpHolder
+    : public RefCountedThreadSafe<ProcessMemoryDumpHolder> {
+ public:
+  ProcessMemoryDumpHolder(
+      MemoryDumpRequestArgs req_args,
+      const scoped_refptr<MemoryDumpSessionState>& session_state,
+      MemoryDumpCallback callback)
+      : process_memory_dump(session_state),
+        req_args(req_args),
+        callback(callback),
+        task_runner(MessageLoop::current()->task_runner()),
+        num_pending_async_requests(0) {}
+
+  ProcessMemoryDump process_memory_dump;
+  const MemoryDumpRequestArgs req_args;
+
+  // Callback passed to the initial call to CreateProcessDump().
+  MemoryDumpCallback callback;
+
+  // Thread on which FinalizeDumpAndAddToTrace() should be called, which is the
+  // same that invoked the initial CreateProcessDump().
+  const scoped_refptr<SingleThreadTaskRunner> task_runner;
+
+  // Number of pending ContinueAsyncProcessDump() calls.
+  int num_pending_async_requests;
+
+ private:
+  friend class RefCountedThreadSafe<ProcessMemoryDumpHolder>;
+  virtual ~ProcessMemoryDumpHolder() {}
+  DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpHolder);
+};
+
+void FinalizeDumpAndAddToTrace(
+    const scoped_refptr<ProcessMemoryDumpHolder>& pmd_holder) {
+  DCHECK_EQ(0, pmd_holder->num_pending_async_requests);
+
+  if (!pmd_holder->task_runner->BelongsToCurrentThread()) {
+    pmd_holder->task_runner->PostTask(
+        FROM_HERE, Bind(&FinalizeDumpAndAddToTrace, pmd_holder));
+    return;
+  }
+
+  scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
+  pmd_holder->process_memory_dump.AsValueInto(
+      static_cast<TracedValue*>(event_value.get()));
+  const char* const event_name =
+      MemoryDumpTypeToString(pmd_holder->req_args.dump_type);
+
+  TRACE_EVENT_API_ADD_TRACE_EVENT(
+      TRACE_EVENT_PHASE_MEMORY_DUMP,
+      TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name,
+      pmd_holder->req_args.dump_guid, kTraceEventNumArgs, kTraceEventArgNames,
+      kTraceEventArgTypes, nullptr /* arg_values */, &event_value,
+      TRACE_EVENT_FLAG_HAS_ID);
+
+  if (!pmd_holder->callback.is_null()) {
+    pmd_holder->callback.Run(pmd_holder->req_args.dump_guid, true);
+    pmd_holder->callback.Reset();
+  }
+}
+
+void RequestPeriodicGlobalDump() {
+  MemoryDumpManager::GetInstance()->RequestGlobalDump(
+      MemoryDumpType::PERIODIC_INTERVAL);
+}
+
 }  // namespace
 
-// TODO(primiano): this should be smarter and should do something similar to
-// trace event synthetic delays.
-const char MemoryDumpManager::kTraceCategory[] =
-    TRACE_DISABLED_BY_DEFAULT("memory-dumps");
+// static
+const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory;
 
 // static
 MemoryDumpManager* MemoryDumpManager::GetInstance() {
@@ -56,11 +138,17 @@
 
 // static
 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
+  if (instance)
+    instance->skip_core_dumpers_auto_registration_for_testing_ = true;
   g_instance_for_testing = instance;
 }
 
 MemoryDumpManager::MemoryDumpManager()
-    : dump_provider_currently_active_(nullptr), memory_tracing_enabled_(0) {
+    : dump_provider_currently_active_(nullptr),
+      delegate_(nullptr),
+      memory_tracing_enabled_(0),
+      skip_core_dumpers_auto_registration_for_testing_(false) {
+  g_next_guid.GetNext();  // Make sure that first guid is not zero.
 }
 
 MemoryDumpManager::~MemoryDumpManager() {
@@ -70,94 +158,176 @@
 void MemoryDumpManager::Initialize() {
   TRACE_EVENT0(kTraceCategory, "init");  // Add to trace-viewer category list.
   trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
+
+  if (skip_core_dumpers_auto_registration_for_testing_)
+    return;
+
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  // Enable the core dump providers.
+  RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
+  RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance());
+  RegisterDumpProvider(MallocDumpProvider::GetInstance());
+#elif defined(OS_WIN)
+  RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
+#endif
+}
+
+void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
+  AutoLock lock(lock_);
+  DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_);
+  delegate_ = delegate;
 }
 
 void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
   AutoLock lock(lock_);
-  if (std::find(dump_providers_registered_.begin(),
-                dump_providers_registered_.end(),
-                mdp) != dump_providers_registered_.end()) {
-    return;
-  }
-  dump_providers_registered_.push_back(mdp);
+  dump_providers_registered_.insert(mdp);
 }
 
 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
   AutoLock lock(lock_);
 
-  // Remove from the registered providers list.
-  auto it = std::find(dump_providers_registered_.begin(),
-                      dump_providers_registered_.end(), mdp);
-  if (it != dump_providers_registered_.end())
-    dump_providers_registered_.erase(it);
+  // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe
+  // only if the MDP has specified a thread affinity (via task_runner()) AND
+  // the unregistration happens on the same thread (so the MDP cannot unregister
+  // and DumpInto() at the same time).
+  // Otherwise, it is not possible to guarantee that its unregistration is
+  // race-free. If you hit this DCHECK, your MDP has a bug.
+  DCHECK_IMPLIES(
+      subtle::NoBarrier_Load(&memory_tracing_enabled_),
+      mdp->task_runner() && mdp->task_runner()->BelongsToCurrentThread())
+      << "The MemoryDumpProvider " << mdp->GetFriendlyName() << " attempted to "
+      << "unregister itself in a racy way. Please file a crbug.";
 
   // Remove from the enabled providers list. This is to deal with the case that
   // UnregisterDumpProvider is called while the trace is enabled.
-  it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(),
-                 mdp);
-  if (it != dump_providers_enabled_.end())
-    dump_providers_enabled_.erase(it);
+  dump_providers_enabled_.erase(mdp);
+  dump_providers_registered_.erase(mdp);
 }
 
-void MemoryDumpManager::RequestDumpPoint(DumpPointType dump_point_type) {
-  // TODO(primiano): this will have more logic to coordinate dump points across
-  // multiple processes via IPC. See crbug.com/462930.
-
+void MemoryDumpManager::RequestGlobalDump(
+    MemoryDumpType dump_type,
+    const MemoryDumpCallback& callback) {
   // Bail out immediately if tracing is not enabled at all.
   if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
     return;
 
-  // TODO(primiano): Make guid actually unique (cross-process) by hashing it
-  // with the PID. See crbug.com/462931 for details.
-  const uint64 guid = g_next_guid.GetNext();
-  CreateLocalDumpPoint(dump_point_type, guid);
-}
+  const uint64 guid =
+      TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());
 
-void MemoryDumpManager::BroadcastDumpRequest() {
-  NOTREACHED();  // TODO(primiano): implement IPC synchronization.
-}
-
-// Creates a dump point for the current process and appends it to the trace.
-void MemoryDumpManager::CreateLocalDumpPoint(DumpPointType dump_point_type,
-                                             uint64 guid) {
-  bool did_any_provider_dump = false;
-  scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump());
-
-  // Serialize dump point generation so that memory dump providers don't have to
-  // deal with thread safety.
+  // The delegate_ is supposed to be thread safe, immutable and long lived.
+  // No need to keep the lock after we ensure that a delegate has been set.
+  MemoryDumpManagerDelegate* delegate;
   {
     AutoLock lock(lock_);
-    for (auto it = dump_providers_enabled_.begin();
-         it != dump_providers_enabled_.end();) {
-      dump_provider_currently_active_ = *it;
-      if (dump_provider_currently_active_->DumpInto(pmd.get())) {
-        did_any_provider_dump = true;
-        ++it;
-      } else {
-        LOG(ERROR) << "The memory dumper "
-                   << dump_provider_currently_active_->GetFriendlyName()
-                   << " failed, possibly due to sandboxing (crbug.com/461788), "
-                      "disabling it for current process. Try restarting chrome "
-                      "with the --no-sandbox switch.";
-        it = dump_providers_enabled_.erase(it);
-      }
-      dump_provider_currently_active_ = nullptr;
-    }
+    delegate = delegate_;
   }
 
-  // Don't create a dump point if all the dumpers failed.
-  if (!did_any_provider_dump)
-    return;
+  if (delegate) {
+    // The delegate is in charge to coordinate the request among all the
+    // processes and call the CreateLocalDumpPoint on the local process.
+    MemoryDumpRequestArgs args = {guid, dump_type};
+    delegate->RequestGlobalMemoryDump(args, callback);
+  } else if (!callback.is_null()) {
+    callback.Run(guid, false /* success */);
+  }
+}
 
-  scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
-  pmd->AsValueInto(static_cast<TracedValue*>(event_value.get()));
-  const char* const event_name = DumpPointTypeToString(dump_point_type);
+void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) {
+  RequestGlobalDump(dump_type, MemoryDumpCallback());
+}
 
-  TRACE_EVENT_API_ADD_TRACE_EVENT(
-      TRACE_EVENT_PHASE_MEMORY_DUMP,
-      TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, guid,
-      kTraceEventNumArgs, kTraceEventArgNames, kTraceEventArgTypes,
-      NULL /* arg_values */, &event_value, TRACE_EVENT_FLAG_HAS_ID);
+// Creates a memory dump for the current process and appends it to the trace.
+void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
+                                          const MemoryDumpCallback& callback) {
+  scoped_refptr<ProcessMemoryDumpHolder> pmd_holder(
+      new ProcessMemoryDumpHolder(args, session_state_, callback));
+  ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
+  bool did_any_provider_dump = false;
+
+  // Iterate over the active dump providers and invoke DumpInto(pmd).
+  // The MDM guarantees linearity (at most one MDP is active within one
+  // process) and thread-safety (MDM enforces the right locking when entering /
+  // leaving the MDP.DumpInto() call). This is to simplify the clients' design
+  // and not let the MDPs worry about locking.
+  // As regards thread affinity, depending on the MDP configuration (see
+  // memory_dump_provider.h), the DumpInto() invocation can happen:
+  //  - Synchronousy on the MDM thread, when MDP.task_runner() is not set.
+  //  - Posted on MDP.task_runner(), when MDP.task_runner() is set.
+  {
+    AutoLock lock(lock_);
+    for (auto dump_provider_iter = dump_providers_enabled_.begin();
+         dump_provider_iter != dump_providers_enabled_.end();) {
+      // InvokeDumpProviderLocked will remove the MDP from the set if it fails.
+      MemoryDumpProvider* mdp = *dump_provider_iter;
+      ++dump_provider_iter;
+      if (mdp->task_runner()) {
+        // The DumpInto() call must be posted.
+        bool did_post_async_task = mdp->task_runner()->PostTask(
+            FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump,
+                            Unretained(this), Unretained(mdp), pmd_holder));
+        // The thread underlying the TaskRunner might have gone away.
+        if (did_post_async_task)
+          ++pmd_holder->num_pending_async_requests;
+      } else {
+        // Invoke the dump provider synchronously.
+        did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd);
+      }
+    }
+  }  // AutoLock
+
+  // If at least one synchronous provider did dump and there are no pending
+  // asynchronous requests, add the dump to the trace and invoke the callback
+  // straight away (FinalizeDumpAndAddToTrace() takes care of the callback).
+  if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0)
+    FinalizeDumpAndAddToTrace(pmd_holder);
+}
+
+// Invokes the MemoryDumpProvider.DumpInto(), taking care of the failsafe logic
+// which disables the dumper when failing (crbug.com/461788).
+bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
+                                                 ProcessMemoryDump* pmd) {
+  lock_.AssertAcquired();
+  dump_provider_currently_active_ = mdp;
+  bool dump_successful = mdp->DumpInto(pmd);
+  dump_provider_currently_active_ = nullptr;
+  if (!dump_successful) {
+    LOG(ERROR) << "The memory dumper " << mdp->GetFriendlyName()
+               << " failed, possibly due to sandboxing (crbug.com/461788), "
+                  "disabling it for current process. Try restarting chrome "
+                  "with the --no-sandbox switch.";
+    dump_providers_enabled_.erase(mdp);
+  }
+  return dump_successful;
+}
+
+// This is posted to arbitrary threads as a continuation of CreateProcessDump(),
+// when one or more MemoryDumpProvider(s) require the DumpInto() call to happen
+// on a different thread.
+void MemoryDumpManager::ContinueAsyncProcessDump(
+    MemoryDumpProvider* mdp,
+    scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) {
+  bool should_finalize_dump = false;
+  {
+    // The lock here is to guarantee that different asynchronous dumps on
+    // different threads are still serialized, so that the MemoryDumpProvider
+    // has a consistent view of the |pmd| argument passed.
+    AutoLock lock(lock_);
+    ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
+
+    // Check if the MemoryDumpProvider is still there. It might have been
+    // destroyed and unregistered while hopping threads.
+    if (dump_providers_enabled_.count(mdp))
+      InvokeDumpProviderLocked(mdp, pmd);
+
+    // Finalize the dump appending it to the trace if this was the last
+    // asynchronous request pending.
+    --pmd_holder->num_pending_async_requests;
+    if (pmd_holder->num_pending_async_requests == 0)
+      should_finalize_dump = true;
+  }  // AutoLock(lock_)
+
+  if (should_finalize_dump)
+    FinalizeDumpAndAddToTrace(pmd_holder);
 }
 
 void MemoryDumpManager::OnTraceLogEnabled() {
@@ -168,19 +338,36 @@
   TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
 
   AutoLock lock(lock_);
-  if (enabled) {
-    dump_providers_enabled_.assign(dump_providers_registered_.begin(),
-                                   dump_providers_registered_.end());
-  } else {
+
+  // There is no point starting the tracing without a delegate.
+  if (!enabled || !delegate_) {
     dump_providers_enabled_.clear();
+    return;
   }
+
+  // Merge the dictionary of allocator attributes from all dump providers
+  // into the session state.
+  session_state_ = new MemoryDumpSessionState();
+  for (const MemoryDumpProvider* mdp : dump_providers_registered_) {
+    session_state_->allocators_attributes_type_info.Update(
+        mdp->allocator_attributes_type_info());
+  }
+  dump_providers_enabled_ = dump_providers_registered_;
   subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
+
+  if (delegate_->IsCoordinatorProcess()) {
+    periodic_dump_timer_.Start(FROM_HERE,
+                               TimeDelta::FromSeconds(kDumpIntervalSeconds),
+                               base::Bind(&RequestPeriodicGlobalDump));
+  }
 }
 
 void MemoryDumpManager::OnTraceLogDisabled() {
   AutoLock lock(lock_);
+  periodic_dump_timer_.Stop();
   dump_providers_enabled_.clear();
   subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
+  session_state_ = nullptr;
 }
 
 }  // namespace trace_event
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
index 04d0135..371a47a 100644
--- a/base/trace_event/memory_dump_manager.h
+++ b/base/trace_event/memory_dump_manager.h
@@ -8,42 +8,58 @@
 #include <vector>
 
 #include "base/atomicops.h"
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
 #include "base/synchronization/lock.h"
+#include "base/timer/timer.h"
+#include "base/trace_event/memory_dump_request_args.h"
 #include "base/trace_event/trace_event.h"
 
 namespace base {
 namespace trace_event {
 
-class MemoryDumpProvider;
+namespace {
+class ProcessMemoryDumpHolder;
+}
 
-// Captures the reason why a dump point is being requested. This is to allow
-// selective enabling of dump points, filtering and post-processing.
-enum class DumpPointType {
-  TASK_BEGIN,         // Dumping memory at the beginning of a message-loop task.
-  TASK_END,           // Dumping memory at the ending of a message-loop task.
-  PERIODIC_INTERVAL,  // Dumping memory at periodic intervals.
-  EXPLICITLY_TRIGGERED,  // Non maskable dump request.
-};
+class MemoryDumpManagerDelegate;
+class MemoryDumpProvider;
+class ProcessMemoryDump;
+class MemoryDumpSessionState;
 
 // This is the interface exposed to the rest of the codebase to deal with
 // memory tracing. The main entry point for clients is represented by
 // RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
 class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
  public:
+  static const char* const kTraceCategoryForTesting;
+
   static MemoryDumpManager* GetInstance();
 
   // Invoked once per process to register the TraceLog observer.
   void Initialize();
 
+  // See the lifetime and thread-safety requirements on the delegate below in
+  // the |MemoryDumpManagerDelegate| docstring.
+  void SetDelegate(MemoryDumpManagerDelegate* delegate);
+
   // MemoryDumpManager does NOT take memory ownership of |mdp|, which is
-  // expected to be a singleton.
+  // expected to either be a singleton or unregister itself.
   void RegisterDumpProvider(MemoryDumpProvider* mdp);
   void UnregisterDumpProvider(MemoryDumpProvider* mdp);
 
   // Requests a memory dump. The dump might happen or not depending on the
   // filters and categories specified when enabling tracing.
-  void RequestDumpPoint(DumpPointType dump_point_type);
+  // The optional |callback| is executed asynchronously, on an arbitrary thread,
+  // to notify about the completion of the global dump (i.e. after all the
+  // processes have dumped) and its success (true iff all the dumps were
+  // successful).
+  void RequestGlobalDump(MemoryDumpType dump_type,
+                         const MemoryDumpCallback& callback);
+
+  // Same as above (still asynchronous), but without callback.
+  void RequestGlobalDump(MemoryDumpType dump_type);
 
   // TraceLog::EnabledStateObserver implementation.
   void OnTraceLogEnabled() override;
@@ -55,41 +71,89 @@
     return dump_provider_currently_active_;
   }
 
+  // Returns the MemoryDumpSessionState object, which is shared by all the
+  // ProcessMemoryDump and MemoryAllocatorDump instances through all the tracing
+  // session lifetime.
+  const scoped_refptr<MemoryDumpSessionState>& session_state() const {
+    return session_state_;
+  }
+
  private:
   friend struct DefaultDeleter<MemoryDumpManager>;  // For the testing instance.
   friend struct DefaultSingletonTraits<MemoryDumpManager>;
+  friend class MemoryDumpManagerDelegate;
   friend class MemoryDumpManagerTest;
 
-  static const char kTraceCategory[];
-
   static void SetInstanceForTesting(MemoryDumpManager* instance);
 
   MemoryDumpManager();
   virtual ~MemoryDumpManager();
 
-  // Broadcasts the dump requests to the other processes.
-  void BroadcastDumpRequest();
+  // Internal, used only by MemoryDumpManagerDelegate.
+  // Creates a memory dump for the current process and appends it to the trace.
+  // |callback| will be invoked asynchronously upon completion on the same
+  // thread on which CreateProcessDump() was called.
+  void CreateProcessDump(const MemoryDumpRequestArgs& args,
+                         const MemoryDumpCallback& callback);
 
-  // Creates a dump point for the current process and appends it to the trace.
-  void CreateLocalDumpPoint(DumpPointType dump_point_type, uint64 guid);
+  bool InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
+                                ProcessMemoryDump* pmd);
+  void ContinueAsyncProcessDump(
+      MemoryDumpProvider* mdp,
+      scoped_refptr<ProcessMemoryDumpHolder> pmd_holder);
 
-  std::vector<MemoryDumpProvider*> dump_providers_registered_;  // Not owned.
-  std::vector<MemoryDumpProvider*> dump_providers_enabled_;     // Not owned.
+  hash_set<MemoryDumpProvider*> dump_providers_registered_;  // Not owned.
+  hash_set<MemoryDumpProvider*> dump_providers_enabled_;     // Not owned.
 
   // TODO(primiano): this is required only until crbug.com/466121 gets fixed.
-  MemoryDumpProvider* dump_provider_currently_active_;  // Now owned.
+  MemoryDumpProvider* dump_provider_currently_active_;  // Not owned.
 
-  // Protects from concurrent accesses to the |dump_providers_*|, e.g., tearing
-  // down logging while creating a dump point on another thread.
+  // Shared among all the PMDs to keep state scoped to the tracing session.
+  scoped_refptr<MemoryDumpSessionState> session_state_;
+
+  MemoryDumpManagerDelegate* delegate_;  // Not owned.
+
+  // Protects from concurrent accesses to the |dump_providers_*| and |delegate_|
+  // to guard against disabling logging while dumping on another thread.
   Lock lock_;
 
-  // Optimization to avoid attempting any dump point (i.e. to not walk an empty
+  // Optimization to avoid attempting any memory dump (i.e. to not walk an empty
   // dump_providers_enabled_ list) when tracing is not enabled.
   subtle::AtomicWord memory_tracing_enabled_;
 
+  // For time-triggered periodic dumps.
+  RepeatingTimer<MemoryDumpManager> periodic_dump_timer_;
+
+  // Skips the auto-registration of the core dumpers during Initialize().
+  bool skip_core_dumpers_auto_registration_for_testing_;
+
   DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
 };
 
+// The delegate is supposed to be long lived (read: a Singleton) and thread
+// safe (i.e. should expect calls from any thread and handle thread hopping).
+class BASE_EXPORT MemoryDumpManagerDelegate {
+ public:
+  virtual void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args,
+                                       const MemoryDumpCallback& callback) = 0;
+
+  // Determines whether the MemoryDumpManager instance should be the master
+  // (the ones which initiates and coordinates the multiprocess dumps) or not.
+  virtual bool IsCoordinatorProcess() const = 0;
+
+ protected:
+  MemoryDumpManagerDelegate() {}
+  virtual ~MemoryDumpManagerDelegate() {}
+
+  void CreateProcessDump(const MemoryDumpRequestArgs& args,
+                         const MemoryDumpCallback& callback) {
+    MemoryDumpManager::GetInstance()->CreateProcessDump(args, callback);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerDelegate);
+};
+
 }  // namespace trace_event
 }  // namespace base
 
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 65e719f..589c406 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -4,6 +4,11 @@
 
 #include "base/trace_event/memory_dump_manager.h"
 
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_vector.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -16,23 +21,46 @@
 namespace base {
 namespace trace_event {
 
+// Testing MemoryDumpManagerDelegate which short-circuits dump requests locally
+// instead of performing IPC dances.
+class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate {
+ public:
+  void RequestGlobalMemoryDump(
+      const base::trace_event::MemoryDumpRequestArgs& args,
+      const MemoryDumpCallback& callback) override {
+    CreateProcessDump(args, callback);
+  }
+
+  bool IsCoordinatorProcess() const override { return false; }
+};
+
 class MemoryDumpManagerTest : public testing::Test {
  public:
   void SetUp() override {
+    message_loop_.reset(new MessageLoop());
     mdm_.reset(new MemoryDumpManager());
     MemoryDumpManager::SetInstanceForTesting(mdm_.get());
     ASSERT_EQ(mdm_, MemoryDumpManager::GetInstance());
     MemoryDumpManager::GetInstance()->Initialize();
+    MemoryDumpManager::GetInstance()->SetDelegate(&delegate_);
   }
 
   void TearDown() override {
     MemoryDumpManager::SetInstanceForTesting(nullptr);
     mdm_.reset();
+    message_loop_.reset();
     TraceLog::DeleteForTesting();
   }
 
+  void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner,
+                           Closure closure,
+                           uint64 dump_guid,
+                           bool success) {
+    task_runner->PostTask(FROM_HERE, closure);
+  }
+
  protected:
-  const char* const kTraceCategory = MemoryDumpManager::kTraceCategory;
+  const char* kTraceCategory = MemoryDumpManager::kTraceCategoryForTesting;
 
   void EnableTracing(const char* category) {
     TraceLog::GetInstance()->SetEnabled(
@@ -44,15 +72,29 @@
   scoped_ptr<MemoryDumpManager> mdm_;
 
  private:
+  scoped_ptr<MessageLoop> message_loop_;
+  MemoryDumpManagerDelegateForTesting delegate_;
+
   // We want our singleton torn down after each test.
   ShadowingAtExitManager at_exit_manager_;
 };
 
 class MockDumpProvider : public MemoryDumpProvider {
  public:
+  MockDumpProvider() {}
+
+  explicit MockDumpProvider(
+      const scoped_refptr<SingleThreadTaskRunner>& task_runner)
+      : MemoryDumpProvider(task_runner) {}
+
+  // Ctor for the SharedSessionState test.
+  explicit MockDumpProvider(const std::string& id) {
+    DeclareAllocatorAttribute("allocator" + id, "attr" + id, "type" + id);
+  }
+
   MOCK_METHOD1(DumpInto, bool(ProcessMemoryDump* pmd));
 
-  // DumpInto() override for the ActiveDumpProviderConsistency test,
+  // DumpInto() override for the ActiveDumpProviderConsistency test.
   bool DumpIntoAndCheckDumpProviderCurrentlyActive(ProcessMemoryDump* pmd) {
     EXPECT_EQ(
         this,
@@ -60,6 +102,22 @@
     return true;
   }
 
+  // DumpInto() override for the RespectTaskRunnerAffinity test.
+  bool DumpIntoAndCheckTaskRunner(ProcessMemoryDump* pmd) {
+    EXPECT_TRUE(task_runner()->RunsTasksOnCurrentThread());
+    return true;
+  }
+
+  // DumpInto() override for the SharedSessionState test.
+  bool DumpIntoAndCheckSessionState(ProcessMemoryDump* pmd) {
+    EXPECT_TRUE(pmd->session_state());
+    const auto& attrs_type_info =
+        pmd->session_state()->allocators_attributes_type_info;
+    EXPECT_TRUE(attrs_type_info.Exists("allocator1", "attr1"));
+    EXPECT_TRUE(attrs_type_info.Exists("allocator2", "attr2"));
+    return true;
+  }
+
   const char* GetFriendlyName() const override { return "MockDumpProvider"; }
 };
 
@@ -70,7 +128,7 @@
   // Check that the dumper is not called if the memory category is not enabled.
   EnableTracing("foo-and-bar-but-not-memory");
   EXPECT_CALL(mdp, DumpInto(_)).Times(0);
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
   DisableTracing();
 
   // Now repeat enabling the memory category and check that the dumper is
@@ -78,7 +136,7 @@
   EnableTracing(kTraceCategory);
   EXPECT_CALL(mdp, DumpInto(_)).Times(3).WillRepeatedly(Return(true));
   for (int i = 0; i < 3; ++i)
-    mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+    mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
   DisableTracing();
 
   mdm_->UnregisterDumpProvider(&mdp);
@@ -86,21 +144,24 @@
   // Finally check the unregister logic (no calls to the mdp after unregister).
   EnableTracing(kTraceCategory);
   EXPECT_CALL(mdp, DumpInto(_)).Times(0);
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
   TraceLog::GetInstance()->SetDisabled();
 }
 
-TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileTracing) {
-  MockDumpProvider mdp;
-  mdm_->RegisterDumpProvider(&mdp);
+TEST_F(MemoryDumpManagerTest, SharedSessionState) {
+  MockDumpProvider mdp1("1");  // Will declare an allocator property "attr1".
+  MockDumpProvider mdp2("2");  // Will declare an allocator property "attr2".
+  mdm_->RegisterDumpProvider(&mdp1);
+  mdm_->RegisterDumpProvider(&mdp2);
 
   EnableTracing(kTraceCategory);
-  EXPECT_CALL(mdp, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  EXPECT_CALL(mdp1, DumpInto(_)).Times(2).WillRepeatedly(
+      Invoke(&mdp1, &MockDumpProvider::DumpIntoAndCheckSessionState));
+  EXPECT_CALL(mdp2, DumpInto(_)).Times(2).WillRepeatedly(
+      Invoke(&mdp2, &MockDumpProvider::DumpIntoAndCheckSessionState));
 
-  mdm_->UnregisterDumpProvider(&mdp);
-  EXPECT_CALL(mdp, DumpInto(_)).Times(0);
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  for (int i = 0; i < 2; ++i)
+    mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
 
   DisableTracing();
 }
@@ -114,7 +175,7 @@
   EnableTracing(kTraceCategory);
   EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
   EXPECT_CALL(mdp2, DumpInto(_)).Times(0);
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
   DisableTracing();
 
   // Invert: enable mdp1 and disable mdp2.
@@ -123,7 +184,7 @@
   EnableTracing(kTraceCategory);
   EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
   EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
   DisableTracing();
 
   // Enable both mdp1 and mdp2.
@@ -131,7 +192,66 @@
   EnableTracing(kTraceCategory);
   EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
   EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
+  DisableTracing();
+}
+
+// Checks that the MemoryDumpManager respects the thread affinity when a
+// MemoryDumpProvider specifies a task_runner(). The test starts creating 8
+// threads and registering a MemoryDumpProvider on each of them. At each
+// iteration, one thread is removed, to check the live unregistration logic.
+TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) {
+  const uint32 kNumInitialThreads = 8;
+
+  ScopedVector<Thread> threads;
+  ScopedVector<MockDumpProvider> mdps;
+
+  // Create the threads and setup the expectations. Given that at each iteration
+  // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be
+  // invoked a number of times equal to its index.
+  for (uint32 i = kNumInitialThreads; i > 0; --i) {
+    threads.push_back(new Thread("test thread"));
+    threads.back()->Start();
+    mdps.push_back(new MockDumpProvider(threads.back()->task_runner()));
+    MockDumpProvider* mdp = mdps.back();
+    mdm_->RegisterDumpProvider(mdp);
+    EXPECT_CALL(*mdp, DumpInto(_))
+        .Times(i)
+        .WillRepeatedly(
+            Invoke(mdp, &MockDumpProvider::DumpIntoAndCheckTaskRunner));
+  }
+
+  EnableTracing(kTraceCategory);
+
+  while (!threads.empty()) {
+    {
+      RunLoop run_loop;
+      MemoryDumpCallback callback =
+          Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this),
+               MessageLoop::current()->task_runner(), run_loop.QuitClosure());
+      mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, callback);
+      // This nested message loop (|run_loop|) will be quit if and only if
+      // the RequestGlobalDump callback is invoked.
+      run_loop.Run();
+    }
+
+    // Unregister a MDP and destroy one thread at each iteration to check the
+    // live unregistration logic. The unregistration needs to happen on the same
+    // thread the MDP belongs to.
+    {
+      RunLoop run_loop;
+      Closure unregistration =
+          Bind(&MemoryDumpManager::UnregisterDumpProvider,
+               Unretained(mdm_.get()), Unretained(mdps.back()));
+      threads.back()->task_runner()->PostTaskAndReply(FROM_HERE, unregistration,
+                                                      run_loop.QuitClosure());
+      run_loop.Run();
+    }
+    mdps.pop_back();
+    threads.back()->Stop();
+    threads.pop_back();
+  }
+
   DisableTracing();
 }
 
@@ -148,11 +268,11 @@
 
   EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(false));
   EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
 
   EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
   EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(false));
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
 
   DisableTracing();
 }
@@ -177,8 +297,8 @@
       .WillRepeatedly(Invoke(
           &mdp2,
           &MockDumpProvider::DumpIntoAndCheckDumpProviderCurrentlyActive));
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
-  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
+  mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
   DisableTracing();
 }
 
diff --git a/base/trace_event/memory_dump_provider.cc b/base/trace_event/memory_dump_provider.cc
index 9518461..a2d3889 100644
--- a/base/trace_event/memory_dump_provider.cc
+++ b/base/trace_event/memory_dump_provider.cc
@@ -4,7 +4,7 @@
 
 #include "base/trace_event/memory_dump_provider.h"
 
-#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
 
 namespace base {
 namespace trace_event {
@@ -12,15 +12,20 @@
 MemoryDumpProvider::MemoryDumpProvider() {
 }
 
+MemoryDumpProvider::MemoryDumpProvider(
+    const scoped_refptr<SingleThreadTaskRunner>& task_runner)
+    : task_runner_(task_runner) {
+}
+
 MemoryDumpProvider::~MemoryDumpProvider() {
 }
 
 void MemoryDumpProvider::DeclareAllocatorAttribute(
-    const MemoryAllocatorDeclaredAttribute& attr) {
-  DCHECK_EQ(0u, allocator_attributes_.count(attr.name))
-      << "Allocator attribute " << attr.name << " already declared for dumper "
-      << GetFriendlyName();
-  allocator_attributes_[attr.name] = attr;
+    const std::string& allocator_name,
+    const std::string& attribute_name,
+    const std::string& attribute_type) {
+  allocator_attributes_type_info_.Set(
+      allocator_name, attribute_name, attribute_type);
 }
 
 }  // namespace trace_event
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h
index 5cc3a6e..9ec7ad9 100644
--- a/base/trace_event/memory_dump_provider.h
+++ b/base/trace_event/memory_dump_provider.h
@@ -6,9 +6,13 @@
 #define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
 
 #include "base/base_export.h"
-#include "base/trace_event/memory_allocator_attributes.h"
+#include "base/memory/ref_counted.h"
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
 
 namespace base {
+
+class SingleThreadTaskRunner;
+
 namespace trace_event {
 
 class ProcessMemoryDump;
@@ -16,27 +20,46 @@
 // The contract interface that memory dump providers must implement.
 class BASE_EXPORT MemoryDumpProvider {
  public:
-  // Called by the MemoryDumpManager when generating dump points.
+  // Called by the MemoryDumpManager when generating memory dumps.
   // Returns: true if the |pmd| was successfully populated, false otherwise.
   virtual bool DumpInto(ProcessMemoryDump* pmd) = 0;
 
   virtual const char* GetFriendlyName() const = 0;
 
-  const MemoryAllocatorDeclaredAttributes& allocator_attributes() const {
-    return allocator_attributes_;
+  const MemoryAllocatorAttributesTypeInfo& allocator_attributes_type_info()
+      const {
+    return allocator_attributes_type_info_;
+  }
+
+  // The dump provider can specify an optional thread affinity (in its
+  // base constructor call). If |task_runner| is non empty, all the calls to
+  // DumpInto are guaranteed to be posted to that TaskRunner.
+  const scoped_refptr<SingleThreadTaskRunner>& task_runner() const {
+    return task_runner_;
   }
 
  protected:
+  // Default ctor: the MDP is not bound to any thread (must be a singleton).
   MemoryDumpProvider();
+
+  // Use this ctor to ensure that DumpInto() is called always on the same thread
+  // specified by |task_runner|.
+  explicit MemoryDumpProvider(
+      const scoped_refptr<SingleThreadTaskRunner>& task_runner);
+
   virtual ~MemoryDumpProvider();
 
-  void DeclareAllocatorAttribute(const MemoryAllocatorDeclaredAttribute& attr);
+  void DeclareAllocatorAttribute(const std::string& allocator_name,
+                                 const std::string& attribute_name,
+                                 const std::string& attribute_type);
 
  private:
-  // The map (attribute name -> type) that specifies the semantic of the
-  // extra attributes that the MemoryAllocatorDump(s) produced by this
-  // MemoryDumpProvider will have.
-  MemoryAllocatorDeclaredAttributes allocator_attributes_;
+  // A map of attributes types (declared through DeclareAllocatorAttribute())
+  // emitted by this allocator dumper.
+  MemoryAllocatorAttributesTypeInfo allocator_attributes_type_info_;
+
+  // (Optional) TaskRunner on which the DumpInfo call should be posted.
+  scoped_refptr<SingleThreadTaskRunner> task_runner_;
 
   DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider);
 };
diff --git a/base/trace_event/memory_dump_request_args.h b/base/trace_event/memory_dump_request_args.h
new file mode 100644
index 0000000..4fb0335
--- /dev/null
+++ b/base/trace_event/memory_dump_request_args.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_H_
+
+// This file defines the types and structs used to issue memory dump requests.
+// These are also used in the IPCs for coordinating inter-process memory dumps.
+
+#include "base/base_export.h"
+#include "base/callback.h"
+
+namespace base {
+namespace trace_event {
+
+// Captures the reason why a memory dump is being requested. This is to allow
+// selective enabling of dumps, filtering and post-processing.
+enum class MemoryDumpType {
+  TASK_BEGIN,         // Dumping memory at the beginning of a message-loop task.
+  TASK_END,           // Dumping memory at the ending of a message-loop task.
+  PERIODIC_INTERVAL,  // Dumping memory at periodic intervals.
+  EXPLICITLY_TRIGGERED,  // Non maskable dump request.
+  LAST = EXPLICITLY_TRIGGERED // For IPC macros.
+};
+
+using MemoryDumpCallback = Callback<void(uint64 dump_guid, bool success)>;
+
+struct BASE_EXPORT MemoryDumpRequestArgs {
+  // Globally unique identifier. In multi-process dumps, all processes issue a
+  // local dump with the same guid. This allows the trace importers to
+  // reconstruct the global dump.
+  uint64 dump_guid;
+
+  MemoryDumpType dump_type;
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_H_
diff --git a/base/trace_event/memory_dump_session_state.cc b/base/trace_event/memory_dump_session_state.cc
new file mode 100644
index 0000000..433ac14
--- /dev/null
+++ b/base/trace_event/memory_dump_session_state.cc
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/memory_dump_session_state.h"
+
+namespace base {
+namespace trace_event {
+
+MemoryDumpSessionState::MemoryDumpSessionState() {
+}
+
+MemoryDumpSessionState::~MemoryDumpSessionState() {
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/trace_event/memory_dump_session_state.h b/base/trace_event/memory_dump_session_state.h
new file mode 100644
index 0000000..38a6fe2
--- /dev/null
+++ b/base/trace_event/memory_dump_session_state.h
@@ -0,0 +1,31 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_SESSION_STATE_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_SESSION_STATE_H_
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/memory/ref_counted.h"
+#include "base/trace_event/memory_allocator_attributes_type_info.h"
+
+namespace base {
+namespace trace_event {
+
+class BASE_EXPORT MemoryDumpSessionState
+    : public RefCountedThreadSafe<MemoryDumpSessionState> {
+ public:
+  MemoryDumpSessionState();
+  MemoryAllocatorAttributesTypeInfo allocators_attributes_type_info;
+
+ private:
+  friend class RefCountedThreadSafe<MemoryDumpSessionState>;
+  ~MemoryDumpSessionState();
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_MEMORY_DUMP_SESSION_STATE_H_
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc
index bbca36c..836d6ae 100644
--- a/base/trace_event/process_memory_dump.cc
+++ b/base/trace_event/process_memory_dump.cc
@@ -10,31 +10,32 @@
 namespace base {
 namespace trace_event {
 
-ProcessMemoryDump::ProcessMemoryDump()
-    : has_process_totals_(false), has_process_mmaps_(false) {
+ProcessMemoryDump::ProcessMemoryDump(
+    const scoped_refptr<MemoryDumpSessionState>& session_state)
+    : has_process_totals_(false),
+      has_process_mmaps_(false),
+      session_state_(session_state) {
 }
 
 ProcessMemoryDump::~ProcessMemoryDump() {
 }
 
 MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
-    const std::string& name) {
-  return CreateAllocatorDump(name, nullptr);
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
-    const std::string& name,
-    MemoryAllocatorDump* parent) {
-  DCHECK_EQ(0ul, allocator_dumps_.count(name));
-  MemoryAllocatorDump* mad = new MemoryAllocatorDump(name, parent);
+    const std::string& allocator_name,
+    const std::string& heap_name) {
+  MemoryAllocatorDump* mad =
+      new MemoryAllocatorDump(allocator_name, heap_name, this);
+  DCHECK_EQ(0ul, allocator_dumps_.count(mad->GetAbsoluteName()));
   allocator_dumps_storage_.push_back(mad);
-  allocator_dumps_[name] = mad;
+  allocator_dumps_[mad->GetAbsoluteName()] = mad;
   return mad;
 }
 
 MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump(
-    const std::string& name) const {
-  auto it = allocator_dumps_.find(name);
+    const std::string& allocator_name,
+    const std::string& heap_name) const {
+  auto it = allocator_dumps_.find(
+      MemoryAllocatorDump::GetAbsoluteName(allocator_name, heap_name));
   return it == allocator_dumps_.end() ? nullptr : it->second;
 }
 
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h
index df6cc82..bd9c543 100644
--- a/base/trace_event/process_memory_dump.h
+++ b/base/trace_event/process_memory_dump.h
@@ -8,8 +8,10 @@
 #include "base/base_export.h"
 #include "base/containers/hash_tables.h"
 #include "base/containers/small_map.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
 #include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/memory_dump_session_state.h"
 #include "base/trace_event/process_memory_maps.h"
 #include "base/trace_event/process_memory_totals.h"
 
@@ -18,19 +20,22 @@
 
 class ConvertableToTraceFormat;
 class MemoryDumpManager;
+class MemoryDumpSessionState;
 
 // ProcessMemoryDump is as a strongly typed container which enforces the data
-// model for each memory dump point and holds the dumps produced by the
+// model for each memory dump and holds the dumps produced by the
 // MemoryDumpProvider(s) for a specific process.
 // At trace generation time (i.e. when AsValue() is called), ProcessMemoryDump
 // will compose a key-value dictionary of the various dumps obtained at trace
 // dump point time.
 class BASE_EXPORT ProcessMemoryDump {
  public:
+  // Maps allocator dumps absolute names (allocator_name/heap/subheap) to
+  // MemoryAllocatorDump instances.
   using AllocatorDumpsMap =
       SmallMap<hash_map<std::string, MemoryAllocatorDump*>>;
 
-  ProcessMemoryDump();
+  ProcessMemoryDump(const scoped_refptr<MemoryDumpSessionState>& session_state);
   ~ProcessMemoryDump();
 
   // Called at trace generation time to populate the TracedValue.
@@ -45,20 +50,34 @@
   void set_has_process_mmaps() { has_process_mmaps_ = true; }
 
   // Creates a new MemoryAllocatorDump with the given name and returns the
-  // empty object back to the caller. The |name| must be unique in the dump.
-  // ProcessMemoryDump handles the memory ownership of the created object.
-  // |parent| can be used to specify a hierarchical relationship of the
-  // allocator dumps.
-  MemoryAllocatorDump* CreateAllocatorDump(const std::string& name);
-  MemoryAllocatorDump* CreateAllocatorDump(const std::string& name,
-                                           MemoryAllocatorDump* parent);
+  // empty object back to the caller.
+  // Arguments:
+  //   allocator_name: a name that univocally identifies allocator dumps
+  //     produced by this provider. It acts as a type w.r.t. the allocator
+  //     attributes, in the sense that all the MAD with the same allocator_name
+  //     are expected to have the same attributes.
+  //   heap_name, either:
+  //     - kRootHeap: if the allocator has only one default heap.
+  //     - a string identifing a heap name (e.g., isolate1, isolate2 ...). It is
+  //       possible to specify nesting by using a path-like string (e.g.,
+  //       isolate1/heap_spaceX, isolate1/heap_spaceY, isolate2/heap_spaceX).
+  // The tuple (|allocator_name|, |heap_name|) is unique inside a PMD.
+  // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps.
+  MemoryAllocatorDump* CreateAllocatorDump(const std::string& allocator_name,
+                                           const std::string& heap_name);
 
-  // Returns a MemoryAllocatorDump given its name or nullptr if not found.
-  MemoryAllocatorDump* GetAllocatorDump(const std::string& name) const;
+  // Looks up a MemoryAllocatorDump given its allocator and heap names, or
+  // nullptr if not found.
+  MemoryAllocatorDump* GetAllocatorDump(const std::string& allocator_name,
+                                        const std::string& heap_name) const;
 
   // Returns the map of the MemoryAllocatorDumps added to this dump.
   const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; }
 
+  const scoped_refptr<MemoryDumpSessionState>& session_state() const {
+    return session_state_;
+  }
+
  private:
   ProcessMemoryTotals process_totals_;
   bool has_process_totals_;
@@ -66,13 +85,14 @@
   ProcessMemoryMaps process_mmaps_;
   bool has_process_mmaps_;
 
-  // A maps of "allocator_name" -> MemoryAllocatorDump populated by
-  // allocator dump providers.
   AllocatorDumpsMap allocator_dumps_;
 
   // ProcessMemoryDump handles the memory ownership of all its belongings.
   ScopedVector<MemoryAllocatorDump> allocator_dumps_storage_;
 
+  // State shared among all PMDs instances created in a given trace session.
+  scoped_refptr<MemoryDumpSessionState> session_state_;
+
   DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
 };
 
diff --git a/base/trace_event/process_memory_maps_dump_provider_unittest.cc b/base/trace_event/process_memory_maps_dump_provider_unittest.cc
index 0bf81ac..2ce2504 100644
--- a/base/trace_event/process_memory_maps_dump_provider_unittest.cc
+++ b/base/trace_event/process_memory_maps_dump_provider_unittest.cc
@@ -114,7 +114,7 @@
   auto pmmdp = ProcessMemoryMapsDumpProvider::GetInstance();
 
   // Emulate a non-existent /proc/self/smaps.
-  ProcessMemoryDump pmd_invalid;
+  ProcessMemoryDump pmd_invalid(nullptr /* session_state */);
   std::ifstream non_existent_file("/tmp/does-not-exist");
   ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = &non_existent_file;
   CHECK_EQ(false, non_existent_file.good());
@@ -129,7 +129,7 @@
   ASSERT_FALSE(pmd_invalid.has_process_mmaps());
 
   // Parse the 1st smaps file.
-  ProcessMemoryDump pmd_1;
+  ProcessMemoryDump pmd_1(nullptr /* session_state */);
   std::istringstream test_smaps_1(kTestSmaps1);
   ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = &test_smaps_1;
   pmmdp->DumpInto(&pmd_1);
@@ -154,7 +154,7 @@
   EXPECT_EQ((60 + 8) * 1024UL, regions_1[1].byte_stats_private_resident);
 
   // Parse the 2nd smaps file.
-  ProcessMemoryDump pmd_2;
+  ProcessMemoryDump pmd_2(nullptr /* session_state */);
   std::istringstream test_smaps_2(kTestSmaps2);
   ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = &test_smaps_2;
   pmmdp->DumpInto(&pmd_2);
diff --git a/base/trace_event/process_memory_totals_dump_provider_unittest.cc b/base/trace_event/process_memory_totals_dump_provider_unittest.cc
index 372db63..ffaf177 100644
--- a/base/trace_event/process_memory_totals_dump_provider_unittest.cc
+++ b/base/trace_event/process_memory_totals_dump_provider_unittest.cc
@@ -13,8 +13,8 @@
 
 TEST(ProcessMemoryTotalsDumpProviderTest, DumpRSS) {
   auto pmtdp = ProcessMemoryTotalsDumpProvider::GetInstance();
-  scoped_ptr<ProcessMemoryDump> pmd_before(new ProcessMemoryDump());
-  scoped_ptr<ProcessMemoryDump> pmd_after(new ProcessMemoryDump());
+  scoped_ptr<ProcessMemoryDump> pmd_before(new ProcessMemoryDump(nullptr));
+  scoped_ptr<ProcessMemoryDump> pmd_after(new ProcessMemoryDump(nullptr));
 
   ProcessMemoryTotalsDumpProvider::rss_bytes_for_testing = 1024;
   pmtdp->DumpInto(pmd_before.get());
diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi
index ca6c076..9bbd172 100644
--- a/base/trace_event/trace_event.gypi
+++ b/base/trace_event/trace_event.gypi
@@ -4,13 +4,19 @@
 {
   'variables': {
     'trace_event_sources' : [
-      'trace_event/memory_allocator_attributes.h',
+      'trace_event/java_heap_dump_provider_android.cc',
+      'trace_event/java_heap_dump_provider_android.h',
+      'trace_event/memory_allocator_attributes_type_info.cc',
+      'trace_event/memory_allocator_attributes_type_info.h',
       'trace_event/memory_allocator_dump.cc',
       'trace_event/memory_allocator_dump.h',
       'trace_event/memory_dump_manager.cc',
       'trace_event/memory_dump_manager.h',
       'trace_event/memory_dump_provider.cc',
       'trace_event/memory_dump_provider.h',
+      'trace_event/memory_dump_request_args.h',
+      'trace_event/memory_dump_session_state.cc',
+      'trace_event/memory_dump_session_state.h',
       'trace_event/process_memory_dump.cc',
       'trace_event/process_memory_dump.h',
       'trace_event/process_memory_maps.cc',
@@ -25,6 +31,8 @@
       'trace_event/trace_event_android.cc',
       'trace_event/trace_event_argument.cc',
       'trace_event/trace_event_argument.h',
+      'trace_event/trace_event_etw_export_win.cc',
+      'trace_event/trace_event_etw_export_win.h',
       'trace_event/trace_event_impl.cc',
       'trace_event/trace_event_impl.h',
       'trace_event/trace_event_impl_constants.cc',
@@ -36,8 +44,19 @@
       'trace_event/trace_event_system_stats_monitor.h',
       'trace_event/trace_event_win.cc',
       'trace_event/trace_event_win.h',
+      'trace_event/winheap_dump_provider_win.cc',
+      'trace_event/winheap_dump_provider_win.h',
+    ],
+    'conditions': [
+      ['OS == "linux" or OS == "android"', {
+          'trace_event_sources': [
+            'trace_event/malloc_dump_provider.cc',
+            'trace_event/malloc_dump_provider.h',
+          ],
+      }],
     ],
     'trace_event_test_sources' : [
+      'trace_event/memory_allocator_attributes_type_info_unittest.cc',
       'trace_event/memory_allocator_dump_unittest.cc',
       'trace_event/memory_dump_manager_unittest.cc',
       'trace_event/process_memory_maps_dump_provider_unittest.cc',
@@ -48,6 +67,7 @@
       'trace_event/trace_event_system_stats_monitor_unittest.cc',
       'trace_event/trace_event_unittest.cc',
       'trace_event/trace_event_win_unittest.cc',
+      'trace_event/winheap_dump_provider_win_unittest.cc',
     ],
   },
 }
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index 1bf9429..e0249f5 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -144,11 +144,11 @@
 //   class MyData : public base::trace_event::ConvertableToTraceFormat {
 //    public:
 //     MyData() {}
-//     virtual void AppendAsTraceFormat(std::string* out) const override {
+//     void AppendAsTraceFormat(std::string* out) const override {
 //       out->append("{\"foo\":1}");
 //     }
 //    private:
-//     virtual ~MyData() {}
+//     ~MyData() override {}
 //     DISALLOW_COPY_AND_ASSIGN(MyData);
 //   };
 //
@@ -601,6 +601,12 @@
         TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
         static_cast<int>(base::PlatformThread::CurrentId()), \
         timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, \
+        name, id, timestamp) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+        TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+        static_cast<int>(base::PlatformThread::CurrentId()), \
+        timestamp, TRACE_EVENT_FLAG_COPY)
 
 // Records a single ASYNC_STEP_INTO event for |step| immediately. If the
 // category is not enabled, then this does nothing. The |name| and |id| must
@@ -828,9 +834,10 @@
         category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE)
 
 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
-    UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
-        (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \
-         base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK))
+  UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) &           \
+           (base::trace_event::TraceLog::ENABLED_FOR_RECORDING |         \
+            base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK |    \
+            base::trace_event::TraceLog::ENABLED_FOR_ETW_EXPORT))
 
 // Macro to efficiently determine if a given category group is enabled.
 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc
new file mode 100644
index 0000000..f7f9ecc
--- /dev/null
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -0,0 +1,239 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/trace_event_etw_export_win.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_impl.h"
+
+// The GetProcAddress technique is borrowed from
+// https://github.com/randomascii/main/tree/master/xperf/ETWProviders
+//
+// EVNTAPI is used in evntprov.h which is included by chrome_events_win.h.
+// We define EVNTAPI without the DECLSPEC_IMPORT specifier so that we can
+// implement these functions locally instead of using the import library, and
+// can therefore still run on Windows XP.
+#define EVNTAPI __stdcall
+// Include the event register/write/unregister macros compiled from the manifest
+// file. Note that this includes evntprov.h which requires a Vista+ Windows SDK.
+//
+// In SHARED_INTERMEDIATE_DIR.
+#include "base/trace_event/etw_manifest/chrome_events_win.h"  // NOLINT
+
+namespace {
+// Typedefs for use with GetProcAddress
+typedef ULONG(__stdcall* tEventRegister)(LPCGUID ProviderId,
+                                         PENABLECALLBACK EnableCallback,
+                                         PVOID CallbackContext,
+                                         PREGHANDLE RegHandle);
+typedef ULONG(__stdcall* tEventWrite)(REGHANDLE RegHandle,
+                                      PCEVENT_DESCRIPTOR EventDescriptor,
+                                      ULONG UserDataCount,
+                                      PEVENT_DATA_DESCRIPTOR UserData);
+typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle);
+
+tEventRegister EventRegisterProc = nullptr;
+tEventWrite EventWriteProc = nullptr;
+tEventUnregister EventUnregisterProc = nullptr;
+}  // namespace
+
+// Redirector function for EventRegister. Called by macros in
+// chrome_events_win.h
+ULONG EVNTAPI EventRegister(LPCGUID ProviderId,
+                            PENABLECALLBACK EnableCallback,
+                            PVOID CallbackContext,
+                            PREGHANDLE RegHandle) {
+  if (EventRegisterProc)
+    return EventRegisterProc(ProviderId, EnableCallback, CallbackContext,
+                             RegHandle);
+  return 0;
+}
+
+// Redirector function for EventWrite. Called by macros in
+// chrome_events_win.h
+ULONG EVNTAPI EventWrite(REGHANDLE RegHandle,
+                         PCEVENT_DESCRIPTOR EventDescriptor,
+                         ULONG UserDataCount,
+                         PEVENT_DATA_DESCRIPTOR UserData) {
+  if (EventWriteProc)
+    return EventWriteProc(RegHandle, EventDescriptor, UserDataCount, UserData);
+  return 0;
+}
+
+// Redirector function for EventUnregister. Called by macros in
+// chrome_events_win.h
+ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) {
+  if (EventUnregisterProc)
+    return EventUnregisterProc(RegHandle);
+  return 0;
+}
+
+namespace base {
+namespace trace_event {
+
+TraceEventETWExport::TraceEventETWExport() : ETWExportEnabled_(false) {
+  // Find Advapi32.dll. This should always succeed.
+  HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll");
+  if (AdvapiDLL) {
+    // Try to find the ETW functions. This will fail on XP.
+    EventRegisterProc = reinterpret_cast<tEventRegister>(
+        ::GetProcAddress(AdvapiDLL, "EventRegister"));
+    EventWriteProc = reinterpret_cast<tEventWrite>(
+        ::GetProcAddress(AdvapiDLL, "EventWrite"));
+    EventUnregisterProc = reinterpret_cast<tEventUnregister>(
+        ::GetProcAddress(AdvapiDLL, "EventUnregister"));
+
+    // Register the ETW provider. If registration fails then the event logging
+    // calls will fail (on XP this call will do nothing).
+    EventRegisterChrome();
+  }
+}
+
+TraceEventETWExport::~TraceEventETWExport() {
+  EventUnregisterChrome();
+}
+
+// static
+TraceEventETWExport* TraceEventETWExport::GetInstance() {
+  return Singleton<TraceEventETWExport,
+                   StaticMemorySingletonTraits<TraceEventETWExport>>::get();
+}
+
+// static
+void TraceEventETWExport::EnableETWExport() {
+  GetInstance()->ETWExportEnabled_ = true;
+}
+
+// static
+void TraceEventETWExport::DisableETWExport() {
+  GetInstance()->ETWExportEnabled_ = false;
+}
+
+// static
+void TraceEventETWExport::AddEvent(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    unsigned long long id,
+    int num_args,
+    const char** arg_names,
+    const unsigned char* arg_types,
+    const unsigned long long* arg_values,
+    const scoped_refptr<ConvertableToTraceFormat>* convertable_values) {
+  // We bail early in case exporting is disabled or no consumer is listening.
+  if (!GetInstance()->ETWExportEnabled_ || !EventEnabledChromeEvent())
+    return;
+
+  std::string phase_string;
+  switch (phase) {
+    case TRACE_EVENT_PHASE_BEGIN:
+      phase_string = "Begin";
+      break;
+    case TRACE_EVENT_PHASE_END:
+      phase_string = "End";
+      break;
+    case TRACE_EVENT_PHASE_COMPLETE:
+      phase_string = "Complete";
+      break;
+    case TRACE_EVENT_PHASE_INSTANT:
+      phase_string = "Instant";
+      break;
+    case TRACE_EVENT_PHASE_ASYNC_BEGIN:
+      phase_string = "Async Begin";
+      break;
+    case TRACE_EVENT_PHASE_ASYNC_STEP_INTO:
+      phase_string = "Async Step Into";
+      break;
+    case TRACE_EVENT_PHASE_ASYNC_STEP_PAST:
+      phase_string = "Async Step Past";
+      break;
+    case TRACE_EVENT_PHASE_ASYNC_END:
+      phase_string = "Async End";
+      break;
+    case TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN:
+      phase_string = "Nestable Async Begin";
+      break;
+    case TRACE_EVENT_PHASE_NESTABLE_ASYNC_END:
+      phase_string = "Nestable Async End";
+      break;
+    case TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT:
+      phase_string = "Nestable Async Instant";
+      break;
+    case TRACE_EVENT_PHASE_FLOW_BEGIN:
+      phase_string = "Phase Flow Begin";
+      break;
+    case TRACE_EVENT_PHASE_FLOW_STEP:
+      phase_string = "Phase Flow Step";
+      break;
+    case TRACE_EVENT_PHASE_FLOW_END:
+      phase_string = "Phase Flow End";
+      break;
+    case TRACE_EVENT_PHASE_METADATA:
+      phase_string = "Phase Metadata";
+      break;
+    case TRACE_EVENT_PHASE_COUNTER:
+      phase_string = "Phase Counter";
+      break;
+    case TRACE_EVENT_PHASE_SAMPLE:
+      phase_string = "Phase Sample";
+      break;
+    case TRACE_EVENT_PHASE_CREATE_OBJECT:
+      phase_string = "Phase Create Object";
+      break;
+    case TRACE_EVENT_PHASE_SNAPSHOT_OBJECT:
+      phase_string = "Phase Snapshot Object";
+      break;
+    case TRACE_EVENT_PHASE_DELETE_OBJECT:
+      phase_string = "Phase Delete Object";
+      break;
+    default:
+      phase_string.push_back(phase);
+      break;
+  }
+
+  std::string arg_values_string[3];
+  for (int i = 0; i < num_args; i++) {
+    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
+      convertable_values[i]->AppendAsTraceFormat(arg_values_string + i);
+    } else {
+      TraceEvent::TraceValue trace_event;
+      trace_event.as_uint = arg_values[i];
+      TraceEvent::AppendValueAsJSON(arg_types[i], trace_event,
+                                    arg_values_string + i);
+    }
+  }
+
+  EventWriteChromeEvent(
+      name, phase_string.c_str(), num_args > 0 ? arg_names[0] : "",
+      arg_values_string[0].c_str(), num_args > 1 ? arg_names[1] : "",
+      arg_values_string[1].c_str(), num_args > 2 ? arg_names[2] : "",
+      arg_values_string[2].c_str());
+}
+
+// static
+void TraceEventETWExport::AddCustomEvent(const char* name,
+                                         char const* phase,
+                                         const char* arg_name_1,
+                                         const char* arg_value_1,
+                                         const char* arg_name_2,
+                                         const char* arg_value_2,
+                                         const char* arg_name_3,
+                                         const char* arg_value_3) {
+  if (!GetInstance()->ETWExportEnabled_ || !EventEnabledChromeEvent())
+    return;
+
+  EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2,
+                        arg_value_2, arg_name_3, arg_value_3);
+}
+
+void TraceEventETWExport::Resurrect() {
+  StaticMemorySingletonTraits<TraceEventETWExport>::Resurrect();
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h
new file mode 100644
index 0000000..0a551c3
--- /dev/null
+++ b/base/trace_event/trace_event_etw_export_win.h
@@ -0,0 +1,73 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains the Windows-specific exporting to ETW.
+#ifndef BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
+#define BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
+
+#include "base/base_export.h"
+#include "base/trace_event/trace_event_impl.h"
+
+// Fwd.
+template <typename Type>
+struct StaticMemorySingletonTraits;
+
+namespace base {
+namespace trace_event {
+
+class BASE_EXPORT TraceEventETWExport {
+ public:
+  ~TraceEventETWExport();
+
+  // Retrieves the singleton.
+  // Note that this may return NULL post-AtExit processing.
+  static TraceEventETWExport* GetInstance();
+
+  // Enables/disables exporting of events to ETW. If disabled,
+  // AddEvent and AddCustomEvent will simply return when called.
+  static void EnableETWExport();
+  static void DisableETWExport();
+
+  static bool isETWExportEnabled() { return GetInstance()->ETWExportEnabled_; }
+
+  // Exports an event to ETW. This is mainly used in
+  // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events.
+  static void AddEvent(
+      char phase,
+      const unsigned char* category_group_enabled,
+      const char* name,
+      unsigned long long id,
+      int num_args,
+      const char** arg_names,
+      const unsigned char* arg_types,
+      const unsigned long long* arg_values,
+      const scoped_refptr<ConvertableToTraceFormat>* convertable_values);
+
+  // Exports an event to ETW. This should be used when exporting an event only
+  // to ETW. Supports three arguments to be passed to ETW.
+  // TODO(georgesak): Allow different providers.
+  static void AddCustomEvent(const char* name,
+                             char const* phase,
+                             const char* arg_name_1,
+                             const char* arg_value_1,
+                             const char* arg_name_2,
+                             const char* arg_value_2,
+                             const char* arg_name_3,
+                             const char* arg_value_3);
+
+  void Resurrect();
+
+ private:
+  bool ETWExportEnabled_;
+  // Ensure only the provider can construct us.
+  friend struct StaticMemorySingletonTraits<TraceEventETWExport>;
+  TraceEventETWExport();
+
+  DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_TRACE_ETW_EXPORT_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 72b46f9..cbeeeab 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -5,12 +5,12 @@
 #include "base/trace_event/trace_event_impl.h"
 
 #include <algorithm>
+#include <cmath>
 
 #include "base/base_switches.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/debug/leak_annotations.h"
-#include "base/float_util.h"
 #include "base/format_macros.h"
 #include "base/json/string_escape.h"
 #include "base/lazy_instance.h"
@@ -30,11 +30,13 @@
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_id_name_manager.h"
+#include "base/threading/worker_pool.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_synthetic_delay.h"
 
 #if defined(OS_WIN)
+#include "base/trace_event/trace_event_etw_export_win.h"
 #include "base/trace_event/trace_event_win.h"
 #endif
 
@@ -73,7 +75,7 @@
     512000000 / kTraceBufferChunkSize;
 const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize;
 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4;
-const size_t kTraceEventBatchChunks = 1000 / kTraceBufferChunkSize;
+const size_t kTraceEventBufferSizeInBytes = 100 * 1024;
 // Can store results for 30 seconds with 1 ms sampling interval.
 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize;
 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events.
@@ -645,7 +647,7 @@
       //        should be made into a common method.
       std::string real;
       double val = value.as_double;
-      if (IsFinite(val)) {
+      if (std::isfinite(val)) {
         real = DoubleToString(val);
         // Ensure that the number has a .0 if there's no decimal or 'e'.  This
         // makes sure that when we read the JSON back, it's interpreted as a
@@ -663,7 +665,7 @@
           // "-.1" bad "-0.1" good
           real.insert(1, "0");
         }
-      } else if (IsNaN(val)){
+      } else if (std::isnan(val)){
         // The JSON spec doesn't allow NaN and Infinity (since these are
         // objects in EcmaScript).  Use strings instead.
         real = "\"NaN\"";
@@ -1208,7 +1210,8 @@
       event_callback_category_filter_(
           CategoryFilter::kDefaultCategoryFilterString),
       thread_shared_chunk_index_(0),
-      generation_(0) {
+      generation_(0),
+      use_worker_thread_(false) {
   // Trace is enabled or disabled on one thread while other threads are
   // accessing the enabled flag. We don't care whether edge-case events are
   // traced or not, so we allow races on the enabled flag to keep the trace
@@ -1290,6 +1293,11 @@
   if (event_callback_ &&
       event_callback_category_filter_.IsCategoryGroupEnabled(category_group))
     enabled_flag |= ENABLED_FOR_EVENT_CALLBACK;
+#if defined(OS_WIN)
+  if (base::trace_event::TraceEventETWExport::isETWExportEnabled())
+    enabled_flag |= ENABLED_FOR_ETW_EXPORT;
+#endif
+
   g_category_group_enabled[category_index] = enabled_flag;
 }
 
@@ -1681,7 +1689,9 @@
 //    - The message loop will be removed from thread_message_loops_;
 //    If this is the last message loop, finish the flush;
 // 4. If any thread hasn't finish its flush in time, finish the flush.
-void TraceLog::Flush(const TraceLog::OutputCallback& cb) {
+void TraceLog::Flush(const TraceLog::OutputCallback& cb,
+                     bool use_worker_thread) {
+  use_worker_thread_ = use_worker_thread;
   if (IsEnabled()) {
     // Can't flush when tracing is enabled because otherwise PostTask would
     // - generate more trace events;
@@ -1735,6 +1745,7 @@
   FinishFlush(generation);
 }
 
+// Usually it runs on a different thread.
 void TraceLog::ConvertTraceEventsToTraceFormat(
     scoped_ptr<TraceBuffer> logged_events,
     const TraceLog::OutputCallback& flush_output_callback) {
@@ -1749,19 +1760,17 @@
     scoped_refptr<RefCountedString> json_events_str_ptr =
         new RefCountedString();
 
-    for (size_t i = 0; i < kTraceEventBatchChunks; ++i) {
+    while (json_events_str_ptr->size() < kTraceEventBufferSizeInBytes) {
       const TraceBufferChunk* chunk = logged_events->NextChunk();
-      if (!chunk) {
-        has_more_events = false;
+      has_more_events = chunk != NULL;
+      if (!chunk)
         break;
-      }
       for (size_t j = 0; j < chunk->size(); ++j) {
-        if (i > 0 || j > 0)
+        if (json_events_str_ptr->size())
           json_events_str_ptr->data().append(",\n");
         chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()));
       }
     }
-
     flush_output_callback.Run(json_events_str_ptr, has_more_events);
   } while (has_more_events);
 }
@@ -1785,6 +1794,16 @@
     flush_output_callback_.Reset();
   }
 
+  if (use_worker_thread_ &&
+      WorkerPool::PostTask(
+          FROM_HERE,
+          Bind(&TraceLog::ConvertTraceEventsToTraceFormat,
+               Passed(&previous_logged_events),
+               flush_output_callback),
+          true)) {
+    return;
+  }
+
   ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(),
                                   flush_output_callback);
 }
@@ -1908,7 +1927,7 @@
   DCHECK(!timestamp.is_null());
 
   if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
-    id ^= process_id_hash_;
+    id = MangleEventId(id);
 
   TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp);
   TimeTicks now = flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP ?
@@ -1971,6 +1990,15 @@
     }
   }
 
+#if defined(OS_WIN)
+  // This is done sooner rather than later, to avoid creating the event and
+  // acquiring the lock, which is not needed for ETW as it's already threadsafe.
+  if (*category_group_enabled & ENABLED_FOR_ETW_EXPORT)
+    TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id,
+                                  num_args, arg_names, arg_types, arg_values,
+                                  convertable_values);
+#endif  // OS_WIN
+
   std::string console_message;
   if (*category_group_enabled &
       (ENABLED_FOR_RECORDING | ENABLED_FOR_MONITORING)) {
@@ -2177,6 +2205,10 @@
   watch_event_callback_.Reset();
 }
 
+uint64 TraceLog::MangleEventId(uint64 id) {
+  return id ^ process_id_hash_;
+}
+
 void TraceLog::AddMetadataEventsWhileLocked() {
   lock_.AssertAcquired();
 
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index efa20c4..33a85c9 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -26,6 +26,7 @@
 
 // Older style trace macros with explicit id and extra data
 // Only these macros result in publishing data to ETW as currently implemented.
+// TODO(georgesak): Update/replace these with new ETW macros.
 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
     base::trace_event::TraceLog::AddTraceEventEtw( \
         TRACE_EVENT_PHASE_BEGIN, \
@@ -446,6 +447,8 @@
     ENABLED_FOR_MONITORING = 1 << 1,
     // Category group enabled by SetEventCallbackEnabled().
     ENABLED_FOR_EVENT_CALLBACK = 1 << 2,
+    // Category group enabled to export events to ETW.
+    ENABLED_FOR_ETW_EXPORT = 1 << 3
   };
 
   static TraceLog* GetInstance();
@@ -538,10 +541,11 @@
   // Due to the implementation of thread-local buffers, flush can't be
   // done when tracing is enabled. If called when tracing is enabled, the
   // callback will be called directly with (empty_string, false) to indicate
-  // the end of this unsuccessful flush.
+  // the end of this unsuccessful flush. Flush does the serialization
+  // on the same thread if the caller doesn't set use_worker_thread explicitly.
   typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&,
                               bool has_more_events)> OutputCallback;
-  void Flush(const OutputCallback& cb);
+  void Flush(const OutputCallback& cb, bool use_worker_thread = false);
   void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback);
 
   // Called by TRACE_EVENT* macros, don't call this directly.
@@ -602,6 +606,8 @@
 
   int process_id() const { return process_id_; }
 
+  uint64 MangleEventId(uint64 id);
+
   // Exposed for unittesting:
 
   void WaitSamplingEventForTesting();
@@ -710,7 +716,9 @@
   // |generation| is used in the following callbacks to check if the callback
   // is called for the flush of the current |logged_events_|.
   void FlushCurrentThread(int generation);
-  void ConvertTraceEventsToTraceFormat(scoped_ptr<TraceBuffer> logged_events,
+  // Usually it runs on a different thread.
+  static void ConvertTraceEventsToTraceFormat(
+      scoped_ptr<TraceBuffer> logged_events,
       const TraceLog::OutputCallback& flush_output_callback);
   void FinishFlush(int generation);
   void OnFlushTimeout(int generation);
@@ -803,6 +811,7 @@
   OutputCallback flush_output_callback_;
   scoped_refptr<MessageLoopProxy> flush_message_loop_proxy_;
   subtle::AtomicWord generation_;
+  bool use_worker_thread_;
 
   DISALLOW_COPY_AND_ASSIGN(TraceLog);
 };
diff --git a/base/trace_event/trace_event_win_unittest.cc b/base/trace_event/trace_event_win_unittest.cc
index 7f1004e..d4dc854 100644
--- a/base/trace_event/trace_event_win_unittest.cc
+++ b/base/trace_event/trace_event_win_unittest.cc
@@ -92,7 +92,7 @@
   TraceEventWinTest() {
   }
 
-  void SetUp() {
+  void SetUp() override {
     bool is_xp = win::GetVersion() < base::win::VERSION_VISTA;
 
     if (is_xp) {
@@ -151,7 +151,7 @@
     EXPECT_TRUE(tracelog->IsTracing());
   }
 
-  void TearDown() {
+  void TearDown() override {
     EtwTraceProperties prop;
     if (controller_.session() != 0)
       EXPECT_HRESULT_SUCCEEDED(controller_.Stop(&prop));
diff --git a/base/trace_event/winheap_dump_provider_win.cc b/base/trace_event/winheap_dump_provider_win.cc
new file mode 100644
index 0000000..3a4fd87
--- /dev/null
+++ b/base/trace_event/winheap_dump_provider_win.cc
@@ -0,0 +1,103 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/winheap_dump_provider_win.h"
+
+#include <windows.h>
+
+#include "base/trace_event/process_memory_dump.h"
+
+namespace base {
+namespace trace_event {
+
+namespace {
+
+const char kDumperFriendlyName[] = "winheap";
+
+// Report a heap dump to a process memory dump. The |heap_info| structure
+// contains the information about this heap, and |heap_name| will be used to
+// represent it in the report.
+bool ReportHeapDump(ProcessMemoryDump* pmd,
+                    const WinHeapInfo& heap_info,
+                    const std::string& heap_name) {
+  MemoryAllocatorDump* dump =
+      pmd->CreateAllocatorDump(kDumperFriendlyName, heap_name);
+  if (!dump)
+    return false;
+  dump->set_physical_size_in_bytes(heap_info.committed_size);
+  dump->set_allocated_objects_count(heap_info.block_count);
+  dump->set_allocated_objects_size_in_bytes(heap_info.allocated_size);
+  return true;
+}
+
+}  // namespace
+
+WinHeapDumpProvider* WinHeapDumpProvider::GetInstance() {
+  return Singleton<WinHeapDumpProvider,
+                   LeakySingletonTraits<WinHeapDumpProvider>>::get();
+}
+
+bool WinHeapDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+  // Retrieves the number of heaps in the current process.
+  DWORD number_of_heaps = ::GetProcessHeaps(0, NULL);
+  WinHeapInfo all_heap_info = {0};
+
+  // Try to retrieve a handle to all the heaps owned by this process. Returns
+  // false if the number of heaps has changed.
+  //
+  // This is inherently racy as is, but it's not something that we observe a lot
+  // in Chrome, the heaps tend to be created at startup only.
+  scoped_ptr<HANDLE[]> all_heaps(new HANDLE[number_of_heaps]);
+  if (::GetProcessHeaps(number_of_heaps, all_heaps.get()) != number_of_heaps)
+    return false;
+
+  // Skip the pointer to the heap array to avoid accounting the memory used by
+  // this dump provider.
+  std::set<void*> block_to_skip;
+  block_to_skip.insert(all_heaps.get());
+
+  // Retrieves some metrics about each heap.
+  for (size_t i = 0; i < number_of_heaps; ++i) {
+    WinHeapInfo heap_info = {0};
+    heap_info.heap_id = all_heaps[i];
+    GetHeapInformation(&heap_info, block_to_skip);
+
+    all_heap_info.allocated_size += heap_info.allocated_size;
+    all_heap_info.committed_size += heap_info.committed_size;
+    all_heap_info.block_count += heap_info.block_count;
+  }
+  // Report the heap dump.
+  if (!ReportHeapDump(pmd, all_heap_info, MemoryAllocatorDump::kRootHeap))
+    return false;
+
+  return true;
+}
+
+const char* WinHeapDumpProvider::GetFriendlyName() const {
+  return kDumperFriendlyName;
+}
+
+bool WinHeapDumpProvider::GetHeapInformation(
+    WinHeapInfo* heap_info,
+    const std::set<void*>& block_to_skip) {
+  CHECK(::HeapLock(heap_info->heap_id) == TRUE);
+  PROCESS_HEAP_ENTRY heap_entry;
+  heap_entry.lpData = nullptr;
+  // Walk over all the entries in this heap.
+  while (::HeapWalk(heap_info->heap_id, &heap_entry) != FALSE) {
+    if (block_to_skip.count(heap_entry.lpData) == 1)
+      continue;
+    if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
+      heap_info->allocated_size += heap_entry.cbData;
+      heap_info->block_count++;
+    } else if ((heap_entry.wFlags & PROCESS_HEAP_REGION) != 0) {
+      heap_info->committed_size += heap_entry.Region.dwCommittedSize;
+    }
+  }
+  CHECK(::HeapUnlock(heap_info->heap_id) == TRUE);
+  return true;
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/trace_event/winheap_dump_provider_win.h b/base/trace_event/winheap_dump_provider_win.h
new file mode 100644
index 0000000..8abac47
--- /dev/null
+++ b/base/trace_event/winheap_dump_provider_win.h
@@ -0,0 +1,53 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_
+#define BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_
+
+#include <set>
+
+#include "base/memory/singleton.h"
+#include "base/trace_event/memory_dump_provider.h"
+
+namespace base {
+namespace trace_event {
+
+// A structure containing some information about a given heap.
+struct WinHeapInfo {
+  HANDLE heap_id;
+  size_t committed_size;
+  size_t allocated_size;
+  size_t block_count;
+};
+
+// Dump provider which collects process-wide heap memory stats. This provider
+// iterates over all the heaps of the current process to gather some metrics
+// about them.
+class BASE_EXPORT WinHeapDumpProvider : public MemoryDumpProvider {
+ public:
+  static WinHeapDumpProvider* GetInstance();
+
+  // MemoryDumpProvider implementation.
+  bool DumpInto(ProcessMemoryDump* pmd) override;
+  const char* GetFriendlyName() const override;
+
+ private:
+  friend struct DefaultSingletonTraits<WinHeapDumpProvider>;
+
+  // Retrieves the information about given heap. The |heap_info| should contain
+  // a valid handle to an existing heap. The blocks contained in the
+  // |block_to_skip| set will be ignored.
+  bool GetHeapInformation(WinHeapInfo* heap_info,
+                          const std::set<void*>& block_to_skip);
+
+  WinHeapDumpProvider() {}
+  ~WinHeapDumpProvider() override {}
+
+  DISALLOW_COPY_AND_ASSIGN(WinHeapDumpProvider);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_
diff --git a/base/trace_event/winheap_dump_provider_win_unittest.cc b/base/trace_event/winheap_dump_provider_win_unittest.cc
new file mode 100644
index 0000000..99da18a
--- /dev/null
+++ b/base/trace_event/winheap_dump_provider_win_unittest.cc
@@ -0,0 +1,27 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/winheap_dump_provider_win.h"
+
+#include <windows.h>
+
+#include "base/trace_event/memory_dump_session_state.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace trace_event {
+
+TEST(WinHeapDumpProviderTest, DumpInto) {
+  ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
+
+  WinHeapDumpProvider* winheap_dump_provider =
+      WinHeapDumpProvider::GetInstance();
+  ASSERT_NE(static_cast<WinHeapDumpProvider*>(nullptr), winheap_dump_provider);
+
+  ASSERT_TRUE(winheap_dump_provider->DumpInto(&pmd));
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc
index 5359d89..a60e260 100644
--- a/base/tracked_objects.cc
+++ b/base/tracked_objects.cc
@@ -28,9 +28,6 @@
 namespace tracked_objects {
 
 namespace {
-// Flag to compile out almost all of the task tracking code.
-const bool kTrackAllTaskObjects = true;
-
 // TODO(jar): Evaluate the perf impact of enabling this.  If the perf impact is
 // negligible, enable by default.
 // Flag to compile out parent-child link recording.
@@ -366,8 +363,6 @@
   DCHECK(thread_data);  // TLS should *never* call us with a NULL.
   // We must NOT do any allocations during this callback. There is a chance
   // that the allocator is no longer active on this thread.
-  if (!kTrackAllTaskObjects)
-    return;  // Not compiled in.
   reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup();
 }
 
@@ -390,23 +385,9 @@
 }
 
 // static
-void ThreadData::Snapshot(ProcessDataSnapshot* process_data) {
-  // Add births that have run to completion to |collected_data|.
-  // |birth_counts| tracks the total number of births recorded at each location
-  // for which we have not seen a death count.
-  BirthCountMap birth_counts;
-  ThreadData::SnapshotAllExecutedTasks(process_data, &birth_counts);
-
-  // Add births that are still active -- i.e. objects that have tallied a birth,
-  // but have not yet tallied a matching death, and hence must be either
-  // running, queued up, or being held in limbo for future posting.
-  for (BirthCountMap::const_iterator it = birth_counts.begin();
-       it != birth_counts.end(); ++it) {
-    if (it->second > 0) {
-      process_data->tasks.push_back(
-          TaskSnapshot(*it->first, DeathData(it->second), "Still_Alive"));
-    }
-  }
+void ThreadData::Snapshot(ProcessDataSnapshot* process_data_snapshot) {
+  ThreadData::SnapshotCurrentPhase(
+      &process_data_snapshot->phased_process_data_snapshots[0]);
 }
 
 Births* ThreadData::TallyABirth(const Location& location) {
@@ -479,9 +460,6 @@
 
 // static
 Births* ThreadData::TallyABirthIfActive(const Location& location) {
-  if (!kTrackAllTaskObjects)
-    return NULL;  // Not compiled in.
-
   if (!TrackingStatus())
     return NULL;
   ThreadData* current_thread_data = Get();
@@ -494,9 +472,6 @@
 void ThreadData::TallyRunOnNamedThreadIfTracking(
     const base::TrackingInfo& completed_task,
     const TaskStopwatch& stopwatch) {
-  if (!kTrackAllTaskObjects)
-    return;  // Not compiled in.
-
   // Even if we have been DEACTIVATED, we will process any pending births so
   // that our data structures (which counted the outstanding births) remain
   // consistent.
@@ -526,9 +501,6 @@
     const Births* birth,
     const TrackedTime& time_posted,
     const TaskStopwatch& stopwatch) {
-  if (!kTrackAllTaskObjects)
-    return;  // Not compiled in.
-
   // Even if we have been DEACTIVATED, we will process any pending births so
   // that our data structures (which counted the outstanding births) remain
   // consistent.
@@ -560,9 +532,6 @@
 void ThreadData::TallyRunInAScopedRegionIfTracking(
     const Births* birth,
     const TaskStopwatch& stopwatch) {
-  if (!kTrackAllTaskObjects)
-    return;  // Not compiled in.
-
   // Even if we have been DEACTIVATED, we will process any pending births so
   // that our data structures (which counted the outstanding births) remain
   // consistent.
@@ -578,11 +547,9 @@
 }
 
 // static
-void ThreadData::SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data,
-                                          BirthCountMap* birth_counts) {
-  if (!kTrackAllTaskObjects)
-    return;  // Not compiled in.
-
+void ThreadData::SnapshotAllExecutedTasks(
+    ProcessDataPhaseSnapshot* process_data_phase,
+    BirthCountMap* birth_counts) {
   // Get an unchanging copy of a ThreadData list.
   ThreadData* my_list = ThreadData::first();
 
@@ -595,12 +562,33 @@
   for (ThreadData* thread_data = my_list;
        thread_data;
        thread_data = thread_data->next()) {
-    thread_data->SnapshotExecutedTasks(process_data, birth_counts);
+    thread_data->SnapshotExecutedTasks(process_data_phase, birth_counts);
   }
 }
 
-void ThreadData::SnapshotExecutedTasks(ProcessDataSnapshot* process_data,
-                                       BirthCountMap* birth_counts) {
+// static
+void ThreadData::SnapshotCurrentPhase(
+    ProcessDataPhaseSnapshot* process_data_phase) {
+  // Add births that have run to completion to |collected_data|.
+  // |birth_counts| tracks the total number of births recorded at each location
+  // for which we have not seen a death count.
+  BirthCountMap birth_counts;
+  ThreadData::SnapshotAllExecutedTasks(process_data_phase, &birth_counts);
+
+  // Add births that are still active -- i.e. objects that have tallied a birth,
+  // but have not yet tallied a matching death, and hence must be either
+  // running, queued up, or being held in limbo for future posting.
+  for (const auto& birth_count : birth_counts) {
+    if (birth_count.second > 0) {
+      process_data_phase->tasks.push_back(TaskSnapshot(
+          *birth_count.first, DeathData(birth_count.second), "Still_Alive"));
+    }
+  }
+}
+
+void ThreadData::SnapshotExecutedTasks(
+    ProcessDataPhaseSnapshot* process_data_phase,
+    BirthCountMap* birth_counts) {
   // Get copy of data, so that the data will not change during the iterations
   // and processing.
   ThreadData::BirthMap birth_map;
@@ -608,24 +596,22 @@
   ThreadData::ParentChildSet parent_child_set;
   SnapshotMaps(&birth_map, &death_map, &parent_child_set);
 
-  for (ThreadData::DeathMap::const_iterator it = death_map.begin();
-       it != death_map.end(); ++it) {
-    process_data->tasks.push_back(
-        TaskSnapshot(*it->first, it->second, thread_name()));
-    (*birth_counts)[it->first] -= it->first->birth_count();
+  for (const auto& death : death_map) {
+    process_data_phase->tasks.push_back(
+        TaskSnapshot(*death.first, death.second, thread_name()));
+    (*birth_counts)[death.first] -= death.first->birth_count();
   }
 
-  for (ThreadData::BirthMap::const_iterator it = birth_map.begin();
-       it != birth_map.end(); ++it) {
-    (*birth_counts)[it->second] += it->second->birth_count();
+  for (const auto& birth : birth_map) {
+    (*birth_counts)[birth.second] += birth.second->birth_count();
   }
 
   if (!kTrackParentChildLinks)
     return;
 
-  for (ThreadData::ParentChildSet::const_iterator it = parent_child_set.begin();
-       it != parent_child_set.end(); ++it) {
-    process_data->descendants.push_back(ParentChildPairSnapshot(*it));
+  for (const auto& parent_child : parent_child_set) {
+    process_data_phase->descendants.push_back(
+        ParentChildPairSnapshot(parent_child));
   }
 }
 
@@ -634,20 +620,16 @@
                               DeathMap* death_map,
                               ParentChildSet* parent_child_set) {
   base::AutoLock lock(map_lock_);
-  for (BirthMap::const_iterator it = birth_map_.begin();
-       it != birth_map_.end(); ++it)
-    (*birth_map)[it->first] = it->second;
-  for (DeathMap::iterator it = death_map_.begin();
-       it != death_map_.end(); ++it) {
-    (*death_map)[it->first] = it->second;
-  }
+  for (const auto& birth : birth_map_)
+    (*birth_map)[birth.first] = birth.second;
+  for (const auto& death : death_map_)
+    (*death_map)[death.first] = death.second;
 
   if (!kTrackParentChildLinks)
     return;
 
-  for (ParentChildSet::iterator it = parent_child_set_.begin();
-       it != parent_child_set_.end(); ++it)
-    parent_child_set->insert(*it);
+  for (const auto& parent_child : parent_child_set_)
+    parent_child_set->insert(parent_child);
 }
 
 static void OptionallyInitializeAlternateTimer() {
@@ -657,8 +639,6 @@
 }
 
 bool ThreadData::Initialize() {
-  if (!kTrackAllTaskObjects)
-    return false;  // Not compiled in.
   if (status_ >= DEACTIVATED)
     return true;  // Someone else did the initialization.
   // Due to racy lazy initialization in tests, we'll need to recheck status_
@@ -759,7 +739,7 @@
 TrackedTime ThreadData::Now() {
   if (kAllowAlternateTimeSourceHandling && now_function_)
     return TrackedTime::FromMilliseconds((*now_function_)());
-  if (kTrackAllTaskObjects && IsProfilerTimingEnabled() && TrackingStatus())
+  if (IsProfilerTimingEnabled() && TrackingStatus())
     return TrackedTime::Now();
   return TrackedTime();  // Super fast when disabled, or not compiled.
 }
@@ -959,13 +939,22 @@
 }
 
 //------------------------------------------------------------------------------
-// ProcessDataSnapshot
+// ProcessDataPhaseSnapshot
+
+ProcessDataPhaseSnapshot::ProcessDataPhaseSnapshot() {
+}
+
+ProcessDataPhaseSnapshot::~ProcessDataPhaseSnapshot() {
+}
+
+//------------------------------------------------------------------------------
+// ProcessDataPhaseSnapshot
 
 ProcessDataSnapshot::ProcessDataSnapshot()
 #if !defined(OS_NACL)
     : process_id(base::GetCurrentProcId()) {
 #else
-    : process_id(0) {
+    : process_id(base::kNullProcessId) {
 #endif
 }
 
diff --git a/base/tracked_objects.h b/base/tracked_objects.h
index 34c3667..9643265 100644
--- a/base/tracked_objects.h
+++ b/base/tracked_objects.h
@@ -18,6 +18,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/lazy_instance.h"
 #include "base/location.h"
+#include "base/process/process_handle.h"
 #include "base/profiler/alternate_timer.h"
 #include "base/profiler/tracked_time.h"
 #include "base/synchronization/lock.h"
@@ -147,10 +148,14 @@
 // TaskSnapshot instances, so that such instances can be sorted and
 // aggregated (and remain frozen during our processing).
 //
-// The ProcessDataSnapshot struct is a serialized representation of the list
-// of ThreadData objects for a process.  It holds a set of TaskSnapshots
-// and tracks parent/child relationships for the executed tasks.  The statistics
-// in a snapshot are gathered asynhcronously relative to their ongoing updates.
+// Profiling consists of phases. The concrete phase in the sequence of phases is
+// identified by its 0-based index.
+//
+// The ProcessDataPhaseSnapshot struct is a serialized representation of the
+// list of ThreadData objects for a process for a concrete profiling phase. It
+// holds a set of TaskSnapshots and tracks parent/child relationships for the
+// executed tasks. The statistics in a snapshot are gathered asynhcronously
+// relative to their ongoing updates.
 // It is possible, though highly unlikely, that stats could be incorrectly
 // recorded by this process (all data is held in 32 bit ints, but we are not
 // atomically collecting all data, so we could have count that does not, for
@@ -342,9 +347,15 @@
 // We also have a linked list of ThreadData instances, and that list is used to
 // harvest data from all existing instances.
 
+struct ProcessDataPhaseSnapshot;
 struct ProcessDataSnapshot;
 class BASE_EXPORT TaskStopwatch;
 
+// Map from profiling phase number to the process-wide snapshotted
+// representation of the list of ThreadData objects that died during the given
+// phase.
+typedef std::map<int, ProcessDataPhaseSnapshot> PhasedProcessDataSnapshotMap;
+
 class BASE_EXPORT ThreadData {
  public:
   // Current allowable states of the tracking system.  The states can vary
@@ -376,8 +387,9 @@
   // This may return NULL if the system is disabled for any reason.
   static ThreadData* Get();
 
-  // Fills |process_data| with all the recursive results in our process.
-  static void Snapshot(ProcessDataSnapshot* process_data);
+  // Fills |process_data_snapshot| with phased snapshots of all profiling
+  // phases, including the current one.
+  static void Snapshot(ProcessDataSnapshot* process_data_snapshot);
 
   // Finds (or creates) a place to count births from the given location in this
   // thread, and increment that tally.
@@ -403,16 +415,14 @@
   // the task.
   // The |end_of_run| was just obtained by a call to Now() (just after the task
   // finished).
-  static void TallyRunOnWorkerThreadIfTracking(
-      const Births* birth,
-      const TrackedTime& time_posted,
-      const TaskStopwatch& stopwatch);
+  static void TallyRunOnWorkerThreadIfTracking(const Births* birth,
+                                               const TrackedTime& time_posted,
+                                               const TaskStopwatch& stopwatch);
 
   // Record the end of execution in region, generally corresponding to a scope
   // being exited.
-  static void TallyRunInAScopedRegionIfTracking(
-      const Births* birth,
-      const TaskStopwatch& stopwatch);
+  static void TallyRunInAScopedRegionIfTracking(const Births* birth,
+                                                const TaskStopwatch& stopwatch);
 
   const std::string& thread_name() const { return thread_name_; }
 
@@ -514,16 +524,21 @@
   // Snapshot (under a lock) the profiled data for the tasks in each ThreadData
   // instance.  Also updates the |birth_counts| tally for each task to keep
   // track of the number of living instances of the task.
-  static void SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data,
-                                       BirthCountMap* birth_counts);
+  static void SnapshotAllExecutedTasks(
+      ProcessDataPhaseSnapshot* process_data_phase,
+      BirthCountMap* birth_counts);
+
+  // Fills |process_data_phase| with all the recursive results in our process.
+  static void SnapshotCurrentPhase(
+      ProcessDataPhaseSnapshot* process_data_phase);
 
   // Snapshots (under a lock) the profiled data for the tasks for this thread
   // and writes all of the executed tasks' data -- i.e. the data for the tasks
-  // with with entries in the death_map_ -- into |process_data|.  Also updates
-  // the |birth_counts| tally for each task to keep track of the number of
-  // living instances of the task -- that is, each task maps to the number of
+  // with with entries in the death_map_ -- into |process_data_phase|.  Also
+  // updates the |birth_counts| tally for each task to keep track of the number
+  // of living instances of the task -- that is, each task maps to the number of
   // births for the task that have not yet been balanced by a death.
-  void SnapshotExecutedTasks(ProcessDataSnapshot* process_data,
+  void SnapshotExecutedTasks(ProcessDataPhaseSnapshot* process_data_phase,
                              BirthCountMap* birth_counts);
 
   // Using our lock, make a copy of the specified maps.  This call may be made
@@ -747,16 +762,29 @@
 };
 
 //------------------------------------------------------------------------------
-// A snapshotted representation of the list of ThreadData objects for a process.
+// A snapshotted representation of the list of ThreadData objects for a process,
+// for a single profiling phase.
+
+struct BASE_EXPORT ProcessDataPhaseSnapshot {
+ public:
+  ProcessDataPhaseSnapshot();
+  ~ProcessDataPhaseSnapshot();
+
+  std::vector<TaskSnapshot> tasks;
+  std::vector<ParentChildPairSnapshot> descendants;
+};
+
+//------------------------------------------------------------------------------
+// A snapshotted representation of the list of ThreadData objects for a process,
+// for all profiling phases, including the current one.
 
 struct BASE_EXPORT ProcessDataSnapshot {
  public:
   ProcessDataSnapshot();
   ~ProcessDataSnapshot();
 
-  std::vector<TaskSnapshot> tasks;
-  std::vector<ParentChildPairSnapshot> descendants;
-  int process_id;
+  PhasedProcessDataSnapshotMap phased_process_data_snapshots;
+  base::ProcessId process_id;
 };
 
 }  // namespace tracked_objects
diff --git a/base/tracked_objects_unittest.cc b/base/tracked_objects_unittest.cc
index 7713091..5455fef 100644
--- a/base/tracked_objects_unittest.cc
+++ b/base/tracked_objects_unittest.cc
@@ -71,28 +71,37 @@
                                int count,
                                int run_ms,
                                int queue_ms) {
-    ASSERT_EQ(1u, process_data.tasks.size());
+    ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+    auto it = process_data.phased_process_data_snapshots.find(0);
+    ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+    const ProcessDataPhaseSnapshot& process_data_phase = it->second;
 
-    EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
+    ASSERT_EQ(1u, process_data_phase.tasks.size());
+
+    EXPECT_EQ(kFile, process_data_phase.tasks[0].birth.location.file_name);
     EXPECT_EQ(function_name,
-              process_data.tasks[0].birth.location.function_name);
-    EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number);
+              process_data_phase.tasks[0].birth.location.function_name);
+    EXPECT_EQ(kLineNumber,
+              process_data_phase.tasks[0].birth.location.line_number);
 
-    EXPECT_EQ(birth_thread, process_data.tasks[0].birth.thread_name);
+    EXPECT_EQ(birth_thread, process_data_phase.tasks[0].birth.thread_name);
 
-    EXPECT_EQ(count, process_data.tasks[0].death_data.count);
+    EXPECT_EQ(count, process_data_phase.tasks[0].death_data.count);
     EXPECT_EQ(count * run_ms,
-              process_data.tasks[0].death_data.run_duration_sum);
-    EXPECT_EQ(run_ms, process_data.tasks[0].death_data.run_duration_max);
-    EXPECT_EQ(run_ms, process_data.tasks[0].death_data.run_duration_sample);
+              process_data_phase.tasks[0].death_data.run_duration_sum);
+    EXPECT_EQ(run_ms, process_data_phase.tasks[0].death_data.run_duration_max);
+    EXPECT_EQ(run_ms,
+              process_data_phase.tasks[0].death_data.run_duration_sample);
     EXPECT_EQ(count * queue_ms,
-              process_data.tasks[0].death_data.queue_duration_sum);
-    EXPECT_EQ(queue_ms, process_data.tasks[0].death_data.queue_duration_max);
-    EXPECT_EQ(queue_ms, process_data.tasks[0].death_data.queue_duration_sample);
+              process_data_phase.tasks[0].death_data.queue_duration_sum);
+    EXPECT_EQ(queue_ms,
+              process_data_phase.tasks[0].death_data.queue_duration_max);
+    EXPECT_EQ(queue_ms,
+              process_data_phase.tasks[0].death_data.queue_duration_sample);
 
-    EXPECT_EQ(death_thread, process_data.tasks[0].death_thread_name);
+    EXPECT_EQ(death_thread, process_data_phase.tasks[0].death_thread_name);
 
-    EXPECT_EQ(0u, process_data.descendants.size());
+    EXPECT_EQ(0u, process_data_phase.descendants.size());
 
     EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
   }
@@ -230,37 +239,49 @@
   ProcessDataSnapshot process_data;
   ThreadData::Snapshot(&process_data);
 
-  ASSERT_EQ(1u, process_data.tasks.size());
-  EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
-  EXPECT_EQ(kFunction, process_data.tasks[0].birth.location.function_name);
-  EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number);
-  EXPECT_EQ(kWorkerThreadName, process_data.tasks[0].birth.thread_name);
-  EXPECT_EQ(1, process_data.tasks[0].death_data.count);
-  EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_sum);
-  EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_max);
-  EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_sample);
-  EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_sum);
-  EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_max);
-  EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_sample);
-  EXPECT_EQ(kWorkerThreadName, process_data.tasks[0].death_thread_name);
+  ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+  auto it = process_data.phased_process_data_snapshots.find(0);
+  ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+  const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+  ASSERT_EQ(1u, process_data_phase.tasks.size());
+  EXPECT_EQ(kFile, process_data_phase.tasks[0].birth.location.file_name);
+  EXPECT_EQ(kFunction,
+            process_data_phase.tasks[0].birth.location.function_name);
+  EXPECT_EQ(kLineNumber,
+            process_data_phase.tasks[0].birth.location.line_number);
+  EXPECT_EQ(kWorkerThreadName, process_data_phase.tasks[0].birth.thread_name);
+  EXPECT_EQ(1, process_data_phase.tasks[0].death_data.count);
+  EXPECT_EQ(time_elapsed,
+            process_data_phase.tasks[0].death_data.run_duration_sum);
+  EXPECT_EQ(time_elapsed,
+            process_data_phase.tasks[0].death_data.run_duration_max);
+  EXPECT_EQ(time_elapsed,
+            process_data_phase.tasks[0].death_data.run_duration_sample);
+  EXPECT_EQ(0, process_data_phase.tasks[0].death_data.queue_duration_sum);
+  EXPECT_EQ(0, process_data_phase.tasks[0].death_data.queue_duration_max);
+  EXPECT_EQ(0, process_data_phase.tasks[0].death_data.queue_duration_sample);
+  EXPECT_EQ(kWorkerThreadName, process_data_phase.tasks[0].death_thread_name);
 
   if (ThreadData::TrackingParentChildStatus()) {
-    ASSERT_EQ(1u, process_data.descendants.size());
-    EXPECT_EQ(kFile, process_data.descendants[0].parent.location.file_name);
+    ASSERT_EQ(1u, process_data_phase.descendants.size());
+    EXPECT_EQ(kFile,
+              process_data_phase.descendants[0].parent.location.file_name);
     EXPECT_EQ(kFunction,
-              process_data.descendants[0].parent.location.function_name);
+              process_data_phase.descendants[0].parent.location.function_name);
     EXPECT_EQ(kLineNumber,
-              process_data.descendants[0].parent.location.line_number);
+              process_data_phase.descendants[0].parent.location.line_number);
     EXPECT_EQ(kWorkerThreadName,
-              process_data.descendants[0].parent.thread_name);
-    EXPECT_EQ(kFile, process_data.descendants[0].child.location.file_name);
+              process_data_phase.descendants[0].parent.thread_name);
+    EXPECT_EQ(kFile,
+              process_data_phase.descendants[0].child.location.file_name);
     EXPECT_EQ(kFunction,
-              process_data.descendants[0].child.location.function_name);
+              process_data_phase.descendants[0].child.location.function_name);
     EXPECT_EQ(kLineNumber,
-              process_data.descendants[0].child.location.line_number);
-    EXPECT_EQ(kWorkerThreadName, process_data.descendants[0].child.thread_name);
+              process_data_phase.descendants[0].child.location.line_number);
+    EXPECT_EQ(kWorkerThreadName,
+              process_data_phase.descendants[0].child.thread_name);
   } else {
-    EXPECT_EQ(0u, process_data.descendants.size());
+    EXPECT_EQ(0u, process_data_phase.descendants.size());
   }
 }
 
@@ -318,8 +339,14 @@
 
   ProcessDataSnapshot process_data;
   ThreadData::Snapshot(&process_data);
-  EXPECT_EQ(0u, process_data.tasks.size());
-  EXPECT_EQ(0u, process_data.descendants.size());
+
+  ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+  auto it = process_data.phased_process_data_snapshots.find(0);
+  ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+  const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+  EXPECT_EQ(0u, process_data_phase.tasks.size());
+  EXPECT_EQ(0u, process_data_phase.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
 }
 
@@ -335,8 +362,14 @@
 
   ProcessDataSnapshot process_data;
   ThreadData::Snapshot(&process_data);
-  EXPECT_EQ(0u, process_data.tasks.size());
-  EXPECT_EQ(0u, process_data.descendants.size());
+
+  ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+  auto it = process_data.phased_process_data_snapshots.find(0);
+  ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+  const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+  EXPECT_EQ(0u, process_data_phase.tasks.size());
+  EXPECT_EQ(0u, process_data_phase.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
 }
 
@@ -425,8 +458,8 @@
   pending_task.time_posted = kTimePosted;  // Overwrite implied Now().
 
   // Turn off tracking now that we have births.
-  EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus(
-      ThreadData::DEACTIVATED));
+  EXPECT_TRUE(
+      ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED));
 
   const unsigned int kStartOfRun = 5;
   const unsigned int kEndOfRun = 7;
@@ -474,8 +507,14 @@
 
   ProcessDataSnapshot process_data;
   ThreadData::Snapshot(&process_data);
-  EXPECT_EQ(0u, process_data.tasks.size());
-  EXPECT_EQ(0u, process_data.descendants.size());
+
+  ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+  auto it = process_data.phased_process_data_snapshots.find(0);
+  ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+  const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+  EXPECT_EQ(0u, process_data_phase.tasks.size());
+  EXPECT_EQ(0u, process_data_phase.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
 }
 
@@ -558,34 +597,43 @@
 
   ProcessDataSnapshot process_data;
   ThreadData::Snapshot(&process_data);
-  ASSERT_EQ(2u, process_data.tasks.size());
 
-  EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
-  EXPECT_EQ(kFunction, process_data.tasks[0].birth.location.function_name);
-  EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number);
-  EXPECT_EQ(kMainThreadName, process_data.tasks[0].birth.thread_name);
-  EXPECT_EQ(1, process_data.tasks[0].death_data.count);
-  EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_sum);
-  EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_max);
-  EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_sample);
-  EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_sum);
-  EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_max);
-  EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_sample);
-  EXPECT_EQ(kMainThreadName, process_data.tasks[0].death_thread_name);
-  EXPECT_EQ(kFile, process_data.tasks[1].birth.location.file_name);
-  EXPECT_EQ(kFunction, process_data.tasks[1].birth.location.function_name);
+  ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+  auto it = process_data.phased_process_data_snapshots.find(0);
+  ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+  const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
+  ASSERT_EQ(2u, process_data_phase.tasks.size());
+
+  EXPECT_EQ(kFile, process_data_phase.tasks[0].birth.location.file_name);
+  EXPECT_EQ(kFunction,
+            process_data_phase.tasks[0].birth.location.function_name);
+  EXPECT_EQ(kLineNumber,
+            process_data_phase.tasks[0].birth.location.line_number);
+  EXPECT_EQ(kMainThreadName, process_data_phase.tasks[0].birth.thread_name);
+  EXPECT_EQ(1, process_data_phase.tasks[0].death_data.count);
+  EXPECT_EQ(2, process_data_phase.tasks[0].death_data.run_duration_sum);
+  EXPECT_EQ(2, process_data_phase.tasks[0].death_data.run_duration_max);
+  EXPECT_EQ(2, process_data_phase.tasks[0].death_data.run_duration_sample);
+  EXPECT_EQ(4, process_data_phase.tasks[0].death_data.queue_duration_sum);
+  EXPECT_EQ(4, process_data_phase.tasks[0].death_data.queue_duration_max);
+  EXPECT_EQ(4, process_data_phase.tasks[0].death_data.queue_duration_sample);
+  EXPECT_EQ(kMainThreadName, process_data_phase.tasks[0].death_thread_name);
+  EXPECT_EQ(kFile, process_data_phase.tasks[1].birth.location.file_name);
+  EXPECT_EQ(kFunction,
+            process_data_phase.tasks[1].birth.location.function_name);
   EXPECT_EQ(kSecondFakeLineNumber,
-            process_data.tasks[1].birth.location.line_number);
-  EXPECT_EQ(kMainThreadName, process_data.tasks[1].birth.thread_name);
-  EXPECT_EQ(1, process_data.tasks[1].death_data.count);
-  EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_sum);
-  EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_max);
-  EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_sample);
-  EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_sum);
-  EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_max);
-  EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_sample);
-  EXPECT_EQ(kStillAlive, process_data.tasks[1].death_thread_name);
-  EXPECT_EQ(0u, process_data.descendants.size());
+            process_data_phase.tasks[1].birth.location.line_number);
+  EXPECT_EQ(kMainThreadName, process_data_phase.tasks[1].birth.thread_name);
+  EXPECT_EQ(1, process_data_phase.tasks[1].death_data.count);
+  EXPECT_EQ(0, process_data_phase.tasks[1].death_data.run_duration_sum);
+  EXPECT_EQ(0, process_data_phase.tasks[1].death_data.run_duration_max);
+  EXPECT_EQ(0, process_data_phase.tasks[1].death_data.run_duration_sample);
+  EXPECT_EQ(0, process_data_phase.tasks[1].death_data.queue_duration_sum);
+  EXPECT_EQ(0, process_data_phase.tasks[1].death_data.queue_duration_max);
+  EXPECT_EQ(0, process_data_phase.tasks[1].death_data.queue_duration_sample);
+  EXPECT_EQ(kStillAlive, process_data_phase.tasks[1].death_thread_name);
+  EXPECT_EQ(0u, process_data_phase.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
 }
 
@@ -719,38 +767,48 @@
   ProcessDataSnapshot process_data;
   ThreadData::Snapshot(&process_data);
 
+  ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size());
+  auto it = process_data.phased_process_data_snapshots.find(0);
+  ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end());
+  const ProcessDataPhaseSnapshot& process_data_phase = it->second;
+
   // The order in which the two task follow is platform-dependent.
-  int t0 = (process_data.tasks[0].birth.location.line_number == kLineNumber) ?
-      0 : 1;
+  int t0 =
+      (process_data_phase.tasks[0].birth.location.line_number == kLineNumber)
+          ? 0
+          : 1;
   int t1 = 1 - t0;
 
-  ASSERT_EQ(2u, process_data.tasks.size());
-  EXPECT_EQ(kFile, process_data.tasks[t0].birth.location.file_name);
-  EXPECT_EQ(kFunction, process_data.tasks[t0].birth.location.function_name);
-  EXPECT_EQ(kLineNumber, process_data.tasks[t0].birth.location.line_number);
-  EXPECT_EQ(kMainThreadName, process_data.tasks[t0].birth.thread_name);
-  EXPECT_EQ(1, process_data.tasks[t0].death_data.count);
-  EXPECT_EQ(6, process_data.tasks[t0].death_data.run_duration_sum);
-  EXPECT_EQ(6, process_data.tasks[t0].death_data.run_duration_max);
-  EXPECT_EQ(6, process_data.tasks[t0].death_data.run_duration_sample);
-  EXPECT_EQ(4, process_data.tasks[t0].death_data.queue_duration_sum);
-  EXPECT_EQ(4, process_data.tasks[t0].death_data.queue_duration_max);
-  EXPECT_EQ(4, process_data.tasks[t0].death_data.queue_duration_sample);
-  EXPECT_EQ(kMainThreadName, process_data.tasks[t0].death_thread_name);
-  EXPECT_EQ(kFile, process_data.tasks[t1].birth.location.file_name);
-  EXPECT_EQ(kFunction, process_data.tasks[t1].birth.location.function_name);
+  ASSERT_EQ(2u, process_data_phase.tasks.size());
+  EXPECT_EQ(kFile, process_data_phase.tasks[t0].birth.location.file_name);
+  EXPECT_EQ(kFunction,
+            process_data_phase.tasks[t0].birth.location.function_name);
+  EXPECT_EQ(kLineNumber,
+            process_data_phase.tasks[t0].birth.location.line_number);
+  EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t0].birth.thread_name);
+  EXPECT_EQ(1, process_data_phase.tasks[t0].death_data.count);
+  EXPECT_EQ(6, process_data_phase.tasks[t0].death_data.run_duration_sum);
+  EXPECT_EQ(6, process_data_phase.tasks[t0].death_data.run_duration_max);
+  EXPECT_EQ(6, process_data_phase.tasks[t0].death_data.run_duration_sample);
+  EXPECT_EQ(4, process_data_phase.tasks[t0].death_data.queue_duration_sum);
+  EXPECT_EQ(4, process_data_phase.tasks[t0].death_data.queue_duration_max);
+  EXPECT_EQ(4, process_data_phase.tasks[t0].death_data.queue_duration_sample);
+  EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t0].death_thread_name);
+  EXPECT_EQ(kFile, process_data_phase.tasks[t1].birth.location.file_name);
+  EXPECT_EQ(kFunction,
+            process_data_phase.tasks[t1].birth.location.function_name);
   EXPECT_EQ(kSecondFakeLineNumber,
-            process_data.tasks[t1].birth.location.line_number);
-  EXPECT_EQ(kMainThreadName, process_data.tasks[t1].birth.thread_name);
-  EXPECT_EQ(1, process_data.tasks[t1].death_data.count);
-  EXPECT_EQ(2, process_data.tasks[t1].death_data.run_duration_sum);
-  EXPECT_EQ(2, process_data.tasks[t1].death_data.run_duration_max);
-  EXPECT_EQ(2, process_data.tasks[t1].death_data.run_duration_sample);
-  EXPECT_EQ(1, process_data.tasks[t1].death_data.queue_duration_sum);
-  EXPECT_EQ(1, process_data.tasks[t1].death_data.queue_duration_max);
-  EXPECT_EQ(1, process_data.tasks[t1].death_data.queue_duration_sample);
-  EXPECT_EQ(kMainThreadName, process_data.tasks[t1].death_thread_name);
-  EXPECT_EQ(0u, process_data.descendants.size());
+            process_data_phase.tasks[t1].birth.location.line_number);
+  EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t1].birth.thread_name);
+  EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.count);
+  EXPECT_EQ(2, process_data_phase.tasks[t1].death_data.run_duration_sum);
+  EXPECT_EQ(2, process_data_phase.tasks[t1].death_data.run_duration_max);
+  EXPECT_EQ(2, process_data_phase.tasks[t1].death_data.run_duration_sample);
+  EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.queue_duration_sum);
+  EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.queue_duration_max);
+  EXPECT_EQ(1, process_data_phase.tasks[t1].death_data.queue_duration_sample);
+  EXPECT_EQ(kMainThreadName, process_data_phase.tasks[t1].death_thread_name);
+  EXPECT_EQ(0u, process_data_phase.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
 }
 
diff --git a/base/tuple.h b/base/tuple.h
index 41c6a00..88c3075 100644
--- a/base/tuple.h
+++ b/base/tuple.h
@@ -81,6 +81,12 @@
 template <> struct MakeIndexSequenceImpl<11> {
   using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10>;
 };
+template <> struct MakeIndexSequenceImpl<12> {
+  using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11>;
+};
+template <> struct MakeIndexSequenceImpl<13> {
+  using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11,12>;
+};
 
 #else  // defined(WIN) && defined(_PREFAST_)
 
diff --git a/base/values.cc b/base/values.cc
index 52876cf..0e1e2b1 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -7,9 +7,9 @@
 #include <string.h>
 
 #include <algorithm>
+#include <cmath>
 #include <ostream>
 
-#include "base/float_util.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/move.h"
@@ -175,7 +175,7 @@
 
 FundamentalValue::FundamentalValue(double in_value)
     : Value(TYPE_DOUBLE), double_value_(in_value) {
-  if (!IsFinite(double_value_)) {
+  if (!std::isfinite(double_value_)) {
     NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
                  << "values cannot be represented in JSON";
     double_value_ = 0.0;
diff --git a/base/win/enum_variant.h b/base/win/enum_variant.h
index d978eaa..2caaccd 100644
--- a/base/win/enum_variant.h
+++ b/base/win/enum_variant.h
@@ -39,7 +39,7 @@
   STDMETHODIMP Clone(IEnumVARIANT** out_cloned_object) override;
 
  private:
-  ~EnumVariant();
+  ~EnumVariant() override;
 
   scoped_ptr<VARIANT[]> items_;
   unsigned long count_;
diff --git a/base/win/event_trace_consumer.h b/base/win/event_trace_consumer.h
index 9322e1e..fd44894 100644
--- a/base/win/event_trace_consumer.h
+++ b/base/win/event_trace_consumer.h
@@ -119,7 +119,7 @@
 template <class ImplClass> inline
 HRESULT EtwTraceConsumerBase<ImplClass>::Consume() {
   ULONG err = ::ProcessTrace(&trace_handles_[0],
-                             trace_handles_.size(),
+                             static_cast<ULONG>(trace_handles_.size()),
                              NULL,
                              NULL);
   return HRESULT_FROM_WIN32(err);
diff --git a/base/win/event_trace_consumer_unittest.cc b/base/win/event_trace_consumer_unittest.cc
index 3043152..ecbf238 100644
--- a/base/win/event_trace_consumer_unittest.cc
+++ b/base/win/event_trace_consumer_unittest.cc
@@ -82,7 +82,7 @@
       : session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
   }
 
-  virtual void SetUp() {
+  void SetUp() override {
     // Cleanup any potentially dangling sessions.
     EtwTraceProperties ignore;
     EtwTraceController::Stop(session_name_.c_str(), &ignore);
@@ -91,7 +91,7 @@
     ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
   }
 
-  virtual void TearDown() {
+  void TearDown() override {
     // Cleanup any potentially dangling sessions.
     EtwTraceProperties ignore;
     EtwTraceController::Stop(session_name_.c_str(), &ignore);
@@ -125,13 +125,13 @@
 
 class EtwTraceConsumerRealtimeTest: public EtwTraceConsumerBaseTest {
  public:
-  virtual void SetUp() {
+  void SetUp() override {
     EtwTraceConsumerBaseTest::SetUp();
     ASSERT_HRESULT_SUCCEEDED(
         consumer_.OpenRealtimeSession(session_name_.c_str()));
   }
 
-  virtual void TearDown() {
+  void TearDown() override {
     consumer_.Close();
     EtwTraceConsumerBaseTest::TearDown();
   }
@@ -261,7 +261,7 @@
   EtwTraceConsumerDataTest() {
   }
 
-  virtual void SetUp() {
+  void SetUp() override {
     EtwTraceConsumerBaseTest::SetUp();
 
     EtwTraceProperties prop;
@@ -273,7 +273,7 @@
     temp_file_ = temp_dir_.path().Append(L"test.etl");
   }
 
-  virtual void TearDown() {
+  void TearDown() override {
     EXPECT_TRUE(base::DeleteFile(temp_file_, false));
 
     EtwTraceConsumerBaseTest::TearDown();
diff --git a/base/win/event_trace_controller_unittest.cc b/base/win/event_trace_controller_unittest.cc
index be11128..a2cd81c 100644
--- a/base/win/event_trace_controller_unittest.cc
+++ b/base/win/event_trace_controller_unittest.cc
@@ -42,12 +42,8 @@
   }
 
  private:
-  virtual void OnEventsEnabled() {
-    ::SetEvent(callback_event_.Get());
-  }
-  virtual void PostEventsDisabled() {
-    ::SetEvent(callback_event_.Get());
-  }
+  void OnEventsEnabled() override { ::SetEvent(callback_event_.Get()); }
+  void PostEventsDisabled() override { ::SetEvent(callback_event_.Get()); }
 
   ScopedHandle callback_event_;
 
@@ -113,7 +109,7 @@
       : session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
   }
 
-  virtual void SetUp() {
+  void SetUp() override {
     EtwTraceProperties ignore;
     EtwTraceController::Stop(session_name_.c_str(), &ignore);
 
@@ -121,7 +117,7 @@
     ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
   }
 
-  virtual void TearDown() {
+  void TearDown() override {
     EtwTraceProperties prop;
     EtwTraceController::Stop(session_name_.c_str(), &prop);
   }
diff --git a/base/win/iunknown_impl.h b/base/win/iunknown_impl.h
index 4283d02..b7de205 100644
--- a/base/win/iunknown_impl.h
+++ b/base/win/iunknown_impl.h
@@ -19,11 +19,11 @@
  public:
   IUnknownImpl();
 
-  virtual ULONG STDMETHODCALLTYPE AddRef() override;
-  virtual ULONG STDMETHODCALLTYPE Release() override;
+  ULONG STDMETHODCALLTYPE AddRef() override;
+  ULONG STDMETHODCALLTYPE Release() override;
 
   // Subclasses should extend this to return any interfaces they provide.
-  virtual STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
+  STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
 
  protected:
   virtual ~IUnknownImpl();
diff --git a/base/win/iunknown_impl_unittest.cc b/base/win/iunknown_impl_unittest.cc
index db86214..874a43a 100644
--- a/base/win/iunknown_impl_unittest.cc
+++ b/base/win/iunknown_impl_unittest.cc
@@ -15,9 +15,7 @@
   TestIUnknownImplSubclass() {
     ++instance_count;
   }
-  virtual ~TestIUnknownImplSubclass() {
-    --instance_count;
-  }
+  ~TestIUnknownImplSubclass() override { --instance_count; }
   static int instance_count;
 };
 
diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h
index 0ae2532..d68d935 100644
--- a/base/win/object_watcher.h
+++ b/base/win/object_watcher.h
@@ -56,7 +56,7 @@
   };
 
   ObjectWatcher();
-  ~ObjectWatcher();
+  ~ObjectWatcher() override;
 
   // When the object is signaled, the given delegate is notified on the thread
   // where StartWatching is called.  The ObjectWatcher is not responsible for
@@ -87,7 +87,7 @@
   void Signal(Delegate* delegate);
 
   // MessageLoop::DestructionObserver implementation:
-  virtual void WillDestroyCurrentMessageLoop();
+  void WillDestroyCurrentMessageLoop() override;
 
   // Internal state.
   Closure callback_;
diff --git a/base/win/object_watcher_unittest.cc b/base/win/object_watcher_unittest.cc
index 1a5e9e2..b30ca41 100644
--- a/base/win/object_watcher_unittest.cc
+++ b/base/win/object_watcher_unittest.cc
@@ -17,7 +17,7 @@
 
 class QuitDelegate : public ObjectWatcher::Delegate {
  public:
-  virtual void OnObjectSignaled(HANDLE object) {
+  void OnObjectSignaled(HANDLE object) override {
     MessageLoop::current()->QuitWhenIdle();
   }
 };
@@ -26,9 +26,8 @@
  public:
   explicit DecrementCountDelegate(int* counter) : counter_(counter) {
   }
-  virtual void OnObjectSignaled(HANDLE object) {
-    --(*counter_);
-  }
+  void OnObjectSignaled(HANDLE object) override { --(*counter_); }
+
  private:
   int* counter_;
 };
diff --git a/base/win/pe_image.cc b/base/win/pe_image.cc
index e226b6a..19b381d 100644
--- a/base/win/pe_image.cc
+++ b/base/win/pe_image.cc
@@ -568,14 +568,12 @@
   if (NULL == section_header)
     return false;
 
-#pragma warning(push)
-#pragma warning(disable: 4311)
+#pragma warning(suppress : 4302) // pointer truncation
   // These casts generate warnings because they are 32 bit specific.
   // Don't follow the virtual RVAToAddr, use the one on the base.
   DWORD offset_within_section = reinterpret_cast<DWORD>(address) -
                                     reinterpret_cast<DWORD>(PEImage::RVAToAddr(
                                         section_header->VirtualAddress));
-#pragma warning(pop)
 
   *on_disk_offset = section_header->PointerToRawData + offset_within_section;
   return true;
diff --git a/base/win/pe_image.h b/base/win/pe_image.h
index 5cef537..343d286 100644
--- a/base/win/pe_image.h
+++ b/base/win/pe_image.h
@@ -238,7 +238,7 @@
  public:
   explicit PEImageAsData(HMODULE hModule) : PEImage(hModule) {}
 
-  virtual PVOID RVAToAddr(DWORD rva) const;
+  PVOID RVAToAddr(DWORD rva) const override;
 };
 
 inline bool PEImage::IsOrdinal(LPCSTR name) {
diff --git a/base/win/registry.cc b/base/win/registry.cc
index d0df48a..47afcbf 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -38,7 +38,7 @@
 class RegKey::Watcher : public ObjectWatcher::Delegate {
  public:
   explicit Watcher(RegKey* owner) : owner_(owner) {}
-  ~Watcher() {}
+  ~Watcher() override {}
 
   bool StartWatching(HKEY key, const ChangeCallback& callback);
 
diff --git a/base/win/registry_unittest.cc b/base/win/registry_unittest.cc
index 6548474..2257663 100644
--- a/base/win/registry_unittest.cc
+++ b/base/win/registry_unittest.cc
@@ -31,7 +31,7 @@
 #endif  //  _WIN64
 
   RegistryTest() {}
-  virtual void SetUp() override {
+  void SetUp() override {
     // Create a temporary key.
     RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
     key.DeleteKey(kRootKey);
@@ -42,7 +42,7 @@
     foo_software_key_ += L"\\Foo";
   }
 
-  virtual void TearDown() override {
+  void TearDown() override {
     // Clean up the temporary key.
     RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE);
     ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
diff --git a/base/win/scoped_handle.cc b/base/win/scoped_handle.cc
index 2803021..33a8aa5 100644
--- a/base/win/scoped_handle.cc
+++ b/base/win/scoped_handle.cc
@@ -12,6 +12,11 @@
 #include "base/logging.h"
 #include "base/synchronization/lock_impl.h"
 
+extern "C" {
+__declspec(dllexport) void* GetHandleVerifier();
+typedef void* (*GetHandleVerifierFn)();
+}
+
 namespace {
 
 struct HandleHash {
@@ -30,20 +35,9 @@
 };
 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap;
 
-// g_lock protects g_handle_map and g_closing.
+// g_lock protects the handle map and setting g_active_verifier.
 typedef base::internal::LockImpl NativeLock;
 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER;
-bool g_closing = false;
-
-// g_verifier_enabled is not protected by g_lock because that would require
-// using the lock (hence, synchornizing multiple threads) even when the
-// verifier is not in use. Note that this variable is initialized to track all
-// handles, and it should only move to the disabled state, and never back to
-// enabled, because that would crash when seeing handles created while the
-// verifier was disabled. This also implies that it is OK if the value change is
-// not propagated immediately to all CPUs (as would happen with a lock).
-bool g_verifier_enabled = true;
 
 bool CloseHandleWrapper(HANDLE handle) {
   if (!::CloseHandle(handle))
@@ -68,81 +62,184 @@
   DISALLOW_COPY_AND_ASSIGN(AutoNativeLock);
 };
 
+// Implements the actual object that is verifying handles for this process.
+// The active instance is shared across the module boundary but there is no
+// way to delete this object from the wrong side of it (or any side, actually).
+class ActiveVerifier {
+ public:
+  explicit ActiveVerifier(bool enabled)
+      : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) {
+  }
+
+  // Retrieves the current verifier.
+  static ActiveVerifier* Get();
+
+  // The methods required by HandleTraits. They are virtual because we need to
+  // forward the call execution to another module, instead of letting the
+  // compiler call the version that is linked in the current module.
+  virtual bool CloseHandle(HANDLE handle);
+  virtual void StartTracking(HANDLE handle, const void* owner,
+                             const void* pc1, const void* pc2);
+  virtual void StopTracking(HANDLE handle, const void* owner,
+                            const void* pc1, const void* pc2);
+  virtual void Disable();
+  virtual void OnHandleBeingClosed(HANDLE handle);
+
+ private:
+  ~ActiveVerifier();  // Not implemented.
+
+  static void InstallVerifier();
+
+  bool enabled_;
+  bool closing_;
+  NativeLock* lock_;
+  HandleMap map_;
+  DISALLOW_COPY_AND_ASSIGN(ActiveVerifier);
+};
+ActiveVerifier* g_active_verifier = NULL;
+
+// static
+ActiveVerifier* ActiveVerifier::Get() {
+  if (!g_active_verifier)
+    ActiveVerifier::InstallVerifier();
+
+  return g_active_verifier;
+}
+
+// static
+void ActiveVerifier::InstallVerifier() {
+#if defined(COMPONENT_BUILD)
+  AutoNativeLock lock(g_lock.Get());
+  g_active_verifier = new ActiveVerifier(true);
+#else
+  // If you are reading this, wondering why your process seems deadlocked, take
+  // a look at your DllMain code and remove things that should not be done
+  // there, like doing whatever gave you that nice windows handle you are trying
+  // to store in a ScopedHandle.
+  HMODULE main_module = ::GetModuleHandle(NULL);
+  GetHandleVerifierFn get_handle_verifier =
+      reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
+          main_module, "GetHandleVerifier"));
+
+  if (!get_handle_verifier) {
+    g_active_verifier = new ActiveVerifier(false);
+    return;
+  }
+
+  ActiveVerifier* verifier =
+      reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
+
+  // This lock only protects against races in this module, which is fine.
+  AutoNativeLock lock(g_lock.Get());
+  g_active_verifier = verifier ? verifier : new ActiveVerifier(true);
+
+  // TODO(shrikant): Enable handle verifier after figuring out
+  // AppContainer/DuplicateHandle error.
+  g_active_verifier->Disable();
+#endif
+}
+
+bool ActiveVerifier::CloseHandle(HANDLE handle) {
+  if (!enabled_)
+    return CloseHandleWrapper(handle);
+
+  AutoNativeLock lock(*lock_);
+  closing_ = true;
+  CloseHandleWrapper(handle);
+  closing_ = false;
+
+  return true;
+}
+
+void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
+                                   const void* pc1, const void* pc2) {
+  if (!enabled_)
+    return;
+
+  // Grab the thread id before the lock.
+  DWORD thread_id = GetCurrentThreadId();
+
+  AutoNativeLock lock(*lock_);
+
+  Info handle_info = { owner, pc1, pc2, thread_id };
+  std::pair<HANDLE, Info> item(handle, handle_info);
+  std::pair<HandleMap::iterator, bool> result = map_.insert(item);
+  if (!result.second) {
+    Info other = result.first->second;
+    base::debug::Alias(&other);
+    CHECK(false);
+  }
+}
+
+void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
+                                  const void* pc1, const void* pc2) {
+  if (!enabled_)
+    return;
+
+  AutoNativeLock lock(*lock_);
+  HandleMap::iterator i = map_.find(handle);
+  if (i == map_.end())
+    CHECK(false);
+
+  Info other = i->second;
+  if (other.owner != owner) {
+    base::debug::Alias(&other);
+    CHECK(false);
+  }
+
+  map_.erase(i);
+}
+
+void ActiveVerifier::Disable() {
+  enabled_ = false;
+}
+
+void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
+  AutoNativeLock lock(*lock_);
+  if (closing_)
+    return;
+
+  HandleMap::iterator i = map_.find(handle);
+  if (i == map_.end())
+    return;
+
+  Info other = i->second;
+  base::debug::Alias(&other);
+  CHECK(false);
+}
+
 }  // namespace
 
+void* GetHandleVerifier() {
+  return g_active_verifier;
+}
+
 namespace base {
 namespace win {
 
 // Static.
 bool HandleTraits::CloseHandle(HANDLE handle) {
-  if (!g_verifier_enabled)
-    return CloseHandleWrapper(handle);
-
-  AutoNativeLock lock(g_lock.Get());
-  g_closing = true;
-  CloseHandleWrapper(handle);
-  g_closing = false;
-
-  return true;
+  return ActiveVerifier::Get()->CloseHandle(handle);
 }
 
 // Static.
 void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
                                    const void* pc1, const void* pc2) {
-  if (!g_verifier_enabled)
-    return;
-
-  // Grab the thread id before the lock.
-  DWORD thread_id = GetCurrentThreadId();
-
-  AutoNativeLock lock(g_lock.Get());
-
-  Info handle_info = { owner, pc1, pc2, thread_id };
-  std::pair<HANDLE, Info> item(handle, handle_info);
-  std::pair<HandleMap::iterator, bool> result = g_handle_map.Get().insert(item);
-  if (!result.second) {
-    Info other = result.first->second;
-    debug::Alias(&other);
-    CHECK(false);
-  }
+  return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2);
 }
 
 // Static.
 void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
                                   const void* pc1, const void* pc2) {
-  if (!g_verifier_enabled)
-    return;
-
-  AutoNativeLock lock(g_lock.Get());
-  HandleMap::iterator i = g_handle_map.Get().find(handle);
-  if (i == g_handle_map.Get().end())
-    CHECK(false);
-
-  Info other = i->second;
-  if (other.owner != owner) {
-    debug::Alias(&other);
-    CHECK(false);
-  }
-
-  g_handle_map.Get().erase(i);
+  return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2);
 }
 
 void DisableHandleVerifier() {
-  g_verifier_enabled = false;
+  return ActiveVerifier::Get()->Disable();
 }
 
 void OnHandleBeingClosed(HANDLE handle) {
-  AutoNativeLock lock(g_lock.Get());
-  if (g_closing)
-    return;
-
-  HandleMap::iterator i = g_handle_map.Get().find(handle);
-  if (i == g_handle_map.Get().end())
-    return;
-
-  Info other = i->second;
-  debug::Alias(&other);
-  CHECK(false);
+  return ActiveVerifier::Get()->OnHandleBeingClosed(handle);
 }
 
 }  // namespace win
diff --git a/base/win/scoped_process_information.cc b/base/win/scoped_process_information.cc
index bb24637..634a538 100644
--- a/base/win/scoped_process_information.cc
+++ b/base/win/scoped_process_information.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
 
 namespace base {
 namespace win {
@@ -20,11 +21,49 @@
     return true;
 
   HANDLE temp = NULL;
-  if (!::DuplicateHandle(::GetCurrentProcess(), source,
-                         ::GetCurrentProcess(), &temp, 0, FALSE,
-                         DUPLICATE_SAME_ACCESS)) {
-    DPLOG(ERROR) << "Failed to duplicate a handle.";
-    return false;
+
+  // TODO(shrikant): Remove following code as soon as we gather some
+  // information regarding AppContainer related DuplicateHandle failures that
+  // only seem to happen on certain machine and only random launches (normally
+  // renderer launches seem to succeed even on those machines.)
+  if (base::win::GetVersion() == base::win::VERSION_WIN8 ||
+      base::win::GetVersion() == base::win::VERSION_WIN8_1) {
+    typedef LONG (WINAPI *NtDuplicateObject)(
+        IN HANDLE SourceProcess,
+        IN HANDLE SourceHandle,
+        IN HANDLE TargetProcess,
+        OUT PHANDLE TargetHandle,
+        IN ACCESS_MASK DesiredAccess,
+        IN ULONG Attributes,
+        IN ULONG Options);
+
+    typedef ULONG (WINAPI *RtlNtStatusToDosError)(IN LONG Status);
+
+    NtDuplicateObject nt_duplicate_object =
+        reinterpret_cast<NtDuplicateObject>(::GetProcAddress(
+            GetModuleHandle(L"ntdll.dll"), "NtDuplicateObject"));
+    if (nt_duplicate_object != NULL) {
+      LONG status = nt_duplicate_object(::GetCurrentProcess(), source,
+                                        ::GetCurrentProcess(), &temp,
+                                        0, FALSE, DUPLICATE_SAME_ACCESS);
+      if (status < 0) {
+        DPLOG(ERROR) << "Failed to duplicate a handle.";
+        RtlNtStatusToDosError ntstatus_to_doserror =
+            reinterpret_cast<RtlNtStatusToDosError>(::GetProcAddress(
+                GetModuleHandle(L"ntdll.dll"), "RtlNtStatusToDosError"));
+        if (ntstatus_to_doserror != NULL) {
+          ::SetLastError(ntstatus_to_doserror(status));
+        }
+        return false;
+      }
+    }
+  } else {
+    if (!::DuplicateHandle(::GetCurrentProcess(), source,
+                           ::GetCurrentProcess(), &temp, 0, FALSE,
+                           DUPLICATE_SAME_ACCESS)) {
+      DPLOG(ERROR) << "Failed to duplicate a handle.";
+      return false;
+    }
   }
   target->Set(temp);
   return true;
diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc
index eb26cea..207fdbe 100644
--- a/base/win/shortcut.cc
+++ b/base/win/shortcut.cc
@@ -42,6 +42,13 @@
 
 }  // namespace
 
+ShortcutProperties::ShortcutProperties()
+    : icon_index(-1), dual_mode(false), options(0U) {
+}
+
+ShortcutProperties::~ShortcutProperties() {
+}
+
 bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path,
                                 const ShortcutProperties& properties,
                                 ShortcutOperation operation) {
diff --git a/base/win/shortcut.h b/base/win/shortcut.h
index 2feb4c3..6f7d10c 100644
--- a/base/win/shortcut.h
+++ b/base/win/shortcut.h
@@ -7,6 +7,7 @@
 
 #include <windows.h>
 
+#include "base/base_export.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/strings/string16.h"
@@ -29,7 +30,7 @@
 // creation/update, others will be ignored.
 // Callers are encouraged to use the setters provided which take care of
 // setting |options| as desired.
-struct ShortcutProperties {
+struct BASE_EXPORT ShortcutProperties {
   enum IndividualProperties {
     PROPERTIES_TARGET = 1U << 0,
     PROPERTIES_WORKING_DIR = 1U << 1,
@@ -48,7 +49,8 @@
     PROPERTIES_ALL = PROPERTIES_BASIC | PROPERTIES_WIN7
   };
 
-  ShortcutProperties() : icon_index(-1), dual_mode(false), options(0U) {}
+  ShortcutProperties();
+  ~ShortcutProperties();
 
   void set_target(const FilePath& target_in) {
     target = target_in;
diff --git a/base/win/shortcut_unittest.cc b/base/win/shortcut_unittest.cc
index 4bb227a..794be23 100644
--- a/base/win/shortcut_unittest.cc
+++ b/base/win/shortcut_unittest.cc
@@ -25,7 +25,7 @@
 
 class ShortcutTest : public testing::Test {
  protected:
-  virtual void SetUp() override {
+  void SetUp() override {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     ASSERT_TRUE(temp_dir_2_.CreateUniqueTempDir());
 
diff --git a/build/PRESUBMIT.py b/build/PRESUBMIT.py
index 3c70193..fca962f 100644
--- a/build/PRESUBMIT.py
+++ b/build/PRESUBMIT.py
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-WHITELIST = [ r'.+_test.py$' ]
-
 
 def _RunTests(input_api, output_api):
   return (input_api.canned_checks.RunUnitTestsInDirectory(
diff --git a/build/all.gyp b/build/all.gyp
index 2813ca2..255a35c 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -74,12 +74,6 @@
             '../content/content_shell_and_tests.gyp:content_shell_apk',
             '<@(android_app_targets)',
             'android_builder_tests',
-            '../android_webview/android_webview.gyp:android_webview_apk',
-            '../android_webview/android_webview.gyp:system_webview_apk',
-            '../android_webview/android_webview_telemetry_shell.gyp:android_webview_telemetry_shell_apk',
-            '../chrome/chrome.gyp:chrome_shell_apk',
-            '../chrome/chrome.gyp:chrome_sync_shell_apk',
-            '../remoting/remoting.gyp:remoting_apk',
             '../tools/telemetry/telemetry.gyp:*#host',
             # TODO(nyquist) This should instead by a target for sync when all of
             # the sync-related code for Android has been upstreamed.
@@ -87,6 +81,17 @@
             '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_javalib',
           ],
           'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../android_webview/android_webview.gyp:android_webview_apk',
+                '../android_webview/android_webview.gyp:system_webview_apk',
+                '../android_webview/android_webview_shell.gyp:android_webview_shell_apk',
+                '../android_webview/android_webview_telemetry_shell.gyp:android_webview_telemetry_shell_apk',
+                '../chrome/chrome.gyp:chrome_shell_apk',
+                '../chrome/chrome.gyp:chrome_sync_shell_apk',
+                '../remoting/remoting.gyp:remoting_apk',
+              ],
+            }],
             ['target_arch == "arm" or target_arch == "arm64"', {
               'dependencies': [
                 # The relocation packer only works on ARM or ARM64.
@@ -101,16 +106,16 @@
             '../sync/sync.gyp:*',
           ],
         }],
-        ['OS!="ios" and OS!="android"', {
+        ['OS!="ios" and OS!="android" and chromecast==0', {
           'dependencies': [
             '../third_party/re2/re2.gyp:re2',
             '../chrome/chrome.gyp:*',
             '../chrome/tools/profile_reset/jtl_compiler.gyp:*',
             '../cc/blink/cc_blink_tests.gyp:*',
             '../cc/cc_tests.gyp:*',
-            '../device/bluetooth/bluetooth.gyp:*',
-            '../device/device_tests.gyp:*',
             '../device/usb/usb.gyp:*',
+            '../extensions/extensions.gyp:*',
+            '../extensions/extensions_tests.gyp:*',
             '../gin/gin.gyp:*',
             '../gpu/gpu.gyp:*',
             '../gpu/tools/tools.gyp:*',
@@ -150,6 +155,12 @@
             '<(libjpeg_gyp_path):*',
           ],
         }],
+        ['OS!="ios"', {
+          'dependencies': [
+            '../device/bluetooth/bluetooth.gyp:*',
+            '../device/device_tests.gyp:*',
+          ],
+        }],
         ['use_openssl==0 and (OS=="mac" or OS=="ios" or OS=="win")', {
           'dependencies': [
             '../third_party/nss/nss.gyp:*',
@@ -170,7 +181,6 @@
         ['OS=="linux"', {
           'dependencies': [
             '../courgette/courgette.gyp:*',
-            '../dbus/dbus.gyp:*',
             '../sandbox/sandbox.gyp:*',
           ],
           'conditions': [
@@ -184,6 +194,11 @@
                 '../tools/ipc_fuzzer/ipc_fuzzer.gyp:*',
               ],
             }],
+            ['use_dbus==1', {
+              'dependencies': [
+                '../dbus/dbus.gyp:*',
+              ],
+            }],
           ],
         }],
         ['chromecast==1', {
@@ -263,7 +278,7 @@
             '../google_apis/gcm/gcm.gyp:*',
           ],
         }],
-        ['chromeos==1 or OS=="linux" or OS=="win" or OS=="mac"', {
+        ['(chromeos==1 or OS=="linux" or OS=="win" or OS=="mac") and chromecast==0', {
           'dependencies': [
             '../extensions/shell/app_shell.gyp:*',
           ],
@@ -315,19 +330,11 @@
           'dependencies': [
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
             '../cc/cc_tests.gyp:cc_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:chromedriver_tests',
-            '../chrome/chrome.gyp:chromedriver_unittests',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:sync_integration_tests',
-            '../chrome/chrome.gyp:unit_tests',
             '../cloud_print/cloud_print.gyp:cloud_print_unittests',
             '../content/content_shell_and_tests.gyp:content_browsertests',
             '../content/content_shell_and_tests.gyp:content_shell',
             '../content/content_shell_and_tests.gyp:content_unittests',
             '../device/device_tests.gyp:device_unittests',
-            '../extensions/extensions_tests.gyp:extensions_browsertests',
-            '../extensions/extensions_tests.gyp:extensions_unittests',
             '../gin/gin.gyp:gin_unittests',
             '../google_apis/google_apis.gyp:google_apis_unittests',
             '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
@@ -348,6 +355,18 @@
             '../tools/telemetry/telemetry.gyp:*',
           ],
         }],
+        ['OS!="ios" and OS!="android" and chromecast==0', {
+          'dependencies': [
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:chromedriver_tests',
+            '../chrome/chrome.gyp:chromedriver_unittests',
+            '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:sync_integration_tests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../extensions/extensions_tests.gyp:extensions_browsertests',
+            '../extensions/extensions_tests.gyp:extensions_unittests',
+          ],
+        }],
         ['OS=="win"', {
           'dependencies': [
             '../chrome/chrome.gyp:app_installer',
@@ -406,10 +425,14 @@
         }],
         ['OS=="linux"', {
           'dependencies': [
-            '../dbus/dbus.gyp:dbus_unittests',
             '../sandbox/sandbox.gyp:sandbox_linux_unittests',
           ],
         }],
+        ['OS=="linux" and use_dbus==1', {
+          'dependencies': [
+            '../dbus/dbus.gyp:dbus_unittests',
+          ],
+        }],
         ['OS=="mac"', {
           'dependencies': [
             '../ui/app_list/app_list.gyp:app_list_unittests',
@@ -436,6 +459,10 @@
             '../ui/app_list/app_list.gyp:app_list_unittests',
             '../ui/aura/aura.gyp:aura_unittests',
             '../ui/compositor/compositor.gyp:compositor_unittests',
+          ],
+        }],
+        ['use_aura==1 and chromecast==0', {
+          'dependencies': [
             '../ui/keyboard/keyboard.gyp:keyboard_unittests',
             '../ui/views/views.gyp:views_unittests',
           ],
@@ -468,7 +495,7 @@
   ],
   'conditions': [
     # TODO(GYP): make gn_migration.gypi work unconditionally.
-    ['OS=="linux" and target_arch=="x64" and chromeos==0 and chromecast==0 and disable_nacl==0', {
+    ['OS=="mac" or OS=="win" or (OS=="linux" and target_arch=="x64" and chromecast==0)', {
       'includes': [
         'gn_migration.gypi',
       ],
@@ -512,14 +539,14 @@
             }],
             ['OS=="linux"', {
               'dependencies': [
-                '../breakpad/breakpad.gyp:dump_syms',
+                '../breakpad/breakpad.gyp:dump_syms#host',
               ],
             }],
           ],
         }, # target_name: blink_tests
       ],
     }], # OS!=ios
-    ['OS!="ios" and OS!="android"', {
+    ['OS!="ios" and OS!="android" and chromecast==0', {
       'targets': [
         {
           'target_name': 'chromium_builder_nacl_win_integration',
@@ -557,6 +584,7 @@
             ['OS=="win"', {
               'dependencies': [
                 '../chrome/chrome.gyp:crash_service',
+                '../gpu/gpu.gyp:angle_perftests',
               ],
             }],
             ['OS=="win" and target_arch=="ia32"', {
@@ -759,7 +787,6 @@
           'target_name': 'android_builder_tests',
           'type': 'none',
           'dependencies': [
-            '../android_webview/android_webview.gyp:android_webview_unittests',
             '../base/android/jni_generator/jni_generator.gyp:jni_generator_tests',
             '../base/base.gyp:base_unittests',
             '../breakpad/breakpad.gyp:breakpad_unittests_deps',
@@ -774,10 +801,10 @@
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
             '../cc/cc_tests.gyp:cc_perftests_apk',
             '../cc/cc_tests.gyp:cc_unittests',
-            '../chrome/chrome.gyp:unit_tests',
             '../components/components_tests.gyp:components_unittests',
             '../content/content_shell_and_tests.gyp:content_browsertests',
             '../content/content_shell_and_tests.gyp:content_gl_tests',
+            '../content/content_shell_and_tests.gyp:content_junit_tests',
             '../content/content_shell_and_tests.gyp:chromium_linker_test_apk',
             '../content/content_shell_and_tests.gyp:content_shell_test_apk',
             '../content/content_shell_and_tests.gyp:content_unittests',
@@ -803,16 +830,10 @@
             '../ui/events/events.gyp:events_unittests',
             '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
             # Unit test bundles packaged as an apk.
-            '../android_webview/android_webview.gyp:android_webview_test_apk',
-            '../android_webview/android_webview.gyp:android_webview_unittests_apk',
             '../base/base.gyp:base_unittests_apk',
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests_apk',
             '../cc/cc_tests.gyp:cc_unittests_apk',
-            '../chrome/chrome.gyp:chrome_shell_test_apk',
-            '../chrome/chrome.gyp:chrome_sync_shell_test_apk',
-            '../chrome/chrome.gyp:chrome_shell_uiautomator_tests',
-            '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
-            '../chrome/chrome.gyp:unit_tests_apk',
+            '../components/components_tests.gyp:components_browsertests_apk',
             '../components/components_tests.gyp:components_unittests_apk',
             '../content/content_shell_and_tests.gyp:content_browsertests_apk',
             '../content/content_shell_and_tests.gyp:content_gl_tests_apk',
@@ -835,6 +856,21 @@
             '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_apk',
           ],
           'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../android_webview/android_webview.gyp:android_webview_unittests',
+                '../chrome/chrome.gyp:unit_tests',
+                # Unit test bundles packaged as an apk.
+                '../android_webview/android_webview.gyp:android_webview_test_apk',
+                '../android_webview/android_webview.gyp:android_webview_unittests_apk',
+                '../chrome/chrome.gyp:chrome_junit_tests',
+                '../chrome/chrome.gyp:chrome_shell_test_apk',
+                '../chrome/chrome.gyp:chrome_sync_shell_test_apk',
+                '../chrome/chrome.gyp:chrome_shell_uiautomator_tests',
+                '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
+                '../chrome/chrome.gyp:unit_tests_apk',
+              ],
+            }],
             ['enable_webrtc==1 and "<(libpeer_target_type)"=="static_library"', {
               'dependencies': [
                 '../components/devtools_bridge.gyp:devtools_bridge_tests_apk',
@@ -1160,14 +1196,10 @@
         ['branding=="Chrome"', {
           'targets': [
             {
-              'target_name': 'chrome_official_builder',
+              'target_name': 'chrome_official_builder_no_unittests',
               'type': 'none',
               'dependencies': [
-                '../base/base.gyp:base_unittests',
                 '../chrome/chrome.gyp:app_installer',
-                '../chrome/chrome.gyp:app_installer_unittests',
-                '../chrome/chrome.gyp:browser_tests',
-                '../chrome/chrome.gyp:sync_integration_tests',
                 '../chrome/chrome.gyp:crash_service',
                 '../chrome/chrome.gyp:gcapi_dll',
                 '../chrome/chrome.gyp:pack_policy_templates',
@@ -1175,19 +1207,8 @@
                 '../cloud_print/cloud_print.gyp:cloud_print',
                 '../courgette/courgette.gyp:courgette',
                 '../courgette/courgette.gyp:courgette64',
-                '../ipc/ipc.gyp:ipc_tests',
-                '../media/media.gyp:media_unittests',
-                '../net/net.gyp:net_unittests_run',
-                '../printing/printing.gyp:printing_unittests',
                 '../remoting/remoting.gyp:remoting_webapp',
-                '../sql/sql.gyp:sql_unittests',
-                '../sync/sync.gyp:sync_unit_tests',
                 '../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
-                '../ui/base/ui_base_tests.gyp:ui_base_unittests',
-                '../ui/gfx/gfx_tests.gyp:gfx_unittests',
-                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
-                '../ui/views/views.gyp:views_unittests',
-                '../url/url.gyp:url_unittests',
               ],
               'conditions': [
                 ['target_arch=="ia32"', {
@@ -1202,6 +1223,27 @@
                   ],
                 }], # component != "shared_library"
               ]
+            }, {
+              'target_name': 'chrome_official_builder',
+              'type': 'none',
+              'dependencies': [
+	        'chrome_official_builder_no_unittests',
+                '../base/base.gyp:base_unittests',
+		'../chrome/chrome.gyp:app_installer_unittests',
+                '../chrome/chrome.gyp:browser_tests',
+                '../chrome/chrome.gyp:sync_integration_tests',
+                '../ipc/ipc.gyp:ipc_tests',
+                '../media/media.gyp:media_unittests',
+                '../net/net.gyp:net_unittests_run',
+                '../printing/printing.gyp:printing_unittests',
+                '../sql/sql.gyp:sql_unittests',
+                '../sync/sync.gyp:sync_unit_tests',
+                '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+                '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+                '../ui/views/views.gyp:views_unittests',
+                '../url/url.gyp:url_unittests',
+              ],
             },
           ], # targets
         }], # branding=="Chrome"
@@ -1215,10 +1257,6 @@
           'dependencies': [
             '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
             '../cc/cc_tests.gyp:cc_unittests',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:chrome',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:unit_tests',
             '../components/components_tests.gyp:components_unittests',
             '../content/content_shell_and_tests.gyp:content_browsertests',
             '../content/content_shell_and_tests.gyp:content_unittests',
@@ -1236,12 +1274,8 @@
             '../ui/events/events.gyp:*',
             '../ui/gfx/gfx_tests.gyp:gfx_unittests',
             '../ui/keyboard/keyboard.gyp:*',
-            '../ui/message_center/message_center.gyp:*',
             '../ui/snapshot/snapshot.gyp:snapshot_unittests',
             '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
-            '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
-            '../ui/views/views.gyp:views',
-            '../ui/views/views.gyp:views_unittests',
             '../ui/wm/wm.gyp:*',
             'blink_tests',
           ],
@@ -1283,6 +1317,18 @@
                 '../ui/ozone/demo/ozone_demos.gyp:*',
               ],
             }],
+            ['chromecast==0', {
+              'dependencies': [
+                '../chrome/chrome.gyp:browser_tests',
+                '../chrome/chrome.gyp:chrome',
+                '../chrome/chrome.gyp:interactive_ui_tests',
+                '../chrome/chrome.gyp:unit_tests',
+                '../ui/message_center/message_center.gyp:*',
+                '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
+                '../ui/views/views.gyp:views',
+                '../ui/views/views.gyp:views_unittests',
+              ],
+            }],
           ],
         },
       ],  # targets
@@ -1294,14 +1340,20 @@
           'type': 'none',
           'dependencies': [
             '../base/base.gyp:base_unittests_run',
-            '../chrome/chrome.gyp:browser_tests_run',
-            '../chrome/chrome.gyp:interactive_ui_tests_run',
-            '../chrome/chrome.gyp:sync_integration_tests_run',
-            '../chrome/chrome.gyp:unit_tests_run',
             '../content/content_shell_and_tests.gyp:content_browsertests_run',
             '../content/content_shell_and_tests.gyp:content_unittests_run',
             '../net/net.gyp:net_unittests_run',
           ],
+          'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../chrome/chrome.gyp:browser_tests_run',
+                '../chrome/chrome.gyp:interactive_ui_tests_run',
+                '../chrome/chrome.gyp:sync_integration_tests_run',
+                '../chrome/chrome.gyp:unit_tests_run',
+              ],
+            }],
+          ],
         }, # target_name: chromium_swarm_tests
       ],
     }],
diff --git a/build/android/AndroidManifest.xml b/build/android/AndroidManifest.xml
index 25e1db0..f27872e 100644
--- a/build/android/AndroidManifest.xml
+++ b/build/android/AndroidManifest.xml
@@ -15,6 +15,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="dummy.package">
 
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
+    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
 
 </manifest>
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index d1daaf2..92095be 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -8,25 +8,6 @@
 details on the presubmit API built into depot_tools.
 """
 
-_DELETIONS_ONLY_FILES = (
-    'build/android/findbugs_filter/findbugs_known_bugs.txt',
-)
-
-
-def _CheckDeletionsOnlyFiles(input_api, output_api):
-  """Check that a certain listed files only have deletions.
-  """
-  warnings = []
-  for f in input_api.AffectedFiles():
-    if f.LocalPath() in _DELETIONS_ONLY_FILES:
-      if f.ChangedContents():
-        warnings.append(f.LocalPath())
-  results = []
-  if warnings:
-    results.append(output_api.PresubmitPromptWarning(
-        'Following files should only contain deletions.', warnings))
-  return results
-
 
 def CommonChecks(input_api, output_api):
   output = []
@@ -61,6 +42,7 @@
       input_api,
       output_api,
       unit_tests=[
+          J('pylib', 'device', 'battery_utils_test.py'),
           J('pylib', 'device', 'device_utils_test.py'),
           J('pylib', 'device', 'logcat_monitor_test.py'),
           J('pylib', 'gtest', 'gtest_test_instance_test.py'),
@@ -70,8 +52,6 @@
           J('pylib', 'utils', 'md5sum_test.py'),
       ],
       env=pylib_test_env))
-  # TODO(jbudorick): Reenable this check once upstreaming is finished.
-  # output.extend(_CheckDeletionsOnlyFiles(input_api, output_api))
   return output
 
 
diff --git a/build/android/adb_install_apk.py b/build/android/adb_install_apk.py
index 5d0fd17..7bc634c 100755
--- a/build/android/adb_install_apk.py
+++ b/build/android/adb_install_apk.py
@@ -10,7 +10,6 @@
 import os
 import sys
 
-from pylib import android_commands
 from pylib import constants
 from pylib.device import device_utils
 
@@ -71,12 +70,13 @@
   constants.SetBuildType(options.build_type)
   ValidateInstallAPKOption(parser, options, args)
 
-  devices = android_commands.GetAttachedDevices()
+  devices = device_utils.DeviceUtils.HealthyDevices()
 
   if options.device:
-    if options.device not in devices:
+    device_serials = [d.adb.GetDeviceSerial() for d in devices]
+    if options.device not in device_serials:
       raise Exception('Error: %s not in attached devices %s' % (options.device,
-                      ','.join(devices)))
+                      ','.join(device_serials)))
     devices = [options.device]
 
   if not devices:
diff --git a/build/android/adb_reverse_forwarder.py b/build/android/adb_reverse_forwarder.py
index 1958fdd..6cae0cf 100755
--- a/build/android/adb_reverse_forwarder.py
+++ b/build/android/adb_reverse_forwarder.py
@@ -11,12 +11,14 @@
 to be built.
 """
 
+import logging
 import optparse
 import sys
 import time
 
-from pylib import android_commands
-from pylib import constants, forwarder
+from pylib import constants
+from pylib import forwarder
+from pylib.device import adb_wrapper
 from pylib.device import device_utils
 from pylib.utils import run_tests_helper
 
@@ -51,19 +53,19 @@
     parser.error('Bad port number')
     sys.exit(1)
 
-  devices = android_commands.GetAttachedDevices()
+  devices = device_utils.DeviceUtils.HealthyDevices()
 
   if options.device:
-    if options.device not in devices:
+    if options.device not in [str(d) for d in devices]:
       raise Exception('Error: %s not in attached devices %s' % (options.device,
                       ','.join(devices)))
     devices = [options.device]
   else:
     if not devices:
       raise Exception('Error: no connected devices')
-    print "No device specified. Defaulting to " + devices[0]
+    logging.info('No device specified. Defaulting to %s', devices[0])
 
-  device = device_utils.DeviceUtils(devices[0])
+  device = devices[0]
   constants.SetBuildType(options.build_type)
   try:
     forwarder.Forwarder.Map(port_pairs, device)
diff --git a/build/android/android_exports.gyp b/build/android/android_exports.gyp
deleted file mode 100644
index bf3424d..0000000
--- a/build/android/android_exports.gyp
+++ /dev/null
@@ -1,43 +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.
-
-# This target is only used when android_webview_build==1 - it implements a
-# whitelist for exported symbols to minimise the binary size and prevent us
-# accidentally exposing things we don't mean to expose.
-
-{
-  'variables': {
-    'android_linker_script%': '<(SHARED_INTERMEDIATE_DIR)/android_webview_export_whitelist.lst',
-  },
-  'targets': [
-    {
-      'target_name': 'android_exports',
-      'type': 'none',
-      'inputs': [
-        '<(DEPTH)/build/android/android_webview_export_whitelist.lst',
-      ],
-      'outputs': [
-        '<(android_linker_script)',
-      ],
-      'copies': [
-        {
-          'destination': '<(SHARED_INTERMEDIATE_DIR)',
-          'files': [
-            '<@(_inputs)',
-         ],
-        },
-      ],
-      'conditions': [
-        ['component=="static_library"', {
-          'link_settings': {
-            'ldflags': [
-              # Only export symbols that are specified in version script.
-              '-Wl,--version-script=<(android_linker_script)',
-            ],
-          },
-        }],
-      ],
-    },
-  ],
-}
diff --git a/build/android/android_webview_export_whitelist.lst b/build/android/android_webview_export_whitelist.lst
deleted file mode 100644
index 2a56a75..0000000
--- a/build/android/android_webview_export_whitelist.lst
+++ /dev/null
@@ -1,16 +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.
-
-# Exports specification for android_webview_build==1, which uses a whitelist to
-# enforce only specific symbols being exported.
-# Check ld version script manual:
-# https://sourceware.org/binutils/docs-2.24/ld/VERSION.html#VERSION
-
-{
-  global:
-    Java_*_native*;
-    JNI_OnLoad;
-    __gcov_*;
-  local: *;
-};
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index 8561c01..8690a60 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -30,9 +30,14 @@
 from pylib import android_commands
 from pylib import constants
 from pylib.cmd_helper import GetCmdOutput
+from pylib.device import battery_utils
 from pylib.device import device_blacklist
+from pylib.device import device_errors
 from pylib.device import device_list
 from pylib.device import device_utils
+from pylib.utils import run_tests_helper
+
+_RE_DEVICE_ID = re.compile('Device ID = (\d+)')
 
 def DeviceInfo(serial, options):
   """Gathers info on a device via various adb calls.
@@ -44,73 +49,62 @@
     Tuple of device type, build id, report as a string, error messages, and
     boolean indicating whether or not device can be used for testing.
   """
+  device = device_utils.DeviceUtils(serial)
+  battery = battery_utils.BatteryUtils(device)
 
-  device_adb = device_utils.DeviceUtils(serial)
-  device_type = device_adb.build_product
-  device_build = device_adb.build_id
-  device_build_type = device_adb.build_type
-  device_product_name = device_adb.product_name
-
-  try:
-    battery_info = device_adb.old_interface.GetBatteryInfo()
-  except Exception as e:
-    battery_info = {}
-    logging.error('Unable to obtain battery info for %s, %s', serial, e)
-
-  def _GetData(re_expression, line, lambda_function=lambda x: x):
-    if not line:
-      return 'Unknown'
-    found = re.findall(re_expression, line)
-    if found and len(found):
-      return lambda_function(found[0])
-    return 'Unknown'
-
-  battery_level = int(battery_info.get('level', 100))
-  imei_slice = _GetData(r'Device ID = (\d+)',
-                        device_adb.old_interface.GetSubscriberInfo(),
-                        lambda x: x[-6:])
-  json_data = {
-    'serial': serial,
-    'type': device_type,
-    'build': device_build,
-    'build_detail': device_adb.GetProp('ro.build.fingerprint'),
-    'battery': battery_info,
-    'imei_slice': imei_slice,
-    'wifi_ip': device_adb.GetProp('dhcp.wlan0.ipaddress'),
-  }
-  report = ['Device %s (%s)' % (serial, device_type),
-            '  Build: %s (%s)' %
-              (device_build, json_data['build_detail']),
-            '  Current Battery Service state: ',
-            '\n'.join(['    %s: %s' % (k, v)
-                       for k, v in battery_info.iteritems()]),
-            '  IMEI slice: %s' % imei_slice,
-            '  Wifi IP: %s' % json_data['wifi_ip'],
-            '']
-
+  battery_info = {}
+  battery_level = 100
   errors = []
   dev_good = True
-  if battery_level < 15:
-    errors += ['Device critically low in battery. Will add to blacklist.']
+  json_data = {
+    'serial': serial,
+    'type': device.build_product,
+    'build': device.build_id,
+    'build_detail': device.GetProp('ro.build.fingerprint'),
+    'battery': {},
+    'imei_slice': 'Unknown',
+    'wifi_ip': device.GetProp('dhcp.wlan0.ipaddress'),
+  }
+
+  try:
+    try:
+      battery_info = battery.GetBatteryInfo(timeout=5)
+      battery_level = int(battery_info.get('level', battery_level))
+      json_data['battery'] = battery_info
+    except device_errors.CommandFailedError:
+      logging.exception('Failed to get battery information for %s', serial)
+
+    try:
+      for l in device.RunShellCommand(['dumpsys', 'iphonesubinfo'],
+                                      check_return=True, timeout=5):
+        m = _RE_DEVICE_ID.match(l)
+        if m:
+          json_data['imei_slice'] = m.group(1)[-6:]
+    except device_errors.CommandFailedError:
+      logging.exception('Failed to get IMEI slice for %s', serial)
+
+    if battery_level < 15:
+      errors += ['Device critically low in battery.']
+      dev_good = False
+      if not battery.GetCharging():
+        battery.SetCharging(True)
+    if not options.no_provisioning_check:
+      setup_wizard_disabled = (
+          device.GetProp('ro.setupwizard.mode') == 'DISABLED')
+      if not setup_wizard_disabled and device.build_type != 'user':
+        errors += ['Setup wizard not disabled. Was it provisioned correctly?']
+    if (device.product_name == 'mantaray' and
+        battery_info.get('AC powered', None) != 'true'):
+      errors += ['Mantaray device not connected to AC power.']
+  except device_errors.CommandFailedError:
+    logging.exception('Failure while getting device status.')
     dev_good = False
-    if not device_adb.old_interface.IsDeviceCharging():
-      if device_adb.old_interface.CanControlUsbCharging():
-        device_adb.old_interface.EnableUsbCharging()
-      else:
-        logging.error('Device %s is not charging' % serial)
-  if not options.no_provisioning_check:
-    setup_wizard_disabled = (
-        device_adb.GetProp('ro.setupwizard.mode') == 'DISABLED')
-    if not setup_wizard_disabled and device_build_type != 'user':
-      errors += ['Setup wizard not disabled. Was it provisioned correctly?']
-  if (device_product_name == 'mantaray' and
-      battery_info.get('AC powered', None) != 'true'):
-    errors += ['Mantaray device not connected to AC power.']
+  except device_errors.CommandTimeoutError:
+    logging.exception('Timeout while getting device status.')
+    dev_good = False
 
-  full_report = '\n'.join(report)
-
-  return (device_type, device_build, battery_level, full_report, errors,
-    dev_good, json_data)
+  return (device.build_product, device.build_id, battery_level, errors,
+          dev_good, json_data)
 
 
 def CheckForMissingDevices(options, adb_online_devs):
@@ -122,11 +116,6 @@
     adb_online_devs: A list of serial numbers of the currently visible
                      and online attached devices.
   """
-  # TODO(navabi): remove this once the bug that causes different number
-  # of devices to be detected between calls is fixed.
-  logger = logging.getLogger()
-  logger.setLevel(logging.INFO)
-
   out_dir = os.path.abspath(options.out_dir)
 
   # last_devices denotes all known devices prior to this run
@@ -189,10 +178,10 @@
                                  os.environ.get('BUILDBOT_SLAVENAME'),
                                  os.environ.get('BUILDBOT_BUILDNUMBER')))))
     return ['Current online devices: %s' % adb_online_devs,
-            '%s are no longer visible. Were they removed?\n' % missing_devs,
-            'SHERIFF:\n',
-            '@@@STEP_LINK@Click here to file a bug@%s@@@\n' % crbug_link,
-            'Cache file: %s\n\n' % last_devices_path,
+            '%s are no longer visible. Were they removed?' % missing_devs,
+            'SHERIFF:',
+            '@@@STEP_LINK@Click here to file a bug@%s@@@' % crbug_link,
+            'Cache file: %s' % last_devices_path,
             'adb devices: %s' % GetCmdOutput(['adb', 'devices']),
             'adb devices(GetAttachedDevices): %s' % adb_online_devs]
   else:
@@ -201,8 +190,9 @@
       bb_annotations.PrintWarning()
       bb_annotations.PrintSummaryText(
           '%d new devices detected' % len(new_devs))
-      print ('New devices detected %s. And now back to your '
-             'regularly scheduled program.' % list(new_devs))
+      logging.info('New devices detected:')
+      for d in new_devs:
+        logging.info('  %s', d)
 
 
 def SendEmail(from_address, to_addresses, cc_addresses, subject, msg):
@@ -214,20 +204,20 @@
     server = smtplib.SMTP('localhost')
     server.sendmail(from_address, to_addresses, msg_body)
     server.quit()
-  except Exception as e:
-    print 'Failed to send alert email. Error: %s' % e
+  except Exception:
+    logging.exception('Failed to send alert email.')
 
 
 def RestartUsb():
   if not os.path.isfile('/usr/bin/restart_usb'):
-    print ('ERROR: Could not restart usb. /usr/bin/restart_usb not installed '
-           'on host (see BUG=305769).')
+    logging.error('Could not restart usb. ''/usr/bin/restart_usb not '
+                  'installed on host (see BUG=305769).')
     return False
 
   lsusb_proc = bb_utils.SpawnCmd(['lsusb'], stdout=subprocess.PIPE)
   lsusb_output, _ = lsusb_proc.communicate()
   if lsusb_proc.returncode:
-    print 'Error: Could not get list of USB ports (i.e. lsusb).'
+    logging.error('Could not get list of USB ports (i.e. lsusb).')
     return lsusb_proc.returncode
 
   usb_devices = [re.findall(r'Bus (\d\d\d) Device (\d\d\d)', lsusb_line)[0]
@@ -243,10 +233,11 @@
     if dev != '001':
       return_code = bb_utils.RunCmd(['/usr/bin/restart_usb', bus, dev])
       if return_code:
-        print 'Error restarting USB device /dev/bus/usb/%s/%s' % (bus, dev)
+        logging.error('Error restarting USB device /dev/bus/usb/%s/%s',
+                      bus, dev)
         all_restarted = False
       else:
-        print 'Restarted USB device /dev/bus/usb/%s/%s' % (bus, dev)
+        logging.info('Restarted USB device /dev/bus/usb/%s/%s', bus, dev)
 
   return all_restarted
 
@@ -263,14 +254,15 @@
   for sig in [signal.SIGTERM, signal.SIGQUIT, signal.SIGKILL]:
     for p in GetAllAdb():
       try:
-        print 'kill %d %d (%s [%s])' % (sig, p.pid, p.name,
-            ' '.join(p.cmdline))
+        logging.info('kill %d %d (%s [%s])', sig, p.pid, p.name,
+                     ' '.join(p.cmdline))
         p.send_signal(sig)
       except (psutil.NoSuchProcess, psutil.AccessDenied):
         pass
   for p in GetAllAdb():
     try:
-      print 'Unable to kill %d (%s [%s])' % (p.pid, p.name, ' '.join(p.cmdline))
+      logging.error('Unable to kill %d (%s [%s])', p.pid, p.name,
+                    ' '.join(p.cmdline))
     except (psutil.NoSuchProcess, psutil.AccessDenied):
       pass
 
@@ -288,11 +280,15 @@
                     help='Restart USB ports before running device check.')
   parser.add_option('--json-output',
                     help='Output JSON information into a specified file.')
+  parser.add_option('-v', '--verbose', action='count', default=1,
+                    help='Log more information.')
 
   options, args = parser.parse_args()
   if args:
     parser.error('Unknown options %s' % args)
 
+  run_tests_helper.SetLogLevel(options.verbose)
+
   # Remove the last build's "bad devices" before checking device statuses.
   device_blacklist.ResetBlacklist()
 
@@ -304,7 +300,8 @@
   devices = android_commands.GetAttachedDevices()
   # Only restart usb if devices are missing.
   if set(expected_devices) != set(devices):
-    print 'expected_devices: %s, devices: %s' % (expected_devices, devices)
+    logging.warning('expected_devices: %s', expected_devices)
+    logging.warning('devices: %s', devices)
     KillAllAdb()
     retries = 5
     usb_restarted = True
@@ -312,9 +309,10 @@
       if not RestartUsb():
         usb_restarted = False
         bb_annotations.PrintWarning()
-        print 'USB reset stage failed, wait for any device to come back.'
+        logging.error('USB reset stage failed, '
+                      'wait for any device to come back.')
     while retries:
-      print 'retry adb devices...'
+      logging.info('retry adb devices...')
       time.sleep(1)
       devices = android_commands.GetAttachedDevices()
       if set(expected_devices) == set(devices):
@@ -330,10 +328,10 @@
   offline_devices = android_commands.GetAttachedDevices(
       hardware=False, emulator=False, offline=True)
 
-  types, builds, batteries, reports, errors, json_data = [], [], [], [], [], []
-  fail_step_lst = []
+  types, builds, batteries, errors, devices_ok, json_data = (
+      [], [], [], [], [], [])
   if devices:
-    types, builds, batteries, reports, errors, fail_step_lst, json_data = (
+    types, builds, batteries, errors, devices_ok, json_data = (
         zip(*[DeviceInfo(dev, options) for dev in devices]))
 
   # Write device info to file for buildbot info display.
@@ -354,7 +352,16 @@
 
   bb_annotations.PrintMsg('Online devices: %d. Device types %s, builds %s'
                            % (len(devices), unique_types, unique_builds))
-  print '\n'.join(reports)
+
+  for j in json_data:
+    logging.info('Device %s (%s)', j.get('serial'), j.get('type'))
+    logging.info('  Build: %s (%s)', j.get('build'), j.get('build_detail'))
+    logging.info('  Current Battery Service state:')
+    for k, v in j.get('battery', {}).iteritems():
+      logging.info('    %s: %s', k, v)
+    logging.info('  IMEI slice: %s', j.get('imei_slice'))
+    logging.info('  WiFi IP: %s', j.get('wifi_ip'))
+
 
   for serial, dev_errors in zip(devices, errors):
     if dev_errors:
@@ -363,14 +370,14 @@
 
   if err_msg:
     bb_annotations.PrintWarning()
-    msg = '\n'.join(err_msg)
-    print msg
+    for e in err_msg:
+      logging.error(e)
     from_address = 'buildbot@chromium.org'
     to_addresses = ['chromium-android-device-alerts@google.com']
     bot_name = os.environ.get('BUILDBOT_BUILDERNAME')
     slave_name = os.environ.get('BUILDBOT_SLAVENAME')
     subject = 'Device status check errors on %s, %s.' % (slave_name, bot_name)
-    SendEmail(from_address, to_addresses, [], subject, msg)
+    SendEmail(from_address, to_addresses, [], subject, '\n'.join(err_msg))
 
   if options.device_status_dashboard:
     perf_tests_results_helper.PrintPerfResult('BotDevices', 'OnlineDevices',
@@ -388,8 +395,9 @@
       f.write(json.dumps(json_data, indent=4))
 
   num_failed_devs = 0
-  for fail_status, device in zip(fail_step_lst, devices):
-    if not fail_status:
+  for device_ok, device in zip(devices_ok, devices):
+    if not device_ok:
+      logging.warning('Blacklisting %s', str(device))
       device_blacklist.ExtendBlacklist([str(device)])
       num_failed_devs += 1
 
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index c9be13a..e5df563 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -94,9 +94,10 @@
                         'ChromeDriverWebViewShell.apk',
                         'org.chromium.chromedriver_webview_shell')]))
 
-VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'gpu',
-                   'telemetry_unittests', 'telemetry_perf_unittests', 'ui',
-                   'unit', 'webkit', 'webkit_layout', 'python_unittests'])
+VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'components_browsertests',
+                   'gpu', 'python_unittests', 'telemetry_unittests',
+                   'telemetry_perf_unittests', 'ui', 'unit', 'webkit',
+                   'webkit_layout'])
 
 RunCmd = bb_utils.RunCmd
 
@@ -172,7 +173,7 @@
     bb_annotations.PrintNamedStep(suite)
     cmd = [suite] + args
     cmd += suites_options.get(suite, [])
-    if suite == 'content_browsertests':
+    if suite == 'content_browsertests' or suite == 'components_browsertests':
       cmd.append('--num_retries=1')
     _RunTest(options, cmd, suite)
 
@@ -315,7 +316,7 @@
       '--build-name', options.build_properties.get('buildername', ''),
       '--platform=android']
 
-  for flag in 'test_results_server', 'driver_name', 'additional_drt_flag':
+  for flag in 'test_results_server', 'driver_name', 'additional_driver_flag':
     if flag in options.factory_properties:
       cmd_args.extend(['--%s' % flag.replace('_', '-'),
                        options.factory_properties.get(flag)])
@@ -557,6 +558,8 @@
   return [
       ('chromedriver', RunChromeDriverTests),
       ('chrome_proxy', RunChromeProxyTests),
+      ('components_browsertests',
+          lambda options: RunTestSuites(options, ['components_browsertests'])),
       ('gpu', RunGPUTests),
       ('python_unittests', RunPythonUnitTests),
       ('telemetry_unittests', RunTelemetryUnitTests),
diff --git a/build/android/buildbot/bb_host_steps.py b/build/android/buildbot/bb_host_steps.py
index 4041ccd..1e927fb 100755
--- a/build/android/buildbot/bb_host_steps.py
+++ b/build/android/buildbot/bb_host_steps.py
@@ -4,6 +4,7 @@
 # found in the LICENSE file.
 
 import os
+import json
 import sys
 
 import bb_utils
@@ -14,7 +15,7 @@
 
 
 SLAVE_SCRIPTS_DIR = os.path.join(bb_utils.BB_BUILD_DIR, 'scripts', 'slave')
-VALID_HOST_TESTS = set(['check_webview_licenses', 'findbugs'])
+VALID_HOST_TESTS = set(['check_webview_licenses'])
 
 DIR_BUILD_ROOT = os.path.dirname(constants.DIR_SOURCE_ROOT)
 
@@ -78,17 +79,6 @@
          + bb_utils.EncodeProperties(options), cwd=DIR_BUILD_ROOT)
 
 
-def FindBugs(options):
-  bb_annotations.PrintNamedStep('findbugs')
-  build_type = []
-  if options.target == 'Release':
-    build_type = ['--release-build']
-  RunCmd([SrcPath('build', 'android', 'findbugs_diff.py')] + build_type)
-  RunCmd([SrcPath(
-      'tools', 'android', 'findbugs_plugin', 'test',
-      'run_findbugs_plugin_tests.py')] + build_type)
-
-
 def BisectPerfRegression(options):
   args = []
   if options.extra_src:
@@ -96,7 +86,9 @@
   RunCmd([SrcPath('tools', 'prepare-bisect-perf-regression.py'),
           '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir)])
   RunCmd([SrcPath('tools', 'run-bisect-perf-regression.py'),
-          '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir)] + args)
+          '-w', os.path.join(constants.DIR_SOURCE_ROOT, os.pardir),
+          '--build-properties=%s' % json.dumps(options.build_properties)] +
+          args)
 
 
 def GetHostStepCmds():
@@ -105,7 +97,6 @@
       ('extract_build', ExtractBuild),
       ('check_webview_licenses', CheckWebViewLicenses),
       ('bisect_perf_regression', BisectPerfRegression),
-      ('findbugs', FindBugs),
       ('zip_build', ZipBuild)
   ]
 
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py
index 29cce1b..a6afb86 100755
--- a/build/android/buildbot/bb_run_bot.py
+++ b/build/android/buildbot/bb_run_bot.py
@@ -117,8 +117,7 @@
   compile_step = ['compile']
   chrome_proxy_tests = ['chrome_proxy']
   python_unittests = ['python_unittests']
-  std_host_tests = ['check_webview_licenses', 'findbugs']
-  emma_coverage_tests = [x for x in std_host_tests if x is not 'findbugs']
+  std_host_tests = ['check_webview_licenses']
   std_build_steps = ['compile', 'zip_build']
   std_test_steps = ['extract_build']
   std_tests = ['ui', 'unit']
@@ -164,7 +163,7 @@
       B('fyi-x86-builder-dbg',
         H(compile_step + std_host_tests, experimental, target_arch='ia32')),
       B('fyi-builder-dbg',
-        H(std_build_steps + emma_coverage_tests, experimental,
+        H(std_build_steps + std_host_tests, experimental,
           extra_gyp='emma_coverage=1')),
       B('x86-builder-dbg',
         H(compile_step + std_host_tests, target_arch='ia32')),
@@ -175,7 +174,7 @@
                       '--coverage-bucket', CHROMIUM_COVERAGE_BUCKET,
                       '--cleanup'])),
       B('user-build-fyi-tests-dbg', H(std_test_steps),
-        T(telemetry_tests_user_build)),
+        T(telemetry_tests_user_build + ['components_browsertests'])),
       B('fyi-component-builder-tests-dbg',
         H(compile_step, extra_gyp='component=shared_library'),
         T(std_tests, ['--experimental', flakiness_server])),
diff --git a/build/android/cpufeatures.gypi b/build/android/cpufeatures.gypi
index b7b0b53..672ff1f 100644
--- a/build/android/cpufeatures.gypi
+++ b/build/android/cpufeatures.gypi
@@ -2,30 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# Depend on the Android NDK's cpu feature detection. The WebView build is part
-# of the system and the library already exists; for the normal build there is a
-# gyp file in the checked-in NDK to build it.
+# Depend on the Android NDK's cpu feature detection. This additional level of
+# abstraction is no longer necessary and targets can depend directly on
+# build/android/ndk.gyp:cpu_features instead.
+# TODO(torne): delete this once all DEPS have been rolled to not use it.
+# http://crbug.com/440793
 {
-  'conditions': [
-    ['android_webview_build == 1', {
-      # This is specified twice intentionally: Android provides include paths
-      # to targets automatically if they depend on libraries, so we add this
-      # library to every target that includes this .gypi to make the headers
-      # available, then also add it to targets that link those targets via
-      # link_settings to ensure it ends up being linked even if the main target
-      # doesn't include this .gypi.
-      'libraries': [
-        'cpufeatures.a',
-      ],
-      'link_settings': {
-        'libraries': [
-          'cpufeatures.a',
-        ],
-      },
-    }, {
-      'dependencies': [
-        '<(DEPTH)/build/android/ndk.gyp:cpu_features',
-      ],
-    }],
+  'dependencies': [
+    '<(DEPTH)/build/android/ndk.gyp:cpu_features',
   ],
 }
diff --git a/build/android/enable_asserts.py b/build/android/enable_asserts.py
index 0e30bc2..8fb7dca 100755
--- a/build/android/enable_asserts.py
+++ b/build/android/enable_asserts.py
@@ -6,33 +6,37 @@
 
 """Enables dalvik vm asserts in the android device."""
 
-from pylib import android_commands
-from pylib.device import device_utils
-import optparse
+import argparse
 import sys
 
+from pylib.device import device_utils
 
-def main(argv):
-  option_parser = optparse.OptionParser()
-  option_parser.add_option('--enable_asserts', dest='set_asserts',
-      action='store_true', default=None,
+
+def main():
+  parser = argparse.ArgumentParser()
+
+  set_asserts_group = parser.add_mutually_exclusive_group(required=True)
+  set_asserts_group.add_argument(
+      '--enable_asserts', dest='set_asserts', action='store_true',
       help='Sets the dalvik.vm.enableassertions property to "all"')
-  option_parser.add_option('--disable_asserts', dest='set_asserts',
-      action='store_false', default=None,
+  set_asserts_group.add_argument(
+      '--disable_asserts', dest='set_asserts', action='store_false',
       help='Removes the dalvik.vm.enableassertions property')
-  options, _ = option_parser.parse_args(argv)
+
+  args = parser.parse_args()
 
   # TODO(jbudorick): Accept optional serial number and run only for the
   # specified device when present.
-  devices = android_commands.GetAttachedDevices()
-  for device in [device_utils.DeviceUtils(serial) for serial in devices]:
-    if options.set_asserts != None:
-      if device.SetJavaAsserts(options.set_asserts):
-        # TODO(jbudorick) How to best do shell restarts after the
-        #                 android_commands refactor?
-        device.RunShellCommand('stop')
-        device.RunShellCommand('start')
+  devices = device_utils.DeviceUtils.parallel()
+
+  def set_java_asserts_and_restart(device):
+    if device.SetJavaAsserts(args.set_asserts):
+      device.RunShellCommand('stop')
+      device.RunShellCommand('start')
+
+  devices.pMap(set_java_asserts_and_restart)
+  return 0
 
 
 if __name__ == '__main__':
-  main(sys.argv)
+  sys.exit(main())
diff --git a/build/android/finalize_apk_action.gypi b/build/android/finalize_apk_action.gypi
index 9934c1a..bdf9966 100644
--- a/build/android/finalize_apk_action.gypi
+++ b/build/android/finalize_apk_action.gypi
@@ -22,16 +22,8 @@
     'keystore_path%': '<(DEPTH)/build/android/ant/chromium-debug.keystore',
     'keystore_name%': 'chromiumdebugkey',
     'keystore_password%': 'chromium',
-    'conditions': [
-        # Webview doesn't use zipalign or rezip_apk_jar.
-        ['android_webview_build==0', {
-          'zipalign_path%': '<(android_sdk_tools)/zipalign',
-          'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar'
-        }, {
-          'zipalign_path%': "",
-          'rezip_apk_jar_path%': "",
-        }],
-    ],
+    'zipalign_path%': '<(android_sdk_tools)/zipalign',
+    'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar',
   },
   'inputs': [
     '<(DEPTH)/build/android/gyp/finalize_apk.py',
diff --git a/build/android/findbugs_action.gypi b/build/android/findbugs_action.gypi
new file mode 100644
index 0000000..e3b3d36
--- /dev/null
+++ b/build/android/findbugs_action.gypi
@@ -0,0 +1,22 @@
+
+{
+  'action_name': 'findbugs_<(_target_name)',
+  'message': 'Running findbugs on <(_target_name)',
+  'variables': {
+  },
+  'inputs': [
+    '<(DEPTH)/build/android/findbugs_diff.py',
+    '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+    '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+    '<(findbugs_target_jar_path)',
+  ],
+  'outputs': [
+    '<(stamp_path)',
+  ],
+  'action': [
+    'python', '<(DEPTH)/build/android/findbugs_diff.py',
+    '--auxclasspath-gyp', '>(auxclasspath)',
+    '--stamp', '<(stamp_path)',
+    '<(findbugs_target_jar_path)',
+  ],
+}
diff --git a/build/android/findbugs_diff.py b/build/android/findbugs_diff.py
index 28224f1..f55e462 100755
--- a/build/android/findbugs_diff.py
+++ b/build/android/findbugs_diff.py
@@ -5,14 +5,6 @@
 # found in the LICENSE file.
 
 """Runs findbugs, and returns an error code if there are new warnings.
-This runs findbugs with an additional flag to exclude known bugs.
-To update the list of known bugs, do this:
-
-   findbugs_diff.py --rebaseline
-
-Note that this is separate from findbugs_exclude.xml. The "exclude" file has
-false positives that we do not plan to fix. The "known bugs" file has real
-bugs that we *do* plan to fix (but haven't done so yet).
 
 Other options
   --only-analyze used to only analyze the class you are interested.
@@ -20,30 +12,99 @@
   --findbugs-args used to passin other findbugs's options.
 
 Run
-  $CHROM_SRC/third_party/findbugs/bin/findbugs -textui for details.
+  $CHROMIUM_SRC/third_party/findbugs/bin/findbugs -textui for details.
 
 """
 
+import argparse
 import os
 import sys
 
 from pylib import constants
 from pylib.utils import findbugs
 
+_DEFAULT_BASE_DIR = os.path.join(
+    constants.DIR_SOURCE_ROOT, 'build', 'android', 'findbugs_filter')
+
+sys.path.append(
+    os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', 'gyp'))
+from util import build_utils
+
 
 def main():
-  parser = findbugs.GetCommonParser()
+  parser = argparse.ArgumentParser()
 
-  options, _ = parser.parse_args()
+  parser.add_argument(
+      '-a', '--auxclasspath', default=None, dest='auxclasspath',
+      help='Set aux classpath for analysis.')
+  parser.add_argument(
+      '--auxclasspath-gyp', dest='auxclasspath_gyp',
+      help='A gyp list containing the aux classpath for analysis')
+  parser.add_argument(
+      '-o', '--only-analyze', default=None,
+      dest='only_analyze', help='Only analyze the given classes and packages.')
+  parser.add_argument(
+      '-e', '--exclude', default=None, dest='exclude',
+      help='Exclude bugs matching given filter.')
+  parser.add_argument(
+      '-l', '--release-build', action='store_true', dest='release_build',
+      help='Analyze release build instead of debug.')
+  parser.add_argument(
+      '-f', '--findbug-args', default=None, dest='findbug_args',
+      help='Additional findbug arguments.')
+  parser.add_argument(
+      '-b', '--base-dir', default=_DEFAULT_BASE_DIR,
+      dest='base_dir', help='Base directory for configuration file.')
+  parser.add_argument(
+      '--output-file', dest='output_file',
+      help='Path to save the output to.')
+  parser.add_argument(
+      '--stamp', help='Path to touch on success.')
+  parser.add_argument(
+      '--depfile', help='Path to the depfile. This must be specified as the '
+                        "action's first output.")
 
-  if not options.base_dir:
-    options.base_dir = os.path.join(constants.DIR_SOURCE_ROOT, 'build',
-                                    'android', 'findbugs_filter')
-  if not options.only_analyze:
-    options.only_analyze = 'org.chromium.-'
+  parser.add_argument(
+      'jar_paths', metavar='JAR_PATH', nargs='+',
+      help='JAR file to analyze')
 
-  return findbugs.Run(options)
+  args = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:]))
+  if args.auxclasspath:
+    args.auxclasspath = args.auxclasspath.split(':')
+  elif args.auxclasspath_gyp:
+    args.auxclasspath = build_utils.ParseGypList(args.auxclasspath_gyp)
+
+  if args.base_dir:
+    if not args.exclude:
+      args.exclude = os.path.join(args.base_dir, 'findbugs_exclude.xml')
+
+  findbugs_command, findbugs_warnings = findbugs.Run(
+      args.exclude, args.only_analyze, args.auxclasspath,
+      args.output_file, args.findbug_args, args.jar_paths)
+
+  if findbugs_warnings:
+    print
+    print '*' * 80
+    print 'FindBugs run via:'
+    print findbugs_command
+    print
+    print 'FindBugs reported the following issues:'
+    for warning in sorted(findbugs_warnings):
+      print str(warning)
+    print '*' * 80
+    print
+  else:
+    if args.depfile:
+      build_utils.WriteDepfile(
+          args.depfile,
+          build_utils.GetPythonDependencies() + args.auxclasspath
+              + args.jar_paths)
+    if args.stamp:
+      build_utils.Touch(args.stamp)
+
+  return len(findbugs_warnings)
 
 
 if __name__ == '__main__':
   sys.exit(main())
+
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml
index 5060e47..dbff9d9 100644
--- a/build/android/findbugs_filter/findbugs_exclude.xml
+++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -12,40 +12,12 @@
 <FindBugsFilter>
   <!-- Skip the generated resource classes (including nested classes). -->
   <Match>
-    <Class name="~org\.chromium\..*\.R(\$\w+)?" />
+    <Class name="~.*\.R(\$\w+)?" />
   </Match>
   <Match>
     <Class name="~org\.chromium\..*\.Manifest(\$\w+)?" />
   </Match>
+  <Bug pattern="DM_STRING_CTOR" />
   <!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform -->
-  <Match>
-    <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
-    <Method name="onCancel" />
-    <Bug code="Dm" />
-  </Match>
-  <Match>
-    <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
-    <Method name="onClick" />
-    <Bug code="Dm" />
-  </Match>
   <Bug pattern="DM_DEFAULT_ENCODING" />
-  <!-- Ignore bugs that are often false-positives in test code -->
-  <Match>
-    <Class name="~org\.chromium\..*Test(\$\w+)?" />
-    <Or>
-      <Bug code="DLS,UrF" />
-      <Bug pattern="DM_GC" />
-    </Or>
-  </Match>
-  <!--
-  crbug.com/449101
-  Ignore findbugs plugin test cases.
-  -->
-  <Match>
-    <Or>
-      <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedMethod" />
-      <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedStaticMethod" />
-      <Class name="~org\.chromium\.tools\.findbugs\.plugin\.SimpleSynchronizedThis" />
-    </Or>
-  </Match>
 </FindBugsFilter>
diff --git a/build/android/gyp/jarjar_resources.py b/build/android/gyp/jarjar_resources.py
deleted file mode 100755
index 67b510b..0000000
--- a/build/android/gyp/jarjar_resources.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""Transforms direct Java class references in Android layout .xml files
-according to the specified JarJar rules."""
-
-import optparse
-import os
-import shutil
-import sys
-from xml.dom import minidom
-
-from util import build_utils
-
-
-class JarJarRules(object):
-  def __init__(self, jarjar_rules):
-    self._rules = []
-    for line in jarjar_rules.splitlines():
-      rule = line.split()
-      if rule[0] != 'rule':
-        continue
-      _, src, dest = rule
-      if src.endswith('**'):
-        src_real_name = src[:-2]
-      else:
-        assert not '*' in src
-        src_real_name = src
-
-      if dest.endswith('@0'):
-        self._rules.append((src, dest[:-2] + src_real_name))
-      elif dest.endswith('@1'):
-        assert '**' in src
-        self._rules.append((src, dest[:-2]))
-      else:
-        assert not '@' in dest
-        self._rules.append((src, dest))
-
-  def RenameClass(self, class_name):
-    for old, new in self._rules:
-      if old.endswith('**') and old[:-2] in class_name:
-        return class_name.replace(old[:-2], new, 1)
-      if '*' not in old and class_name.endswith(old):
-        return class_name.replace(old, new, 1)
-    return class_name
-
-
-def RenameNodes(node, rules):
-  if node.nodeType == node.ELEMENT_NODE:
-    if node.tagName.lower() == 'view' and  node.attributes.has_key('class'):
-      node.attributes['class'] = rules.RenameClass(node.attributes['class'])
-    else:
-      node.tagName = rules.RenameClass(node.tagName)
-  for child in node.childNodes:
-    RenameNodes(child, rules)
-
-
-def ProcessLayoutFile(path, rules):
-  xmldoc = minidom.parse(path)
-  RenameNodes(xmldoc.documentElement, rules)
-  with open(path, 'w') as f:
-    xmldoc.writexml(f)
-
-
-def LayoutFilesFilter(src, names):
-  if os.path.basename(src).lower() != 'layout':
-    return []
-  else:
-    return filter(lambda n: n.endswith('.xml'), names)
-
-
-def ProcessResources(options):
-  with open(options.rules_path) as f:
-    rules = JarJarRules(f.read())
-
-  build_utils.DeleteDirectory(options.output_dir)
-  for input_dir in options.input_dir:
-    shutil.copytree(input_dir, options.output_dir)
-
-  for root, _dirnames, filenames in os.walk(options.output_dir):
-    layout_files = LayoutFilesFilter(root, filenames)
-    for layout_file in layout_files:
-      ProcessLayoutFile(os.path.join(root, layout_file), rules)
-
-
-def ParseArgs():
-  parser = optparse.OptionParser()
-  parser.add_option('--input-dir', action='append',
-                    help='Path to the resources folder to process.')
-  parser.add_option('--output-dir',
-                    help=('Directory to hold processed resources. Note: the ' +
-                          'directory will be clobbered on every invocation.'))
-  parser.add_option('--rules-path',
-                    help='Path to the jarjar rules file.')
-  parser.add_option('--stamp', help='Path to touch on success.')
-
-  options, args = parser.parse_args()
-
-  if args:
-    parser.error('No positional arguments should be given.')
-
-  # Check that required options have been provided.
-  required_options = ('input_dir', 'output_dir', 'rules_path')
-  build_utils.CheckOptions(options, parser, required=required_options)
-
-  return options
-
-
-def main():
-  options = ParseArgs()
-
-  ProcessResources(options)
-
-  if options.stamp:
-    build_utils.Touch(options.stamp)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/build/android/gyp/jinja_template.py b/build/android/gyp/jinja_template.py
index 9e9705c..6653f21 100755
--- a/build/android/gyp/jinja_template.py
+++ b/build/android/gyp/jinja_template.py
@@ -34,15 +34,17 @@
     return list(self.loaded_templates)
 
 
-def ProcessFile(env, input_filename, output_filename, variables):
-  input_rel_path = os.path.relpath(input_filename, build_utils.CHROMIUM_SRC)
+def ProcessFile(env, input_filename, loader_base_dir, output_filename,
+                variables):
+  input_rel_path = os.path.relpath(input_filename, loader_base_dir)
   template = env.get_template(input_rel_path)
   output = template.render(variables)
   with codecs.open(output_filename, 'w', 'utf-8') as output_file:
     output_file.write(output)
 
 
-def ProcessFiles(env, input_filenames, inputs_base_dir, outputs_zip, variables):
+def ProcessFiles(env, input_filenames, loader_base_dir, inputs_base_dir,
+                 outputs_zip, variables):
   with build_utils.TempDir() as temp_dir:
     for input_filename in input_filenames:
       relpath = os.path.relpath(os.path.abspath(input_filename),
@@ -54,7 +56,8 @@
       output_filename = os.path.join(temp_dir, relpath)
       parent_dir = os.path.dirname(output_filename)
       build_utils.MakeDirectory(parent_dir)
-      ProcessFile(env, input_filename, output_filename, variables)
+      ProcessFile(env, input_filename, loader_base_dir, output_filename,
+                  variables)
 
     build_utils.ZipDir(outputs_zip, temp_dir)
 
@@ -71,6 +74,10 @@
                     'the inputs. Each output\'s path in the output zip will '
                     'match the relative path from INPUTS_BASE_DIR to the '
                     'input. Required if --output-zip is given.')
+  parser.add_option('--loader-base-dir', help='Base path used by the template '
+                    'loader. Must be a common ancestor directory of '
+                    'the inputs. Defaults to CHROMIUM_SRC.',
+                    default=build_utils.CHROMIUM_SRC)
   parser.add_option('--variables', help='Variables to be made available in the '
                     'template processing environment, as a GYP list (e.g. '
                     '--variables "channel=beta mstone=39")', default='')
@@ -95,14 +102,15 @@
     name, _, value = v.partition('=')
     variables[name] = value
 
-  loader = RecordingFileSystemLoader(build_utils.CHROMIUM_SRC)
+  loader = RecordingFileSystemLoader(options.loader_base_dir)
   env = jinja2.Environment(loader=loader, undefined=jinja2.StrictUndefined,
                            line_comment_prefix='##')
   if options.output:
-    ProcessFile(env, inputs[0], options.output, variables)
+    ProcessFile(env, inputs[0], options.loader_base_dir, options.output,
+                variables)
   else:
-    ProcessFiles(env, inputs, options.inputs_base_dir, options.outputs_zip,
-                 variables)
+    ProcessFiles(env, inputs, options.loader_base_dir, options.inputs_base_dir,
+                 options.outputs_zip, variables)
 
   if options.depfile:
     deps = loader.get_loaded_templates() + build_utils.GetPythonDependencies()
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index 52cf143..4e6c27d 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -10,6 +10,7 @@
 (see generate_v14_compatible_resources.py).
 """
 
+import codecs
 import optparse
 import os
 import re
@@ -112,14 +113,15 @@
   if len(java_files) != 1:
     return
   r_java_file = java_files[0]
-  r_java_contents = open(r_java_file).read()
+  r_java_contents = codecs.open(r_java_file, encoding='utf-8').read()
 
   for package in extra_packages:
     package_r_java_dir = os.path.join(r_dir, *package.split('.'))
     build_utils.MakeDirectory(package_r_java_dir)
     package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
-    open(package_r_java_path, 'w').write(
-        re.sub(r'package [.\w]*;', 'package %s;' % package, r_java_contents))
+    new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package,
+                        r_java_contents)
+    codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java)
     # TODO(cjhopman): These extra package's R.java files should be filtered to
     # only contain the resources listed in their R.txt files. At this point, we
     # have already compiled those other libraries, so doing this would only
diff --git a/build/android/gyp/util/build_device.py b/build/android/gyp/util/build_device.py
index b153a15..7e0d57b 100644
--- a/build/android/gyp/util/build_device.py
+++ b/build/android/gyp/util/build_device.py
@@ -40,7 +40,7 @@
     return self.id
 
   def Install(self, *args, **kwargs):
-    return self.device.old_interface.Install(*args, **kwargs)
+    return self.device.Install(*args, **kwargs)
 
   def GetInstallMetadata(self, apk_package):
     """Gets the metadata on the device for the apk_package apk."""
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index a0cd7c1..65b1a64 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -24,7 +24,7 @@
                              'third_party', 'colorama', 'src')
 # aapt should ignore OWNERS files in addition the default ignore pattern.
 AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' +
-                       '!CVS:!thumbs.db:!picasa.ini:!*~')
+                       '!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp')
 
 
 @contextlib.contextmanager
@@ -236,6 +236,7 @@
 
 
 def MergeZips(output, inputs, exclude_patterns=None):
+  added_names = set()
   def Allow(name):
     if exclude_patterns is not None:
       for p in exclude_patterns:
@@ -247,8 +248,9 @@
     for in_file in inputs:
       with zipfile.ZipFile(in_file, 'r') as in_zip:
         for name in in_zip.namelist():
-          if Allow(name):
+          if name not in added_names and Allow(name):
             out_zip.writestr(name, in_zip.read(name))
+            added_names.add(name)
 
 
 def PrintWarning(message):
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 5fc8955..1b4379d 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -29,11 +29,43 @@
 import optparse
 import os
 import sys
+import xml.dom.minidom
 
 from util import build_utils
 
 import write_ordered_libraries
 
+class AndroidManifest(object):
+  def __init__(self, path):
+    self.path = path
+    dom = xml.dom.minidom.parse(path)
+    manifests = dom.getElementsByTagName('manifest')
+    assert len(manifests) == 1
+    self.manifest = manifests[0]
+
+  def GetInstrumentation(self):
+    instrumentation_els = self.manifest.getElementsByTagName('instrumentation')
+    if len(instrumentation_els) == 0:
+      return None
+    if len(instrumentation_els) != 1:
+      raise Exception(
+          'More than one <instrumentation> element found in %s' % self.path)
+    return instrumentation_els[0]
+
+  def CheckInstrumentation(self, expected_package):
+    instr = self.GetInstrumentation()
+    if not instr:
+      raise Exception('No <instrumentation> elements found in %s' % self.path)
+    instrumented_package = instr.getAttributeNS(
+        'http://schemas.android.com/apk/res/android', 'targetPackage')
+    if instrumented_package != expected_package:
+      raise Exception(
+          'Wrong instrumented package. Expected %s, got %s'
+          % (expected_package, instrumented_package))
+
+  def GetPackageName(self):
+    return self.manifest.getAttribute('package')
+
 
 dep_config_cache = {}
 def GetDepConfig(path):
@@ -88,6 +120,10 @@
   parser.add_option('--native-libs', help='List of top-level native libs.')
   parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.')
 
+  parser.add_option('--tested-apk-config',
+      help='Path to the build config of the tested apk (for an instrumentation '
+      'test apk).')
+
   options, args = parser.parse_args(argv)
 
   if args:
@@ -154,7 +190,6 @@
   }
   deps_info = config['deps_info']
 
-
   if options.type == 'java_library' and not options.bypass_platform_checks:
     deps_info['requires_android'] = options.requires_android
     deps_info['supports_android'] = options.supports_android
@@ -172,7 +207,6 @@
       raise Exception('Not all deps support the Android platform: ' +
           str(deps_not_support_android))
 
-
   if options.type in ['java_library', 'android_apk']:
     javac_classpath = [c['jar_path'] for c in direct_library_deps]
     java_full_classpath = [c['jar_path'] for c in all_library_deps]
@@ -216,14 +250,31 @@
     config['resources']['extra_package_names'] = [
         c['package_name'] for c in all_resources_deps if 'package_name' in c]
 
+  if options.type in ['android_apk', 'deps_dex']:
+    deps_dex_files = [c['dex_path'] for c in all_library_deps]
+
+  # An instrumentation test apk should exclude the dex files that are in the apk
+  # under test.
+  if options.type == 'android_apk' and options.tested_apk_config:
+    tested_apk_config_paths = GetAllDepsConfigsInOrder(
+        [options.tested_apk_config])
+    tested_apk_configs = [GetDepConfig(p) for p in tested_apk_config_paths]
+    tested_apk_library_deps = DepsOfType('java_library', tested_apk_configs)
+    tested_apk_deps_dex_files = [c['dex_path'] for c in tested_apk_library_deps]
+    deps_dex_files = [
+        p for p in deps_dex_files if not p in tested_apk_deps_dex_files]
+
+    tested_apk_config = GetDepConfig(options.tested_apk_config)
+    expected_tested_package = tested_apk_config['package_name']
+    AndroidManifest(options.android_manifest).CheckInstrumentation(
+        expected_tested_package)
 
   # Dependencies for the final dex file of an apk or a 'deps_dex'.
   if options.type in ['android_apk', 'deps_dex']:
     config['final_dex'] = {}
     dex_config = config['final_dex']
     # TODO(cjhopman): proguard version
-    dex_deps_files = [c['dex_path'] for c in all_library_deps]
-    dex_config['dependency_dex_files'] = dex_deps_files
+    dex_config['dependency_dex_files'] = deps_dex_files
 
   if options.type == 'android_apk':
     config['dist_jar'] = {
@@ -231,6 +282,11 @@
         c['jar_path'] for c in all_library_deps
       ]
     }
+    manifest = AndroidManifest(options.android_manifest)
+    deps_info['package_name'] = manifest.GetPackageName()
+    if not options.tested_apk_config and manifest.GetInstrumentation():
+      # This must then have instrumentation only for itself.
+      manifest.CheckInstrumentation(manifest.GetPackageName())
 
     library_paths = []
     java_libraries_list = []
diff --git a/build/android/host_heartbeat.py b/build/android/host_heartbeat.py
index 429fca9..6a7cdd1 100755
--- a/build/android/host_heartbeat.py
+++ b/build/android/host_heartbeat.py
@@ -12,7 +12,6 @@
 import sys
 import time
 
-from pylib import android_commands
 from pylib.device import device_utils
 
 PULSE_PERIOD = 20
@@ -20,10 +19,10 @@
 def main():
   while True:
     try:
-      devices = android_commands.GetAttachedDevices()
-      for device_serial in devices:
-        device_utils.DeviceUtils(device_serial).RunShellCommand(
-            'touch /sdcard/host_heartbeat')
+      devices = device_utils.DeviceUtils.HealthyDevices()
+      for d in devices:
+        d.RunShellCommand(['touch', '/sdcard/host_heartbeat'],
+                          check_return=True)
     except:
       # Keep the heatbeat running bypassing all errors.
       pass
diff --git a/build/android/java_cpp_enum.gypi b/build/android/java_cpp_enum.gypi
index b51351b..d4abafa 100644
--- a/build/android/java_cpp_enum.gypi
+++ b/build/android/java_cpp_enum.gypi
@@ -33,6 +33,11 @@
       'generated_src_dirs': [
         '<(output_dir)/',
       ],
+      # Ensure that the targets depending on this one are rebuilt if the sources
+      # of this one are modified.
+      'additional_input_paths': [
+        '<(source_file)',
+      ],
     },
   },
   'actions': [
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index 5f00b31..ee52c71 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -19,9 +19,9 @@
 import sys
 import time
 
-from pylib import android_commands
 from pylib import constants
 from pylib import device_settings
+from pylib.device import battery_utils
 from pylib.device import device_blacklist
 from pylib.device import device_errors
 from pylib.device import device_utils
@@ -41,54 +41,148 @@
   HELP_TEXT = '{}s on L, {}s on pre-L'.format(LOLLIPOP, PRE_LOLLIPOP)
 
 
-def KillHostHeartbeat():
-  ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
-  stdout, _ = ps.communicate()
-  matches = re.findall('\\n.*host_heartbeat.*', stdout)
-  for match in matches:
-    logging.info('An instance of host heart beart running... will kill')
-    pid = re.findall(r'(\S+)', match)[1]
-    subprocess.call(['kill', str(pid)])
+class _PHASES(object):
+  WIPE = 'wipe'
+  PROPERTIES = 'properties'
+  FINISH = 'finish'
+
+  ALL = [WIPE, PROPERTIES, FINISH]
 
 
-def LaunchHostHeartbeat():
-  # Kill if existing host_heartbeat
-  KillHostHeartbeat()
-  # Launch a new host_heartbeat
-  logging.info('Spawning host heartbeat...')
-  subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
-                                 'build/android/host_heartbeat.py')])
+def ProvisionDevices(options):
+  if options.device is not None:
+    devices = [options.device]
+  else:
+    devices = device_utils.DeviceUtils.HealthyDevices()
+
+  parallel_devices = device_utils.DeviceUtils.parallel(devices)
+  parallel_devices.pMap(ProvisionDevice, options)
+  if options.auto_reconnect:
+    _LaunchHostHeartbeat()
+  blacklist = device_blacklist.ReadBlacklist()
+  if all(d in blacklist for d in devices):
+    raise device_errors.NoDevicesError
+  return 0
 
 
-def PushAndLaunchAdbReboot(device, target):
-  """Pushes and launches the adb_reboot binary on the device.
+def ProvisionDevice(device, options):
+  if options.reboot_timeout:
+    reboot_timeout = options.reboot_timeout
+  elif (device.build_version_sdk >=
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+    reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP
+  else:
+    reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP
+
+  def should_run_phase(phase_name):
+    return not options.phases or phase_name in options.phases
+
+  def run_phase(phase_func, reboot=True):
+    device.WaitUntilFullyBooted(timeout=reboot_timeout)
+    phase_func(device, options)
+    if reboot:
+      device.Reboot(False, retries=0)
+      device.adb.WaitForDevice()
+
+  try:
+    if should_run_phase(_PHASES.WIPE):
+      run_phase(WipeDevice)
+
+    if should_run_phase(_PHASES.PROPERTIES):
+      run_phase(SetProperties)
+
+    if should_run_phase(_PHASES.FINISH):
+      run_phase(FinishProvisioning, reboot=False)
+
+  except (errors.WaitForResponseTimedOutError,
+          device_errors.CommandTimeoutError):
+    logging.exception('Timed out waiting for device %s. Adding to blacklist.',
+                      str(device))
+    device_blacklist.ExtendBlacklist([str(device)])
+
+  except device_errors.CommandFailedError:
+    logging.exception('Failed to provision device %s. Adding to blacklist.',
+                      str(device))
+    device_blacklist.ExtendBlacklist([str(device)])
+
+
+def WipeDevice(device, options):
+  """Wipes data from device, keeping only the adb_keys for authorization.
+
+  After wiping data on a device that has been authorized, adb can still
+  communicate with the device, but after reboot the device will need to be
+  re-authorized because the adb keys file is stored in /data/misc/adb/.
+  Thus, adb_keys file is rewritten so the device does not need to be
+  re-authorized.
 
   Arguments:
-    device: The DeviceUtils instance for the device to which the adb_reboot
-            binary should be pushed.
-    target: The build target (example, Debug or Release) which helps in
-            locating the adb_reboot binary.
+    device: the device to wipe
   """
-  logging.info('Will push and launch adb_reboot on %s' % str(device))
-  # Kill if adb_reboot is already running.
+  if options.skip_wipe:
+    return
+
   try:
-    # Don't try to kill adb_reboot more than once. We don't expect it to be
-    # running at all.
-    device.KillAll('adb_reboot', blocking=True, timeout=2, retries=0)
+    device.EnableRoot()
+    device_authorized = device.FileExists(constants.ADB_KEYS_FILE)
+    if device_authorized:
+      adb_keys = device.ReadFile(constants.ADB_KEYS_FILE,
+                                 as_root=True).splitlines()
+    device.RunShellCommand(['wipe', 'data'],
+                           as_root=True, check_return=True)
+    device.adb.WaitForDevice()
+
+    if device_authorized:
+      adb_keys_set = set(adb_keys)
+      for adb_key_file in options.adb_key_files or []:
+        try:
+          with open(adb_key_file, 'r') as f:
+            adb_public_keys = f.readlines()
+          adb_keys_set.update(adb_public_keys)
+        except IOError:
+          logging.warning('Unable to find adb keys file %s.' % adb_key_file)
+      _WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
   except device_errors.CommandFailedError:
-    # We can safely ignore the exception because we don't expect adb_reboot
-    # to be running.
-    pass
-  # Push adb_reboot
-  logging.info('  Pushing adb_reboot ...')
-  adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
-                            'out/%s/adb_reboot' % target)
-  device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')])
-  # Launch adb_reboot
-  logging.info('  Launching adb_reboot ...')
-  device.RunShellCommand([
-      device.GetDevicePieWrapper(),
-      '/data/local/tmp/adb_reboot'])
+    logging.exception('Possible failure while wiping the device. '
+                      'Attempting to continue.')
+
+
+def _WriteAdbKeysFile(device, adb_keys_string):
+  dir_path = posixpath.dirname(constants.ADB_KEYS_FILE)
+  device.RunShellCommand(['mkdir', '-p', dir_path],
+                         as_root=True, check_return=True)
+  device.RunShellCommand(['restorecon', dir_path],
+                         as_root=True, check_return=True)
+  device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True)
+  device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE],
+                         as_root=True, check_return=True)
+
+
+def SetProperties(device, options):
+  try:
+    device.EnableRoot()
+  except device_errors.CommandFailedError as e:
+    logging.warning(str(e))
+
+  _ConfigureLocalProperties(device, options.enable_java_debug)
+  device_settings.ConfigureContentSettings(
+      device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
+  if options.disable_location:
+    device_settings.ConfigureContentSettings(
+        device, device_settings.DISABLE_LOCATION_SETTINGS)
+  else:
+    device_settings.ConfigureContentSettings(
+        device, device_settings.ENABLE_LOCATION_SETTINGS)
+  device_settings.SetLockScreenSettings(device)
+  if options.disable_network:
+    device_settings.ConfigureContentSettings(
+        device, device_settings.NETWORK_DISABLED_SETTINGS)
+
+  if options.min_battery_level is not None:
+    try:
+      battery = battery_utils.BatteryUtils(device)
+      battery.ChargeDeviceToLevel(options.min_battery_level)
+    except device_errors.CommandFailedError as e:
+      logging.exception('Unable to charge device to specified level.')
 
 
 def _ConfigureLocalProperties(device, java_debug=True):
@@ -101,7 +195,8 @@
       'ro.setupwizard.mode=DISABLED',
       ]
   if java_debug:
-    local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY)
+    local_props.append(
+        '%s=all' % device_utils.DeviceUtils.JAVA_ASSERT_PROPERTY)
     local_props.append('debug.checkjni=1')
   try:
     device.WriteFile(
@@ -110,153 +205,66 @@
     # Android will not respect the local props file if it is world writable.
     device.RunShellCommand(
         ['chmod', '644', constants.DEVICE_LOCAL_PROPERTIES_PATH],
-        as_root=True)
-  except device_errors.CommandFailedError as e:
-    logging.warning(str(e))
-
-  # LOCAL_PROPERTIES_PATH = '/data/local.prop'
-
-def WriteAdbKeysFile(device, adb_keys_string):
-  dir_path = posixpath.dirname(constants.ADB_KEYS_FILE)
-  device.RunShellCommand('mkdir -p %s' % dir_path, as_root=True)
-  device.RunShellCommand('restorecon %s' % dir_path, as_root=True)
-  device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True)
-  device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE,
-                         as_root=True)
+        as_root=True, check_return=True)
+  except device_errors.CommandFailedError:
+    logging.exception('Failed to configure local properties.')
 
 
-def WipeDeviceData(device, options):
-  """Wipes data from device, keeping only the adb_keys for authorization.
+def FinishProvisioning(device, options):
+  device.RunShellCommand(
+      ['date', '-s', time.strftime('%Y%m%d.%H%M%S', time.gmtime())],
+      as_root=True, check_return=True)
+  props = device.RunShellCommand('getprop', check_return=True)
+  for prop in props:
+    logging.info('  %s' % prop)
+  if options.auto_reconnect:
+    _PushAndLaunchAdbReboot(device, options.target)
 
-  After wiping data on a device that has been authorized, adb can still
-  communicate with the device, but after reboot the device will need to be
-  re-authorized because the adb keys file is stored in /data/misc/adb/.
-  Thus, adb_keys file is rewritten so the device does not need to be
-  re-authorized.
+
+def _PushAndLaunchAdbReboot(device, target):
+  """Pushes and launches the adb_reboot binary on the device.
 
   Arguments:
-    device: the device to wipe
+    device: The DeviceUtils instance for the device to which the adb_reboot
+            binary should be pushed.
+    target: The build target (example, Debug or Release) which helps in
+            locating the adb_reboot binary.
   """
-  device_authorized = device.FileExists(constants.ADB_KEYS_FILE)
-  if device_authorized:
-    adb_keys = device.ReadFile(constants.ADB_KEYS_FILE,
-                               as_root=True).splitlines()
-  device.RunShellCommand('wipe data', as_root=True)
-  if device_authorized:
-    adb_keys_set = set(adb_keys)
-    for adb_key_file in options.adb_key_files or []:
-      try:
-        with open(adb_key_file, 'r') as f:
-          adb_public_keys = f.readlines()
-        adb_keys_set.update(adb_public_keys)
-      except IOError:
-        logging.warning('Unable to find adb keys file %s.' % adb_key_file)
-    WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
+  logging.info('Will push and launch adb_reboot on %s' % str(device))
+  # Kill if adb_reboot is already running.
+  device.KillAll('adb_reboot', blocking=True, timeout=2, quiet=True)
+  # Push adb_reboot
+  logging.info('  Pushing adb_reboot ...')
+  adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
+                            'out/%s/adb_reboot' % target)
+  device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')])
+  # Launch adb_reboot
+  logging.info('  Launching adb_reboot ...')
+  device.RunShellCommand(
+      [device.GetDevicePieWrapper(), '/data/local/tmp/adb_reboot'],
+      check_return=True)
 
 
-def WipeDeviceIfPossible(device, timeout, options):
-  try:
-    device.EnableRoot()
-    WipeDeviceData(device, options)
-    device.Reboot(True, timeout=timeout, retries=0)
-  except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError):
-    pass
+def _LaunchHostHeartbeat():
+  # Kill if existing host_heartbeat
+  KillHostHeartbeat()
+  # Launch a new host_heartbeat
+  logging.info('Spawning host heartbeat...')
+  subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
+                                 'build/android/host_heartbeat.py')])
 
 
-def ChargeDeviceToLevel(device, level):
-  def device_charged():
-    battery_level = device.GetBatteryInfo().get('level')
-    if battery_level is None:
-      logging.warning('Unable to find current battery level.')
-      battery_level = 100
-    else:
-      logging.info('current battery level: %d', battery_level)
-      battery_level = int(battery_level)
-    return battery_level >= level
-
-  timeout_retry.WaitFor(device_charged, wait_period=60)
-
-
-def ProvisionDevice(device, options):
-  if options.reboot_timeout:
-    reboot_timeout = options.reboot_timeout
-  elif (device.build_version_sdk >=
-        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
-    reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP
-  else:
-    reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP
-
-  try:
-    if not options.skip_wipe:
-      WipeDeviceIfPossible(device, reboot_timeout, options)
-    try:
-      device.EnableRoot()
-    except device_errors.CommandFailedError as e:
-      logging.warning(str(e))
-    _ConfigureLocalProperties(device, options.enable_java_debug)
-    device_settings.ConfigureContentSettings(
-        device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
-    if options.disable_location:
-      device_settings.ConfigureContentSettings(
-          device, device_settings.DISABLE_LOCATION_SETTINGS)
-    else:
-      device_settings.ConfigureContentSettings(
-          device, device_settings.ENABLE_LOCATION_SETTINGS)
-    device_settings.SetLockScreenSettings(device)
-    if options.disable_network:
-      device_settings.ConfigureContentSettings(
-          device, device_settings.NETWORK_DISABLED_SETTINGS)
-    if options.min_battery_level is not None:
-      try:
-        device.SetCharging(True)
-        ChargeDeviceToLevel(device, options.min_battery_level)
-      except device_errors.CommandFailedError as e:
-        logging.exception('Unable to charge device to specified level.')
-
-    if not options.skip_wipe:
-      device.Reboot(True, timeout=reboot_timeout, retries=0)
-    device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S',
-                                                        time.gmtime()),
-                           as_root=True)
-    props = device.RunShellCommand('getprop')
-    for prop in props:
-      logging.info('  %s' % prop)
-    if options.auto_reconnect:
-      PushAndLaunchAdbReboot(device, options.target)
-  except (errors.WaitForResponseTimedOutError,
-          device_errors.CommandTimeoutError):
-    logging.info('Timed out waiting for device %s. Adding to blacklist.',
-                 str(device))
-    # Device black list is reset by bb_device_status_check.py per build.
-    device_blacklist.ExtendBlacklist([str(device)])
-  except device_errors.CommandFailedError:
-    logging.exception('Failed to provision device %s. Adding to blacklist.',
-                      str(device))
-    device_blacklist.ExtendBlacklist([str(device)])
-
-
-def ProvisionDevices(options):
-  if options.device is not None:
-    devices = [options.device]
-  else:
-    devices = android_commands.GetAttachedDevices()
-
-  parallel_devices = device_utils.DeviceUtils.parallel(devices)
-  parallel_devices.pMap(ProvisionDevice, options)
-  if options.auto_reconnect:
-    LaunchHostHeartbeat()
-  blacklist = device_blacklist.ReadBlacklist()
-  if all(d in blacklist for d in devices):
-    raise device_errors.NoDevicesError
-  return 0
+def KillHostHeartbeat():
+  ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  stdout, _ = ps.communicate()
+  matches = re.findall('\\n.*host_heartbeat.*', stdout)
+  for match in matches:
+    logging.info('An instance of host heart beart running... will kill')
+    pid = re.findall(r'(\S+)', match)[1]
+    subprocess.call(['kill', str(pid)])
 
 
 def main():
-  custom_handler = logging.StreamHandler(sys.stdout)
-  custom_handler.setFormatter(run_tests_helper.CustomFormatter())
-  logging.getLogger().addHandler(custom_handler)
-  logging.getLogger().setLevel(logging.INFO)
-
   # Recommended options on perf bots:
   # --disable-network
   #     TODO(tonyg): We eventually want network on. However, currently radios
@@ -271,6 +279,10 @@
   parser.add_argument('-d', '--device', metavar='SERIAL',
                       help='the serial number of the device to be provisioned'
                       ' (the default is to provision all devices attached)')
+  parser.add_argument('--phase', action='append', choices=_PHASES.ALL,
+                      dest='phases',
+                      help='Phases of provisioning to run. '
+                           '(If omitted, all phases will be run.)')
   parser.add_argument('--skip-wipe', action='store_true', default=False,
                       help="don't wipe device data during provisioning")
   parser.add_argument('--reboot-timeout', metavar='SECS', type=int,
@@ -294,9 +306,13 @@
                       ' disconnections')
   parser.add_argument('--adb-key-files', type=str, nargs='+',
                       help='list of adb keys to push to device')
+  parser.add_argument('-v', '--verbose', action='count', default=1,
+                      help='Log more information.')
   args = parser.parse_args()
   constants.SetBuildType(args.target)
 
+  run_tests_helper.SetLogLevel(args.verbose)
+
   return ProvisionDevices(args)
 
 
diff --git a/build/android/pylib/base/base_test_runner.py b/build/android/pylib/base/base_test_runner.py
index 4e2eae7..1ca0338 100644
--- a/build/android/pylib/base/base_test_runner.py
+++ b/build/android/pylib/base/base_test_runner.py
@@ -26,12 +26,11 @@
 class BaseTestRunner(object):
   """Base class for running tests on a single device."""
 
-  def __init__(self, device_serial, tool, cleanup_test_files=False):
+  def __init__(self, device_serial, tool):
     """
       Args:
         device: Tests will run on the device of this ID.
         tool: Name of the Valgrind tool.
-        cleanup_test_files: Whether or not to cleanup test files on device.
     """
     self.device_serial = device_serial
     self.device = device_utils.DeviceUtils(device_serial)
@@ -45,7 +44,6 @@
     # starting it in TestServerThread.
     self.test_server_spawner_port = 0
     self.test_server_port = 0
-    self._cleanup_test_files = cleanup_test_files
 
   def _PushTestServerPortInfoToDevice(self):
     """Pushes the latest port information to device."""
@@ -77,8 +75,6 @@
   def TearDown(self):
     """Run once after all tests are run."""
     self.ShutdownHelperToolsForTestSuite()
-    if self._cleanup_test_files:
-      self.device.old_interface.RemovePushedFiles()
 
   def LaunchTestHttpServer(self, document_root, port=None,
                            extra_config_contents=None):
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants/__init__.py
similarity index 95%
rename from build/android/pylib/constants.py
rename to build/android/pylib/constants/__init__.py
index 34dbf19..6e92f6d 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants/__init__.py
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 """Defines a set of constants shared by test runners and other scripts."""
+
+# TODO(jbudorick): Split these constants into coherent modules.
+
 # pylint: disable=W0212
 
 import collections
@@ -13,7 +16,7 @@
 
 DIR_SOURCE_ROOT = os.environ.get('CHECKOUT_SOURCE_ROOT',
     os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                 os.pardir, os.pardir, os.pardir)))
+                                 os.pardir, os.pardir, os.pardir, os.pardir)))
 ISOLATE_DEPS_DIR = os.path.join(DIR_SOURCE_ROOT, 'isolate_deps_dir')
 
 CHROME_SHELL_HOST_DRIVEN_DIR = os.path.join(
@@ -50,7 +53,7 @@
         'chrome_devtools_remote',
         None),
     'chrome_dev': PackageInfo(
-        'com.google.android.apps.chrome_dev',
+        'com.chrome.dev',
         'com.google.android.apps.chrome.Main',
         '/data/local/chrome-command-line',
         'chrome_devtools_remote',
@@ -103,6 +106,13 @@
         '/data/local/tmp/chrome-native-tests-command-line',
         None,
         None),
+    'components_browsertests': PackageInfo(
+        'org.chromium.components_browsertests_apk',
+        ('org.chromium.components_browsertests_apk' +
+         '.ComponentsBrowserTestsActivity'),
+        '/data/local/tmp/components-browser-tests-command-line',
+        None,
+        None),
     'content_browsertests': PackageInfo(
         'org.chromium.content_browsertests_apk',
         'org.chromium.content_browsertests_apk.ContentBrowserTestsActivity',
diff --git a/build/android/pylib/constants/keyevent.py b/build/android/pylib/constants/keyevent.py
new file mode 100644
index 0000000..06736b3
--- /dev/null
+++ b/build/android/pylib/constants/keyevent.py
@@ -0,0 +1,14 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Android KeyEvent constants.
+
+http://developer.android.com/reference/android/view/KeyEvent.html
+"""
+
+KEYCODE_BACK = 4
+KEYCODE_DPAD_RIGHT = 22
+KEYCODE_ENTER = 66
+KEYCODE_MENU = 82
+
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index 36f8f48..20787c1 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -12,6 +12,7 @@
 import errno
 import logging
 import os
+import re
 
 from pylib import cmd_helper
 from pylib import constants
@@ -23,6 +24,10 @@
 _DEFAULT_TIMEOUT = 30
 _DEFAULT_RETRIES = 2
 
+_EMULATOR_RE = re.compile(r'^emulator-[0-9]+$')
+
+_READY_STATE = 'device'
+
 
 def _VerifyLocalFileExists(path):
   """Verifies a local file exists.
@@ -158,9 +163,15 @@
     cls._RunAdbCmd(['start-server'], timeout=timeout, retries=retries,
                    cpu_affinity=0)
 
-  # TODO(craigdh): Determine the filter criteria that should be supported.
   @classmethod
   def GetDevices(cls, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
+    """DEPRECATED. Refer to Devices(...) below."""
+    # TODO(jbudorick): Remove this function once no more clients are using it.
+    return cls.Devices(timeout=timeout, retries=retries)
+
+  @classmethod
+  def Devices(cls, is_ready=True, timeout=_DEFAULT_TIMEOUT,
+              retries=_DEFAULT_RETRIES):
     """Get the list of active attached devices.
 
     Args:
@@ -171,9 +182,9 @@
       AdbWrapper instances.
     """
     output = cls._RunAdbCmd(['devices'], timeout=timeout, retries=retries)
-    lines = [line.split() for line in output.splitlines()]
+    lines = (line.split() for line in output.splitlines())
     return [AdbWrapper(line[0]) for line in lines
-            if len(line) == 2 and line[1] == 'device']
+            if len(line) == 2 and (not is_ready or line[1] == _READY_STATE)]
 
   def GetDeviceSerial(self):
     """Gets the device serial number associated with this object.
@@ -530,3 +541,15 @@
     if 'cannot' in output:
       raise device_errors.AdbCommandFailedError(
           ['root'], output, device_serial=self._device_serial)
+
+  @property
+  def is_emulator(self):
+    return _EMULATOR_RE.match(self._device_serial)
+
+  @property
+  def is_ready(self):
+    try:
+      return self.GetState() == _READY_STATE
+    except device_errors.CommandFailedError:
+      return False
+
diff --git a/build/android/pylib/device/adb_wrapper_test.py b/build/android/pylib/device/adb_wrapper_test.py
index 52ba2e3..5fc9eb6 100644
--- a/build/android/pylib/device/adb_wrapper_test.py
+++ b/build/android/pylib/device/adb_wrapper_test.py
@@ -16,7 +16,7 @@
 class TestAdbWrapper(unittest.TestCase):
 
   def setUp(self):
-    devices = adb_wrapper.AdbWrapper.GetDevices()
+    devices = adb_wrapper.AdbWrapper.Devices()
     assert devices, 'A device must be attached'
     self._adb = devices[0]
     self._adb.WaitForDevice()
diff --git a/build/android/pylib/device/battery_utils.py b/build/android/pylib/device/battery_utils.py
new file mode 100644
index 0000000..cca2cf9
--- /dev/null
+++ b/build/android/pylib/device/battery_utils.py
@@ -0,0 +1,386 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Provides a variety of device interactions with power.
+"""
+# pylint: disable=unused-argument
+
+import collections
+import contextlib
+import csv
+import logging
+
+from pylib import constants
+from pylib.device import decorators
+from pylib.device import device_errors
+from pylib.device import device_utils
+from pylib.utils import timeout_retry
+
+_DEFAULT_TIMEOUT = 30
+_DEFAULT_RETRIES = 3
+
+_CONTROL_CHARGING_COMMANDS = [
+  {
+    # Nexus 4
+    'witness_file': '/sys/module/pm8921_charger/parameters/disabled',
+    'enable_command': 'echo 0 > /sys/module/pm8921_charger/parameters/disabled',
+    'disable_command':
+        'echo 1 > /sys/module/pm8921_charger/parameters/disabled',
+  },
+  {
+    # Nexus 5
+    # Setting the HIZ bit of the bq24192 causes the charger to actually ignore
+    # energy coming from USB. Setting the power_supply offline just updates the
+    # Android system to reflect that.
+    'witness_file': '/sys/kernel/debug/bq24192/INPUT_SRC_CONT',
+    'enable_command': (
+        'echo 0x4A > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
+        'echo 1 > /sys/class/power_supply/usb/online'),
+    'disable_command': (
+        'echo 0xCA > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
+        'chmod 644 /sys/class/power_supply/usb/online && '
+        'echo 0 > /sys/class/power_supply/usb/online'),
+  },
+]
+
+# The list of useful dumpsys columns.
+# Index of the column containing the format version.
+_DUMP_VERSION_INDEX = 0
+# Index of the column containing the type of the row.
+_ROW_TYPE_INDEX = 3
+# Index of the column containing the uid.
+_PACKAGE_UID_INDEX = 4
+# Index of the column containing the application package.
+_PACKAGE_NAME_INDEX = 5
+# The column containing the uid of the power data.
+_PWI_UID_INDEX = 1
+# The column containing the type of consumption. Only consumtion since last
+# charge are of interest here.
+_PWI_AGGREGATION_INDEX = 2
+# The column containing the amount of power used, in mah.
+_PWI_POWER_CONSUMPTION_INDEX = 5
+
+
+class BatteryUtils(object):
+
+  def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
+               default_retries=_DEFAULT_RETRIES):
+    """BatteryUtils constructor.
+
+      Args:
+        device: A DeviceUtils instance.
+        default_timeout: An integer containing the default number of seconds to
+                         wait for an operation to complete if no explicit value
+                         is provided.
+        default_retries: An integer containing the default number or times an
+                         operation should be retried on failure if no explicit
+                         value is provided.
+
+      Raises:
+        TypeError: If it is not passed a DeviceUtils instance.
+    """
+    if not isinstance(device, device_utils.DeviceUtils):
+      raise TypeError('Must be initialized with DeviceUtils object.')
+    self._device = device
+    self._cache = device.GetClientCache(self.__class__.__name__)
+    self._default_timeout = default_timeout
+    self._default_retries = default_retries
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetNetworkData(self, package, timeout=None, retries=None):
+    """ Get network data for specific package.
+
+    Args:
+      package: package name you want network data for.
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Returns:
+      Tuple of (sent_data, recieved_data)
+      None if no network data found
+    """
+    # If device_utils clears cache, cache['uids'] doesn't exist
+    if 'uids' not in self._cache:
+      self._cache['uids'] = {}
+    if package not in self._cache['uids']:
+      self.GetPowerData()
+      if package not in self._cache['uids']:
+        logging.warning('No UID found for %s. Can\'t get network data.',
+                        package)
+        return None
+
+    network_data_path = '/proc/uid_stat/%s/' % self._cache['uids'][package]
+    try:
+      send_data = int(self._device.ReadFile(network_data_path + 'tcp_snd'))
+    # If ReadFile throws exception, it means no network data usage file for
+    # package has been recorded. Return 0 sent and 0 received.
+    except device_errors.AdbShellCommandFailedError:
+      logging.warning('No sent data found for package %s', package)
+      send_data = 0
+    try:
+      recv_data = int(self._device.ReadFile(network_data_path + 'tcp_rcv'))
+    except device_errors.AdbShellCommandFailedError:
+      logging.warning('No received data found for package %s', package)
+      recv_data = 0
+    return (send_data, recv_data)
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetPowerData(self, timeout=None, retries=None):
+    """ Get power data for device.
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Returns:
+      Dict of power data, keyed on package names.
+      {
+        package_name: {
+          'uid': uid,
+          'data': [1,2,3]
+        },
+      }
+    """
+    if 'uids' not in self._cache:
+      self._cache['uids'] = {}
+    dumpsys_output = self._device.RunShellCommand(
+        ['dumpsys', 'batterystats', '-c'], check_return=True)
+    csvreader = csv.reader(dumpsys_output)
+    pwi_entries = collections.defaultdict(list)
+    for entry in csvreader:
+      if entry[_DUMP_VERSION_INDEX] not in ['8', '9']:
+        # Wrong dumpsys version.
+        raise device_errors.DeviceVersionError(
+            'Dumpsys version must be 8 or 9. %s found.'
+            % entry[_DUMP_VERSION_INDEX])
+      if _ROW_TYPE_INDEX < len(entry) and entry[_ROW_TYPE_INDEX] == 'uid':
+        current_package = entry[_PACKAGE_NAME_INDEX]
+        if (self._cache['uids'].get(current_package)
+            and self._cache['uids'].get(current_package)
+            != entry[_PACKAGE_UID_INDEX]):
+          raise device_errors.CommandFailedError(
+              'Package %s found multiple times with differnt UIDs %s and %s'
+               % (current_package, self._cache['uids'][current_package],
+               entry[_PACKAGE_UID_INDEX]))
+        self._cache['uids'][current_package] = entry[_PACKAGE_UID_INDEX]
+      elif (_PWI_POWER_CONSUMPTION_INDEX < len(entry)
+          and entry[_ROW_TYPE_INDEX] == 'pwi'
+          and entry[_PWI_AGGREGATION_INDEX] == 'l'):
+        pwi_entries[entry[_PWI_UID_INDEX]].append(
+            float(entry[_PWI_POWER_CONSUMPTION_INDEX]))
+
+    return {p: {'uid': uid, 'data': pwi_entries[uid]}
+            for p, uid in self._cache['uids'].iteritems()}
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetPackagePowerData(self, package, timeout=None, retries=None):
+    """ Get power data for particular package.
+
+    Args:
+      package: Package to get power data on.
+
+    returns:
+      Dict of UID and power data.
+      {
+        'uid': uid,
+        'data': [1,2,3]
+      }
+      None if the package is not found in the power data.
+    """
+    return self.GetPowerData().get(package)
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetBatteryInfo(self, timeout=None, retries=None):
+    """Gets battery info for the device.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+    Returns:
+      A dict containing various battery information as reported by dumpsys
+      battery.
+    """
+    result = {}
+    # Skip the first line, which is just a header.
+    for line in self._device.RunShellCommand(
+        ['dumpsys', 'battery'], check_return=True)[1:]:
+      # If usb charging has been disabled, an extra line of header exists.
+      if 'UPDATES STOPPED' in line:
+        logging.warning('Dumpsys battery not receiving updates. '
+                        'Run dumpsys battery reset if this is in error.')
+      elif ':' not in line:
+        logging.warning('Unknown line found in dumpsys battery: "%s"', line)
+      else:
+        k, v = line.split(':', 1)
+        result[k.strip()] = v.strip()
+    return result
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetCharging(self, timeout=None, retries=None):
+    """Gets the charging state of the device.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+    Returns:
+      True if the device is charging, false otherwise.
+    """
+    battery_info = self.GetBatteryInfo()
+    for k in ('AC powered', 'USB powered', 'Wireless powered'):
+      if (k in battery_info and
+          battery_info[k].lower() in ('true', '1', 'yes')):
+        return True
+    return False
+
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def SetCharging(self, enabled, timeout=None, retries=None):
+    """Enables or disables charging on the device.
+
+    Args:
+      enabled: A boolean indicating whether charging should be enabled or
+        disabled.
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.CommandFailedError: If method of disabling charging cannot
+        be determined.
+    """
+    if 'charging_config' not in self._cache:
+      for c in _CONTROL_CHARGING_COMMANDS:
+        if self._device.FileExists(c['witness_file']):
+          self._cache['charging_config'] = c
+          break
+      else:
+        raise device_errors.CommandFailedError(
+            'Unable to find charging commands.')
+
+    if enabled:
+      command = self._cache['charging_config']['enable_command']
+    else:
+      command = self._cache['charging_config']['disable_command']
+
+    def set_and_verify_charging():
+      self._device.RunShellCommand(command, check_return=True)
+      return self.GetCharging() == enabled
+
+    timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
+
+  # TODO(rnephew): Make private when all use cases can use the context manager.
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def DisableBatteryUpdates(self, timeout=None, retries=None):
+    """ Resets battery data and makes device appear like it is not
+    charging so that it will collect power data since last charge.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.CommandFailedError: When resetting batterystats fails to
+        reset power values.
+      device_errors.DeviceVersionError: If device is not L or higher.
+    """
+    def battery_updates_disabled():
+      return self.GetCharging() is False
+
+    if (self._device.build_version_sdk <
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+      raise device_errors.DeviceVersionError('Device must be L or higher.')
+
+    self._device.RunShellCommand(
+        ['dumpsys', 'battery', 'reset'], check_return=True)
+    self._device.RunShellCommand(
+        ['dumpsys', 'batterystats', '--reset'], check_return=True)
+    battery_data = self._device.RunShellCommand(
+        ['dumpsys', 'batterystats', '--charged', '--checkin'],
+        check_return=True)
+    ROW_TYPE_INDEX = 3
+    PWI_POWER_INDEX = 5
+    for line in battery_data:
+      l = line.split(',')
+      if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi'
+          and l[PWI_POWER_INDEX] != 0):
+        raise device_errors.CommandFailedError(
+            'Non-zero pmi value found after reset.')
+    self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'ac', '0'],
+                                 check_return=True)
+    self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
+                                 check_return=True)
+    timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
+
+  # TODO(rnephew): Make private when all use cases can use the context manager.
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def EnableBatteryUpdates(self, timeout=None, retries=None):
+    """ Restarts device charging so that dumpsys no longer collects power data.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.DeviceVersionError: If device is not L or higher.
+    """
+    def battery_updates_enabled():
+      return self.GetCharging() is True
+
+    if (self._device.build_version_sdk <
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+      raise device_errors.DeviceVersionError('Device must be L or higher.')
+
+    self._device.RunShellCommand(['dumpsys', 'battery', 'reset'],
+                                 check_return=True)
+    timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
+
+  @contextlib.contextmanager
+  def BatteryMeasurement(self, timeout=None, retries=None):
+    """Context manager that enables battery data collection. It makes
+    the device appear to stop charging so that dumpsys will start collecting
+    power data since last charge. Once the with block is exited, charging is
+    resumed and power data since last charge is no longer collected.
+
+    Only for devices L and higher.
+
+    Example usage:
+      with BatteryMeasurement():
+        browser_actions()
+        get_power_data() # report usage within this block
+      after_measurements() # Anything that runs after power
+                           # measurements are collected
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Raises:
+      device_errors.DeviceVersionError: If device is not L or higher.
+    """
+    if (self._device.build_version_sdk <
+        constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
+      raise device_errors.DeviceVersionError('Device must be L or higher.')
+    try:
+      self.DisableBatteryUpdates(timeout=timeout, retries=retries)
+      yield
+    finally:
+      self.EnableBatteryUpdates(timeout=timeout, retries=retries)
+
+  def ChargeDeviceToLevel(self, level, wait_period=60):
+    """Enables charging and waits for device to be charged to given level.
+
+    Args:
+      level: level of charge to wait for.
+      wait_period: time in seconds to wait between checking.
+    """
+    self.SetCharging(True)
+
+    def device_charged():
+      battery_level = self.GetBatteryInfo().get('level')
+      if battery_level is None:
+        logging.warning('Unable to find current battery level.')
+        battery_level = 100
+      else:
+        logging.info('current battery level: %s', battery_level)
+        battery_level = int(battery_level)
+      return battery_level >= level
+
+    timeout_retry.WaitFor(device_charged, wait_period=wait_period)
diff --git a/build/android/pylib/device/battery_utils_test.py b/build/android/pylib/device/battery_utils_test.py
new file mode 100755
index 0000000..15b4c34
--- /dev/null
+++ b/build/android/pylib/device/battery_utils_test.py
@@ -0,0 +1,316 @@
+#!/usr/bin/env python
+# 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.
+
+"""
+Unit tests for the contents of battery_utils.py
+"""
+
+# pylint: disable=W0613
+
+import logging
+import os
+import sys
+import unittest
+
+from pylib import android_commands
+from pylib import constants
+from pylib.device import battery_utils
+from pylib.device import device_errors
+from pylib.device import device_utils
+from pylib.device import device_utils_test
+from pylib.utils import mock_calls
+
+# RunCommand from third_party/android_testrunner/run_command.py is mocked
+# below, so its path needs to be in sys.path.
+sys.path.append(os.path.join(
+    constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner'))
+
+sys.path.append(os.path.join(
+    constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
+import mock # pylint: disable=F0401
+
+_DUMPSYS_OUTPUT = [
+    '9,0,i,uid,1000,test_package1',
+    '9,0,i,uid,1001,test_package2',
+    '9,1000,l,pwi,uid,1',
+    '9,1001,l,pwi,uid,2'
+]
+
+
+class BatteryUtilsTest(mock_calls.TestCase):
+
+  def ShellError(self, output=None, status=1):
+    def action(cmd, *args, **kwargs):
+      raise device_errors.AdbShellCommandFailedError(
+          cmd, output, status, str(self.device))
+    if output is None:
+      output = 'Permission denied\n'
+    return action
+
+  def setUp(self):
+    self.adb = device_utils_test._AdbWrapperMock('0123456789abcdef')
+    self.device = device_utils.DeviceUtils(
+        self.adb, default_timeout=10, default_retries=0)
+    self.watchMethodCalls(self.call.adb, ignore=['GetDeviceSerial'])
+    self.battery = battery_utils.BatteryUtils(
+        self.device, default_timeout=10, default_retries=0)
+
+
+class BatteryUtilsInitTest(unittest.TestCase):
+
+  def testInitWithDeviceUtil(self):
+    serial = '0fedcba987654321'
+    a = android_commands.AndroidCommands(device=serial)
+    d = device_utils.DeviceUtils(a)
+    b = battery_utils.BatteryUtils(d)
+    self.assertEqual(d, b._device)
+
+  def testInitWithMissing_fails(self):
+    with self.assertRaises(TypeError):
+      battery_utils.BatteryUtils(None)
+    with self.assertRaises(TypeError):
+      battery_utils.BatteryUtils('')
+
+
+class BatteryUtilsSetChargingTest(BatteryUtilsTest):
+
+  @mock.patch('time.sleep', mock.Mock())
+  def testSetCharging_enabled(self):
+    with self.assertCalls(
+        (self.call.device.FileExists(mock.ANY), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), False),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), True)):
+      self.battery.SetCharging(True)
+
+  def testSetCharging_alreadyEnabled(self):
+    with self.assertCalls(
+        (self.call.device.FileExists(mock.ANY), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), True)):
+      self.battery.SetCharging(True)
+
+  @mock.patch('time.sleep', mock.Mock())
+  def testSetCharging_disabled(self):
+    with self.assertCalls(
+        (self.call.device.FileExists(mock.ANY), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.battery.GetCharging(), False)):
+      self.battery.SetCharging(False)
+
+
+class BatteryUtilsSetBatteryMeasurementTest(BatteryUtilsTest):
+
+  def testBatteryMeasurement(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            mock.ANY, retries=0, single_line=True,
+            timeout=10, check_return=True), '22'),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'reset'], check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '--charged', '--checkin'],
+            check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
+        (self.call.battery.GetCharging(), False),
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'battery', 'reset'], check_return=True), []),
+        (self.call.battery.GetCharging(), True)):
+      with self.battery.BatteryMeasurement():
+        pass
+
+
+class BatteryUtilsGetPowerData(BatteryUtilsTest):
+
+  def testGetPowerData(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      data = self.battery.GetPowerData()
+      check = {
+          'test_package1': {'uid': '1000', 'data': [1.0]},
+          'test_package2': {'uid': '1001', 'data': [2.0]}
+      }
+      self.assertEqual(data, check)
+
+  def testGetPowerData_packageCollisionSame(self):
+      self.battery._cache['uids'] = {'test_package1': '1000'}
+      with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT):
+        data = self.battery.GetPowerData()
+        check = {
+            'test_package1': {'uid': '1000', 'data': [1.0]},
+            'test_package2': {'uid': '1001', 'data': [2.0]}
+        }
+        self.assertEqual(data, check)
+
+  def testGetPowerData_packageCollisionDifferent(self):
+      self.battery._cache['uids'] = {'test_package1': '1'}
+      with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT):
+        with self.assertRaises(device_errors.CommandFailedError):
+          self.battery.GetPowerData()
+
+  def testGetPowerData_cacheCleared(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      self.battery._cache.clear()
+      data = self.battery.GetPowerData()
+      check = {
+          'test_package1': {'uid': '1000', 'data': [1.0]},
+          'test_package2': {'uid': '1001', 'data': [2.0]}
+      }
+      self.assertEqual(data, check)
+
+  def testGetPackagePowerData(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      data = self.battery.GetPackagePowerData('test_package2')
+      self.assertEqual(data, {'uid': '1001', 'data': [2.0]})
+
+  def testGetPackagePowerData_badPackage(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT)):
+      data = self.battery.GetPackagePowerData('not_a_package')
+      self.assertEqual(data, None)
+
+
+class BatteryUtilsChargeDevice(BatteryUtilsTest):
+
+  @mock.patch('time.sleep', mock.Mock())
+  def testChargeDeviceToLevel(self):
+    with self.assertCalls(
+        (self.call.battery.SetCharging(True)),
+        (self.call.battery.GetBatteryInfo(), {'level': '50'}),
+        (self.call.battery.GetBatteryInfo(), {'level': '100'})):
+      self.battery.ChargeDeviceToLevel(95)
+
+
+class DeviceUtilsGetBatteryInfoTest(BatteryUtilsTest):
+
+  def testGetBatteryInfo_normal(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'battery'], check_return=True),
+        [
+          'Current Battery Service state:',
+          '  AC powered: false',
+          '  USB powered: true',
+          '  level: 100',
+          '  temperature: 321',
+        ]):
+      self.assertEquals(
+          {
+            'AC powered': 'false',
+            'USB powered': 'true',
+            'level': '100',
+            'temperature': '321',
+          },
+          self.battery.GetBatteryInfo())
+
+  def testGetBatteryInfo_nothing(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'battery'], check_return=True), []):
+      self.assertEquals({}, self.battery.GetBatteryInfo())
+
+
+class DeviceUtilsGetChargingTest(BatteryUtilsTest):
+
+  def testGetCharging_usb(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'USB powered': 'true'}):
+      self.assertTrue(self.battery.GetCharging())
+
+  def testGetCharging_usbFalse(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'USB powered': 'false'}):
+      self.assertFalse(self.battery.GetCharging())
+
+  def testGetCharging_ac(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'AC powered': 'true'}):
+      self.assertTrue(self.battery.GetCharging())
+
+  def testGetCharging_wireless(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'Wireless powered': 'true'}):
+      self.assertTrue(self.battery.GetCharging())
+
+  def testGetCharging_unknown(self):
+    with self.assertCall(
+        self.call.battery.GetBatteryInfo(), {'level': '42'}):
+      self.assertFalse(self.battery.GetCharging())
+
+
+class DeviceUtilsGetNetworkDataTest(BatteryUtilsTest):
+
+  def testGetNetworkData_noDataUsage(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'),
+            self.ShellError()),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'),
+            self.ShellError())):
+      self.assertEquals(self.battery.GetNetworkData('test_package1'), (0, 0))
+
+  def testGetNetworkData_badPackage(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT):
+      self.assertEqual(self.battery.GetNetworkData('asdf'), None)
+
+  def testGetNetworkData_packageNotCached(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+      self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+  def testGetNetworkData_packageCached(self):
+    self.battery._cache['uids'] = {'test_package1': '1000'}
+    with self.assertCalls(
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+      self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+  def testGetNetworkData_clearedCache(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['dumpsys', 'batterystats', '-c'], check_return=True),
+            _DUMPSYS_OUTPUT),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
+        (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
+      self.battery._cache.clear()
+      self.assertEqual(self.battery.GetNetworkData('test_package1'), (1,2))
+
+
+if __name__ == '__main__':
+  logging.getLogger().setLevel(logging.DEBUG)
+  unittest.main(verbosity=2)
diff --git a/build/android/pylib/device/decorators.py b/build/android/pylib/device/decorators.py
index 074a0fc..73c13da 100644
--- a/build/android/pylib/device/decorators.py
+++ b/build/android/pylib/device/decorators.py
@@ -11,6 +11,7 @@
 import sys
 import threading
 
+from pylib import cmd_helper
 from pylib import constants
 from pylib.device import device_errors
 from pylib.utils import reraiser_thread
@@ -56,13 +57,16 @@
         return timeout_retry.Run(impl, timeout, retries)
     except old_errors.WaitForResponseTimedOutError as e:
       raise device_errors.CommandTimeoutError(str(e)), None, (
-             sys.exc_info()[2])
+          sys.exc_info()[2])
     except old_errors.DeviceUnresponsiveError as e:
       raise device_errors.DeviceUnreachableError(str(e)), None, (
-             sys.exc_info()[2])
+          sys.exc_info()[2])
     except reraiser_thread.TimeoutError as e:
       raise device_errors.CommandTimeoutError(str(e)), None, (
-             sys.exc_info()[2])
+          sys.exc_info()[2])
+    except cmd_helper.TimeoutError as e:
+      raise device_errors.CommandTimeoutError(str(e)), None, (
+          sys.exc_info()[2])
   return TimeoutRetryWrapper
 
 
diff --git a/build/android/pylib/device/device_errors.py b/build/android/pylib/device/device_errors.py
index 26d9eaf..e94968f 100644
--- a/build/android/pylib/device/device_errors.py
+++ b/build/android/pylib/device/device_errors.py
@@ -42,6 +42,13 @@
     super(AdbCommandFailedError, self).__init__(message, device_serial)
 
 
+class DeviceVersionError(CommandFailedError):
+  """Exception for device version failures."""
+
+  def __init__(self, message, device_serial=None):
+    super(DeviceVersionError, self).__init__(message, device_serial)
+
+
 class AdbShellCommandFailedError(AdbCommandFailedError):
   """Exception for shell command failures run via adb."""
 
@@ -52,7 +59,11 @@
     message.append('  exit status: %s\n' % status)
     if output:
       message.append('  output:\n')
-      message.extend('  - %s\n' % line for line in output.splitlines())
+      if isinstance(output, basestring):
+        output_lines = output.splitlines()
+      else:
+        output_lines = output
+      message.extend('  - %s\n' % line for line in output_lines)
     else:
       message.append("  output: ''\n")
     message = ''.join(message)
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 9f538e1..46aec6f 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -25,8 +25,10 @@
 import pylib.android_commands
 from pylib import cmd_helper
 from pylib import constants
+from pylib import device_signal
 from pylib.device import adb_wrapper
 from pylib.device import decorators
+from pylib.device import device_blacklist
 from pylib.device import device_errors
 from pylib.device import intent
 from pylib.device import logcat_monitor
@@ -72,6 +74,7 @@
   },
 ]
 
+
 @decorators.WithExplicitTimeoutAndRetries(
     _DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
 def GetAVDs():
@@ -168,6 +171,7 @@
     self._default_timeout = default_timeout
     self._default_retries = default_retries
     self._cache = {}
+    self._client_caches = {}
     assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)
     assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR)
 
@@ -406,7 +410,7 @@
       return not self.IsOnline()
 
     self.adb.Reboot()
-    self._cache = {}
+    self._ClearCache()
     timeout_retry.WaitFor(device_offline, wait_period=1)
     if block:
       self.WaitUntilFullyBooted(wifi=wifi)
@@ -446,8 +450,8 @@
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None,
-                      as_root=False, single_line=False, timeout=None,
-                      retries=None):
+                      as_root=False, single_line=False, large_output=False,
+                      timeout=None, retries=None):
     """Run an ADB shell command.
 
     The command to run |cmd| should be a sequence of program arguments or else
@@ -480,6 +484,8 @@
         with root privileges.
       single_line: A boolean indicating if only a single line of output is
         expected.
+      large_output: Uses a work-around for large shell command output. Without
+        this large output will be truncated.
       timeout: timeout in seconds
       retries: number of retries
 
@@ -502,15 +508,49 @@
       # using double quotes here to allow interpolation of shell variables
       return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
 
-    def do_run(cmd):
+    def run(cmd):
+      return self.adb.Shell(cmd)
+
+    def handle_check_return(cmd):
       try:
-        return self.adb.Shell(cmd)
+        return run(cmd)
       except device_errors.AdbCommandFailedError as exc:
         if check_return:
           raise
         else:
           return exc.output
 
+    def handle_large_command(cmd):
+      if len(cmd) < self._MAX_ADB_COMMAND_LENGTH:
+        return handle_check_return(cmd)
+      else:
+        with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script:
+          self._WriteFileWithPush(script.name, cmd)
+          logging.info('Large shell command will be run from file: %s ...',
+                       cmd[:100])
+          return handle_check_return('sh %s' % script.name_quoted)
+
+    def handle_large_output(cmd, large_output_mode):
+      if large_output_mode:
+        with device_temp_file.DeviceTempFile(self.adb) as large_output_file:
+          cmd = '%s > %s' % (cmd, large_output_file.name)
+          logging.info('Large output mode enabled. Will write output to device '
+                       ' and read results from file.')
+          handle_large_command(cmd)
+          return self.ReadFile(large_output_file.name)
+      else:
+        try:
+          return handle_large_command(cmd)
+        except device_errors.AdbCommandFailedError as exc:
+          if exc.status is None:
+            logging.exception('No output found for %s', cmd)
+            logging.warning('Attempting to run in large_output mode.')
+            logging.warning('Use RunShellCommand(..., large_output=True) for '
+                            'shell commands that expect a lot of output.')
+            return handle_large_output(cmd, True)
+          else:
+            raise
+
     if not isinstance(cmd, basestring):
       cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
     if env:
@@ -521,19 +561,9 @@
     if as_root and self.NeedsSU():
       # "su -c sh -c" allows using shell features in |cmd|
       cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
-    if timeout is None:
-      timeout = self._default_timeout
 
-    if len(cmd) < self._MAX_ADB_COMMAND_LENGTH:
-      output = do_run(cmd)
-    else:
-      with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script:
-        self._WriteFileWithPush(script.name, cmd)
-        logging.info('Large shell command will be run from file: %s ...',
-                     cmd[:100])
-        output = do_run('sh %s' % script.name_quoted)
+    output = handle_large_output(cmd, large_output).splitlines()
 
-    output = output.splitlines()
     if single_line:
       if not output:
         return ''
@@ -545,38 +575,70 @@
     else:
       return output
 
+  def _RunPipedShellCommand(self, script, **kwargs):
+    PIPESTATUS_LEADER = 'PIPESTATUS: '
+
+    script += '; echo "%s${PIPESTATUS[@]}"' % PIPESTATUS_LEADER
+    kwargs['check_return'] = True
+    output = self.RunShellCommand(script, **kwargs)
+    pipestatus_line = output[-1]
+
+    if not pipestatus_line.startswith(PIPESTATUS_LEADER):
+      logging.error('Pipe exit statuses of shell script missing.')
+      raise device_errors.AdbShellCommandFailedError(
+          script, output, status=None,
+          device_serial=self.adb.GetDeviceSerial())
+
+    output = output[:-1]
+    statuses = [
+        int(s) for s in pipestatus_line[len(PIPESTATUS_LEADER):].split()]
+    if any(statuses):
+      raise device_errors.AdbShellCommandFailedError(
+          script, output, status=statuses,
+          device_serial=self.adb.GetDeviceSerial())
+    return output
+
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
-              timeout=None, retries=None):
+  def KillAll(self, process_name, signum=device_signal.SIGKILL, as_root=False,
+              blocking=False, quiet=False, timeout=None, retries=None):
     """Kill all processes with the given name on the device.
 
     Args:
       process_name: A string containing the name of the process to kill.
       signum: An integer containing the signal number to send to kill. Defaults
-              to 9 (SIGKILL).
+              to SIGKILL (9).
       as_root: A boolean indicating whether the kill should be executed with
                root privileges.
       blocking: A boolean indicating whether we should wait until all processes
                 with the given |process_name| are dead.
+      quiet: A boolean indicating whether to ignore the fact that no processes
+             to kill were found.
       timeout: timeout in seconds
       retries: number of retries
 
+    Returns:
+      The number of processes attempted to kill.
+
     Raises:
-      CommandFailedError if no process was killed.
+      CommandFailedError if no process was killed and |quiet| is False.
       CommandTimeoutError on timeout.
       DeviceUnreachableError on missing device.
     """
-    pids = self._GetPidsImpl(process_name)
+    pids = self.GetPids(process_name)
     if not pids:
-      raise device_errors.CommandFailedError(
-          'No process "%s"' % process_name, str(self))
+      if quiet:
+        return 0
+      else:
+        raise device_errors.CommandFailedError(
+            'No process "%s"' % process_name, str(self))
 
     cmd = ['kill', '-%d' % signum] + pids.values()
     self.RunShellCommand(cmd, as_root=as_root, check_return=True)
 
     if blocking:
+      # TODO(perezu): use timeout_retry.WaitFor
       wait_period = 0.1
-      while self._GetPidsImpl(process_name):
+      while self.GetPids(process_name):
         time.sleep(wait_period)
 
     return len(pids)
@@ -791,29 +853,27 @@
     if not real_device_path:
       return [(host_path, device_path)]
 
-    host_hash_tuples = md5sum.CalculateHostMd5Sums([real_host_path])
+    host_checksums = md5sum.CalculateHostMd5Sums([real_host_path])
     device_paths_to_md5 = (
         real_device_path if os.path.isfile(real_host_path)
         else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path))
-              for _, p in host_hash_tuples))
-    device_hash_tuples = md5sum.CalculateDeviceMd5Sums(
+              for p in host_checksums.iterkeys()))
+    device_checksums = md5sum.CalculateDeviceMd5Sums(
         device_paths_to_md5, self)
 
     if os.path.isfile(host_path):
-      if (not device_hash_tuples
-          or device_hash_tuples[0].hash != host_hash_tuples[0].hash):
+      host_checksum = host_checksums.get(real_host_path)
+      device_checksum = device_checksums.get(real_device_path)
+      if host_checksum != device_checksum:
         return [(host_path, device_path)]
       else:
         return []
     else:
-      device_tuple_dict = dict((d.path, d.hash) for d in device_hash_tuples)
       to_push = []
-      for host_hash, host_abs_path in (
-          (h.hash, h.path) for h in host_hash_tuples):
+      for host_abs_path, host_checksum in host_checksums.iteritems():
         device_abs_path = '%s/%s' % (
             real_device_path, os.path.relpath(host_abs_path, real_host_path))
-        if (device_abs_path not in device_tuple_dict
-            or device_tuple_dict[device_abs_path] != host_hash):
+        if (device_checksums.get(device_abs_path) != host_checksum):
           to_push.append((host_abs_path, device_abs_path))
       return to_push
 
@@ -991,7 +1051,7 @@
     else:
       logging.warning('Could not determine size of %s.', device_path)
 
-    if size is None or size <= self._MAX_ADB_OUTPUT_LENGTH:
+    if 0 < size <= self._MAX_ADB_OUTPUT_LENGTH:
       return _JoinLines(self.RunShellCommand(
           ['cat', device_path], as_root=as_root, check_return=True))
     elif as_root and self.NeedsSU():
@@ -1326,11 +1386,19 @@
       CommandTimeoutError on timeout.
       DeviceUnreachableError on missing device.
     """
-    return self._GetPidsImpl(process_name)
-
-  def _GetPidsImpl(self, process_name):
     procs_pids = {}
-    for line in self.RunShellCommand('ps', check_return=True):
+    try:
+      ps_output = self._RunPipedShellCommand(
+          'ps | grep -F %s' % cmd_helper.SingleQuote(process_name))
+    except device_errors.AdbShellCommandFailedError as e:
+      if e.status and isinstance(e.status, list) and not e.status[0]:
+        # If ps succeeded but grep failed, there were no processes with the
+        # given name.
+        return procs_pids
+      else:
+        raise
+
+    for line in ps_output:
       try:
         ps_data = line.split()
         if process_name in ps_data[-1]:
@@ -1402,10 +1470,8 @@
         'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean',
         'Private_Dirty')
 
-    showmap_out = self.RunShellCommand(
-        ['showmap', str(pid)], as_root=True, check_return=True)
-    if not showmap_out:
-      raise device_errors.CommandFailedError('No output from showmap')
+    showmap_out = self._RunPipedShellCommand(
+        'showmap %d | grep TOTAL' % int(pid), as_root=True)
 
     split_totals = showmap_out[-1].split()
     if (not split_totals
@@ -1439,155 +1505,6 @@
     return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs)
 
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def GetBatteryInfo(self, timeout=None, retries=None):
-    """Gets battery info for the device.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    Returns:
-      A dict containing various battery information as reported by dumpsys
-      battery.
-    """
-    result = {}
-    # Skip the first line, which is just a header.
-    for line in self.RunShellCommand(
-        ['dumpsys', 'battery'], check_return=True)[1:]:
-      # If usb charging has been disabled, an extra line of header exists.
-      if 'UPDATES STOPPED' in line:
-        logging.warning('Dumpsys battery not receiving updates. '
-                        'Run dumpsys battery reset if this is in error.')
-      elif ':' not in line:
-        logging.warning('Unknown line found in dumpsys battery.')
-        logging.warning(line)
-      else:
-        k, v = line.split(': ', 1)
-        result[k.strip()] = v.strip()
-    return result
-
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def GetCharging(self, timeout=None, retries=None):
-    """Gets the charging state of the device.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    Returns:
-      True if the device is charging, false otherwise.
-    """
-    battery_info = self.GetBatteryInfo()
-    for k in ('AC powered', 'USB powered', 'Wireless powered'):
-      if (k in battery_info and
-          battery_info[k].lower() in ('true', '1', 'yes')):
-        return True
-    return False
-
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def SetCharging(self, enabled, timeout=None, retries=None):
-    """Enables or disables charging on the device.
-
-    Args:
-      enabled: A boolean indicating whether charging should be enabled or
-        disabled.
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    if 'charging_config' not in self._cache:
-      for c in _CONTROL_CHARGING_COMMANDS:
-        if self.FileExists(c['witness_file']):
-          self._cache['charging_config'] = c
-          break
-      else:
-        raise device_errors.CommandFailedError(
-            'Unable to find charging commands.')
-
-    if enabled:
-      command = self._cache['charging_config']['enable_command']
-    else:
-      command = self._cache['charging_config']['disable_command']
-
-    def set_and_verify_charging():
-      self.RunShellCommand(command, check_return=True)
-      return self.GetCharging() == enabled
-
-    timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
-
-  # TODO(rnephew): Make private when all use cases can use the context manager.
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def DisableBatteryUpdates(self, timeout=None, retries=None):
-    """ Resets battery data and makes device appear like it is not
-    charging so that it will collect power data since last charge.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    def battery_updates_disabled():
-      return self.GetCharging() is False
-
-    self.RunShellCommand(
-        ['dumpsys', 'batterystats', '--reset'], check_return=True)
-    battery_data = self.RunShellCommand(
-        ['dumpsys', 'batterystats', '--charged', '--checkin'],
-        check_return=True)
-    ROW_TYPE_INDEX = 3
-    PWI_POWER_INDEX = 5
-    for line in battery_data:
-      l = line.split(',')
-      if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi'
-          and l[PWI_POWER_INDEX] != 0):
-        raise device_errors.CommandFailedError(
-            'Non-zero pmi value found after reset.')
-    self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
-                         check_return=True)
-    timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
-
-  # TODO(rnephew): Make private when all use cases can use the context manager.
-  @decorators.WithTimeoutAndRetriesFromInstance()
-  def EnableBatteryUpdates(self, timeout=None, retries=None):
-    """ Restarts device charging so that dumpsys no longer collects power data.
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    def battery_updates_enabled():
-      return self.GetCharging() is True
-
-    self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'],
-                         check_return=True)
-    self.RunShellCommand(['dumpsys', 'battery', 'reset'], check_return=True)
-    timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
-
-  @contextlib.contextmanager
-  def BatteryMeasurement(self, timeout=None, retries=None):
-    """Context manager that enables battery data collection. It makes
-    the device appear to stop charging so that dumpsys will start collecting
-    power data since last charge. Once the with block is exited, charging is
-    resumed and power data since last charge is no longer collected.
-
-    Only for devices L and higher.
-
-    Example usage:
-      with BatteryMeasurement():
-        browser_actions()
-        get_power_data() # report usage within this block
-      after_measurements() # Anything that runs after power
-                           # measurements are collected
-
-    Args:
-      timeout: timeout in seconds
-      retries: number of retries
-    """
-    if self.build_version_sdk < constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP:
-      raise device_errors.CommandFailedError('Device must be L or higher.')
-    try:
-      self.DisableBatteryUpdates(timeout=timeout, retries=retries)
-      yield
-    finally:
-      self.EnableBatteryUpdates(timeout=timeout, retries=retries)
-
-  @decorators.WithTimeoutAndRetriesFromInstance()
   def GetDevicePieWrapper(self, timeout=None, retries=None):
     """Gets the absolute path to the run_pie wrapper on the device.
 
@@ -1622,12 +1539,24 @@
 
     return self._cache['run_pie']
 
+  def GetClientCache(self, client_name):
+    """Returns client cache."""
+    if client_name not in self._client_caches:
+      self._client_caches[client_name] = {}
+    return self._client_caches[client_name]
+
+  def _ClearCache(self):
+    """Clears all caches."""
+    for client in self._client_caches:
+      self._client_caches[client].clear()
+    self._cache.clear()
+
   @classmethod
   def parallel(cls, devices=None, async=False):
     """Creates a Parallelizer to operate over the provided list of devices.
 
     If |devices| is either |None| or an empty list, the Parallelizer will
-    operate over all attached devices.
+    operate over all attached devices that have not been blacklisted.
 
     Args:
       devices: A list of either DeviceUtils instances or objects from
@@ -1640,11 +1569,25 @@
       A Parallelizer operating over |devices|.
     """
     if not devices:
-      devices = adb_wrapper.AdbWrapper.GetDevices()
+      devices = cls.HealthyDevices()
       if not devices:
         raise device_errors.NoDevicesError()
+
     devices = [d if isinstance(d, cls) else cls(d) for d in devices]
     if async:
       return parallelizer.Parallelizer(devices)
     else:
       return parallelizer.SyncParallelizer(devices)
+
+  @classmethod
+  def HealthyDevices(cls):
+    blacklist = device_blacklist.ReadBlacklist()
+    def blacklisted(adb):
+      if adb.GetDeviceSerial() in blacklist:
+        logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial())
+        return True
+      return False
+
+    return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices()
+            if not blacklisted(adb)]
+
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 98e3539..4301e9d 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -16,13 +16,13 @@
 import logging
 import os
 import re
-import signal
 import sys
 import unittest
 
 from pylib import android_commands
 from pylib import cmd_helper
 from pylib import constants
+from pylib import device_signal
 from pylib.device import adb_wrapper
 from pylib.device import device_errors
 from pylib.device import device_utils
@@ -114,6 +114,10 @@
   def __exit__(self, exc_type, exc_val, exc_tb):
     pass
 
+  @property
+  def name(self):
+    return self.file.name
+
 
 class _PatchedFunction(object):
   def __init__(self, patched=None, mocked=None):
@@ -582,6 +586,81 @@
       self.assertEquals([output.rstrip()],
                         self.device.RunShellCommand(cmd, check_return=False))
 
+  def testRunShellCommand_largeOutput_enabled(self):
+    cmd = 'echo $VALUE'
+    temp_file = MockTempFile('/sdcard/temp-123')
+    cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+    with self.assertCalls(
+        (mock.call.pylib.utils.device_temp_file.DeviceTempFile(self.adb),
+            temp_file),
+        (self.call.adb.Shell(cmd_redirect)),
+        (self.call.device.ReadFile(temp_file.name), 'something')):
+      self.assertEquals(
+          ['something'],
+          self.device.RunShellCommand(
+              cmd, large_output=True, check_return=True))
+
+  def testRunShellCommand_largeOutput_disabledNoTrigger(self):
+    cmd = 'something'
+    with self.assertCall(self.call.adb.Shell(cmd), self.ShellError('')):
+      with self.assertRaises(device_errors.AdbCommandFailedError):
+        self.device.RunShellCommand(cmd, check_return=True)
+
+  def testRunShellCommand_largeOutput_disabledTrigger(self):
+    cmd = 'echo $VALUE'
+    temp_file = MockTempFile('/sdcard/temp-123')
+    cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+    with self.assertCalls(
+        (self.call.adb.Shell(cmd), self.ShellError('', None)),
+        (mock.call.pylib.utils.device_temp_file.DeviceTempFile(self.adb),
+            temp_file),
+        (self.call.adb.Shell(cmd_redirect)),
+        (self.call.device.ReadFile(mock.ANY), 'something')):
+      self.assertEquals(['something'],
+                        self.device.RunShellCommand(cmd, check_return=True))
+
+
+class DeviceUtilsRunPipedShellCommandTest(DeviceUtilsTest):
+
+  def testRunPipedShellCommand_success(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['This line contains foo', 'PIPESTATUS: 0 0']):
+      self.assertEquals(['This line contains foo'],
+                        self.device._RunPipedShellCommand('ps | grep foo'))
+
+  def testRunPipedShellCommand_firstCommandFails(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['PIPESTATUS: 1 0']):
+      with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+        self.device._RunPipedShellCommand('ps | grep foo')
+      self.assertEquals([1, 0], ec.exception.status)
+
+  def testRunPipedShellCommand_secondCommandFails(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['PIPESTATUS: 0 1']):
+      with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+        self.device._RunPipedShellCommand('ps | grep foo')
+      self.assertEquals([0, 1], ec.exception.status)
+
+  def testRunPipedShellCommand_outputCutOff(self):
+    with self.assertCall(
+        self.call.device.RunShellCommand(
+            'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
+            check_return=True),
+        ['foo.bar'] * 256 + ['foo.ba']):
+      with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
+        self.device._RunPipedShellCommand('ps | grep foo')
+      self.assertIs(None, ec.exception.status)
+
 
 class DeviceUtilsGetDevicePieWrapper(DeviceUtilsTest):
 
@@ -604,53 +683,45 @@
 @mock.patch('time.sleep', mock.Mock())
 class DeviceUtilsKillAllTest(DeviceUtilsTest):
 
-  def testKillAll_noMatchingProcesses(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'):
+  def testKillAll_noMatchingProcessesFailure(self):
+    with self.assertCall(self.call.device.GetPids('test_process'), {}):
       with self.assertRaises(device_errors.CommandFailedError):
         self.device.KillAll('test_process')
 
+  def testKillAll_noMatchingProcessesQuiet(self):
+    with self.assertCall(self.call.device.GetPids('test_process'), {}):
+      self.assertEqual(0, self.device.KillAll('test_process', quiet=True))
+
   def testKillAll_nonblocking(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.adb.Shell('kill -9 1234'), '')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', blocking=False))
+      self.assertEquals(
+          1, self.device.KillAll('some.process', blocking=False))
 
   def testKillAll_blocking(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.adb.Shell('kill -9 1234'), ''),
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', blocking=True))
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
+        (self.call.device.GetPids('some.process'), [])):
+      self.assertEquals(
+          1, self.device.KillAll('some.process', blocking=True))
 
   def testKillAll_root(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.device.NeedsSU(), True),
         (self.call.adb.Shell("su -c sh -c 'kill -9 1234'"), '')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', as_root=True))
+      self.assertEquals(
+          1, self.device.KillAll('some.process', as_root=True))
 
   def testKillAll_sigterm(self):
     with self.assertCalls(
-        (self.call.adb.Shell('ps'),
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab some.process\n'),
+        (self.call.device.GetPids('some.process'), {'some.process': '1234'}),
         (self.call.adb.Shell('kill -15 1234'), '')):
-      self.assertEquals(1,
-          self.device.KillAll('some.process', signum=signal.SIGTERM))
+      self.assertEquals(
+          1, self.device.KillAll('some.process', signum=device_signal.SIGTERM))
 
 
 class DeviceUtilsStartActivityTest(DeviceUtilsTest):
@@ -1078,7 +1149,8 @@
             as_root=False, check_return=True),
          ['-rw-rw---- root foo 256 1970-01-01 00:00 file']),
         (self.call.device.RunShellCommand(
-            ['cat', '/read/this/test/file'], as_root=False, check_return=True),
+            ['cat', '/read/this/test/file'],
+            as_root=False, check_return=True),
          ['this is a test file'])):
       self.assertEqual('this is a test file\n',
                        self.device.ReadFile('/read/this/test/file'))
@@ -1092,6 +1164,17 @@
       with self.assertRaises(device_errors.CommandFailedError):
         self.device.ReadFile('/this/file/does.not.exist')
 
+  def testReadFile_zeroSize(self):
+    with self.assertCalls(
+        (self.call.device.RunShellCommand(
+            ['ls', '-l', '/this/file/has/zero/size'],
+            as_root=False, check_return=True),
+         ['-r--r--r-- root foo 0 1970-01-01 00:00 zero_size_file']),
+        (self.call.device._ReadFileWithPull('/this/file/has/zero/size'),
+         'but it has contents\n')):
+      self.assertEqual('but it has contents\n',
+                       self.device.ReadFile('/this/file/has/zero/size'))
+
   def testReadFile_withSU(self):
     with self.assertCalls(
         (self.call.device.RunShellCommand(
@@ -1350,38 +1433,43 @@
 class DeviceUtilsGetPidsTest(DeviceUtilsTest):
 
   def testGetPids_noMatches(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 no.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F does.not.match'),
+        []):
       self.assertEqual({}, self.device.GetPids('does.not.match'))
 
   def testGetPids_oneMatch(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 not.a.match\n'
-        'user  1001    100   1024 1024   ffffffff 00000000 one.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F one.match'),
+        ['user  1001    100   1024 1024   ffffffff 00000000 one.match']):
       self.assertEqual({'one.match': '1001'}, self.device.GetPids('one.match'))
 
   def testGetPids_mutlipleMatches(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 not\n'
-        'user  1001    100   1024 1024   ffffffff 00000000 one.match\n'
-        'user  1002    100   1024 1024   ffffffff 00000000 two.match\n'
-        'user  1003    100   1024 1024   ffffffff 00000000 three.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F match'),
+        ['user  1001    100   1024 1024   ffffffff 00000000 one.match',
+         'user  1002    100   1024 1024   ffffffff 00000000 two.match',
+         'user  1003    100   1024 1024   ffffffff 00000000 three.match']):
       self.assertEqual(
           {'one.match': '1001', 'two.match': '1002', 'three.match': '1003'},
           self.device.GetPids('match'))
 
   def testGetPids_exactMatch(self):
-    with self.assertCall(self.call.adb.Shell('ps'),
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\n'
-        'user  1000    100   1024 1024   ffffffff 00000000 not.exact.match\n'
-        'user  1234    100   1024 1024   ffffffff 00000000 exact.match\n'):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand('ps | grep -F exact.match'),
+        ['user  1000    100   1024 1024   ffffffff 00000000 not.exact.match',
+         'user  1234    100   1024 1024   ffffffff 00000000 exact.match']):
       self.assertEqual(
           {'not.exact.match': '1000', 'exact.match': '1234'},
           self.device.GetPids('exact.match'))
 
+  def testGetPids_quotable(self):
+    with self.assertCall(
+        self.call.device._RunPipedShellCommand("ps | grep -F 'my$process'"),
+        ['user  1234    100   1024 1024   ffffffff 00000000 my$process']):
+      self.assertEqual(
+          {'my$process': '1234'}, self.device.GetPids('my$process'))
+
 
 class DeviceUtilsTakeScreenshotTest(DeviceUtilsTest):
 
@@ -1404,8 +1492,8 @@
 
   def testGetMemoryUsageForPid_validPid(self):
     with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            ['showmap', '1234'], as_root=True, check_return=True),
+        (self.call.device._RunPipedShellCommand(
+            'showmap 1234 | grep TOTAL', as_root=True),
          ['100 101 102 103 104 105 106 107 TOTAL']),
         (self.call.device.ReadFile('/proc/1234/status', as_root=True),
          'VmHWM: 1024 kB\n')):
@@ -1424,8 +1512,8 @@
 
   def testGetMemoryUsageForPid_noSmaps(self):
     with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            ['showmap', '4321'], as_root=True, check_return=True),
+        (self.call.device._RunPipedShellCommand(
+            'showmap 4321 | grep TOTAL', as_root=True),
          ['cannot open /proc/4321/smaps: No such file or directory']),
         (self.call.device.ReadFile('/proc/4321/status', as_root=True),
          'VmHWM: 1024 kb\n')):
@@ -1433,8 +1521,8 @@
 
   def testGetMemoryUsageForPid_noStatus(self):
     with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            ['showmap', '4321'], as_root=True, check_return=True),
+        (self.call.device._RunPipedShellCommand(
+            'showmap 4321 | grep TOTAL', as_root=True),
          ['100 101 102 103 104 105 106 107 TOTAL']),
         (self.call.device.ReadFile('/proc/4321/status', as_root=True),
          self.CommandError())):
@@ -1451,116 +1539,6 @@
           self.device.GetMemoryUsageForPid(4321))
 
 
-class DeviceUtilsGetBatteryInfoTest(DeviceUtilsTest):
-  def testGetBatteryInfo_normal(self):
-    with self.assertCall(
-        self.call.device.RunShellCommand(
-            ['dumpsys', 'battery'], check_return=True),
-        [
-          'Current Battery Service state:',
-          '  AC powered: false',
-          '  USB powered: true',
-          '  level: 100',
-          '  temperature: 321',
-        ]):
-      self.assertEquals(
-          {
-            'AC powered': 'false',
-            'USB powered': 'true',
-            'level': '100',
-            'temperature': '321',
-          },
-          self.device.GetBatteryInfo())
-
-
-  def testGetBatteryInfo_nothing(self):
-    with self.assertCall(
-        self.call.device.RunShellCommand(
-            ['dumpsys', 'battery'], check_return=True), []):
-      self.assertEquals({}, self.device.GetBatteryInfo())
-
-
-class DeviceUtilsGetChargingTest(DeviceUtilsTest):
-  def testGetCharging_usb(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'USB powered': 'true'}):
-      self.assertTrue(self.device.GetCharging())
-
-  def testGetCharging_usbFalse(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'USB powered': 'false'}):
-      self.assertFalse(self.device.GetCharging())
-
-  def testGetCharging_ac(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'AC powered': 'true'}):
-      self.assertTrue(self.device.GetCharging())
-
-  def testGetCharging_wireless(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'Wireless powered': 'true'}):
-      self.assertTrue(self.device.GetCharging())
-
-  def testGetCharging_unknown(self):
-    with self.assertCall(
-        self.call.device.GetBatteryInfo(), {'level': '42'}):
-      self.assertFalse(self.device.GetCharging())
-
-
-class DeviceUtilsSetChargingTest(DeviceUtilsTest):
-
-  @mock.patch('time.sleep', mock.Mock())
-  def testSetCharging_enabled(self):
-    with self.assertCalls(
-        (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), False),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), True)):
-      self.device.SetCharging(True)
-
-  def testSetCharging_alreadyEnabled(self):
-    with self.assertCalls(
-        (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), True)):
-      self.device.SetCharging(True)
-
-  @mock.patch('time.sleep', mock.Mock())
-  def testSetCharging_disabled(self):
-    with self.assertCalls(
-        (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), True),
-        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
-        (self.call.device.GetCharging(), False)):
-      self.device.SetCharging(False)
-
-
-class DeviceUtilsSetBatteryMeasurementTest(DeviceUtilsTest):
-
-  def testBatteryMeasurement(self):
-    with self.assertCalls(
-        (self.call.device.RunShellCommand(
-            mock.ANY, retries=0, single_line=True,
-            timeout=10, check_return=True), '22'),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'batterystats', '--charged', '--checkin'],
-            check_return=True), []),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
-        (self.call.device.GetCharging(), False),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True), []),
-        (self.call.device.RunShellCommand(
-            ['dumpsys', 'battery', 'reset'], check_return=True), []),
-        (self.call.device.GetCharging(), True)):
-      with self.device.BatteryMeasurement():
-        pass
-
-
 class DeviceUtilsStrTest(DeviceUtilsTest):
 
   def testStr_returnsSerial(self):
@@ -1569,27 +1547,83 @@
       self.assertEqual('0123456789abcdef', str(self.device))
 
 
+class DeviceUtilsClientCache(DeviceUtilsTest):
+
+  def testClientCache_twoCaches(self):
+    self.device._cache['test'] = 0
+    client_cache_one = self.device.GetClientCache('ClientOne')
+    client_cache_one['test'] = 1
+    client_cache_two = self.device.GetClientCache('ClientTwo')
+    client_cache_two['test'] = 2
+    self.assertEqual(self.device._cache, {'test': 0})
+    self.assertEqual(client_cache_one, {'test': 1})
+    self.assertEqual(client_cache_two, {'test': 2})
+    self.device._ClearCache()
+    self.assertEqual(self.device._cache, {})
+    self.assertEqual(client_cache_one, {})
+    self.assertEqual(client_cache_two, {})
+
+  def testClientCache_multipleInstances(self):
+    client_cache_one = self.device.GetClientCache('ClientOne')
+    client_cache_one['test'] = 1
+    client_cache_two = self.device.GetClientCache('ClientOne')
+    self.assertEqual(client_cache_one, {'test': 1})
+    self.assertEqual(client_cache_two, {'test': 1})
+    self.device._ClearCache()
+    self.assertEqual(client_cache_one, {})
+    self.assertEqual(client_cache_two, {})
+
+
 class DeviceUtilsParallelTest(mock_calls.TestCase):
 
   def testParallel_default(self):
     test_serials = ['0123456789abcdef', 'fedcba9876543210']
     with self.assertCall(
-        mock.call.pylib.device.adb_wrapper.AdbWrapper.GetDevices(),
-        [_AdbWrapperMock(serial) for serial in test_serials]):
+        mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(),
+        [device_utils.DeviceUtils(s) for s in test_serials]):
       parallel_devices = device_utils.DeviceUtils.parallel()
     for serial, device in zip(test_serials, parallel_devices.pGet(None)):
-      self.assertTrue(
-          isinstance(device, device_utils.DeviceUtils)
-          and serial == str(device),
-          'Expected a DeviceUtils object with serial %s' % serial)
+      self.assertTrue(isinstance(device, device_utils.DeviceUtils))
+      self.assertEquals(serial, device.adb.GetDeviceSerial())
 
   def testParallel_noDevices(self):
     with self.assertCall(
-        mock.call.pylib.device.adb_wrapper.AdbWrapper.GetDevices(), []):
+        mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(), []):
       with self.assertRaises(device_errors.NoDevicesError):
         device_utils.DeviceUtils.parallel()
 
 
+class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
+
+  def _createAdbWrapperMock(self, serial, is_ready=True):
+    adb = _AdbWrapperMock(serial)
+    adb.is_ready = is_ready
+    return adb
+
+  def testHealthyDevices_default(self):
+    test_serials = ['0123456789abcdef', 'fedcba9876543210']
+    with self.assertCalls(
+        (mock.call.pylib.device.device_blacklist.ReadBlacklist(), []),
+        (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(),
+         [self._createAdbWrapperMock(s) for s in test_serials])):
+      devices = device_utils.DeviceUtils.HealthyDevices()
+    for serial, device in zip(test_serials, devices):
+      self.assertTrue(isinstance(device, device_utils.DeviceUtils))
+      self.assertEquals(serial, device.adb.GetDeviceSerial())
+
+  def testHealthyDevices_blacklisted(self):
+    test_serials = ['0123456789abcdef', 'fedcba9876543210']
+    with self.assertCalls(
+        (mock.call.pylib.device.device_blacklist.ReadBlacklist(),
+         ['fedcba9876543210']),
+        (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(),
+         [self._createAdbWrapperMock(s) for s in test_serials])):
+      devices = device_utils.DeviceUtils.HealthyDevices()
+    self.assertEquals(1, len(devices))
+    self.assertTrue(isinstance(devices[0], device_utils.DeviceUtils))
+    self.assertEquals('0123456789abcdef', devices[0].adb.GetDeviceSerial())
+
+
 if __name__ == '__main__':
   logging.getLogger().setLevel(logging.DEBUG)
   unittest.main(verbosity=2)
diff --git a/build/android/pylib/device_signal.py b/build/android/pylib/device_signal.py
new file mode 100644
index 0000000..6a5b709
--- /dev/null
+++ b/build/android/pylib/device_signal.py
@@ -0,0 +1,41 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Defines constants for signals that should be supported on devices.
+
+Note: Obtained by running `kill -l` on a user device.
+"""
+
+
+SIGHUP = 1 # Hangup
+SIGINT = 2 # Interrupt
+SIGQUIT = 3 # Quit
+SIGILL = 4 # Illegal instruction
+SIGTRAP = 5 # Trap
+SIGABRT = 6 # Aborted
+SIGBUS = 7 # Bus error
+SIGFPE = 8 # Floating point exception
+SIGKILL = 9 # Killed
+SIGUSR1 = 10 # User signal 1
+SIGSEGV = 11 # Segmentation fault
+SIGUSR2 = 12 # User signal 2
+SIGPIPE = 13 # Broken pipe
+SIGALRM = 14 # Alarm clock
+SIGTERM = 15 # Terminated
+SIGSTKFLT = 16 # Stack fault
+SIGCHLD = 17 # Child exited
+SIGCONT = 18 # Continue
+SIGSTOP = 19 # Stopped (signal)
+SIGTSTP = 20 # Stopped
+SIGTTIN = 21 # Stopped (tty input)
+SIGTTOU = 22 # Stopped (tty output)
+SIGURG = 23 # Urgent I/O condition
+SIGXCPU = 24 # CPU time limit exceeded
+SIGXFSZ = 25 # File size limit exceeded
+SIGVTALRM = 26 # Virtual timer expired
+SIGPROF = 27 # Profiling timer expired
+SIGWINCH = 28 # Window size changed
+SIGIO = 29 # I/O possible
+SIGPWR = 30 # Power failure
+SIGSYS = 31 # Bad system call
diff --git a/build/android/pylib/forwarder.py b/build/android/pylib/forwarder.py
index eb83d68..d16b9b1 100644
--- a/build/android/pylib/forwarder.py
+++ b/build/android/pylib/forwarder.py
@@ -288,11 +288,8 @@
         self._device_forwarder_path_on_host,
         Forwarder._DEVICE_FORWARDER_FOLDER)])
     cmd = '%s %s' % (tool.GetUtilWrapper(), Forwarder._DEVICE_FORWARDER_PATH)
-    (exit_code, output) = device.old_interface.GetAndroidToolStatusAndOutput(
-        cmd, lib_path=Forwarder._DEVICE_FORWARDER_FOLDER)
-    if exit_code != 0:
-      raise Exception(
-          'Failed to start device forwarder:\n%s' % '\n'.join(output))
+    device.RunShellCommand(
+        cmd, env={'LD_LIBRARY_PATH': Forwarder._DEVICE_FORWARDER_FOLDER})
     self._initialized_devices.add(device_serial)
 
   def _KillHostLocked(self):
@@ -328,5 +325,5 @@
 
     cmd = '%s %s --kill-server' % (tool.GetUtilWrapper(),
                                    Forwarder._DEVICE_FORWARDER_PATH)
-    device.old_interface.GetAndroidToolStatusAndOutput(
-        cmd, lib_path=Forwarder._DEVICE_FORWARDER_FOLDER)
+    device.RunShellCommand(
+        cmd, env={'LD_LIBRARY_PATH': Forwarder._DEVICE_FORWARDER_FOLDER})
diff --git a/build/android/pylib/gtest/filter/content_browsertests_disabled b/build/android/pylib/gtest/filter/content_browsertests_disabled
index 3c36264..39eff4d 100644
--- a/build/android/pylib/gtest/filter/content_browsertests_disabled
+++ b/build/android/pylib/gtest/filter/content_browsertests_disabled
@@ -2,13 +2,6 @@
 # Timeouts
 Http/MediaTest.*
 File/MediaTest.*
-WorkerTest.IncognitoSharedWorkers
-WorkerTest.MultipleSharedWorkers
-WorkerTest.PassMessagePortToSharedWorker
-WorkerTest.PassMessagePortToSharedWorkerDontWaitForConnect
-WorkerTest.SharedWorkerHttpAuth
-WorkerTest.SingleSharedWorker
-WorkerTest.WebSocketSharedWorker
 MediaTest.*
 DatabaseTest.*
 
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py
index 8608ed7..6ce0fb1 100644
--- a/build/android/pylib/gtest/gtest_config.py
+++ b/build/android/pylib/gtest/gtest_config.py
@@ -6,6 +6,7 @@
 
 # Add new suites here before upgrading them to the stable list below.
 EXPERIMENTAL_TEST_SUITES = [
+    'components_browsertests',
     'content_gl_tests',
     'heap_profiler_unittests',
     'devtools_bridge_tests',
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
index 186b8fc..b6f83b3 100644
--- a/build/android/pylib/gtest/gtest_test_instance.py
+++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -92,9 +92,10 @@
       raise ValueError('Platform mode currently supports only 1 gtest suite')
     self._suite = args.suite_name[0]
 
-    if self._suite == 'content_browsertests':
-      error_func('content_browsertests are not currently supported '
-                 'in platform mode.')
+    if (self._suite == 'content_browsertests' or
+        self._suite == 'components_browsertests'):
+      error_func('%s are not currently supported '
+                 'in platform mode.' % self._suite)
       self._apk_path = os.path.join(
           constants.GetOutDirectory(), 'apks', '%s.apk' % self._suite)
     else:
diff --git a/build/android/pylib/gtest/local_device_gtest_run.py b/build/android/pylib/gtest/local_device_gtest_run.py
index c48c865..fd143d6 100644
--- a/build/android/pylib/gtest/local_device_gtest_run.py
+++ b/build/android/pylib/gtest/local_device_gtest_run.py
@@ -30,7 +30,8 @@
 # TODO(jbudorick): Move this up to the test instance if the net test server is
 # handled outside of the APK for the remote_device environment.
 _SUITE_REQUIRES_TEST_SERVER_SPAWNER = [
-  'content_unittests', 'content_browsertests', 'net_unittests', 'unit_tests'
+  'components_browsertests', 'content_unittests', 'content_browsertests',
+  'net_unittests', 'unit_tests'
 ]
 
 class _ApkDelegate(object):
@@ -112,12 +113,7 @@
     return output
 
   def Clear(self, device):
-    try:
-      device.KillAll(self._exe_file_name, blocking=True, timeout=30, retries=0)
-    except device_errors.CommandFailedError:
-      # Raised if there is no process with the given name, which in this case
-      # is all we care about.
-      pass
+    device.KillAll(self._exe_file_name, blocking=True, timeout=30, quiet=True)
 
 
 class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun):
diff --git a/build/android/pylib/gtest/setup.py b/build/android/pylib/gtest/setup.py
index 1b882ca..44662d0 100644
--- a/build/android/pylib/gtest/setup.py
+++ b/build/android/pylib/gtest/setup.py
@@ -31,6 +31,7 @@
       'third_party/WebKit/Source/platform/heap/BlinkHeapUnitTests.isolate',
     'breakpad_unittests': 'breakpad/breakpad_unittests.isolate',
     'cc_perftests': 'cc/cc_perftests.isolate',
+    'components_browsertests': 'components/components_browsertests.isolate',
     'components_unittests': 'components/components_unittests.isolate',
     'content_browsertests': 'content/content_browsertests.isolate',
     'content_unittests': 'content/content_unittests.isolate',
@@ -236,7 +237,8 @@
     tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter)
 
   # Coalesce unit tests into a single test per device
-  if test_options.suite_name != 'content_browsertests':
+  if (test_options.suite_name != 'content_browsertests' and
+      test_options.suite_name != 'components_browsertests'):
     num_devices = len(devices)
     tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)]
     tests = [t for t in tests if t]
diff --git a/build/android/pylib/gtest/test_options.py b/build/android/pylib/gtest/test_options.py
index 5099ba6..58cd82b 100644
--- a/build/android/pylib/gtest/test_options.py
+++ b/build/android/pylib/gtest/test_options.py
@@ -8,7 +8,6 @@
 
 GTestOptions = collections.namedtuple('GTestOptions', [
     'tool',
-    'cleanup_test_files',
     'gtest_filter',
     'run_disabled',
     'test_arguments',
diff --git a/build/android/pylib/gtest/test_package_apk.py b/build/android/pylib/gtest/test_package_apk.py
index cdb6daf..8da3c74 100644
--- a/build/android/pylib/gtest/test_package_apk.py
+++ b/build/android/pylib/gtest/test_package_apk.py
@@ -34,6 +34,10 @@
       self.suite_path = os.path.join(
           constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name)
       self._package_info = constants.PACKAGE_INFO['content_browsertests']
+    elif suite_name == 'components_browsertests':
+      self.suite_path = os.path.join(
+          constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name)
+      self._package_info = constants.PACKAGE_INFO['components_browsertests']
     else:
       self.suite_path = os.path.join(
           constants.GetOutDirectory(), '%s_apk' % suite_name,
@@ -46,7 +50,7 @@
 
   def _GetFifo(self):
     # The test.fifo path is determined by:
-    # testing/android/java/src/org/chromium/native_test/
+    # testing/android/native_test/java/src/org/chromium/native_test/
     #     ChromeNativeTestActivity.java and
     # testing/android/native_test_launcher.cc
     return '/data/data/' + self._package_info.package + '/files/test.fifo'
@@ -90,6 +94,15 @@
         # TODO(jbudorick) Handle this exception appropriately once the
         #                 conversions are done.
         pass
+    elif self.suite_name == 'components_browsertests':
+      try:
+        device.RunShellCommand(
+            'rm -r %s/components_shell' % device.GetExternalStoragePath(),
+            timeout=60 * 2)
+      except device_errors.CommandFailedError:
+        # TODO(jbudorick) Handle this exception appropriately once the
+        #                 conversions are done.
+        pass
 
   #override
   def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
diff --git a/build/android/pylib/gtest/test_package_exe.py b/build/android/pylib/gtest/test_package_exe.py
index e607cad..aa3374e 100644
--- a/build/android/pylib/gtest/test_package_exe.py
+++ b/build/android/pylib/gtest/test_package_exe.py
@@ -6,6 +6,7 @@
 
 import logging
 import os
+import posixpath
 import sys
 import tempfile
 
@@ -78,15 +79,7 @@
 
   #override
   def ClearApplicationState(self, device):
-    try:
-      # We don't expect the executable to be running, so we don't attempt
-      # to retry on failure.
-      device.KillAll(self.suite_name, blocking=True, timeout=30, retries=0)
-    except device_errors.CommandFailedError:
-      # KillAll raises an exception if it can't find a process with the given
-      # name. We only care that there is no process with the given name, so
-      # we can safely eat the exception.
-      pass
+    device.KillAll(self.suite_name, blocking=True, timeout=30, quiet=True)
 
   #override
   def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
@@ -119,14 +112,19 @@
 
   #override
   def GetAllTests(self, device):
-    cmd = '%s %s/%s --gtest_list_tests' % (self.tool.GetTestWrapper(),
-        constants.TEST_EXECUTABLE_DIR, self.suite_name)
-    lib_path = '%s/%s_deps' % (constants.TEST_EXECUTABLE_DIR, self.suite_name)
-    (exit_code, output) = device.old_interface.GetAndroidToolStatusAndOutput(
-        cmd, lib_path=lib_path)
-    if exit_code != 0:
-      raise Exception(
-          'Failed to start binary:\n%s' % '\n'.join(output))
+    lib_path = posixpath.join(
+        constants.TEST_EXECUTABLE_DIR, '%s_deps' % self.suite_name)
+
+    cmd = []
+    for wrapper in (device.GetDevicePieWrapper(), self.tool.GetTestWrapper()):
+      if wrapper:
+        cmd.append(wrapper)
+    cmd.extend([
+        posixpath.join(constants.TEST_EXECUTABLE_DIR, self.suite_name),
+        '--gtest_list_tests'])
+
+    output = device.RunShellCommand(
+        cmd, check_return=True, env={'LD_LIBRARY_PATH': lib_path})
     return gtest_test_instance.ParseGTestListTests(output)
 
   #override
diff --git a/build/android/pylib/gtest/test_runner.py b/build/android/pylib/gtest/test_runner.py
index 4bb9737..4926388 100644
--- a/build/android/pylib/gtest/test_runner.py
+++ b/build/android/pylib/gtest/test_runner.py
@@ -26,10 +26,15 @@
 # to output the CRASHED marker when a crash happens.
 RE_CRASH = re.compile('\\[ CRASHED      \\](.*)\r\n')
 
+# Bots that don't output anything for 20 minutes get timed out, so that's our
+# hard cap.
+_INFRA_STDOUT_TIMEOUT = 20 * 60
+
 
 def _TestSuiteRequiresMockTestServer(suite_name):
   """Returns True if the test suite requires mock test server."""
   tests_require_net_test_server = ['unit_tests', 'net_unittests',
+                                   'components_browsertests',
                                    'content_unittests',
                                    'content_browsertests']
   return (suite_name in
@@ -49,8 +54,7 @@
       test_package: An instance of TestPackage class.
     """
 
-    super(TestRunner, self).__init__(device, test_options.tool,
-                                     test_options.cleanup_test_files)
+    super(TestRunner, self).__init__(device, test_options.tool)
 
     self.test_package = test_package
     self.test_package.tool = self.tool
@@ -63,7 +67,8 @@
     if os.environ.get('BUILDBOT_SLAVENAME'):
       timeout = timeout * 2
 
-    self._timeout = timeout * self.tool.GetTimeoutScale()
+    self._timeout = min(timeout * self.tool.GetTimeoutScale(),
+                        _INFRA_STDOUT_TIMEOUT)
     if _TestSuiteRequiresHighPerfMode(self.test_package.suite_name):
       self._perf_controller = perf_control.PerfControl(self.device)
 
diff --git a/build/android/pylib/host_driven/setup.py b/build/android/pylib/host_driven/setup.py
index 285bcd4..b2ed348 100644
--- a/build/android/pylib/host_driven/setup.py
+++ b/build/android/pylib/host_driven/setup.py
@@ -195,7 +195,6 @@
   def TestRunnerFactory(device, shard_index):
     return test_runner.HostDrivenTestRunner(
         device, shard_index,
-        instrumentation_options.tool,
-        instrumentation_options.cleanup_test_files)
+        instrumentation_options.tool)
 
   return (TestRunnerFactory, available_tests)
diff --git a/build/android/pylib/host_driven/test_case.py b/build/android/pylib/host_driven/test_case.py
index 8c372cd..a7c6a18 100644
--- a/build/android/pylib/host_driven/test_case.py
+++ b/build/android/pylib/host_driven/test_case.py
@@ -50,8 +50,6 @@
       instrumentation_options: An InstrumentationOptions object.
     """
     class_name = self.__class__.__name__
-    self.adb = None
-    self.cleanup_test_files = False
     self.device = None
     self.device_id = ''
     self.has_forwarded_ports = False
@@ -67,15 +65,12 @@
 
   # TODO(bulach): make ports_to_forward not optional and move the Forwarder
   # mapping here.
-  def SetUp(self, device, shard_index,
-            cleanup_test_files, ports_to_forward=None):
+  def SetUp(self, device, shard_index, ports_to_forward=None):
     if not ports_to_forward:
       ports_to_forward = []
     self.device_id = device
     self.shard_index = shard_index
     self.device = device_utils.DeviceUtils(self.device_id)
-    self.adb = self.device.old_interface
-    self.cleanup_test_files = cleanup_test_files
     if ports_to_forward:
       self.ports_to_forward = ports_to_forward
 
diff --git a/build/android/pylib/host_driven/test_runner.py b/build/android/pylib/host_driven/test_runner.py
index 865be20..5e175bc 100644
--- a/build/android/pylib/host_driven/test_runner.py
+++ b/build/android/pylib/host_driven/test_runner.py
@@ -47,23 +47,27 @@
   result, rather than being re-raised on the main thread.
   """
 
+  # TODO(jbudorick): Remove cleanup_test_files once it's no longer used.
+  # pylint: disable=unused-argument
   #override
-  def __init__(self, device, shard_index, tool, cleanup_test_files):
+  def __init__(self, device, shard_index, tool, cleanup_test_files=None):
     """Creates a new HostDrivenTestRunner.
 
     Args:
       device: Attached android device.
       shard_index: Shard index.
       tool: Name of the Valgrind tool.
-      cleanup_test_files: Whether or not to cleanup test files on device.
+      cleanup_test_files: Deprecated.
     """
 
-    super(HostDrivenTestRunner, self).__init__(device, tool, cleanup_test_files)
+    super(HostDrivenTestRunner, self).__init__(device, tool)
 
     # The shard index affords the ability to create unique port numbers (e.g.
     # DEFAULT_PORT + shard_index) if the test so wishes.
     self.shard_index = shard_index
 
+  # pylint: enable=unused-argument
+
   #override
   def RunTest(self, test):
     """Sets up and runs a test case.
@@ -82,7 +86,7 @@
     exception_raised = False
 
     try:
-      test.SetUp(str(self.device), self.shard_index, self._cleanup_test_files)
+      test.SetUp(str(self.device), self.shard_index)
     except Exception:
       logging.exception(
           'Caught exception while trying to run SetUp() for test: ' +
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 3f56e6d..ccc0e72 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -335,7 +335,7 @@
 
     with open(pickle_path, 'r') as pickle_file:
       pickle_data = pickle.loads(pickle_file.read())
-    jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0]
+    jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path]
 
     try:
       if pickle_data['VERSION'] != _PICKLE_FORMAT_VERSION:
@@ -377,7 +377,7 @@
             if is_test_class(c)]
 
   def _SaveTestsToPickle(self, pickle_path, jar_path, tests):
-    jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0]
+    jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path]
     pickle_data = {
       'VERSION': _PICKLE_FORMAT_VERSION,
       'JAR_MD5SUM': jar_md5,
diff --git a/build/android/pylib/instrumentation/test_jar.py b/build/android/pylib/instrumentation/test_jar.py
index c3faef3..9c38510 100644
--- a/build/android/pylib/instrumentation/test_jar.py
+++ b/build/android/pylib/instrumentation/test_jar.py
@@ -65,7 +65,7 @@
       try:
         with open(self._pickled_proguard_name, 'r') as r:
           d = pickle.loads(r.read())
-        jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash
+        jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path]
         if (d['JAR_MD5SUM'] == jar_md5 and
             d['VERSION'] == PICKLE_FORMAT_VERSION):
           self._test_methods = d['TEST_METHODS']
@@ -105,7 +105,8 @@
     logging.info('Storing proguard output to %s', self._pickled_proguard_name)
     d = {'VERSION': PICKLE_FORMAT_VERSION,
          'TEST_METHODS': self._test_methods,
-         'JAR_MD5SUM': md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash}
+         'JAR_MD5SUM':
+              md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path]}
     with open(self._pickled_proguard_name, 'w') as f:
       f.write(pickle.dumps(d))
 
diff --git a/build/android/pylib/instrumentation/test_options.py b/build/android/pylib/instrumentation/test_options.py
index 4a16b11..792010b 100644
--- a/build/android/pylib/instrumentation/test_options.py
+++ b/build/android/pylib/instrumentation/test_options.py
@@ -8,7 +8,6 @@
 
 InstrumentationOptions = collections.namedtuple('InstrumentationOptions', [
     'tool',
-    'cleanup_test_files',
     'annotations',
     'exclude_annotations',
     'test_filter',
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index f3983fd..6e8be34 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -48,8 +48,7 @@
       test_pkg: A TestPackage object.
       additional_flags: A list of additional flags to add to the command line.
     """
-    super(TestRunner, self).__init__(device, test_options.tool,
-                                     test_options.cleanup_test_files)
+    super(TestRunner, self).__init__(device, test_options.tool)
     self._lighttp_port = constants.LIGHTTPD_RANDOM_PORT_FIRST + shard_index
     self._logcat_monitor = None
 
@@ -229,7 +228,7 @@
     # just quits and does not do anything.  The java test harness will still
     # print the appropriate annotation for us, but will add --NORUN-- for
     # us so we know to ignore the results.
-    # The --NORUN-- tag is managed by MainActivityTestBase.java
+    # The --NORUN-- tag is managed by ChromeTabbedActivityTestBase.java
     if regex.group(1) != '--NORUN--':
 
       # Obtain the relevant perf data.  The data is dumped to a
diff --git a/build/android/pylib/junit/test_dispatcher.py b/build/android/pylib/junit/test_dispatcher.py
index b821b75..6e0d865 100644
--- a/build/android/pylib/junit/test_dispatcher.py
+++ b/build/android/pylib/junit/test_dispatcher.py
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from pylib import constants
+from pylib.base import base_test_result
+
 def RunTests(tests, runner_factory):
   """Runs a set of java tests on the host.
 
@@ -11,9 +14,15 @@
   def run(t):
     runner = runner_factory(None, None)
     runner.SetUp()
-    result = runner.RunTest(t)
+    results_list, return_code = runner.RunTest(t)
     runner.TearDown()
-    return result == 0
+    return (results_list, return_code == 0)
 
-  return (None, 0 if all(run(t) for t in tests) else 1)
-
+  test_run_results = base_test_result.TestRunResults()
+  exit_code = 0
+  for t in tests:
+    results_list, passed = run(t)
+    test_run_results.AddResults(results_list)
+    if not passed:
+      exit_code = constants.ERROR_EXIT_CODE
+  return (test_run_results, exit_code)
\ No newline at end of file
diff --git a/build/android/pylib/junit/test_runner.py b/build/android/pylib/junit/test_runner.py
index b85967b..a6d3bf9 100644
--- a/build/android/pylib/junit/test_runner.py
+++ b/build/android/pylib/junit/test_runner.py
@@ -2,10 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import json
 import os
+import tempfile
 
 from pylib import cmd_helper
 from pylib import constants
+from pylib.base import base_test_result
+from pylib.results import json_results
 
 class JavaTestRunner(object):
   """Runs java tests on the host."""
@@ -22,22 +26,24 @@
 
   def RunTest(self, _test):
     """Runs junit tests from |self._test_suite|."""
-
-    command = ['java',
-               '-Drobolectric.dependency.dir=%s' %
-                    os.path.join(constants.GetOutDirectory(), 'lib.java'),
-               '-jar', os.path.join(constants.GetOutDirectory(), 'lib.java',
-                                    '%s.jar' % self._test_suite)]
-
-    if self._test_filter:
-      command.extend(['-gtest-filter', self._test_filter])
-    if self._package_filter:
-      command.extend(['-package-filter', self._package_filter])
-    if self._runner_filter:
-      command.extend(['-runner-filter', self._runner_filter])
-    if self._sdk_version:
-      command.extend(['-sdk-version', self._sdk_version])
-    return cmd_helper.RunCmd(command)
+    with tempfile.NamedTemporaryFile() as json_file:
+      java_script = os.path.join(
+          constants.GetOutDirectory(), 'bin', self._test_suite)
+      command = [java_script,
+                 '-test-jars', self._test_suite + '.jar',
+                 '-json-results-file', json_file.name]
+      if self._test_filter:
+        command.extend(['-gtest-filter', self._test_filter])
+      if self._package_filter:
+        command.extend(['-package-filter', self._package_filter])
+      if self._runner_filter:
+        command.extend(['-runner-filter', self._runner_filter])
+      if self._sdk_version:
+        command.extend(['-sdk-version', self._sdk_version])
+      return_code = cmd_helper.RunCmd(command)
+      results_list = json_results.ParseResultsFromJson(
+          json.loads(json_file.read()))
+      return (results_list, return_code)
 
   def TearDown(self):
     pass
diff --git a/build/android/pylib/linker/setup.py b/build/android/pylib/linker/setup.py
index ff21f10..5776f5a 100644
--- a/build/android/pylib/linker/setup.py
+++ b/build/android/pylib/linker/setup.py
@@ -40,7 +40,6 @@
                  if t.qualified_name in filtered_test_names]
 
   def TestRunnerFactory(device, _shard_index):
-    return test_runner.LinkerTestRunner(
-        device, args.tool, args.cleanup_test_files)
+    return test_runner.LinkerTestRunner(device, args.tool)
 
   return (TestRunnerFactory, all_tests)
diff --git a/build/android/pylib/linker/test_runner.py b/build/android/pylib/linker/test_runner.py
index 3680f83..b6803e4 100644
--- a/build/android/pylib/linker/test_runner.py
+++ b/build/android/pylib/linker/test_runner.py
@@ -49,16 +49,14 @@
   """
 
   #override
-  def __init__(self, device, tool, cleanup_test_files):
+  def __init__(self, device, tool):
     """Creates a new LinkerTestRunner.
 
     Args:
       device: Attached android device.
       tool: Name of the Valgrind tool.
-      cleanup_test_files: Whether or not to cleanup test files on device.
     """
-
-    super(LinkerTestRunner, self).__init__(device, tool, cleanup_test_files)
+    super(LinkerTestRunner, self).__init__(device, tool)
 
   #override
   def InstallTestPackage(self):
@@ -68,8 +66,7 @@
     if not os.path.exists(apk_path):
       raise Exception('%s not found, please build it' % apk_path)
 
-    package_name = apk_helper.GetPackageName(apk_path)
-    self.device.old_interface.ManagedInstall(apk_path, package_name)
+    self.device.Install(apk_path)
 
   #override
   def RunTest(self, test):
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py
index 72acb6e..0d02ca3 100644
--- a/build/android/pylib/local/device/local_device_environment.py
+++ b/build/android/pylib/local/device/local_device_environment.py
@@ -13,26 +13,24 @@
 
   def __init__(self, args, _error_func):
     super(LocalDeviceEnvironment, self).__init__()
-    self._device = args.test_device
+    self._device_serial = args.test_device
     self._devices = []
     self._max_tries = 1 + args.num_retries
     self._tool_name = args.tool
 
   #override
   def SetUp(self):
-    # TODO(jbudorick): This can be refined to support filters etc.
-    available_devices = adb_wrapper.AdbWrapper.GetDevices()
+    available_devices = device_utils.DeviceUtils.HealthyDevices()
     if not available_devices:
       raise device_errors.NoDevicesError
-    if self._device:
-      if self._device not in available_devices:
+    if self._device_serial:
+      self._devices = [d for d in available_devices
+                       if d.adb.GetDeviceSerial == self._device_serial]
+      if not self._devices:
         raise device_errors.DeviceUnreachableError(
-            'Could not find device %r' % self._device)
-      self._devices = [device_utils.DeviceUtils(self._device)]
+            'Could not find device %r' % self._device_serial)
     else:
-      self._devices = [
-          device_utils.DeviceUtils(s)
-          for s in available_devices]
+      self._devices = available_devices
 
   @property
   def devices(self):
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index ac3f5b1..adc1037 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -3,11 +3,14 @@
 # found in the LICENSE file.
 
 import logging
+import re
 import time
 
 from pylib import flag_changer
 from pylib.base import base_test_result
 from pylib.base import test_run
+from pylib.constants import keyevent
+from pylib.device import device_errors
 from pylib.local.device import local_device_test_run
 
 
@@ -27,16 +30,39 @@
 def DidPackageCrashOnDevice(package_name, device):
   # Dismiss any error dialogs. Limit the number in case we have an error
   # loop or we are failing to dismiss.
-  for _ in xrange(10):
-    package = device.old_interface.DismissCrashDialogIfNeeded()
-    if not package:
-      return False
-    # Assume test package convention of ".test" suffix
-    if package in package_name:
-      return True
+  try:
+    for _ in xrange(10):
+      package = _DismissCrashDialog(device)
+      if not package:
+        return False
+      # Assume test package convention of ".test" suffix
+      if package in package_name:
+        return True
+  except device_errors.CommandFailedError:
+    logging.exception('Error while attempting to dismiss crash dialog.')
   return False
 
 
+_CURRENT_FOCUS_CRASH_RE = re.compile(
+    r'\s*mCurrentFocus.*Application (Error|Not Responding): (\S+)}')
+
+
+def _DismissCrashDialog(device):
+  # TODO(jbudorick): Try to grep the output on the device instead of using
+  # large_output if/when DeviceUtils exposes a public interface for piped
+  # shell command handling.
+  for l in device.RunShellCommand(
+      ['dumpsys', 'window', 'windows'], check_return=True, large_output=True):
+    m = re.match(_CURRENT_FOCUS_CRASH_RE, l)
+    if m:
+      device.SendKeyEvent(keyevent.KEYCODE_DPAD_RIGHT)
+      device.SendKeyEvent(keyevent.KEYCODE_DPAD_RIGHT)
+      device.SendKeyEvent(keyevent.KEYCODE_ENTER)
+      return m.group(2)
+
+  return None
+
+
 class LocalDeviceInstrumentationTestRun(
     local_device_test_run.LocalDeviceTestRun):
   def __init__(self, env, test_instance):
diff --git a/build/android/pylib/monkey/test_runner.py b/build/android/pylib/monkey/test_runner.py
index 19dd339..3fd1797 100644
--- a/build/android/pylib/monkey/test_runner.py
+++ b/build/android/pylib/monkey/test_runner.py
@@ -10,8 +10,11 @@
 from pylib import constants
 from pylib.base import base_test_result
 from pylib.base import base_test_runner
+from pylib.device import device_errors
 from pylib.device import intent
 
+_CHROME_PACKAGE = constants.PACKAGE_INFO['chrome'].package
+
 class TestRunner(base_test_runner.BaseTestRunner):
   """A TestRunner instance runs a monkey test on a single device."""
 
@@ -87,9 +90,17 @@
           test_name, base_test_result.ResultType.FAIL, log=output)
       if 'chrome' in self._options.package:
         logging.warning('Starting MinidumpUploadService...')
+        # TODO(jbudorick): Update this after upstreaming.
+        minidump_intent = intent.Intent(
+            action='%s.crash.ACTION_FIND_ALL' % _CHROME_PACKAGE,
+            package=self._package,
+            activity='%s.crash.MinidumpUploadService' % _CHROME_PACKAGE)
         try:
-          self.device.old_interface.StartCrashUploadService(self._package)
-        except AssertionError as e:
-          logging.error('Failed to start MinidumpUploadService: %s', e)
+          self.device.RunShellCommand(
+              ['am', 'startservice'] + minidump_intent.am_args,
+              as_root=True, check_return=True)
+        except device_errors.CommandFailedError:
+          logging.exception('Failed to start MinidumpUploadService')
+
     results.AddResult(result)
     return results, False
diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py
index 97fa4a7..b6a0989 100644
--- a/build/android/pylib/perf/perf_control.py
+++ b/build/android/pylib/perf/perf_control.py
@@ -28,7 +28,7 @@
 
   def SetHighPerfMode(self):
     """Sets the highest stable performance mode for the device."""
-    if not self._device.old_interface.IsRootEnabled():
+    if not self._device.HasRoot():
       message = 'Need root for performance mode. Results may be NOISY!!'
       logging.warning(message)
       # Add an additional warning at exit, such that it's clear that any results
@@ -58,13 +58,13 @@
     self._ForceAllCpusOnline(True)
     self._SetScalingGovernorInternal('performance')
     if not self._AllCpusAreOnline():
-      if not self._device.old_interface.IsRootEnabled():
+      if not self._device.HasRoot():
         raise RuntimeError('Need root to force CPUs online.')
       raise RuntimeError('Failed to force CPUs online.')
 
   def SetDefaultPerfMode(self):
     """Sets the performance mode for the device to its default mode."""
-    if not self._device.old_interface.IsRootEnabled():
+    if not self._device.HasRoot():
       return
     product_model = self._device.product_model
     if 'Nexus 5' == product_model:
diff --git a/build/android/pylib/perf/test_runner.py b/build/android/pylib/perf/test_runner.py
index da66d07..9d1f437 100644
--- a/build/android/pylib/perf/test_runner.py
+++ b/build/android/pylib/perf/test_runner.py
@@ -170,7 +170,7 @@
       tests: a dict mapping test_name to command.
       flaky_tests: a list of flaky test_name.
     """
-    super(TestRunner, self).__init__(device, None, 'Release')
+    super(TestRunner, self).__init__(device, None)
     self._options = test_options
     self._shard_index = shard_index
     self._max_shard = max_shard
diff --git a/build/android/pylib/remote/device/appurify_constants.py b/build/android/pylib/remote/device/appurify_constants.py
new file mode 100644
index 0000000..9343178
--- /dev/null
+++ b/build/android/pylib/remote/device/appurify_constants.py
@@ -0,0 +1,57 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Defines a set of constants specific to appurify."""
+
+# Appurify network config constants.
+class NETWORK(object):
+  WIFI_1_BAR = 1
+  SPRINT_4G_LTE_4_BARS = 2
+  SPRINT_3G_5_BARS = 3
+  SPRINT_3G_4_BARS = 4
+  SPRINT_3G_3_BARS = 5
+  SPRINT_3G_2_BARS = 6
+  SPRINT_3G_1_BAR = 7
+  SPRING_4G_1_BAR = 8
+  VERIZON_3G_5_BARS = 9
+  VERIZON_3G_4_BARS = 10
+  VERIZON_3G_3_BARS = 11
+  VERIZON_3G_2_BARS = 12
+  VERIZON_3G_1_BAR = 13
+  VERIZON_4G_1_BAR = 14
+  ATANDT_3G_5_BARS = 15
+  ATANDT_3G_4_BARS = 16
+  ATANDT_3G_3_BARS = 17
+  ATANDT_3G_2_BARS = 18
+  ATANDT_3G_1_BAR = 19
+  GENERIC_2G_4_BARS = 20
+  GENERIC_2G_3_BARS = 21
+  GENERIC_EVOLVED_EDGE = 22
+  GENERIC_GPRS = 23
+  GENERIC_ENHANCED_GPRS = 24
+  GENERIC_LTE = 25
+  GENERIC_HIGH_LATENCY_DNS = 26
+  GENERIC_100_PERCENT_PACKET_LOSS = 27
+  ATANDT_HSPA_PLUS = 28
+  ATANDT_4G_LTE_4_BARS = 29
+  VERIZON_4G_LTE_4_BARS = 30
+  GENERIC_DIGITAL_SUBSCRIBE_LINE = 31
+  WIFI_STARBUCKS_3_BARS = 32
+  WIFI_STARBUCKS_4_BARS = 33
+  WIFI_STARBUCKS_HIGH_TRAFFIC = 34
+  WIFI_TARGET_1_BAR = 35
+  WIFI_TARGET_3_BARS = 36
+  WIFI_TARGET_4_BARS = 37
+  PUBLIC_WIFI_MCDONALDS_5_BARS = 38
+  PUBLIC_WIFI_MCDONALDS_4_BARS = 39
+  PUBLIC_WIFI_MCDONALDS_2_BARS = 40
+  PUBLIC_WIFI_MCDONALDS_1_BAR = 41
+  PUBLIC_WIFI_KOHLS_5_BARS = 42
+  PUBLIC_WIFI_KOHLS_4_BARS = 43
+  PUBLIC_WIFI_KOHLS_2_BARS = 44
+  PUBLIC_WIFI_ATANDT_5_BARS = 45
+  PUBLIC_WIFI_ATANDT_4_BARS = 46
+  PUBLIC_WIFI_ATANDT_2_BARS = 47
+  PUBLIC_WIFI_ATANDT_1_BAR = 48
+  BOINGO = 49
\ No newline at end of file
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index 8875096..b69c7b2 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -73,6 +73,7 @@
     self._api_secret = device_json.get('api_secret', None)
     self._device_oem = device_json.get('device_oem', None)
     self._device_type = device_json.get('device_type', 'Android')
+    self._network_config = device_json.get('network_config', None)
     self._remote_device = device_json.get('remote_device', None)
     self._remote_device_minimum_os = device_json.get(
         'remote_device_minimum_os', None)
@@ -81,9 +82,7 @@
     self._results_path = device_json.get('results_path', None)
     self._runner_package = device_json.get('runner_package', None)
     self._runner_type = device_json.get('runner_type', None)
-    if 'timeouts' in device_json:
-      for key in device_json['timeouts']:
-        self._timeouts[key] = device_json['timeouts'][key]
+    self._timeouts.update(device_json.get('timeouts', {}))
 
     def command_line_override(
         file_value, cmd_line_value, desc, print_value=True):
@@ -107,6 +106,8 @@
         self._device_oem, args.device_oem, 'device_oem')
     self._device_type = command_line_override(
         self._device_type, args.device_type, 'device_type')
+    self._network_config = command_line_override(
+        self._network_config, args.network_config, 'network_config')
     self._remote_device = command_line_override(
         self._remote_device, args.remote_device, 'remote_device')
     self._remote_device_minimum_os = command_line_override(
@@ -325,6 +326,10 @@
     return self._device['device_type_id']
 
   @property
+  def network_config(self):
+    return self._network_config
+
+  @property
   def only_output_failures(self):
     # TODO(jbudorick): Remove this once b/18981674 is fixed.
     return True
diff --git a/build/android/pylib/remote/device/remote_device_test_run.py b/build/android/pylib/remote/device/remote_device_test_run.py
index 4a155ac..7aa91ae 100644
--- a/build/android/pylib/remote/device/remote_device_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -14,6 +14,7 @@
 
 from pylib import constants
 from pylib.base import test_run
+from pylib.remote.device import appurify_constants
 from pylib.remote.device import appurify_sanitized
 from pylib.remote.device import remote_device_helper
 from pylib.utils import zip_utils
@@ -230,7 +231,10 @@
       self._test_id = self._UploadTestToDevice('robotium', test_path)
 
     logging.info('Setting config: %s' % config)
-    self._SetTestConfig('robotium', config)
+    appurify_configs = {}
+    if self._env.network_config:
+      appurify_configs['network'] = self._env.network_config
+    self._SetTestConfig('robotium', config, **appurify_configs)
 
   def _UploadAppToDevice(self, app_path):
     """Upload app to device."""
@@ -259,21 +263,32 @@
           'Unable to upload %s.' % test_path)
       return upload_results.json()['response']['test_id']
 
-  def _SetTestConfig(self, runner_type, body):
+  def _SetTestConfig(self, runner_type, runner_configs,
+                     network=appurify_constants.NETWORK.WIFI_1_BAR,
+                     pcap=0, profiler=0, videocapture=0):
     """Generates and uploads config file for test.
     Args:
-      extras: Extra arguments to set in the config file.
+      runner_configs: Configs specific to the runner you are using.
+      network: Config to specify the network environment the devices running
+          the tests will be in.
+      pcap: Option to set the recording the of network traffic from the device.
+      profiler: Option to set the recording of CPU, memory, and network
+          transfer usage in the tests.
+      videocapture: Option to set video capture during the tests.
+
     """
     logging.info('Generating config file for test.')
     with tempfile.TemporaryFile() as config:
       config_data = [
-        '[appurify]',
-        'pcap=0',
-        'profiler=0',
-        'videocapture=0',
-        '[%s]' % runner_type
+          '[appurify]',
+          'network=%s' % network,
+          'pcap=%s' % pcap,
+          'profiler=%s' % profiler,
+          'videocapture=%s' % videocapture,
+          '[%s]' % runner_type
       ]
-      config_data.extend('%s=%s' % (k, v) for k, v in body.iteritems())
+      config_data.extend(
+          '%s=%s' % (k, v) for k, v in runner_configs.iteritems())
       config.write(''.join('%s\n' % l for l in config_data))
       config.flush()
       config.seek(0)
@@ -282,4 +297,4 @@
         config_response = appurify_sanitized.api.config_upload(
             self._env.token, config, self._test_id)
       remote_device_helper.TestHttpResponse(
-          config_response, 'Unable to upload test config.')
+          config_response, 'Unable to upload test config.')
\ No newline at end of file
diff --git a/build/android/pylib/results/json_results.py b/build/android/pylib/results/json_results.py
index c34244e..65664e3 100644
--- a/build/android/pylib/results/json_results.py
+++ b/build/android/pylib/results/json_results.py
@@ -16,6 +16,38 @@
     A results dict that mirrors the one generated by
       base/test/launcher/test_results_tracker.cc:SaveSummaryAsJSON.
   """
+  # Example json output.
+  # {
+  #   "global_tags": [],
+  #   "all_tests": [
+  #     "test1",
+  #     "test2",
+  #    ],
+  #   "disabled_tests": [],
+  #   "per_iteration_data": [
+  #     {
+  #       "test1": [
+  #         {
+  #           "status": "SUCCESS",
+  #           "elapsed_time_ms": 1,
+  #           "output_snippet": "",
+  #           "output_snippet_base64": "",
+  #           "losless_snippet": "",
+  #         },
+  #       ],
+  #       "test2": [
+  #         {
+  #           "status": "FAILURE",
+  #           "elapsed_time_ms": 12,
+  #           "output_snippet": "",
+  #           "output_snippet_base64": "",
+  #           "losless_snippet": "",
+  #         },
+  #       ],
+  #     },
+  #   ],
+  # }
+
   assert isinstance(test_run_result, base_test_result.TestRunResults)
 
   def status_as_string(s):
@@ -71,3 +103,37 @@
   with open(file_path, 'w') as json_result_file:
     json_result_file.write(json.dumps(GenerateResultsDict(test_run_result)))
 
+
+def ParseResultsFromJson(json_results):
+  """Creates a list of BaseTestResult objects from JSON.
+
+  Args:
+    json_results: A JSON dict in the format created by
+                  GenerateJsonResultsFile.
+  """
+
+  def string_as_status(s):
+    if s == 'SUCCESS':
+      return base_test_result.ResultType.PASS
+    elif s == 'SKIPPED':
+      return base_test_result.ResultType.SKIP
+    elif s == 'FAILURE':
+      return base_test_result.ResultType.FAIL
+    elif s == 'CRASH':
+      return base_test_result.ResultType.CRASH
+    elif s == 'TIMEOUT':
+      return base_test_result.ResultType.TIMEOUT
+    else:
+      return base_test_result.ResultType.UNKNOWN
+
+  results_list = []
+  testsuite_runs = json_results['per_iteration_data']
+  for testsuite_run in testsuite_runs:
+    for test, test_runs in testsuite_run.iteritems():
+      results_list.extend(
+          [base_test_result.BaseTestResult(test,
+                                           string_as_status(tr['status']),
+                                           duration=tr['elapsed_time_ms'])
+          for tr in test_runs])
+  return results_list
+
diff --git a/build/android/pylib/screenshot.py b/build/android/pylib/screenshot.py
index e21d756..0fcc590 100644
--- a/build/android/pylib/screenshot.py
+++ b/build/android/pylib/screenshot.py
@@ -2,11 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import logging
 import os
-import signal
 import tempfile
+import time
 
 from pylib import cmd_helper
+from pylib import device_signal
+from pylib.device import device_errors
 
 # TODO(jbudorick) Remove once telemetry gets switched over.
 import pylib.android_commands
@@ -71,7 +74,9 @@
     self._is_started = False
     if not self._recorder:
       return
-    self._device.KillAll('screenrecord', signum=signal.SIGINT)
+    if not self._device.KillAll('screenrecord', signum=device_signal.SIGINT,
+                                quiet=True):
+      logging.warning('Nothing to kill: screenrecord was not running')
     self._recorder.wait()
 
   def Pull(self, host_file=None):
@@ -82,10 +87,13 @@
     Returns:
       Output video file name on the host.
     """
-    host_file_name = host_file or ('screen-recording-%s.mp4' %
-                                   self._device.old_interface.GetTimestamp())
+    # TODO(jbudorick): Merge filename generation with the logic for doing so in
+    # DeviceUtils.
+    host_file_name = (
+        host_file
+        or 'screen-recording-%s.mp4' % time.strftime('%Y%m%dT%H%M%S',
+                                                     time.localtime()))
     host_file_name = os.path.abspath(host_file_name)
-    self._device.old_interface.EnsureHostDirectory(host_file_name)
     self._device.PullFile(self._device_file, host_file_name)
     self._device.RunShellCommand('rm -f "%s"' % self._device_file)
     return host_file_name
diff --git a/build/android/pylib/uiautomator/test_options.py b/build/android/pylib/uiautomator/test_options.py
index b383b20..3f5f950 100644
--- a/build/android/pylib/uiautomator/test_options.py
+++ b/build/android/pylib/uiautomator/test_options.py
@@ -8,7 +8,6 @@
 
 UIAutomatorOptions = collections.namedtuple('UIAutomatorOptions', [
     'tool',
-    'cleanup_test_files',
     'annotations',
     'exclude_annotations',
     'test_filter',
diff --git a/build/android/pylib/uiautomator/test_runner.py b/build/android/pylib/uiautomator/test_runner.py
index d7a4bdf..296bd47 100644
--- a/build/android/pylib/uiautomator/test_runner.py
+++ b/build/android/pylib/uiautomator/test_runner.py
@@ -26,7 +26,6 @@
     # Create an InstrumentationOptions object to pass to the super class
     instrumentation_options = instr_test_options.InstrumentationOptions(
         test_options.tool,
-        test_options.cleanup_test_files,
         test_options.annotations,
         test_options.exclude_annotations,
         test_options.test_filter,
diff --git a/build/android/pylib/utils/emulator.py b/build/android/pylib/utils/emulator.py
index 81b9c98..26b9109 100644
--- a/build/android/pylib/utils/emulator.py
+++ b/build/android/pylib/utils/emulator.py
@@ -19,6 +19,7 @@
 from pylib import cmd_helper
 from pylib import constants
 from pylib import pexpect
+from pylib.device import device_errors
 from pylib.device import device_utils
 from pylib.utils import time_profile
 
@@ -394,33 +395,30 @@
     """
     seconds_waited = 0
     number_of_waits = 2  # Make sure we can wfd twice
-    # TODO(jbudorick) Un-handroll this in the implementation switch.
-    adb_cmd = "adb -s %s %s" % (self.device_serial, 'wait-for-device')
+
+    device = device_utils.DeviceUtils(self.device_serial)
     while seconds_waited < self._LAUNCH_TIMEOUT:
       try:
-        run_command.RunCommand(adb_cmd,
-                               timeout_time=self._WAITFORDEVICE_TIMEOUT,
-                               retry_count=1)
+        device.adb.WaitForDevice(
+            timeout=self._WAITFORDEVICE_TIMEOUT, retries=1)
         number_of_waits -= 1
         if not number_of_waits:
           break
-      except errors.WaitForResponseTimedOutError:
+      except device_errors.CommandTimeoutError:
         seconds_waited += self._WAITFORDEVICE_TIMEOUT
-        adb_cmd = "adb -s %s %s" % (self.device_serial, 'kill-server')
-        run_command.RunCommand(adb_cmd)
+        device.adb.KillServer()
       self.popen.poll()
       if self.popen.returncode != None:
         raise EmulatorLaunchException('EMULATOR DIED')
+
     if seconds_waited >= self._LAUNCH_TIMEOUT:
       raise EmulatorLaunchException('TIMEOUT with wait-for-device')
+
     logging.info('Seconds waited on wait-for-device: %d', seconds_waited)
     if wait_for_boot:
       # Now that we checked for obvious problems, wait for a boot complete.
       # Waiting for the package manager is sometimes problematic.
-      # TODO(jbudorick) Convert this once waiting for the package manager and
-      #                 the external storage is no longer problematic.
-      d = device_utils.DeviceUtils(self.device_serial)
-      d.old_interface.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT)
+      device.WaitUntilFullyBooted(timeout=self._WAITFORBOOT_TIMEOUT)
 
   def Shutdown(self):
     """Shuts down the process started by launch."""
diff --git a/build/android/pylib/utils/findbugs.py b/build/android/pylib/utils/findbugs.py
index 82408b0..8deb0fe 100644
--- a/build/android/pylib/utils/findbugs.py
+++ b/build/android/pylib/utils/findbugs.py
@@ -2,254 +2,153 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import optparse
+import argparse
+import logging
 import os
 import re
 import shlex
-import subprocess
 import sys
+import xml.dom.minidom
 
 from pylib import cmd_helper
 from pylib import constants
 
 
-def _PrintMessage(warnings, title, action, known_bugs_file):
-  if warnings:
-    print
-    print '*' * 80
-    print '%s warnings.' % title
-    print '%s %s' % (action, known_bugs_file)
-    print '-' * 80
-    for warning in warnings:
-      print warning
-    print '-' * 80
-    print
+_FINDBUGS_HOME = os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
+                              'findbugs')
+_FINDBUGS_JAR = os.path.join(_FINDBUGS_HOME, 'lib', 'findbugs.jar')
+_FINDBUGS_MAX_HEAP = 768
+_FINDBUGS_PLUGIN_PATH = os.path.join(
+    constants.DIR_SOURCE_ROOT, 'tools', 'android', 'findbugs_plugin', 'lib',
+    'chromiumPlugin.jar')
 
 
-def _StripLineNumbers(current_warnings):
-  re_line = r':\[line.*?\]$'
-  return [re.sub(re_line, '', x) for x in current_warnings]
+def _ParseXmlResults(results_doc):
+  warnings = set()
+  for en in (n for n in results_doc.documentElement.childNodes
+             if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+    if en.tagName == 'BugInstance':
+      warnings.add(_ParseBugInstance(en))
+  return warnings
 
 
-def _DiffKnownWarnings(current_warnings_set, known_bugs_file):
-  if os.path.exists(known_bugs_file):
-    with open(known_bugs_file, 'r') as known_bugs:
-      known_bugs_set = set(known_bugs.read().splitlines())
-  else:
-    known_bugs_set = set()
-
-  new_warnings = current_warnings_set - known_bugs_set
-  _PrintMessage(sorted(new_warnings), 'New', 'Please fix, or perhaps add to',
-                known_bugs_file)
-
-  obsolete_warnings = known_bugs_set - current_warnings_set
-  _PrintMessage(sorted(obsolete_warnings), 'Obsolete', 'Please remove from',
-                known_bugs_file)
-
-  count = len(new_warnings) + len(obsolete_warnings)
-  if count:
-    print '*** %d FindBugs warning%s! ***' % (count, 's' * (count > 1))
-    if len(new_warnings):
-      print '*** %d: new ***' % len(new_warnings)
-    if len(obsolete_warnings):
-      print '*** %d: obsolete ***' % len(obsolete_warnings)
-    print
-    print 'Alternatively,  rebaseline with --rebaseline command option'
-    print
-  else:
-    print 'No new FindBugs warnings.'
-  print
-  return count
+def _GetMessage(node):
+  for c in (n for n in node.childNodes
+            if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+    if c.tagName == 'Message':
+      if (len(c.childNodes) == 1
+          and c.childNodes[0].nodeType == xml.dom.Node.TEXT_NODE):
+        return c.childNodes[0].data
+  return None
 
 
-def _Rebaseline(current_warnings_set, known_bugs_file):
-  with file(known_bugs_file, 'w') as known_bugs:
-    for warning in sorted(current_warnings_set):
-      print >> known_bugs, warning
-  return 0
+def _ParseBugInstance(node):
+  bug = FindBugsWarning(node.getAttribute('type'))
+  msg_parts = []
+  for c in (n for n in node.childNodes
+            if n.nodeType == xml.dom.Node.ELEMENT_NODE):
+    if c.tagName == 'Class':
+      msg_parts.append(_GetMessage(c))
+    elif c.tagName == 'Method':
+      msg_parts.append(_GetMessage(c))
+    elif c.tagName == 'Field':
+      msg_parts.append(_GetMessage(c))
+    elif c.tagName == 'SourceLine':
+      bug.file_name = c.getAttribute('sourcefile')
+      if c.hasAttribute('start'):
+        bug.start_line = int(c.getAttribute('start'))
+      if c.hasAttribute('end'):
+        bug.end_line = int(c.getAttribute('end'))
+      msg_parts.append(_GetMessage(c))
+    elif (c.tagName == 'ShortMessage' and len(c.childNodes) == 1
+          and c.childNodes[0].nodeType == xml.dom.Node.TEXT_NODE):
+      msg_parts.append(c.childNodes[0].data)
+  bug.message = tuple(m for m in msg_parts if m)
+  return bug
 
 
-def _GetChromeJars(release_version):
-  version = 'Debug'
-  if release_version:
-    version = 'Release'
-  path = os.path.join(constants.DIR_SOURCE_ROOT,
-                      os.environ.get('CHROMIUM_OUT_DIR', 'out'),
-                      version,
-                      'lib.java')
-  cmd = 'find %s -name "*.jar"' % path
-  out = cmd_helper.GetCmdOutput(shlex.split(cmd))
-  out = [p for p in out.splitlines() if not p.endswith('.dex.jar')]
-  if not out:
-    print 'No classes found in %s' % path
-  return ' '.join(out)
+class FindBugsWarning(object):
+
+  def __init__(self, bug_type='', end_line=0, file_name='', message=None,
+               start_line=0):
+    self.bug_type = bug_type
+    self.end_line = end_line
+    self.file_name = file_name
+    if message is None:
+      self.message = tuple()
+    else:
+      self.message = message
+    self.start_line = start_line
+
+  def __cmp__(self, other):
+    return (cmp(self.file_name, other.file_name)
+            or cmp(self.start_line, other.start_line)
+            or cmp(self.end_line, other.end_line)
+            or cmp(self.bug_type, other.bug_type)
+            or cmp(self.message, other.message))
+
+  def __eq__(self, other):
+    return self.__dict__ == other.__dict__
+
+  def __hash__(self):
+    return hash((self.bug_type, self.end_line, self.file_name, self.message,
+                 self.start_line))
+
+  def __ne__(self, other):
+    return not self == other
+
+  def __str__(self):
+    return '%s: %s' % (self.bug_type, '\n  '.join(self.message))
 
 
-def _Run(exclude, known_bugs, classes_to_analyze, auxiliary_classes,
-        rebaseline, release_version, findbug_args):
-  """Run the FindBugs.
+def Run(exclude, classes_to_analyze, auxiliary_classes, output_file,
+        findbug_args, jars):
+  """Run FindBugs.
 
   Args:
     exclude: the exclude xml file, refer to FindBugs's -exclude command option.
-    known_bugs: the text file of known bugs. The bugs in it will not be
-                reported.
     classes_to_analyze: the list of classes need to analyze, refer to FindBug's
                         -onlyAnalyze command line option.
     auxiliary_classes: the classes help to analyze, refer to FindBug's
                        -auxclasspath command line option.
-    rebaseline: True if the known_bugs file needs rebaseline.
-    release_version: True if the release version needs check, otherwise check
-                     debug version.
-    findbug_args: addtional command line options needs pass to Findbugs.
+    output_file: An optional path to dump XML results to.
+    findbug_args: A list of addtional command line options to pass to Findbugs.
   """
+  # TODO(jbudorick): Get this from the build system.
+  system_classes = [
+    os.path.join(constants.ANDROID_SDK_ROOT, 'platforms',
+                 'android-%s' % constants.ANDROID_SDK_VERSION, 'android.jar')
+  ]
+  system_classes.extend(os.path.abspath(classes)
+                        for classes in auxiliary_classes or [])
 
-  chrome_src = constants.DIR_SOURCE_ROOT
-  sdk_root = constants.ANDROID_SDK_ROOT
-  sdk_version = constants.ANDROID_SDK_VERSION
-
-  system_classes = []
-  system_classes.append(os.path.join(sdk_root, 'platforms',
-                                     'android-%s' % sdk_version, 'android.jar'))
-  if auxiliary_classes:
-    for classes in auxiliary_classes:
-      system_classes.append(os.path.abspath(classes))
-
-  findbugs_javacmd = 'java'
-  findbugs_home = os.path.join(chrome_src, 'third_party', 'findbugs')
-  findbugs_jar = os.path.join(findbugs_home, 'lib', 'findbugs.jar')
-  findbugs_pathsep = ':'
-  findbugs_maxheap = '768'
-
-  cmd = '%s ' % findbugs_javacmd
-  cmd = '%s -classpath %s%s' % (cmd, findbugs_jar, findbugs_pathsep)
-  cmd = '%s -Xmx%sm ' % (cmd, findbugs_maxheap)
-  cmd = '%s -Dfindbugs.home="%s" ' % (cmd, findbugs_home)
-  cmd = '%s -jar %s ' % (cmd, findbugs_jar)
-
-  cmd = '%s -textui -sortByClass ' % cmd
-  cmd = '%s -pluginList %s' % (cmd, os.path.join(chrome_src, 'tools', 'android',
-                                                 'findbugs_plugin', 'lib',
-                                                 'chromiumPlugin.jar'))
-  if len(system_classes):
-    cmd = '%s -auxclasspath %s ' % (cmd, ':'.join(system_classes))
-
+  cmd = ['java',
+         '-classpath', '%s:' % _FINDBUGS_JAR,
+         '-Xmx%dm' % _FINDBUGS_MAX_HEAP,
+         '-Dfindbugs.home="%s"' % _FINDBUGS_HOME,
+         '-jar', _FINDBUGS_JAR,
+         '-textui', '-sortByClass',
+         '-pluginList', _FINDBUGS_PLUGIN_PATH, '-xml:withMessages']
+  if system_classes:
+    cmd.extend(['-auxclasspath', ':'.join(system_classes)])
   if classes_to_analyze:
-    cmd = '%s -onlyAnalyze %s ' % (cmd, classes_to_analyze)
-
+    cmd.extend(['-onlyAnalyze', classes_to_analyze])
   if exclude:
-    cmd = '%s -exclude %s ' % (cmd, os.path.abspath(exclude))
-
+    cmd.extend(['-exclude', os.path.abspath(exclude)])
+  if output_file:
+    cmd.extend(['-output', output_file])
   if findbug_args:
-    cmd = '%s %s ' % (cmd, findbug_args)
+    cmd.extend(findbug_args)
+  cmd.extend(os.path.abspath(j) for j in jars or [])
 
-  chrome_classes = _GetChromeJars(release_version)
-  if not chrome_classes:
-    return 1
-  cmd = '%s %s ' % (cmd, chrome_classes)
-
-  print
-  print '*' * 80
-  print 'Command used to run findbugs:'
-  print cmd
-  print '*' * 80
-  print
-
-  proc = subprocess.Popen(shlex.split(cmd),
-                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-  out, _err = proc.communicate()
-  current_warnings_set = set(_StripLineNumbers(filter(None, out.splitlines())))
-
-  if rebaseline:
-    return _Rebaseline(current_warnings_set, known_bugs)
+  if output_file:
+    cmd_helper.RunCmd(cmd)
+    results_doc = xml.dom.minidom.parse(output_file)
   else:
-    return _DiffKnownWarnings(current_warnings_set, known_bugs)
+    raw_out = cmd_helper.GetCmdOutput(cmd)
+    results_doc = xml.dom.minidom.parseString(raw_out)
 
-def Run(options):
-  exclude_file = None
-  known_bugs_file = None
+  current_warnings_set = _ParseXmlResults(results_doc)
 
-  if options.exclude:
-    exclude_file = options.exclude
-  elif options.base_dir:
-    exclude_file = os.path.join(options.base_dir, 'findbugs_exclude.xml')
+  return (' '.join(cmd), current_warnings_set)
 
-  if options.known_bugs:
-    known_bugs_file = options.known_bugs
-  elif options.base_dir:
-    known_bugs_file = os.path.join(options.base_dir, 'findbugs_known_bugs.txt')
-
-  auxclasspath = None
-  if options.auxclasspath:
-    auxclasspath = options.auxclasspath.split(':')
-  return _Run(exclude_file, known_bugs_file, options.only_analyze, auxclasspath,
-              options.rebaseline, options.release_build, options.findbug_args)
-
-
-def GetCommonParser():
-  parser = optparse.OptionParser()
-  parser.add_option('-r',
-                    '--rebaseline',
-                    action='store_true',
-                    dest='rebaseline',
-                    help='Rebaseline known findbugs issues.')
-
-  parser.add_option('-a',
-                    '--auxclasspath',
-                    action='store',
-                    default=None,
-                    dest='auxclasspath',
-                    help='Set aux classpath for analysis.')
-
-  parser.add_option('-o',
-                    '--only-analyze',
-                    action='store',
-                    default=None,
-                    dest='only_analyze',
-                    help='Only analyze the given classes and packages.')
-
-  parser.add_option('-e',
-                    '--exclude',
-                    action='store',
-                    default=None,
-                    dest='exclude',
-                    help='Exclude bugs matching given filter.')
-
-  parser.add_option('-k',
-                    '--known-bugs',
-                    action='store',
-                    default=None,
-                    dest='known_bugs',
-                    help='Not report the bugs in the given file.')
-
-  parser.add_option('-l',
-                    '--release-build',
-                    action='store_true',
-                    dest='release_build',
-                    help='Analyze release build instead of debug.')
-
-  parser.add_option('-f',
-                    '--findbug-args',
-                    action='store',
-                    default=None,
-                    dest='findbug_args',
-                    help='Additional findbug arguments.')
-
-  parser.add_option('-b',
-                    '--base-dir',
-                    action='store',
-                    default=None,
-                    dest='base_dir',
-                    help='Base directory for configuration file.')
-
-  return parser
-
-
-def main():
-  parser = GetCommonParser()
-  options, _ = parser.parse_args()
-
-  return Run(options)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py
index fcbe427..90d5ca0 100644
--- a/build/android/pylib/utils/isolator.py
+++ b/build/android/pylib/utils/isolator.py
@@ -24,12 +24,16 @@
 
 
 def DefaultConfigVariables():
+  # Note: This list must match the --config-vars in build/isolate.gypi
   return {
     'CONFIGURATION_NAME': constants.GetBuildType(),
     'OS': 'android',
     'asan': '0',
+    'branding': 'Chromium',
     'chromeos': '0',
     'component': 'static_library',
+    'enable_pepper_cdms': '0',
+    'enable_plugins': '0',
     'fastbuild': '0',
     'icu_use_data_file_flag': '1',
     'lsan': '0',
@@ -39,6 +43,7 @@
     'tsan': '0',
     'use_custom_libcxx': '0',
     'use_instrumented_libraries': '0',
+    'use_prebuilt_instrumented_libraries': '0',
     'use_openssl': '0',
     'use_ozone': '0',
     'use_x11': '0',
diff --git a/build/android/pylib/utils/md5sum.py b/build/android/pylib/utils/md5sum.py
index da3cd15..4d7d0b0 100644
--- a/build/android/pylib/utils/md5sum.py
+++ b/build/android/pylib/utils/md5sum.py
@@ -5,6 +5,7 @@
 import collections
 import logging
 import os
+import re
 import tempfile
 import types
 
@@ -12,8 +13,6 @@
 from pylib import constants
 from pylib.utils import device_temp_file
 
-HashAndPath = collections.namedtuple('HashAndPath', ['hash', 'path'])
-
 MD5SUM_DEVICE_LIB_PATH = '/data/local/tmp/md5sum/'
 MD5SUM_DEVICE_BIN_PATH = MD5SUM_DEVICE_LIB_PATH + 'md5sum_bin'
 
@@ -21,6 +20,8 @@
     'test -f {path} -o -d {path} '
     '&& LD_LIBRARY_PATH={md5sum_lib} {device_pie_wrapper} {md5sum_bin} {path}')
 
+_STARTS_WITH_CHECKSUM_RE = re.compile(r'^\s*[0-9a-fA-f]{32}\s+')
+
 
 def CalculateHostMd5Sums(paths):
   """Calculates the MD5 sum value for all items in |paths|.
@@ -28,7 +29,7 @@
   Args:
     paths: A list of host paths to md5sum.
   Returns:
-    A list of named tuples with 'hash' and 'path' attributes.
+    A dict mapping paths to their respective md5sum checksums.
   """
   if isinstance(paths, basestring):
     paths = [paths]
@@ -36,7 +37,8 @@
   out = cmd_helper.GetCmdOutput(
       [os.path.join(constants.GetOutDirectory(), 'md5sum_bin_host')] +
           [p for p in paths])
-  return [HashAndPath(*l.split(None, 1)) for l in out.splitlines()]
+
+  return _ParseMd5SumOutput(out.splitlines())
 
 
 def CalculateDeviceMd5Sums(paths, device):
@@ -45,7 +47,7 @@
   Args:
     paths: A list of device paths to md5sum.
   Returns:
-    A list of named tuples with 'hash' and 'path' attributes.
+    A dict mapping paths to their respective md5sum checksums.
   """
   if isinstance(paths, basestring):
     paths = [paths]
@@ -72,5 +74,11 @@
       device.adb.Push(md5sum_script_file.name, md5sum_device_script_file.name)
       out = device.RunShellCommand(['sh', md5sum_device_script_file.name])
 
-  return [HashAndPath(*l.split(None, 1)) for l in out if l]
+  return _ParseMd5SumOutput(out)
+
+
+def _ParseMd5SumOutput(out):
+  hash_and_path = (l.split(None, 1) for l in out
+                   if l and _STARTS_WITH_CHECKSUM_RE.match(l))
+  return dict((p, h) for h, p in hash_and_path)
 
diff --git a/build/android/pylib/utils/md5sum_test.py b/build/android/pylib/utils/md5sum_test.py
index 6c689fb..de9cd35 100755
--- a/build/android/pylib/utils/md5sum_test.py
+++ b/build/android/pylib/utils/md5sum_test.py
@@ -39,8 +39,9 @@
     with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
       out = md5sum.CalculateHostMd5Sums(test_path)
       self.assertEquals(1, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/test/host/file.dat', out[0].path)
+      self.assertTrue('/test/host/file.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/test/host/file.dat'])
       mock_get_cmd_output.assert_called_once_with(
           [HOST_MD5_EXECUTABLE, '/test/host/file.dat'])
 
@@ -52,10 +53,12 @@
     with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
       out = md5sum.CalculateHostMd5Sums(test_paths)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/test/host/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/test/host/file1.dat', out[1].path)
+      self.assertTrue('/test/host/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/test/host/file0.dat'])
+      self.assertTrue('/test/host/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/test/host/file1.dat'])
       mock_get_cmd_output.assert_called_once_with(
           [HOST_MD5_EXECUTABLE, '/test/host/file0.dat',
            '/test/host/file1.dat'])
@@ -68,10 +71,12 @@
     with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output):
       out = md5sum.CalculateHostMd5Sums(test_paths)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/test/host/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/test/host/file1.dat', out[1].path)
+      self.assertTrue('/test/host/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/test/host/file0.dat'])
+      self.assertTrue('/test/host/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/test/host/file1.dat'])
       mock_get_cmd_output.assert_called_once_with(
           [HOST_MD5_EXECUTABLE, '/test/host/file0.dat', '/test/host/file1.dat'])
 
@@ -99,8 +104,9 @@
                     new=mock_device_temp_file)):
       out = md5sum.CalculateDeviceMd5Sums(test_path, device)
       self.assertEquals(1, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file.dat', out[0].path)
+      self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file.dat'])
       device.adb.Push.assert_called_once_with(
           '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
       device.RunShellCommand.assert_called_once_with(
@@ -132,10 +138,12 @@
                     new=mock_device_temp_file)):
       out = md5sum.CalculateDeviceMd5Sums(test_path, device)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+      self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file0.dat'])
+      self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/storage/emulated/legacy/test/file1.dat'])
       device.adb.Push.assert_called_once_with(
           '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
       device.RunShellCommand.assert_called_once_with(
@@ -168,10 +176,47 @@
                     new=mock_device_temp_file)):
       out = md5sum.CalculateDeviceMd5Sums(test_path, device)
       self.assertEquals(2, len(out))
-      self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path)
-      self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash)
-      self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path)
+      self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file0.dat'])
+      self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
+      self.assertEquals('123456789abcdef00fedcba987654321',
+                        out['/storage/emulated/legacy/test/file1.dat'])
+      device.adb.Push.assert_called_once_with(
+          '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
+      device.RunShellCommand.assert_called_once_with(
+          ['sh', '/data/local/tmp/test/script/file.sh'])
+
+  def testCalculateDeviceMd5Sums_singlePath_linkerWarning(self):
+    # See crbug/479966
+    test_path = '/storage/emulated/legacy/test/file.dat'
+
+    device = mock.NonCallableMock()
+    device.adb = mock.NonCallableMock()
+    device.adb.Push = mock.Mock()
+    device_md5sum_output = [
+        'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: '
+            'unused DT entry: type 0x1d arg 0x15db',
+        '0123456789abcdeffedcba9876543210 '
+            '/storage/emulated/legacy/test/file.dat',
+    ]
+    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
+
+    mock_temp_file = mock.mock_open()
+    mock_temp_file.return_value.name = '/tmp/test/script/file.sh'
+
+    mock_device_temp_file = mock.mock_open()
+    mock_device_temp_file.return_value.name = (
+        '/data/local/tmp/test/script/file.sh')
+
+    with mock.patch('tempfile.NamedTemporaryFile', new=mock_temp_file), (
+         mock.patch('pylib.utils.device_temp_file.DeviceTempFile',
+                    new=mock_device_temp_file)):
+      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
+      self.assertEquals(1, len(out))
+      self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
+      self.assertEquals('0123456789abcdeffedcba9876543210',
+                        out['/storage/emulated/legacy/test/file.dat'])
       device.adb.Push.assert_called_once_with(
           '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh')
       device.RunShellCommand.assert_called_once_with(
diff --git a/build/android/pylib/utils/mock_calls.py b/build/android/pylib/utils/mock_calls.py
index 3052b0d..59167ba 100644
--- a/build/android/pylib/utils/mock_calls.py
+++ b/build/android/pylib/utils/mock_calls.py
@@ -36,7 +36,7 @@
           expected_call, action = self._expected_calls.pop(0)
           self._test_case.assertTrue(
               received_call == expected_call,
-              msg=('Expected call missmatch:\n'
+              msg=('Expected call mismatch:\n'
                    '  expected: %s\n'
                    '  received: %s\n'
                    % (str(expected_call), str(received_call))))
diff --git a/build/android/pylib/utils/test_environment.py b/build/android/pylib/utils/test_environment.py
index 4d88a45..e78eb5c 100644
--- a/build/android/pylib/utils/test_environment.py
+++ b/build/android/pylib/utils/test_environment.py
@@ -34,13 +34,14 @@
   """Clean up the test environment, restarting fresh adb and HTTP daemons."""
   _KillWebServers()
   device_utils.RestartServer()
-  p = device_utils.DeviceUtils.parallel()
-  p.old_interface.RestartAdbdOnDevice()
-  try:
-    p.EnableRoot()
-  except device_errors.CommandFailedError as e:
-    # TODO(jbudorick) Handle this exception appropriately after interface
-    #                 conversions are finished.
-    logging.error(str(e))
-  p.WaitUntilFullyBooted()
+
+  def cleanup_device(d):
+    d.old_interface.RestartAdbdOnDevice()
+    try:
+      d.EnableRoot()
+    except device_errors.CommandFailedError as e:
+      logging.error(str(e))
+    d.WaitUntilFullyBooted()
+
+  device_utils.DeviceUtils.parallel().pMap(cleanup_device)
 
diff --git a/build/android/screenshot.py b/build/android/screenshot.py
index 8fe2a95..c48a255 100755
--- a/build/android/screenshot.py
+++ b/build/android/screenshot.py
@@ -11,8 +11,8 @@
 import os
 import sys
 
-from pylib import android_commands
 from pylib import screenshot
+from pylib.device import device_errors
 from pylib.device import device_utils
 
 def _PrintMessage(heading, eol='\n'):
@@ -66,21 +66,25 @@
 
   (options, args) = parser.parse_args()
 
-  if options.verbose:
-    logging.getLogger().setLevel(logging.DEBUG)
-
-  devices = android_commands.GetAttachedDevices()
-
-  if not options.device and len(devices) > 1:
-    parser.error('Multiple devices are attached. '
-                 'Please specify device serial number with --device.')
-  elif not options.device and len(devices) == 1:
-    options.device = devices[0]
-
   if len(args) > 1:
     parser.error('Too many positional arguments.')
   host_file = args[0] if args else options.file
-  device = device_utils.DeviceUtils(options.device)
+
+  if options.verbose:
+    logging.getLogger().setLevel(logging.DEBUG)
+
+  devices = device_utils.DeviceUtils.HealthyDevices()
+
+  if not options.device:
+    if len(devices) > 1:
+      parser.error('Multiple devices are attached. '
+                   'Please specify device serial number with --device.')
+    elif len(devices) == 1:
+      device = devices[0]
+    else:
+      raise device_errors.NoDevicesError()
+  else:
+    device = device_utils.DeviceUtils(options.device)
 
   if options.video:
     _CaptureVideo(device, host_file, options)
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 368ac06..c54ed28 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -152,6 +152,9 @@
                            'Overrides all other flags.'))
   group.add_argument('--remote-device-timeout', type=int,
                      help='Times to retry finding remote device')
+  group.add_argument('--network-config', type=int,
+                     help='Integer that specifies the network environment '
+                          'that the tests will be run in.')
 
   device_os_group = group.add_mutually_exclusive_group()
   device_os_group.add_argument('--remote-device-minimum-os',
@@ -175,9 +178,6 @@
 def AddDeviceOptions(parser):
   """Adds device options to |parser|."""
   group = parser.add_argument_group(title='Device Options')
-  group.add_argument('-c', dest='cleanup_test_files',
-                     help='Cleanup test files on the device after run',
-                     action='store_true')
   group.add_argument('--tool',
                      dest='tool',
                      help=('Run the test under a tool '
@@ -372,7 +372,6 @@
   # TODO(jbudorick): Get rid of InstrumentationOptions.
   return instrumentation_test_options.InstrumentationOptions(
       args.tool,
-      args.cleanup_test_files,
       args.annotations,
       args.exclude_annotations,
       args.test_filter,
@@ -437,7 +436,6 @@
 
   return uiautomator_test_options.UIAutomatorOptions(
       args.tool,
-      args.cleanup_test_files,
       args.annotations,
       args.exclude_annotations,
       args.test_filter,
@@ -636,7 +634,6 @@
     # into the gtest code.
     gtest_options = gtest_test_options.GTestOptions(
         args.tool,
-        args.cleanup_test_files,
         args.test_filter,
         args.run_disabled,
         args.test_arguments,
@@ -768,7 +765,16 @@
 def _RunJUnitTests(args):
   """Subcommand of RunTestsCommand which runs junit tests."""
   runner_factory, tests = junit_setup.Setup(args)
-  _, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
+  results, exit_code = junit_dispatcher.RunTests(tests, runner_factory)
+
+  report_results.LogFull(
+      results=results,
+      test_type='JUnit',
+      test_package=args.test_suite)
+
+  if args.json_results_file:
+    json_results.GenerateJsonResultsFile(results, args.json_results_file)
+
   return exit_code
 
 
diff --git a/build/android/tombstones.py b/build/android/tombstones.py
index 1a958ac..c83a584 100755
--- a/build/android/tombstones.py
+++ b/build/android/tombstones.py
@@ -19,7 +19,7 @@
 import sys
 import optparse
 
-from pylib import android_commands
+from pylib.device import adb_wrapper
 from pylib.device import device_errors
 from pylib.device import device_utils
 from pylib.utils import run_tests_helper
@@ -233,19 +233,19 @@
   options, _ = parser.parse_args()
 
   if options.device:
-    devices = [options.device]
+    devices = [device_utils.DeviceUtils(options.device)]
   else:
-    devices = android_commands.GetAttachedDevices()
+    devices = device_utils.DeviceUtils.HealthyDevices()
 
   # This must be done serially because strptime can hit a race condition if
   # used for the first time in a multithreaded environment.
   # http://bugs.python.org/issue7980
   tombstones = []
-  for device_serial in devices:
-    device = device_utils.DeviceUtils(device_serial)
+  for device in devices:
     tombstones += _GetTombstonesForDevice(device, options)
 
   _ResolveTombstones(options.jobs, tombstones)
 
+
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/build/android/update_verification.py b/build/android/update_verification.py
index fe89567..45c6e98 100755
--- a/build/android/update_verification.py
+++ b/build/android/update_verification.py
@@ -12,12 +12,11 @@
 import sys
 import time
 
-from pylib import android_commands
 from pylib.device import device_utils
 
 def _SaveAppData(device, package_name, from_apk=None, data_dir=None):
   def _BackupAppData(data_dir=None):
-    device.old_interface.Adb().SendCommand('backup %s' % package_name)
+    device.adb.Backup(package_name)
     backup_file = os.path.join(os.getcwd(), 'backup.ab')
     assert os.path.exists(backup_file), 'Backup failed.'
     if data_dir:
@@ -29,8 +28,7 @@
 
   if from_apk:
     logging.info('Installing %s...', from_apk)
-    # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-    output = device.old_interface.Install(from_apk, reinstall=True)
+    output = device.Install(from_apk, reinstall=True)
     if 'Success' not in output:
       raise Exception('Unable to install %s. output: %s' % (from_apk, output))
 
@@ -42,14 +40,13 @@
 def _VerifyAppUpdate(device, to_apk, app_data, from_apk=None):
   def _RestoreAppData():
     assert os.path.exists(app_data), 'Backup file does not exist!'
-    device.old_interface.Adb().SendCommand('restore %s' % app_data)
+    device.adb.Restore(app_data)
     # It seems restore command is not synchronous.
     time.sleep(15)
 
   if from_apk:
     logging.info('Installing %s...', from_apk)
-    # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-    output = device.old_interface.Install(from_apk, reinstall=True)
+    output = device.Install(from_apk, reinstall=True)
     if 'Success' not in output:
       raise Exception('Unable to install %s. output: %s' % (from_apk, output))
 
@@ -59,8 +56,7 @@
 
   logging.info('Verifying that %s cannot be installed side-by-side...',
                to_apk)
-  # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-  output = device.old_interface.Install(to_apk)
+  output = device.Install(to_apk)
   if 'INSTALL_FAILED_ALREADY_EXISTS' not in output:
     if 'Success' in output:
       raise Exception('Package name has changed! output: %s' % output)
@@ -68,8 +64,7 @@
       raise Exception(output)
 
   logging.info('Verifying that %s can be overinstalled...', to_apk)
-  # TODO(jbudorick) Switch to AdbWrapper.Install on the impl switch.
-  output = device.old_interface.Install(to_apk, reinstall=True)
+  output = device.adb.Install(to_apk, reinstall=True)
   if 'Success' not in output:
     raise Exception('Unable to install %s.\n output: %s' % (to_apk, output))
   logging.info('Successfully updated to the new apk. Please verify that the '
@@ -112,10 +107,10 @@
     parser.print_help(sys.stderr)
     parser.error('Unknown arguments: %s.' % args)
 
-  devices = android_commands.GetAttachedDevices()
+  devices = device_utils.DeviceUtils.HealthyDevices()
   if len(devices) != 1:
     parser.error('Exactly 1 device must be attached.')
-  device = device_utils.DeviceUtils(devices[0])
+  device = devices[0]
 
   if options.from_apk:
     assert os.path.isfile(options.from_apk)
diff --git a/build/apk_test.gypi b/build/apk_test.gypi
index 05bafab..792d92c 100644
--- a/build/apk_test.gypi
+++ b/build/apk_test.gypi
@@ -31,7 +31,7 @@
          'apk_name': '<(test_suite_name)',
          'intermediate_dir': '<(PRODUCT_DIR)/<(test_suite_name)_apk',
          'final_apk_path': '<(intermediate_dir)/<(test_suite_name)-debug.apk',
-         'java_in_dir': '<(DEPTH)/testing/android/java',
+         'java_in_dir': '<(DEPTH)/testing/android/native_test/java',
          'native_lib_target': 'lib<(test_suite_name)',
          # TODO(yfriedman, cjhopman): Support managed installs for gtests.
          'gyp_managed_install': 0,
diff --git a/build/build_config.h b/build/build_config.h
index b07660d..d8c3db6 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -61,8 +61,8 @@
 #error Please add support for your platform in build/build_config.h
 #endif
 
-#if defined(USE_OPENSSL) && defined(USE_NSS)
-#error Cannot use both OpenSSL and NSS
+#if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS)
+#error Cannot use both OpenSSL and NSS for certificates
 #endif
 
 // For access to standard BSD features, use OS_BSD instead of a
diff --git a/build/common.gypi b/build/common.gypi
index e900cc4..c5a8fac 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -70,7 +70,10 @@
           # certificates, use_openssl_certs must be set.
           'use_openssl%': 0,
 
-          # Typedef X509Certificate::OSCertHandle to OpenSSL's struct X509*.
+          # Use OpenSSL for representing certificates. When targeting Android,
+          # the platform certificate library is used for certificate
+          # verification. On other targets, this flag also enables OpenSSL for
+          # certificate verification, but this configuration is unsupported.
           'use_openssl_certs%': 0,
 
           # Disable viewport meta tag by default.
@@ -146,6 +149,7 @@
         'enable_hidpi%': '<(enable_hidpi)',
         'buildtype%': '<(buildtype)',
         'branding%': '<(branding)',
+        'branding_path_component%': '<(branding)',
         'host_arch%': '<(host_arch)',
         'target_arch%': '<(target_arch)',
 
@@ -155,12 +159,6 @@
         # default. "default" should be used on non-official builds.
         'android_channel%': 'default',
 
-        # This is set when building the Android WebView inside the Android
-        # build system, using the 'android' gyp backend. The WebView code is
-        # still built when this is unset, but builds using the normal chromium
-        # build system.
-        'android_webview_build%': 0,
-
         # Set ARM architecture version.
         'arm_version%': 7,
 
@@ -191,6 +189,14 @@
         'mips_dsp_rev%': 0,
 
         'conditions': [
+          ['branding == "Chrome"', {
+            'branding_path_component%': 'google_chrome',
+          }],
+
+          ['branding == "Chromium"', {
+            'branding_path_component%': 'chromium',
+          }],
+
           # Ash needs Aura.
           ['use_aura==0', {
             'use_ash%': 0,
@@ -248,14 +254,8 @@
 
           # Set the default "target_subarch" on iOS. Valid values are "arm32",
           # "arm64" and "both" (meaning a fat binary).
-          #
-          # TODO(sdefresne): change the default from "arm32" to "both" for
-          # "target_subarch" once http://crbug.com/339477 is fixed.
-          #
-          # TODO(sdefresne): set the "target_arch" to "arm" once compilation
-          # of skia has been fixed for simulator. http://crbug.com/342377
           ['OS=="ios"', {
-            'target_subarch%': 'arm32',
+            'target_subarch%': 'arm64',
           }],
 
           # Set arch variants for MIPS platforms.
@@ -298,13 +298,13 @@
       'enable_viewport%': '<(enable_viewport)',
       'enable_hidpi%': '<(enable_hidpi)',
       'android_channel%': '<(android_channel)',
-      'android_webview_build%': '<(android_webview_build)',
       'use_goma%': '<(use_goma)',
       'gomadir%': '<(gomadir)',
       'enable_app_list%': '<(enable_app_list)',
       'use_default_render_theme%': '<(use_default_render_theme)',
       'buildtype%': '<(buildtype)',
       'branding%': '<(branding)',
+      'branding_path_component%': '<(branding_path_component)',
       'arm_version%': '<(arm_version)',
       'sysroot%': '<(sysroot)',
       'chroot_cmd%': '<(chroot_cmd)',
@@ -633,14 +633,23 @@
       # compiler. Always do this by default.
       'host_clang%': 1,
 
-      # Variables to control Link-Time Optimizations (LTO).
-      # Note: the variables must *not* be enabled at the same time.
-      #       In this case LTO would 'merge' the optimization flags
-      #       at link-time which would lead to all code be optimized with -O2.
-      # Enable LTO on the code compiled with -Os.
-      # See crbug.com/407544
+      # Variables to control Link-Time Optimization (LTO).
+      # On Android, the variable use_lto enables LTO on code compiled with -Os,
+      # and use_lto_o2 enables LTO on code compiled with -O2. On other
+      # platforms, use_lto enables LTO in all translation units, and use_lto_o2
+      # has no effect.
+      #
+      # On Linux and Android, when using LLVM LTO, the script
+      # build/download_gold_plugin.py must be run to download a linker plugin.
+      # On Mac, LLVM needs to be built from scratch using
+      # tools/clang/scripts/update.py and the absolute path to
+      # third_party/llvm-build/Release+Asserts/lib must be added to
+      # $DYLD_LIBRARY_PATH to pick up the right version of the linker plugin.
+      #
+      # On Android, the variables must *not* be enabled at the same time.
+      # In this case LTO would 'merge' the optimization flags at link-time
+      # which would lead to all code be optimized with -O2. See crbug.com/407544
       'use_lto%': 0,
-      # Enable LTO on code compiled with -O2.
       'use_lto_o2%': 0,
 
       # Allowed level of identical code folding in the gold linker.
@@ -653,9 +662,22 @@
       # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
       'cfi_vptr%': 0,
 
+      # Control Flow Integrity for casts.
+      # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
+      'cfi_derived_cast%': 0,
+      'cfi_unrelated_cast%': 0,
+
+      'cfi_blacklist%': '<(PRODUCT_DIR)/../../tools/cfi/blacklist.txt',
+
       # Whether the entire browser uses toolkit-views on Mac instead of Cocoa.
       'mac_views_browser%': 0,
 
+      # By default, use ICU data file (icudtl.dat).
+      'icu_use_data_file_flag%': 1,
+
+      # Turn on JNI generation optimizations by default.
+      'optimize_jni_generation%': 1,
+
       'conditions': [
         # A flag for POSIX platforms
         ['OS=="win"', {
@@ -672,18 +694,10 @@
         }],
 
         # NSS usage.
-        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and use_openssl==0', {
-          'use_nss%': 1,
+        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris")', {
+          'use_nss_certs%': 1,
         }, {
-          'use_nss%': 0,
-        }],
-
-        # When OpenSSL is used for SSL and crypto on Unix-like systems, use
-        # OpenSSL's certificate definition.
-        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and use_openssl==1', {
-          'use_openssl_certs%': 1,
-        }, {
-          'use_openssl_certs%': 0,
+          'use_nss_certs%': 0,
         }],
 
         # libudev usage.  This currently only affects the content layer.
@@ -786,8 +800,8 @@
           'native_memory_pressure_signals%': 1,
         }],
 
-        # Enable autofill dialog for Android, Mac and Views-enabled platforms.
-        ['toolkit_views==1 or (OS=="android" and android_webview_build==0) or OS=="mac"', {
+        # Enable autofill dialog when not on iOS.
+        ['OS!="ios"', {
           'enable_autofill_dialog%': 1,
 
           'conditions': [
@@ -852,7 +866,7 @@
         # are using a custom toolchain and need to control -B in ldflags.
         # Do not use 32-bit gold on 32-bit hosts as it runs out address space
         # for component=static_library builds.
-        ['OS=="linux" and (target_arch=="x64" or target_arch=="arm")', {
+        ['(OS=="linux" or OS=="android") and (target_arch=="x64" or target_arch=="arm")', {
           'linux_use_bundled_gold%': 1,
         }, {
           'linux_use_bundled_gold%': 0,
@@ -901,7 +915,7 @@
         #
         # On Aura, this allows per-tile painting to be used in the browser
         # compositor.
-        ['OS!="android"', {
+        ['OS!="android" and OS!="ios"', {
           'use_canvas_skia%': 1,
         }],
 
@@ -986,15 +1000,6 @@
           'enable_print_preview%': 0,
         }],
 
-        # By default, use ICU data file (icudtl.dat) on all platforms
-        # except when building Android WebView.
-        # TODO(jshin): Handle 'use_system_icu' on Linux (Chromium).
-        # Set the data reduction proxy origin for Android Webview.
-        ['android_webview_build==0', {
-          'icu_use_data_file_flag%' : 1,
-        }, {
-          'icu_use_data_file_flag%' : 0,
-        }],
         ['OS=="win" or OS=="mac"', {
           'enable_wifi_bootstrapping%' : 1,
         }],
@@ -1006,23 +1011,12 @@
         }, {
           'sas_dll_path%': '<(DEPTH)/third_party/platformsdk_win7/files/redist/x86',
         }],
-
-        # Turn on JNI generation optimizations on non-WebView builds.
-        ['OS=="android" and android_webview_build==0', {
-          'optimize_jni_generation%': 1,
-        }, {
-          'optimize_jni_generation%': 0,
-        }],
-
-        # TODO(rmcilroy): Enable v8_use_external_startup_data on ChromeOS
-        # http://crbug.com/421063
-        ['android_webview_build==0 and chromecast==0 and chromeos==0 and OS!="ios"', {
-          'v8_use_external_startup_data%': 1,
-        }, {
-          'v8_use_external_startup_data%': 0,
-        }],
       ],
 
+      # Setting this to '0' will cause V8's startup snapshot to be
+      # embedded in the binary instead of being a external files.
+      'v8_use_external_startup_data%': 1,
+
       # Set this to 1 to enable use of concatenated impulse responses
       # for the HRTF panner in WebAudio.
       'use_concatenated_impulse_responses': 1,
@@ -1073,10 +1067,16 @@
       'google_default_client_secret%': '',
       # Native Client is enabled by default.
       'disable_nacl%': '0',
+
+      # Sets the default version name and code for Android app, by default we
+      # do a developer build.
+      'android_app_version_name%': 'Developer Build',
+      'android_app_version_code%': 1,
     },
 
     # Copy conditionally-set variables out one scope.
     'branding%': '<(branding)',
+    'branding_path_component%': '<(branding_path_component)',
     'buildtype%': '<(buildtype)',
     'target_arch%': '<(target_arch)',
     'target_subarch%': '<(target_subarch)',
@@ -1091,7 +1091,7 @@
     'use_libpci%': '<(use_libpci)',
     'use_openssl%': '<(use_openssl)',
     'use_openssl_certs%': '<(use_openssl_certs)',
-    'use_nss%': '<(use_nss)',
+    'use_nss_certs%': '<(use_nss_certs)',
     'use_udev%': '<(use_udev)',
     'os_bsd%': '<(os_bsd)',
     'os_posix%': '<(os_posix)',
@@ -1196,7 +1196,6 @@
     'use_libjpeg_turbo%': '<(use_libjpeg_turbo)',
     'use_system_libjpeg%': '<(use_system_libjpeg)',
     'android_channel%': '<(android_channel)',
-    'android_webview_build%': '<(android_webview_build)',
     'icu_use_data_file_flag%': '<(icu_use_data_file_flag)',
     'gyp_managed_install%': 0,
     'create_standalone_apk%': 1,
@@ -1224,7 +1223,12 @@
     'video_hole%': '<(video_hole)',
     'v8_use_external_startup_data%': '<(v8_use_external_startup_data)',
     'cfi_vptr%': '<(cfi_vptr)',
+    'cfi_derived_cast%': '<(cfi_derived_cast)',
+    'cfi_unrelated_cast%': '<(cfi_unrelated_cast)',
+    'cfi_blacklist%': '<(cfi_blacklist)',
     'mac_views_browser%': '<(mac_views_browser)',
+    'android_app_version_name%': '<(android_app_version_name)',
+    'android_app_version_code%': '<(android_app_version_code)',
 
     # Use system protobuf instead of bundled one.
     'use_system_protobuf%': 0,
@@ -1417,7 +1421,7 @@
 
     # Pseudo locales are special locales which are used for testing and
     # debugging. They don't get copied to the final app. For more info,
-    # check out https://sites.google.com/a/chromium.org/dev/Home/fake-bidi
+    # check out https://www.chromium.org/developers/testing/fake-bidi
     'pseudo_locales': [
       'fake-bidi',
     ],
@@ -1456,11 +1460,6 @@
     # we can build a debug version with acceptable size and performance.
     'android_full_debug%': 0,
 
-    # Sets the default version name and code for Android app, by default we
-    # do a developer build.
-    'android_app_version_name%': 'Developer Build',
-    'android_app_version_code%': 1,
-
     # Contains data about the attached devices for gyp_managed_install.
     'build_device_config_path': '<(PRODUCT_DIR)/build_devices.cfg',
 
@@ -1503,6 +1502,7 @@
 
     # Ozone platforms to include in the build.
     'ozone_platform_caca%': 0,
+    'ozone_platform_cast%': 0,
     'ozone_platform_dri%': 0,
     'ozone_platform_drm%': 0,
     'ozone_platform_egltest%': 0,
@@ -1564,18 +1564,11 @@
       # it takes effect here.
       ['os_posix==1 and OS!="mac" and OS!="ios" and clang==0 and asan==0 and lsan==0 and tsan==0 and msan==0 and ubsan_vptr==0', {
         'conditions': [
-          ['OS=="android" and android_webview_build==0', {
+          ['OS=="android"', {
             'host_gcc_version%': '<!pymod_do_main(compiler_version host compiler)',
             # We directly set the gcc version since we know what we use.
             'gcc_version%': 49,
-          }],
-          ['OS=="android" and android_webview_build==1', {
-            # Android WebView uses a hermetic clang toolchain for host builds.
-            'host_gcc_version%': 0,
-            # Android WebView uses the GCC toolchain from the Android build.
-            'gcc_version%': 48,
-          }],
-          ['OS!="android"', {
+          }, {
             'host_gcc_version%': '<!pymod_do_main(compiler_version host compiler)',
             'gcc_version%': '<!pymod_do_main(compiler_version target compiler)',
           }],
@@ -1817,13 +1810,6 @@
 
         # Uses system APIs for decoding audio and video.
         'use_libffmpeg%': '0',
-
-        # TODO(torne): Remove this unsupported option once all the places that
-        # test it have been updated.
-        'use_system_stlport%': 0,
-
-        # Copy it out one scope.
-        'android_webview_build%': '<(android_webview_build)',
       }],  # OS=="android"
       ['embedded==1', {
         'use_system_fontconfig%': 0,
@@ -1844,10 +1830,8 @@
           }],
         ],
       }],
-      ['android_webview_build==1', {
-        # When building the WebView in the Android tree, jarjar will remap all
-        # the class names, so the JNI generator needs to know this.
-        'jni_generator_jarjar_file': '../android_webview/build/jarjar-rules.txt',
+      ['chromecast==1 and OS!="android"', {
+        'ozone_platform_cast%': 1
       }],
       ['OS=="linux" and target_arch!="mipsel"', {
         'clang%': 1,
@@ -2052,8 +2036,8 @@
       ['use_ash==1', {
         'grit_defines': ['-D', 'use_ash'],
       }],
-      ['use_nss==1', {
-        'grit_defines': ['-D', 'use_nss'],
+      ['use_nss_certs==1', {
+        'grit_defines': ['-D', 'use_nss_certs'],
       }],
       ['use_ozone==1', {
         'grit_defines': ['-D', 'use_ozone'],
@@ -2080,11 +2064,6 @@
           '-E', 'ANDROID_JAVA_TAGGED_ONLY=true',
           '--no-output-all-resource-defines',
         ],
-        'conditions': [
-          ['<(android_webview_build)==1', {
-            'grit_defines': ['-D', 'is_android_webview_build'],
-          }],
-        ],
       }],
       ['OS=="mac" or OS=="ios"', {
         'grit_defines': ['-D', 'scale_factors=2x'],
@@ -2175,20 +2154,31 @@
         'grit_defines': ['-D', 'enable_service_discovery'],
         'enable_service_discovery%': 1
       }],
-      ['clang_use_chrome_plugins==1 and OS!="win"', {
+      ['clang_use_chrome_plugins==1', {
         'variables': {
           'conditions': [
-            ['OS=="mac" or OS=="ios"', {
-              'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib',
-            }, { # OS != "mac" or OS != "ios"
-              'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so',
-            }],
+            ['OS!="win"', {
+              'variables': {
+                'conditions': [
+                  ['OS=="mac" or OS=="ios"', {
+                    'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib',
+                  }, { # OS != "mac" or OS != "ios"
+                    'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so',
+                  }],
+                ],
+              },
+              'clang_dynlib_flags%': '-Xclang -load -Xclang <(clang_lib_path) ',
+            }, { # OS == "win"
+              # On Windows, the plugin is built directly into clang, so there's
+              # no need to load it dynamically.
+              'clang_dynlib_flags%': '',
+            }]
           ],
         },
         # If you change these, also change build/config/clang/BUILD.gn.
         'clang_chrome_plugins_flags%':
-          '-Xclang -load -Xclang <(clang_lib_path)'
-          ' -Xclang -add-plugin -Xclang find-bad-constructs',
+          '<(clang_dynlib_flags)'
+          '-Xclang -add-plugin -Xclang find-bad-constructs',
       }],
       ['asan==1 or msan==1 or lsan==1 or tsan==1', {
         'clang%': 1,
@@ -2241,9 +2231,9 @@
       }],
 
       ['OS=="win"', {
-        # The Clang plugins don't currently work on Windows.
+        # The Blink GC plugin doesn't currently work on Windows.
         # TODO(hans): One day, this will work. (crbug.com/82385)
-        'clang_use_chrome_plugins%': 0,
+        'blink_gc_plugin%': 0,
       }],
 
       # On valgrind bots, override the optimizer settings so we don't inline too
@@ -2305,14 +2295,14 @@
       }],
 
       # Set default compiler flags depending on ARM version.
-      ['arm_version==6 and android_webview_build==0', {
+      ['arm_version==6', {
         'arm_arch%': 'armv6',
         'arm_tune%': '',
         'arm_fpu%': 'vfp',
         'arm_float_abi%': 'softfp',
         'arm_thumb%': 0,
       }],
-      ['arm_version==7 and android_webview_build==0', {
+      ['arm_version==7', {
         'arm_arch%': 'armv7-a',
         'arm_tune%': 'generic-armv7-a',
         'conditions': [
@@ -2328,24 +2318,13 @@
       }],
 
       # Set default compiler flags for MIPS floating-point support.
-      ['target_arch=="mipsel" and android_webview_build==0', {
+      ['target_arch=="mipsel"', {
         'mips_float_abi%': 'hard',
       }],
-      ['target_arch=="mipsel" and mips_arch_variant=="r2" and android_webview_build==0', {
+      ['target_arch=="mipsel" and mips_arch_variant=="r2"', {
         'mips_fpu_mode%': 'fp32',
       }],
 
-      ['android_webview_build==1', {
-        # The WebView build gets its cpu-specific flags from the Android build system.
-        'arm_arch%': '',
-        'arm_tune%': '',
-        'arm_fpu%': '',
-        'arm_float_abi%': '',
-        'arm_thumb%': 0,
-        'mips_float_abi%': '',
-        'mips_fpu_mode%': '',
-      }],
-
       # Enable brlapi by default for chromeos.
       [ 'chromeos==1', {
         'use_brlapi%': 1,
@@ -2403,7 +2382,7 @@
          'use_seccomp_bpf%': 0,
       }],
 
-      ['cfi_vptr==1', {
+      ['cfi_vptr==1 or cfi_derived_cast==1 or cfi_unrelated_cast==1', {
         'use_lto%': 1,
       }],
     ],
@@ -2702,6 +2681,9 @@
       ['enable_webrtc==1', {
         'defines': ['ENABLE_WEBRTC=1'],
       }],
+      ['enable_media_router==1', {
+        'defines': ['ENABLE_MEDIA_ROUTER=1'],
+      }],
       ['proprietary_codecs==1', {
         'defines': ['USE_PROPRIETARY_CODECS'],
         'conditions': [
@@ -3012,6 +2994,27 @@
       ['v8_use_external_startup_data==1', {
        'defines': ['V8_USE_EXTERNAL_STARTUP_DATA'],
       }],
+
+      # SAFE_BROWSING_SERVICE - browser manages a safe-browsing service.
+      # SAFE_BROWSING_DB_LOCAL - service manages a local database.
+      # SAFE_BROWSING_DB_REMOTE - service talks via API to a database
+      # SAFE_BROWSING_CSD - enable client-side phishing detection.
+      ['safe_browsing==1', {
+        # TODO(nparker): Remove existing uses of FULL_SAFE_BROWSING
+        'defines': [
+          'FULL_SAFE_BROWSING',
+          'SAFE_BROWSING_CSD',
+          'SAFE_BROWSING_DB_LOCAL',
+          'SAFE_BROWSING_SERVICE',
+        ],
+      }],
+      ['safe_browsing==2', {
+        'defines': [
+          # TODO(nparker): Remove existing uses of MOBILE_SAFE_BROWSING
+          'MOBILE_SAFE_BROWSING',
+          'SAFE_BROWSING_SERVICE',
+        ],
+      }],
     ],  # conditions for 'target_defaults'
     'target_conditions': [
       ['<(use_libpci)==1', {
@@ -3032,8 +3035,8 @@
       ['<(use_glib)==1 and >(nacl_untrusted_build)==0', {
         'defines': ['USE_GLIB=1'],
       }],
-      ['<(use_nss)==1 and >(nacl_untrusted_build)==0', {
-        'defines': ['USE_NSS=1'],
+      ['<(use_nss_certs)==1 and >(nacl_untrusted_build)==0', {
+        'defines': ['USE_NSS_CERTS=1'],
       }],
       ['<(chromeos)==1 and >(nacl_untrusted_build)==0', {
         'defines': ['OS_CHROMEOS=1'],
@@ -3603,8 +3606,6 @@
           '-pthread',
           '-fno-strict-aliasing',  # See http://crbug.com/32204
           '-Wall',
-          # TODO(evan): turn this back on once all the builds work.
-          # '-Wextra',
           # Don't warn about unused function params.  We use those everywhere.
           '-Wno-unused-parameter',
           # Don't warn about the "struct foo f = {0};" initialization pattern.
@@ -3676,6 +3677,12 @@
                   '-fomit-frame-pointer',
                 ],
               }],
+              ['OS!="android"', {
+                'defines': [
+                  '_LARGEFILE_SOURCE',
+                  '_LARGEFILE64_SOURCE',
+                ],
+              }],
               ['OS=="linux" and target_arch=="ia32"', {
                 'ldflags': [
                   '-Wl,--no-as-needed',
@@ -4025,6 +4032,8 @@
                           '-no-integrated-as',
                           '-B<(android_toolchain)',  # Else /usr/bin/as gets picked up.
                         ],
+                      }],
+                      ['clang==1 and linux_use_bundled_gold==0', {
                         'ldflags': [
                           # Let clang find the ld.gold in the NDK.
                           '--gcc-toolchain=<(android_toolchain)/..',
@@ -4076,10 +4085,6 @@
                     'cflags!': [
                        '-fstack-protector',  # stack protector is always enabled on arm64.
                     ],
-                  }],
-                  # TODO: Remove webview test once webview fully compiles from
-                  # Chromium. crbug.com/440793
-                  ['OS=="android" and android_webview_build==0', {
                     'ldflags': [
                       '-fuse-ld=gold',
                     ],
@@ -4092,38 +4097,74 @@
             'target_conditions': [
               ['_toolset=="target"', {
                 'conditions': [
-                  ['android_webview_build==0', {
+                  ['mips_arch_variant=="r6"', {
                     'conditions': [
-                      ['mips_arch_variant=="r6"', {
-                        'cflags': ['-mips32r6', '-Wa,-mips32r6'],
-                        'conditions': [
-                          ['OS=="android"', {
-                            'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
-                          }],
-                        ],
+                      ['clang==1', {
+                        'cflags': [ '-target mipsel-linux-gnu', '-march=mips32r6', ],
+                        'ldflags': [ '-target mipsel-linux-gnu', ],
+                      }, { # clang==0
+                        'cflags': ['-mips32r6', '-Wa,-mips32r6', ],
                       }],
-                      ['mips_arch_variant=="r2"', {
-                        'cflags': ['-mips32r2', '-Wa,-mips32r2'],
-                        'conditions': [
-                          ['mips_float_abi=="hard" and mips_fpu_mode!=""', {
-                            'cflags': ['-m<(mips_fpu_mode)'],
-                          }],
-                        ],
+                      ['clang==0 and OS=="android"', {
+                        'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
                       }],
-                      ['mips_arch_variant=="r1"', {
-                        'cflags': ['-mips32', '-Wa,-mips32'],
-                      }],
-                      ['mips_dsp_rev==1', {
-                        'cflags': ['-mdsp'],
-                      }],
-                      ['mips_dsp_rev==2', {
-                        'cflags': ['-mdspr2'],
-                      }],
-                    ],
-                    'cflags': [
-                      '-m<(mips_float_abi)-float'
                     ],
                   }],
+                  ['mips_arch_variant=="r2"', {
+                    'conditions': [
+                      ['mips_float_abi=="hard" and mips_fpu_mode!=""', {
+                        'cflags': ['-m<(mips_fpu_mode)'],
+                      }],
+                      ['clang==1', {
+                         'conditions': [
+                          ['OS=="android"', {
+                            'cflags': [ '-target mipsel-linux-android', '-march=mipsel', '-mcpu=mips32r2'],
+                            'ldflags': [ '-target mipsel-linux-android', ],
+                          }],
+                         ],
+                      }, { # clang==0
+                        'cflags': ['-mips32r2', '-Wa,-mips32r2', ],
+                      }],
+                    ],
+                  }],
+                  ['mips_arch_variant=="r1"', {
+                    'conditions': [
+                      ['clang==1', {
+                        'conditions': [
+                          ['OS=="android"', {
+                            'cflags': [ '-target mipsel-linux-android', '-march=mipsel', '-mcpu=mips32'],
+                            'ldflags': [ '-target mipsel-linux-android', ],
+                          }],
+                        ],
+                      }, { # clang==0
+                        'cflags': ['-mips32', '-Wa,-mips32', ],
+                      }],
+                    ],
+                  }],
+                  ['clang==1', {
+                    'cflags!': [
+                      # Clang does not support the following options.
+                      '-finline-limit=64',
+                    ],
+                    'cflags': [
+                      # TODO(gordanac) Enable integrated-as.
+                      '-no-integrated-as',
+                      '-B<(android_toolchain)',  # Else /usr/bin/as gets picked up.
+                    ],
+                    'ldflags': [
+                      # Let clang find the ld in the NDK.
+                      '--gcc-toolchain=<(android_toolchain)/..',
+                    ],
+                  }],
+                  ['mips_dsp_rev==1', {
+                    'cflags': ['-mdsp'],
+                  }],
+                  ['mips_dsp_rev==2', {
+                    'cflags': ['-mdspr2'],
+                  }],
+                ],
+                'cflags': [
+                  '-m<(mips_float_abi)-float'
                 ],
                 'ldflags': [
                   '-Wl,--no-keep-memory'
@@ -4138,17 +4179,13 @@
             'target_conditions': [
               ['_toolset=="target"', {
                 'conditions': [
-                  ['android_webview_build==0', {
-                    'conditions': [
-                      ['mips_arch_variant=="r6"', {
-                        'cflags': ['-mips64r6', '-Wa,-mips64r6'],
-                        'ldflags': ['-mips64r6'],
-                      }],
-                      ['mips_arch_variant=="r2"', {
-                        'cflags': ['-mips64r2', '-Wa,-mips64r2'],
-                        'ldflags': ['-mips64r2'],
-                      }],
-                    ],
+                  ['mips_arch_variant=="r6"', {
+                    'cflags': ['-mips64r6', '-Wa,-mips64r6'],
+                    'ldflags': ['-mips64r6'],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'cflags': ['-mips64r2', '-Wa,-mips64r2'],
+                    'ldflags': ['-mips64r2'],
                   }],
                 ],
                 'cflags_cc': [
@@ -4517,11 +4554,16 @@
               '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
             ],
           }],
-          ['linux_use_bundled_gold==1', {
+          ['linux_use_bundled_gold==1 and '
+           'not (clang==0 and (use_lto==1 or use_lto_o2==1))', {
             # Put our binutils, which contains gold in the search path. We pass
             # the path to gold to the compiler. gyp leaves unspecified what the
             # cwd is when running the compiler, so the normal gyp path-munging
             # fails us. This hack gets the right path.
+            #
+            # Disabled when using GCC LTO because GCC also uses the -B search
+            # path at link time to find "as", and our bundled "as" can only
+            # target x86.
             'ldflags': [
               '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
             ],
@@ -4668,8 +4710,13 @@
               '-fstack-protector',
               '-fno-short-enums',
               '-finline-limit=64',
-              '-Wa,--noexecstack',
               '<@(release_extra_cflags)',
+              '--sysroot=<(android_ndk_sysroot)',
+              # NOTE: The stlport header include paths below are specified in
+              # cflags rather than include_dirs because they need to come
+              # after include_dirs.
+              # The include ordering here is important; change with caution.
+              '-isystem<(android_stlport_include)',
             ],
             'defines': [
               'ANDROID',
@@ -4677,15 +4724,43 @@
               'USE_STLPORT=1',
               '_STLP_USE_PTR_SPECIALIZATIONS=1',
               'CHROME_BUILD_ID="<(chrome_build_id)"',
+              # The NDK has these things, but doesn't define the constants
+              # to say that it does. Define them here instead.
+              'HAVE_SYS_UIO_H',
             ],
             'ldflags!': [
               '-pthread',  # Not supported by Android toolchain.
             ],
             'ldflags': [
               '-Wl,--no-undefined',
+              '--sysroot=<(android_ndk_sysroot)',
+              '-nostdlib',
+              '-L<(android_stlport_libs_dir)',
+              # Don't allow visible symbols from libgcc or stlport to be
+              # re-exported.
+              '-Wl,--exclude-libs=libgcc.a',
+              '-Wl,--exclude-libs=libstlport_static.a',
+              # Don't allow visible symbols from libraries that contain
+              # assembly code with symbols that aren't hidden properly.
+              # http://crbug.com/448386
+              '-Wl,--exclude-libs=libcommon_audio.a',
+              '-Wl,--exclude-libs=libcommon_audio_neon.a',
+              '-Wl,--exclude-libs=libcommon_audio_sse2.a',
+              '-Wl,--exclude-libs=libiSACFix.a',
+              '-Wl,--exclude-libs=libisac_neon.a',
+              '-Wl,--exclude-libs=libopus.a',
+              '-Wl,--exclude-libs=libvpx.a',
+            ],
+            'libraries': [
+              '-l<(android_stlport_library)',
+              # Manually link the libgcc.a that the cross compiler uses.
+              '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
+              '-lc',
+              '-ldl',
+              '-lm',
             ],
             'conditions': [
-              ['component=="static_library" and android_webview_build==0', {
+              ['component=="static_library"', {
                 'target_conditions': [
                   ['use_native_jni_exports==0', {
                     # Use a linker version script to strip JNI exports from
@@ -4741,112 +4816,12 @@
                   '-mllvm -asan-globals=0',
                 ],
               }],
-              ['android_webview_build==0', {
-                'defines': [
-                  # The NDK has these things, but doesn't define the constants
-                  # to say that it does. Define them here instead.
-                  'HAVE_SYS_UIO_H',
-                ],
-                'cflags': [
-                  '--sysroot=<(android_ndk_sysroot)',
-                ],
-                'ldflags': [
-                  '--sysroot=<(android_ndk_sysroot)',
-                  '-nostdlib',
-                  # Don't allow visible symbols from libgcc or stlport to be
-                  # re-exported.
-                  '-Wl,--exclude-libs=libgcc.a',
-                  '-Wl,--exclude-libs=libstlport_static.a',
-                  # Don't allow visible symbols from libraries that contain
-                  # assembly code with symbols that aren't hidden properly.
-                  # http://crbug.com/448386
-                  '-Wl,--exclude-libs=libcommon_audio.a',
-                  '-Wl,--exclude-libs=libcommon_audio_neon.a',
-                  '-Wl,--exclude-libs=libcommon_audio_sse2.a',
-                  '-Wl,--exclude-libs=libiSACFix.a',
-                  '-Wl,--exclude-libs=libisac_neon.a',
-                  '-Wl,--exclude-libs=libopus.a',
-                  '-Wl,--exclude-libs=libvpx.a',
-                ],
-                'libraries': [
-                  '-l<(android_stlport_library)',
-                  # Manually link the libgcc.a that the cross compiler uses.
-                  '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
-                  '-lc',
-                  '-ldl',
-                  '-lm',
-                ],
-              }],
-              ['android_webview_build==1', {
-                'cflags': [
-                  # Android predefines this as 1; undefine it here so Chromium
-                  # can redefine it later to be 2 for chromium code and unset
-                  # for third party code. This works because cflags are added
-                  # before defines.
-                  '-U_FORTIFY_SOURCE',
-                  # Disable any additional warnings enabled by the Android build system but which
-                  # chromium does not build cleanly with (when treating warning as errors).
-                  # Things that are part of -Wextra:
-                  '-Wno-extra', # Enabled by -Wextra, but no specific flag
-                  '-Wno-ignored-qualifiers',
-                  '-Wno-type-limits',
-                  '-Wno-unused-but-set-variable',
-                ],
-                'cflags_cc': [
-                  # Other things unrelated to -Wextra:
-                  '-Wno-non-virtual-dtor',
-                  '-Wno-sign-promo',
-                ],
-                'libraries': [
-                  '-ldl',
-                ],
-              }],
-              ['android_webview_build==1', {
-                'target_conditions': [
-                  ['chromium_code==0', {
-                    'cflags': [
-                      # There is a class of warning which:
-                      #  1) Android always enables and also treats as errors
-                      #  2) Chromium ignores in third party code
-                      # So we re-enable those warnings when building Android.
-                      '-Wno-address',
-                      '-Wno-format-security',
-                      '-Wno-return-type',
-                      '-Wno-sequence-point',
-                    ],
-                    'cflags_cc': [
-                      '-Wno-non-virtual-dtor',
-                    ],
-                  }],
-                ],
-              }],
               ['target_arch == "arm" and order_profiling==0', {
                 'ldflags': [
                   # Enable identical code folding to reduce size.
                   '-Wl,--icf=<(gold_icf_level)',
                 ],
               }],
-              # NOTE: The stlport header include paths below are specified in
-              # cflags rather than include_dirs because they need to come
-              # after include_dirs. Think of them like system headers, but
-              # don't use '-isystem' because the arm-linux-androideabi-4.4.3
-              # toolchain (circa Gingerbread) will exhibit strange errors.
-              # The include ordering here is important; change with caution.
-              ['android_webview_build==0', {
-                'cflags': [
-                  '-isystem<(android_stlport_include)',
-                ],
-                'ldflags': [
-                  '-L<(android_stlport_libs_dir)',
-                ],
-              }, { # else: android_webview_build!=0
-                'aosp_build_settings': {
-                  # Specify that we want to statically link stlport from the
-                  # NDK. This will provide all the include and library paths
-                  # automatically at build time, and link the right library.
-                  'LOCAL_NDK_STL_VARIANT': 'stlport_static',
-                },
-              }],
               ['target_arch=="ia32"', {
                 # The x86 toolchain currently has problems with stack-protector.
                 'cflags!': [
@@ -4885,19 +4860,13 @@
               ['_type=="shared_library" or _type=="loadable_module"', {
                 'ldflags': [
                   '-Wl,-shared,-Bsymbolic',
+                  # crtbegin_so.o should be the last item in ldflags.
+                  '<(android_ndk_lib)/crtbegin_so.o',
                 ],
-                'conditions': [
-                  ['android_webview_build==0', {
-                    'ldflags': [
-                      # crtbegin_so.o should be the last item in ldflags.
-                      '<(android_ndk_lib)/crtbegin_so.o',
-                    ],
-                    'libraries': [
-                      # crtend_so.o needs to be the last item in libraries.
-                      # Do not add any libraries after this!
-                      '<(android_ndk_lib)/crtend_so.o',
-                    ],
-                  }],
+                'libraries': [
+                  # crtend_so.o needs to be the last item in libraries.
+                  # Do not add any libraries after this!
+                  '<(android_ndk_lib)/crtend_so.o',
                 ],
               }],
             ],
@@ -5167,6 +5136,16 @@
             # specified or not.
             '-fno-strict-aliasing',  # See http://crbug.com/32204.
           ],
+          'conditions': [
+            ['branding=="Chrome" and buildtype=="Official"', {
+              'OTHER_CFLAGS': [
+                # The Google Chrome Framework dSYM generated by dsymutil has
+                # grown larger than 4GB, which dsymutil can't handle. Reduce
+                # the amount of debug symbols.
+                '-gline-tables-only',  # See http://crbug.com/479841
+              ]
+            }],
+          ],
         },
         'target_conditions': [
           ['_type=="executable"', {
@@ -5546,6 +5525,11 @@
           4512, # Assignment operator could not be generated
           4610, # Object can never be instantiated
           4996, # 'X': was declared deprecated (for GetVersionEx).
+
+          # These are variable shadowing warnings that are new in VS2015. We
+          # should work through these at some point -- they may be removed from
+          # the RTM release in the /W4 set.
+          4456, 4457, 4458, 4459,
         ],
         'msvs_settings': {
           'VCCLCompilerTool': {
@@ -5681,6 +5665,13 @@
                 ],
               },
             }],
+            ['clang==1 and clang_use_chrome_plugins==1', {
+              'VCCLCompilerTool': {
+                'AdditionalOptions': [
+                  '<@(clang_chrome_plugins_flags)',
+                ],
+              },
+            }],
           ],
         },
       },
@@ -5770,6 +5761,19 @@
                     }],
                   ],
                 }],
+                ['sanitizer_coverage!=0', {
+                  # TODO(asan/win): Move this down into the general
+                  # win-target_defaults section once the 64-bit asan runtime
+                  # exists.  See crbug.com/345874.
+                  'VCCLCompilerTool': {
+                    'AdditionalOptions': [
+                      '-fsanitize-coverage=<(sanitizer_coverage)',
+                    ],
+                    'defines': [
+                      'SANITIZER_COVERAGE',
+                    ],
+                  },
+                }],
               ],
             },
           },
@@ -5813,45 +5817,6 @@
         ],
       },
     }],
-    # In the android webview build, force host targets to be compiled with clang
-    # as the hermetic host gcc is very old on some platforms. This is already
-    # the default on the current development version of AOSP but we force it
-    # here in case we need to compile against an older release version. We also
-    # explicitly set it to false for target binaries to avoid causing problems
-    # for the work to enable clang by default in AOSP. We also force the use of
-    # libstdc++ on host as peculiarities of the android gyp backend mean that
-    # using libc++ doesn't work, and Chromium doesn't yet require a more modern
-    # C++ library.
-    ['android_webview_build==1', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="host"', {
-            'aosp_build_settings': {
-              'LOCAL_CLANG': 'true',
-              'LOCAL_CXX_STL': 'libstdc++',
-            },
-          }, {  # else: _toolset != "host"
-            'aosp_build_settings': {
-              'LOCAL_CLANG': 'false',
-            },
-          }],
-        ],
-      },
-    }],
-    # We need a special case to handle the android webview build on mac because
-    # the host gcc there doesn't accept this flag, but the target gcc may
-    # require it.
-    ['gcc_version>=48 and android_webview_build==1 and host_os=="mac"', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="host"', {
-            'cflags!': [
-              '-Wno-unused-local-typedefs',
-            ],
-          }],
-        ],
-      },
-    }],
     ['clang==1 and ((OS!="mac" and OS!="ios") or clang_xcode==0) '
         'and OS!="win"', {
       'make_global_settings': [
@@ -5921,6 +5886,17 @@
             'cflags': [
               '-flto',
             ],
+            'xcode_settings': {
+              'LLVM_LTO': 'YES',
+            },
+          }],
+          # Work-around for http://openradar.appspot.com/20356002
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings': {
+              'OTHER_LDFLAGS': [
+                '-Wl,-all_load',
+              ],
+            },
           }],
         ],
       },
@@ -5947,6 +5923,25 @@
         ],
       },
     }],
+    # Apply a lower LTO optimization level in non-official builds.
+    ['use_lto==1 and clang==1 and buildtype!="Official"', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'ldflags': [
+              '-Wl,--plugin-opt,O1',
+            ],
+          }],
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings':  {
+              'OTHER_LDFLAGS': [
+                '-Wl,-mllvm,-O1',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
     ['use_lto==1 and clang==1 and (target_arch=="ia32" or target_arch=="x64")', {
       'target_defaults': {
         'target_conditions': [
@@ -6030,6 +6025,74 @@
         ],
       },
     }],
+    ['cfi_derived_cast==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize=cfi-derived-cast',
+            ],
+            'ldflags': [
+              '-fsanitize=cfi-derived-cast',
+            ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-fsanitize=cfi-derived-cast',
+              ],
+            },
+          }],
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings':  {
+              'OTHER_LDFLAGS': [
+                '-fsanitize=cfi-derived-cast',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
+    ['cfi_unrelated_cast==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize=cfi-unrelated-cast',
+            ],
+            'ldflags': [
+              '-fsanitize=cfi-unrelated-cast',
+            ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-fsanitize=cfi-unrelated-cast',
+              ],
+            },
+          }],
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings':  {
+              'OTHER_LDFLAGS': [
+                '-fsanitize=cfi-unrelated-cast',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
+    ['cfi_vptr==1 or cfi_derived_cast==1 or cfi_unrelated_cast==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize-blacklist=<(cfi_blacklist)',
+            ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-fsanitize-blacklist=<(cfi_blacklist)',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
   ],
   'xcode_settings': {
     # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 15441a9..22cb45a 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -27,6 +27,9 @@
 
   # Set to true to enable dcheck in Release builds.
   dcheck_always_on = false
+
+  # Set to true to compile with the OpenGL ES 2.0 conformance tests.
+  internal_gles2_conform_tests = false
 }
 
 # TODO(brettw) Most of these should be removed. Instead of global feature
@@ -119,14 +122,12 @@
   }
   if (use_openssl) {
     defines += [ "USE_OPENSSL=1" ]
-    if (use_openssl_certs) {
-      defines += [ "USE_OPENSSL_CERTS=1" ]
-    }
-  } else if (use_nss_certs) {
-    # USE_NSS really means "use nss for certificate validation and storage"
-    # (like USE_OPENSSL_CERTS) and not "we're linking to NSS." It might be nice
-    # to rename this but we're hoping to transition away from NSS.
-    defines += [ "USE_NSS=1" ]
+  }
+  if (use_openssl_certs) {
+    defines += [ "USE_OPENSSL_CERTS=1" ]
+  }
+  if (use_nss_certs) {
+    defines += [ "USE_NSS_CERTS=1" ]
   }
   if (use_ozone) {
     defines += [ "USE_OZONE=1" ]
@@ -225,6 +226,18 @@
   if (enable_pre_sync_backup) {
     defines += [ "ENABLE_PRE_SYNC_BACKUP" ]
   }
+  if (enable_video_hole) {
+    defines += [ "VIDEO_HOLE=1" ]
+  }
+  if (safe_browsing_mode == 1) {
+    defines += [ "FULL_SAFE_BROWSING" ]
+    defines += [ "SAFE_BROWSING_CSD" ]
+    defines += [ "SAFE_BROWSING_DB_LOCAL" ]
+    defines += [ "SAFE_BROWSING_SERVICE" ]
+  } else if (safe_browsing_mode == 2) {
+    defines += [ "MOBILE_SAFE_BROWSING" ]
+    defines += [ "SAFE_BROWSING_SERVICE" ]
+  }
 }
 
 # Debug/release ----------------------------------------------------------------
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 8e30c4a..455ec0d 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -17,27 +17,12 @@
 # Use "is_*" names for intrinsic platform descriptions and build modes, and
 # "use_*" names for optional features libraries, and configurations.
 
-# TODO(dpranke): The os and cpu_arch variables exist for backwards
-# compatibility and should be deleted once all of the build files and
-# bots have been updated to use current_cpu/target_cpu and
-# current_os/target_os instead.
-
 if (target_os == "") {
-  if (defined(os)) {
-    # If os is defined, it was set in an args file and needs to be
-    # used for backwards-compatibility.
-    target_os = os
-  } else {
-    target_os = host_os
-  }
+  target_os = host_os
 }
 
 if (target_cpu == "") {
-  if (defined(cpu_arch)) {
-    # If cpu_arch is defined, it was set in an args file and needs to be
-    # used for backwards-compatibility.
-    target_cpu = cpu_arch
-  } else if (target_os == "android") {
+  if (target_os == "android") {
     # If we're building for Android, we should assume that we want to
     # build for ARM by default, not the host_cpu (which is likely x64).
     # This allows us to not have to specify both target_os and target_cpu
@@ -56,13 +41,6 @@
 }
 
 declare_args() {
-  # TODO(dpranke): These values are here for backwards compatibility and
-  # should be deleted when all of the builders and configs have been updated.
-  cpu_arch = target_cpu
-  os = target_os
-  build_cpu_arch = host_cpu
-  build_os = host_os
-
   # How many symbols to include in the build. This affects the performance of
   # the build since the symbols are large and dealing with them is slow.
   #   2 means regular build with symbols.
@@ -115,10 +93,6 @@
   }
 }
 
-# TODO(dpranke): Remove these asserts when os and cpu_arch are removed.
-assert(current_cpu == cpu_arch)
-assert(current_os == os)
-
 # =============================================================================
 # OS DEFINITIONS
 # =============================================================================
@@ -539,8 +513,8 @@
 } else if (is_nacl) {
   # TODO(GYP): This will need to change when we get NaCl working
   # on multiple platforms, but this whole block of code (how we define
-  # host_toolchain) needs to be reworked regardless to key off of build_os
-  # and build_cpu_arch rather than the is_* variables.
+  # host_toolchain) needs to be reworked regardless to key off of host_os
+  # and host_cpu rather than the is_* variables.
   host_toolchain = "//build/toolchain/linux:clang_x64"
 }
 
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 5a27e78..77ee311 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -30,11 +30,6 @@
     android_sdk_version = default_android_sdk_version
     android_sdk_build_tools_version = default_android_sdk_build_tools_version
 
-    # This is set when building the Android WebView inside the Android build
-    # system, using the 'android' gyp backend. The WebView code is still built
-    # when this is unset, but builds using the normal chromium build system.
-    is_android_webview_build = false
-
     android_default_keystore_path =
         "//build/android/ant/chromium-debug.keystore"
     android_default_keystore_name = "chromiumdebugkey"
@@ -44,6 +39,9 @@
     # identifying various build artifacts corresponding to a particular build of
     # chrome (e.g. where to find archived symbols).
     android_chrome_build_id = "\"\""
+
+    # Set to true to run findbugs on JAR targets.
+    run_findbugs = false
   }
 
   # Host stuff -----------------------------------------------------------------
@@ -189,8 +187,4 @@
   } else {
     assert(false, "Unknown Android ABI: " + current_cpu)
   }
-} else {
-  if (!defined(is_android_webview_build)) {
-    is_android_webview_build = false
-  }
 }
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 8920e95..ab773ea 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -62,6 +62,44 @@
   }
 }
 
+template("findbugs") {
+  jar_path = invoker.jar_path
+
+  build_config = invoker.build_config
+
+  action(target_name) {
+    script = "//build/android/findbugs_diff.py"
+    depfile = "$target_gen_dir/$target_name.d"
+    result_path = "$target_gen_dir/$target_name/result.xml"
+    exclusions_file = "//build/android/findbugs_filter/findbugs_exclude.xml"
+
+    rebased_build_config = rebase_path(build_config, root_build_dir)
+
+    inputs = [
+      "//build/android/pylib/utils/findbugs.py",
+      exclusions_file,
+      jar_path,
+    ]
+
+    outputs = [
+      depfile,
+      result_path,
+    ]
+
+    args = [
+      "--depfile",
+      rebase_path(depfile, root_build_dir),
+      "--exclude",
+      rebase_path(exclusions_file, root_build_dir),
+      "--auxclasspath-gyp",
+      "@FileArg($rebased_build_config:javac:classpath)",
+      "--output-file",
+      rebase_path(result_path, root_build_dir),
+      rebase_path(jar_path, root_build_dir),
+    ]
+  }
+}
+
 template("dex") {
   set_sources_assignment_filter([])
   if (defined(invoker.testonly)) {
@@ -188,7 +226,8 @@
       dep_name = get_label_info(d, "name")
       possible_deps_configs += [ "$dep_gen_dir/$dep_name.build_config" ]
     }
-    rebase_possible_deps_configs = rebase_path(possible_deps_configs)
+    rebase_possible_deps_configs =
+        rebase_path(possible_deps_configs, root_build_dir)
 
     outputs = [
       depfile,
@@ -250,6 +289,19 @@
       args += [ "--bypass-platform-checks" ]
     }
 
+    if (defined(invoker.apk_under_test)) {
+      deps += [ invoker.apk_under_test ]
+      apk_under_test_gen_dir =
+          get_label_info(invoker.apk_under_test, "target_gen_dir")
+      apk_under_test_name = get_label_info(invoker.apk_under_test, "name")
+      apk_under_test_config =
+          "$apk_under_test_gen_dir/$apk_under_test_name.build_config"
+      args += [
+        "--tested-apk-config",
+        rebase_path(apk_under_test_config, root_build_dir),
+      ]
+    }
+
     if (is_android_resources || is_apk) {
       assert(defined(invoker.resources_zip))
       args += [
@@ -262,6 +314,8 @@
           "--android-manifest",
           rebase_path(invoker.android_manifest, root_build_dir),
         ]
+      } else {
+        assert(!is_apk, "apk build configs require an android_manifest")
       }
       if (defined(invoker.custom_package)) {
         args += [
@@ -914,6 +968,14 @@
         jar_path = _jar_path
         java_files = _java_files
       }
+
+      if (run_findbugs) {
+        _final_datadeps += [ ":${_template_name}__findbugs" ]
+        findbugs("${_template_name}__findbugs") {
+          build_config = _build_config
+          jar_path = _jar_path
+        }
+      }
     }
 
     _final_deps += [ ":${_template_name}__dex" ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index a056997..39b2f39 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -49,9 +49,6 @@
     script = "//base/android/jni_generator/jni_generator.py"
     depfile = "$target_gen_dir/$target_name.{{source_name_part}}.d"
     sources = invoker.sources
-    inputs = [
-      jni_generator_include,
-    ]
     outputs = [
       depfile,
       "${jni_output_dir}/{{source_name_part}}_jni.h",
@@ -66,7 +63,7 @@
       "--output_dir",
       rebase_path(jni_output_dir, root_build_dir),
       "--includes",
-      rebase_path(jni_generator_include, "//"),
+      rebase_path(jni_generator_include, jni_output_dir),
       "--native_exports_optional",
     ]
     if (defined(invoker.jni_generator_jarjar_file)) {
@@ -166,7 +163,6 @@
       script = "//base/android/jni_generator/jni_generator.py"
       sources = [
         jar_file,
-        jni_generator_include,
       ]
       outputs = [
         depfile,
@@ -185,7 +181,7 @@
         "--output_dir",
         rebase_path(jni_output_dir, root_build_dir),
         "--includes",
-        rebase_path(jni_generator_include, root_build_dir),
+        rebase_path(jni_generator_include, jni_output_dir),
         "--native_exports_optional",
       ]
     }
@@ -733,7 +729,7 @@
 #   datadeps, testonly
 #
 # Example
-#   java_library("foo") {
+#   java_binary("foo") {
 #     java_files = [ "org/chromium/foo/FooMain.java" ]
 #     deps = [ ":bar_java" ]
 #     main_class = "org.chromium.foo.FooMain"
@@ -776,7 +772,65 @@
   }
 }
 
-# Declare an java library target
+# Declare a Junit executable target
+#
+# This target creates an executable from java code for running as a junit test
+# suite. The executable will be in the output folder's /bin/ directory.
+#
+# Variables
+#   deps: Specifies the dependencies of this target. Java targets in this list
+#     will be included in the executable (and the javac classpath).
+#
+#   java_files: List of .java files included in this library.
+#   srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
+#     will be added to java_files and be included in this library.
+#   srcjars: List of srcjars to be included in this library, together with the
+#     ones obtained from srcjar_deps.
+#
+#   chromium_code: If true, extra analysis warning/errors will be enabled.
+#
+# Example
+#   junit_binary("foo") {
+#     java_files = [ "org/chromium/foo/FooTest.java" ]
+#     deps = [ ":bar_java" ]
+#   }
+template("junit_binary") {
+  set_sources_assignment_filter([])
+
+  java_binary(target_name) {
+    bypass_platform_checks = true
+    main_class = "org.chromium.testing.local.JunitTestMain"
+    testonly = true
+
+    if (defined(invoker.DEPRECATED_java_in_dir)) {
+      DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir
+    }
+    if (defined(invoker.chromium_code)) {
+      chromium_code = invoker.chromium_code
+    }
+    deps = [
+      "//testing/android/junit:junit_test_support",
+      "//third_party/junit",
+      "//third_party/mockito:mockito_java",
+      "//third_party/robolectric:robolectric_java",
+      "//third_party/robolectric:android-all-4.3_r2-robolectric-0",
+    ]
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
+    if (defined(invoker.java_files)) {
+      java_files = invoker.java_files
+    }
+    if (defined(invoker.srcjar_deps)) {
+      srcjar_deps = invoker.srcjar_deps
+    }
+    if (defined(invoker.srcjars)) {
+      srcjars = invoker.srcjars
+    }
+  }
+}
+
+# Declare a java library target
 #
 # Variables
 #   deps: Specifies the dependencies of this target. Java targets in this list
@@ -874,7 +928,7 @@
   }
 }
 
-# Declare an java library target for a prebuilt jar
+# Declare a java library target for a prebuilt jar
 #
 # Variables
 #   deps: Specifies the dependencies of this target. Java targets in this list
@@ -1107,6 +1161,8 @@
 #   native_libs: List paths of native libraries to include in this apk. If these
 #     libraries depend on other shared_library targets, those dependencies will
 #     also be included in the apk.
+#   apk_under_test: For an instrumentation test apk, this is the target of the
+#     tested apk.
 #   testonly: Marks this target as "test-only".
 #
 #   DEPRECATED_java_in_dir: Directory containing java files. All .java files in
@@ -1138,9 +1194,10 @@
   }
 
   assert(defined(invoker.final_apk_path) || defined(invoker.apk_name))
+  assert(defined(invoker.android_manifest))
   gen_dir = "$target_gen_dir/$target_name"
   base_path = "$gen_dir/$target_name"
-  _build_config = "$base_path.build_config"
+  _build_config = "$target_gen_dir/$target_name.build_config"
   resources_zip_path = "$base_path.resources.zip"
   all_resources_zip_path = "$base_path.resources.all.zip"
   jar_path = "$base_path.jar"
@@ -1223,6 +1280,7 @@
     }
   }
 
+  _android_manifest = invoker.android_manifest
   _rebased_build_config = rebase_path(_build_config, root_build_dir)
 
   write_build_config("${_template_name}__build_config") {
@@ -1230,11 +1288,16 @@
     dex_path = final_dex_path
     resources_zip = resources_zip_path
     build_config = _build_config
+    android_manifest = _android_manifest
 
     if (defined(invoker.deps)) {
       deps = invoker.deps
     }
 
+    if (defined(invoker.apk_under_test)) {
+      apk_under_test = invoker.apk_under_test
+    }
+
     native_libs = _native_libs
   }
 
@@ -1243,7 +1306,7 @@
   final_deps += [ ":${_template_name}__process_resources" ]
   process_resources("${_template_name}__process_resources") {
     srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
-    android_manifest = invoker.android_manifest
+    android_manifest = _android_manifest
     resource_dirs = [ "//build/android/ant/empty/res" ]
     zip_path = resources_zip_path
     generate_constant_ids = true
@@ -1289,7 +1352,7 @@
     supports_android = true
     requires_android = true
     override_build_config = _build_config
-    android_manifest = invoker.android_manifest
+    android_manifest = _android_manifest
     chromium_code = true
     if (defined(invoker.java_files)) {
       java_files = invoker.java_files
@@ -1397,7 +1460,7 @@
   final_deps += [ ":${_template_name}__create" ]
   create_apk("${_template_name}__create") {
     apk_path = _final_apk_path
-    android_manifest = invoker.android_manifest
+    android_manifest = _android_manifest
     resources_zip = all_resources_zip_path
     dex_path = final_dex_path
     load_library_from_apk = _load_library_from_apk
@@ -1490,13 +1553,12 @@
   }
 
   android_apk(target_name) {
-    _apk_name = apk_name
-    final_apk_path = "$root_build_dir/${_apk_name}_apk/${_apk_name}-debug.apk"
+    final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk"
     java_files = [
-      "//testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java",
-      "//testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java",
+      "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java",
+      "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java",
     ]
-    android_manifest = "//testing/android/java/AndroidManifest.xml"
+    android_manifest = "//testing/android/native_test/java/AndroidManifest.xml"
     native_libs = [ unittests_binary ]
     if (defined(invoker.asset_location)) {
       asset_location = invoker.asset_location
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
index 39fe251..3d96500 100644
--- a/build/config/clang/BUILD.gn
+++ b/build/config/clang/BUILD.gn
@@ -6,20 +6,29 @@
 
 config("find_bad_constructs") {
   if (clang_use_chrome_plugins) {
-    cflags = [
-      "-Xclang",
-      "-load",
-      "-Xclang",
-    ]
+    cflags = []
+
+    # On Windows, the plugin is built directly into clang, so there's
+    # no need to load it dynamically.
 
     if (is_mac || is_ios) {
-      cflags += [ rebase_path(
-              "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib",
-              root_build_dir) ]
+      cflags += [
+        "-Xclang",
+        "-load",
+        "-Xclang",
+        rebase_path(
+            "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib",
+            root_build_dir),
+      ]
     } else if (is_linux) {
-      cflags += [ rebase_path(
-              "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
-              root_build_dir) ]
+      cflags += [
+        "-Xclang",
+        "-load",
+        "-Xclang",
+        rebase_path(
+            "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+            root_build_dir),
+      ]
     }
 
     cflags += [
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 42dc584..c217154 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -165,7 +165,7 @@
     defines += [ "CR_CLANG_REVISION=" +
                  exec_script("//tools/clang/scripts/posix-print-revision.py",
                              [],
-                             "value") ]
+                             "trim string") ]
   }
 
   # Mac-specific compiler flags setup.
@@ -194,16 +194,11 @@
     cflags_objcc = [ "-fobjc-call-cxx-cdtors" ]
 
     cflags_c += [ "-std=c99" ]
-    cflags_cc += [ "-std=gnu++11" ]
 
     ldflags += common_mac_flags
   } else if (is_posix) {
     # Non-Mac Posix compiler flags setup.
     # -----------------------------------
-    if (gcc_version >= 48) {
-      cflags_cc += [ "-std=gnu++11" ]
-    }
-
     if (enable_profiling && !is_debug) {
       # The GYP build spams this define into every compilation unit, as we do
       # here, but it only appears to be used in base and a couple other places.
@@ -246,98 +241,93 @@
         ]
       }
     } else if (current_cpu == "arm") {
-      # Don't set the compiler flags for the WebView build. These will come
-      # from the Android build system.
-      if (!is_android_webview_build) {
+      cflags += [
+        "-march=$arm_arch",
+        "-mfloat-abi=$arm_float_abi",
+      ]
+      if (arm_tune != "") {
+        cflags += [ "-mtune=$arm_tune" ]
+      }
+      if (arm_use_thumb) {
+        cflags += [ "-mthumb" ]
+        if (is_android && !is_clang) {  # Clang doesn't support this option.
+          cflags += [ "-mthumb-interwork" ]
+        }
+      }
+      if (!is_clang) {
+        # Clang doesn't support these flags.
         cflags += [
-          "-march=$arm_arch",
-          "-mfloat-abi=$arm_float_abi",
-        ]
-        if (arm_tune != "") {
-          cflags += [ "-mtune=$arm_tune" ]
-        }
-        if (arm_use_thumb) {
-          cflags += [ "-mthumb" ]
-          if (is_android && !is_clang) {  # Clang doesn't support this option.
-            cflags += [ "-mthumb-interwork" ]
-          }
-        }
-        if (!is_clang) {
-          # Clang doesn't support these flags.
-          cflags += [
-            # The tree-sra optimization (scalar replacement for
-            # aggregates enabling subsequent optimizations) leads to
-            # invalid code generation when using the Android NDK's
-            # compiler (r5-r7). This can be verified using
-            # webkit_unit_tests' WTF.Checked_int8_t test.
-            "-fno-tree-sra",
+          # The tree-sra optimization (scalar replacement for
+          # aggregates enabling subsequent optimizations) leads to
+          # invalid code generation when using the Android NDK's
+          # compiler (r5-r7). This can be verified using
+          # webkit_unit_tests' WTF.Checked_int8_t test.
+          "-fno-tree-sra",
 
-            # The following option is disabled to improve binary
-            # size and performance in gcc 4.9.
-            "-fno-caller-saves",
-          ]
-        }
+          # The following option is disabled to improve binary
+          # size and performance in gcc 4.9.
+          "-fno-caller-saves",
+        ]
       }
     } else if (current_cpu == "mipsel") {
-      # Don't set the compiler flags for the WebView build. These will come
-      # from the Android build system.
-      if (!is_android_webview_build) {
-        if (mips_arch_variant == "r6") {
-          cflags += [
+      if (mips_arch_variant == "r6") {
+        cflags += [
+          "-mips32r6",
+          "-Wa,-mips32r6",
+        ]
+        if (is_android) {
+          ldflags += [
             "-mips32r6",
-            "-Wa,-mips32r6",
-          ]
-          if (is_android) {
-            ldflags += [
-              "-mips32r6",
-              "-Wl,-melf32ltsmip",
-            ]
-          }
-        } else if (mips_arch_variant == "r2") {
-          cflags += [
-            "-mips32r2",
-            "-Wa,-mips32r2",
-          ]
-          if (mips_float_abi == "hard" && mips_fpu_mode != "") {
-            cflags += [ "-m$mips_fpu_mode" ]
-          }
-        } else if (mips_arch_variant == "r1") {
-          cflags += [
-            "-mips32",
-            "-Wa,-mips32",
+            "-Wl,-melf32ltsmip",
           ]
         }
-
-        if (mips_dsp_rev == 1) {
-          cflags += [ "-mdsp" ]
-        } else if (mips_dsp_rev == 2) {
-          cflags += [ "-mdspr2" ]
+      } else if (mips_arch_variant == "r2") {
+        cflags += [
+          "-mips32r2",
+          "-Wa,-mips32r2",
+        ]
+        if (mips_float_abi == "hard" && mips_fpu_mode != "") {
+          cflags += [ "-m$mips_fpu_mode" ]
         }
-
-        cflags += [ "-m${mips_float_abi}-float" ]
+      } else if (mips_arch_variant == "r1") {
+        cflags += [
+          "-mips32",
+          "-Wa,-mips32",
+        ]
       }
+
+      if (mips_dsp_rev == 1) {
+        cflags += [ "-mdsp" ]
+      } else if (mips_dsp_rev == 2) {
+        cflags += [ "-mdspr2" ]
+      }
+
+      cflags += [ "-m${mips_float_abi}-float" ]
     } else if (current_cpu == "mips64el") {
-      # Don't set the compiler flags for the WebView build. These will come
-      # from the Android build system.
-      if (!is_android_webview_build) {
-        if (mips_arch_variant == "r6") {
-          cflags += [
-            "-mips64r6",
-            "-Wa,-mips64r6",
-          ]
-          ldflags += [ "-mips64r6" ]
-        } else if (mips_arch_variant == "r2") {
-          cflags += [
-            "-mips64r2",
-            "-Wa,-mips64r2",
-          ]
-          ldflags += [ "-mips64r2" ]
-        }
+      if (mips_arch_variant == "r6") {
+        cflags += [
+          "-mips64r6",
+          "-Wa,-mips64r6",
+        ]
+        ldflags += [ "-mips64r6" ]
+      } else if (mips_arch_variant == "r2") {
+        cflags += [
+          "-mips64r2",
+          "-Wa,-mips64r2",
+        ]
+        ldflags += [ "-mips64r2" ]
       }
     }
 
     defines += [ "_FILE_OFFSET_BITS=64" ]
 
+    if (!is_android) {
+      defines += [
+        "_LARGEFILE_SOURCE",
+        "_LARGEFILE64_SOURCE",
+      ]
+    }
+
     # Omit unwind support in official builds to save space. We can use breakpad
     # for these builds.
     if (is_chrome_branded && is_official_build) {
@@ -418,7 +408,18 @@
   # ------------------------------------
   if (is_clang) {
     cflags += [ "-fcolor-diagnostics" ]
+  }
+
+  # C++11 compiler flags setup.
+  # ---------------------------
+  if (is_linux || is_android || is_nacl) {
+    # gnu++11 instead of c++11 is needed because some code uses typeof() (a
+    # GNU extension).
+    # TODO(thakis): Eventually switch this to c++11 instead,
+    # http://crbug.com/427584
     cflags_cc += [ "-std=gnu++11" ]
+  } else if (!is_win) {
+    cflags_cc += [ "-std=c++11" ]
   }
 
   # Android-specific flags setup.
@@ -433,15 +434,6 @@
       # Clang doesn't support these flags.
       cflags += [ "-finline-limit=64" ]
     }
-    if (is_android_webview_build) {
-      # Android predefines this as 1; undefine it here so Chromium can redefine
-      # it later to be 2 for chromium code and unset for third party code. This
-      # works because cflags are added before defines.
-      # TODO(brettw) the above comment seems incorrect. We specify defines
-      # before cflags on our compiler command lines.
-      cflags += [ "-U_FORTIFY_SOURCE" ]
-    }
-
     if (is_asan) {
       # Android build relies on -Wl,--gc-sections removing unreachable code.
       # ASan instrumentation for globals inhibits this and results in a library
@@ -451,11 +443,10 @@
     }
 
     defines += [ "ANDROID" ]
-    if (!is_android_webview_build) {
-      # The NDK has these things, but doesn't define the constants
-      # to say that it does. Define them here instead.
-      defines += [ "HAVE_SYS_UIO_H" ]
-    }
+
+    # The NDK has these things, but doesn't define the constants
+    # to say that it does. Define them here instead.
+    defines += [ "HAVE_SYS_UIO_H" ]
 
     # Use gold for Android for most CPU architectures.
     if (current_cpu == "x86" || current_cpu == "x64" || current_cpu == "arm") {
@@ -500,7 +491,7 @@
 }
 
 config("compiler_arm_fpu") {
-  if (current_cpu == "arm" && !is_android_webview_build) {
+  if (current_cpu == "arm") {
     cflags = [ "-mfpu=$arm_fpu" ]
   }
 }
@@ -573,7 +564,7 @@
 
     # TODO(jdduke) Re-enable on mips after resolving linking
     # issues with libc++ (crbug.com/456380).
-    if (cpu_arch != "mipsel" && cpu_arch != "mips64el") {
+    if (current_cpu != "mipsel" && current_cpu != "mips64el") {
       ldflags += [ "-Wl,--warn-shared-textrel" ]
     }
     ldflags += [ "-nostdlib" ]
@@ -684,20 +675,6 @@
       "-Wno-deprecated",
     ]
   }
-
-  if (is_android_webview_build) {
-    # There is a class of warning which:
-    #  1) Android always enables and also treats as errors
-    #  2) Chromium ignores in third party code
-    # So we re-enable those warnings when building Android.
-    cflags += [
-      "-Wno-address",
-      "-Wno-format-security",
-      "-Wno-return-type",
-      "-Wno-sequence-point",
-    ]
-    cflags_cc += [ "-Wno-non-virtual-dtor" ]
-  }
 }
 
 # rtti ------------------------------------------------------------------------
@@ -983,7 +960,7 @@
 
     # TODO(jdduke) Re-enable on mips after resolving linking
     # issues with libc++ (crbug.com/456380).
-    if (cpu_arch != "mipsel" && cpu_arch != "mips64el") {
+    if (current_cpu != "mipsel" && current_cpu != "mips64el") {
       common_optimize_on_ldflags += [
         # Warn in case of text relocations.
         "-Wl,--warn-shared-textrel",
diff --git a/build/config/crypto.gni b/build/config/crypto.gni
index ee23569..7f090b7 100644
--- a/build/config/crypto.gni
+++ b/build/config/crypto.gni
@@ -14,10 +14,13 @@
   use_openssl = is_android || is_mac || is_nacl || is_win
 }
 
-# True when we're using OpenSSL for certificate verification and storage. We
-# only do this when we're using OpenSSL on desktop Linux systems. For other
-# systems (Mac/Win/Android) we use the system certificate features.
-use_openssl_certs = use_openssl && (is_linux || is_android)
+# True when we're using OpenSSL for representing certificates. When targeting
+# Android, the platform certificate library is used for certificate
+# verification. On other targets, this flag also enables OpenSSL for certificate
+# verification, but this configuration is unsupported.
+use_openssl_certs = is_android
 
-# Same meaning as use_openssl_certs but for NSS.
-use_nss_certs = !use_openssl && is_linux
+# True if NSS is used for certificate verification. Note that this is
+# independent from use_openssl. It is possible to use OpenSSL for the crypto
+# library, but NSS for the platform certificate library.
+use_nss_certs = is_linux
diff --git a/build/config/features.gni b/build/config/features.gni
index 783e32d..dd7b081 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -47,6 +47,9 @@
   # TODO(GYP) make mac and android work.
   enable_webrtc = !is_ios && !is_mac && !is_android
 
+  # Enables the Media Router.
+  enable_media_router = !is_ios && !is_android
+
   # Enables proprietary codecs and demuxers; e.g. H264, MOV, AAC, and MP3.
   proprietary_codecs = false
 
@@ -67,13 +70,20 @@
 
   enable_supervised_users = !is_ios
 
-  enable_autofill_dialog = !is_ios && !(is_android && is_android_webview_build)
+  enable_autofill_dialog = !is_ios
 
   enable_google_now = !is_ios && !is_android
 
   enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
 
   enable_remoting = !is_ios && !is_android
+
+  # Enable hole punching for the protected video.
+  enable_video_hole = is_android
+
+  # Enables browser side Content Decryption Modules. Required for embedders
+  # (e.g. Android and ChromeCast) that use a browser side CDM.
+  enable_browser_cdms = is_android
 }
 
 # Additional dependent variables -----------------------------------------------
@@ -96,8 +106,6 @@
 
 enable_pepper_cdms = enable_plugins && (is_linux || is_mac || is_win)
 
-enable_browser_cdms = is_android
-
 # Enable basic printing support and UI.
 enable_basic_printing = !is_chromeos
 
diff --git a/build/config/gcc/gcc_version.gni b/build/config/gcc/gcc_version.gni
index f5c1c1a..6741e45 100644
--- a/build/config/gcc/gcc_version.gni
+++ b/build/config/gcc/gcc_version.gni
@@ -3,12 +3,7 @@
 # found in the LICENSE file.
 
 if (is_android) {
-  import("//build/config/android/config.gni")
-  if (is_android_webview_build) {
-    gcc_version = 48
-  } else {
-    gcc_version = 49
-  }
+  gcc_version = 49
 } else if (current_toolchain == "//build/toolchain/cros:target" ||
            current_toolchain == "//build/toolchain/linux:mipsel") {
   gcc_version = exec_script("../../compiler_version.py",
diff --git a/build/config/linux/gtk/BUILD.gn b/build/config/linux/gtk/BUILD.gn
index 4968e2d..9c9c696 100644
--- a/build/config/linux/gtk/BUILD.gn
+++ b/build/config/linux/gtk/BUILD.gn
@@ -26,9 +26,12 @@
 group("gtk") {
   visibility = [
     "//chrome/browser/ui/libgtk2ui",
+    "//gpu/gles2_conform_support:gles2_conform_test_windowless",
     "//remoting/host",
+    "//remoting/host/it2me:remote_assistance_host",
+    "//remoting/host:remoting_me2me_host_static",
   ]
-  direct_dependent_configs = [ ":gtk_internal_config" ]
+  public_configs = [ ":gtk_internal_config" ]
 }
 
 # Depend on "gtkprint" to get this.
@@ -38,5 +41,5 @@
 
 group("gtkprint") {
   visibility = [ "//chrome/browser/ui/libgtk2ui" ]
-  direct_dependent_configs = [ ":gtkprint_internal_config" ]
+  public_configs = [ ":gtkprint_internal_config" ]
 }
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index 941c77a..057971d 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -15,22 +15,18 @@
   sysroot = target_sysroot
 } else if (is_android) {
   import("//build/config/android/config.gni")
-  if (!is_android_webview_build) {
-    if (current_cpu == "x86") {
-      sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir")
-    } else if (current_cpu == "arm") {
-      sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
-    } else if (current_cpu == "mipsel") {
-      sysroot = rebase_path("$android_ndk_root/$mips_android_sysroot_subdir")
-    } else if (current_cpu == "x64") {
-      sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
-    } else if (current_cpu == "arm64") {
-      sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
-    } else if (current_cpu == "mips64") {
-      sysroot = rebase_path("$android_ndk_root/$mips64_android_sysroot_subdir")
-    } else {
-      sysroot = ""
-    }
+  if (current_cpu == "x86") {
+    sysroot = rebase_path("$android_ndk_root/$x86_android_sysroot_subdir")
+  } else if (current_cpu == "arm") {
+    sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
+  } else if (current_cpu == "mipsel") {
+    sysroot = rebase_path("$android_ndk_root/$mips_android_sysroot_subdir")
+  } else if (current_cpu == "x64") {
+    sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
+  } else if (current_cpu == "arm64") {
+    sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
+  } else if (current_cpu == "mips64") {
+    sysroot = rebase_path("$android_ndk_root/$mips64_android_sysroot_subdir")
   } else {
     sysroot = ""
   }
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 4ca22f7..8b0910f 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -97,25 +97,36 @@
 
 # Subsystem --------------------------------------------------------------------
 
+# This is appended to the subsystem to specify a minimum version.
+if (current_cpu == "x64") {
+  # The number after the comma is the minimum required OS version.
+  # 5.02 = Windows Server 2003.
+  subsystem_version_suffix = ",5.02"
+} else {
+  # Don't specify a min version on x86.
+  subsystem_version_suffix = ""
+}
+
 config("console") {
-  ldflags = [ "/SUBSYSTEM:CONSOLE" ]
+  ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ]
 }
 config("windowed") {
-  ldflags = [ "/SUBSYSTEM:WINDOWS" ]
+  ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ]
 }
 
 # Incremental linking ----------------------------------------------------------
 
 incremental_linking_on_switch = [ "/INCREMENTAL" ]
 incremental_linking_off_switch = [ "/INCREMENTAL:NO" ]
+if (is_debug) {
+  default_incremental_linking_switch = incremental_linking_on_switch
+} else {
+  default_incremental_linking_switch = incremental_linking_off_switch
+}
 
 # Applies incremental linking or not depending on the current configuration.
 config("default_incremental_linking") {
-  if (is_debug) {
-    ldflags = incremental_linking_on_switch
-  } else {
-    ldflags = incremental_linking_off_switch
-  }
+  ldflags = default_incremental_linking_switch
 }
 
 # Explicitly on or off incremental linking
@@ -130,17 +141,13 @@
 # config should be applied to large modules to turn off incremental linking
 # when it won't work.
 config("default_large_module_incremental_linking") {
-  if (!is_debug) {
-    # Default is always off in release build.
-    ldflags = incremental_linking_off_switch
-  } else if ((symbol_level == 0 || symbol_level == 1) &&
-             (current_cpu == "x86" || !is_component_build)) {
-    # When full symbols are on, don't do incremental linking for large modules
-    # on 32-bit or in non-component mode as the toolchain fails due to the size
-    # of the .ilk files.
+  if (symbol_level > 0 && (current_cpu == "x86" || !is_component_build)) {
+    # When symbols are on, things get so large that the tools fail due to the
+    # size of the .ilk files.
     ldflags = incremental_linking_off_switch
   } else {
-    ldflags = incremental_linking_on_switch
+    # Otherwise just do the default incremental linking for this build type.
+    ldflags = default_incremental_linking_switch
   }
 }
 
diff --git a/build/escape_unicode.py b/build/escape_unicode.py
deleted file mode 100755
index 859ba5d..0000000
--- a/build/escape_unicode.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 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.
-
-"""Convert any unicode characters found in the input file to C literals."""
-
-import codecs
-import optparse
-import os
-import sys
-
-
-def main(argv):
-  parser = optparse.OptionParser()
-  usage = 'Usage: %prog -o <output_dir> <input_file>'
-  parser.set_usage(usage)
-  parser.add_option('-o', dest='output_dir')
-
-  options, arglist = parser.parse_args(argv)
-
-  if not options.output_dir:
-    print "output_dir required"
-    return 1
-
-  if len(arglist) != 2:
-    print "input_file required"
-    return 1
-
-  in_filename = arglist[1]
-
-  if not in_filename.endswith('.utf8'):
-    print "input_file should end in .utf8"
-    return 1
-
-  out_filename = os.path.join(options.output_dir, os.path.basename(
-      os.path.splitext(in_filename)[0]))
-
-  WriteEscapedFile(in_filename, out_filename)
-  return 0
-
-
-def WriteEscapedFile(in_filename, out_filename):
-  input_data = codecs.open(in_filename, 'r', 'utf8').read()
-  with codecs.open(out_filename, 'w', 'ascii') as out_file:
-    for i, char in enumerate(input_data):
-      if ord(char) > 127:
-        out_file.write(repr(char.encode('utf8'))[1:-1])
-        if input_data[i + 1:i + 2] in '0123456789abcdefABCDEF':
-          out_file.write('""')
-      else:
-        out_file.write(char.encode('ascii'))
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index 8413002..58e7ff5 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -39,12 +39,6 @@
         '../base/base.gyp:base_unittests',
         '../base/base.gyp:build_utf8_validator_tables#host',
         '../base/base.gyp:check_example',
-        '../base/base.gyp:protect_file_posix',
-        '../breakpad/breakpad.gyp:core-2-minidump',
-        '../breakpad/breakpad.gyp:microdump_stackwalk',
-        '../breakpad/breakpad.gyp:minidump_dump',
-        '../breakpad/breakpad.gyp:minidump_stackwalk',
-        '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
         '../cc/cc_tests.gyp:cc_perftests',
         '../cc/cc_tests.gyp:cc_unittests',
         '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
@@ -56,16 +50,18 @@
         '../chrome/chrome.gyp:chromedriver_unittests',
         '../chrome/chrome.gyp:interactive_ui_tests',
         '../chrome/chrome.gyp:load_library_perf_tests',
-        '../chrome/chrome.gyp:service_discovery_sniffer',
+        '../chrome/chrome.gyp:performance_browser_tests',
         '../chrome/chrome.gyp:sync_integration_tests',
         '../chrome/chrome.gyp:sync_performance_tests',
         '../chrome/chrome.gyp:unit_tests',
         '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler',
+        '../cloud_print/cloud_print.gyp:cloud_print_unittests',
         '../components/components.gyp:network_hints_browser',
+        '../components/components.gyp:policy_templates',
         '../components/components.gyp:webui_generator',
+        '../components/components_tests.gyp:components_browsertests',
         '../components/components_tests.gyp:components_perftests',
         '../components/components_tests.gyp:components_unittests',
-        '../components/nacl.gyp:nacl_loader_unittests',
         '../content/content.gyp:content_app_browser',
         '../content/content.gyp:content_app_child',
         '../content/content_shell_and_tests.gyp:content_browsertests',
@@ -92,6 +88,9 @@
         '../gpu/gpu.gyp:gl_tests',
         '../gpu/gpu.gyp:gpu_perftests',
         '../gpu/gpu.gyp:gpu_unittests',
+        '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',  # TODO(GYP) crbug.com/471920
+        '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',  # TODO(GYP) crbug.com/471920
+        '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',  # TODO(GYP) crbug.com/471903 to make this complete.
         '../ipc/ipc.gyp:ipc_perftests',
         '../ipc/ipc.gyp:ipc_tests',
         '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
@@ -121,9 +120,43 @@
         '../net/net.gyp:run_testserver',
         '../net/net.gyp:stress_cache',
         '../net/net.gyp:tld_cleanup',
-        '../ppapi/ppapi_internal.gyp:*',  # TODO(GYP) - list all of the examples explicitly.
-        '../ppapi/ppapi_internal.gyp:ppapi_tests',  # TODO(GYP): Split out the examples and tests
+        '../ppapi/ppapi_internal.gyp:ppapi_example_audio',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_audio_input',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_c_stub',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_cc_stub',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_compositor',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_crxfs',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_enumerate_devices',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_file_chooser',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_flash_topmost',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_gamepad',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_gles2',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_gles2_spinning_cube',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_graphics_2d',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_ime',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_input',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_media_stream_audio',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_media_stream_video',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_mouse_cursor',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_mouse_lock',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_paint_manager',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_post_message',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_printing',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_scaling',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_scroll',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_simple_font',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_threading',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_url_loader',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_url_loader_file',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_vc',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode_dev',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_effects',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_video_encode',
+        '../ppapi/ppapi_internal.gyp:ppapi_tests',
+        '../ppapi/ppapi_internal.gyp:ppapi_perftests',
         '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+        '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
         '../printing/printing.gyp:printing_unittests',
         '../skia/skia_tests.gyp:skia_unittests',
         '../skia/skia.gyp:filter_fuzz_stub',
@@ -148,9 +181,9 @@
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
+        '../third_party/pdfium/samples/samples.gyp:pdfium_diff',
         '../third_party/pdfium/samples/samples.gyp:pdfium_test',
         '../third_party/smhasher/smhasher.gyp:pmurhash',
-        '../third_party/sqlite/sqlite.gyp:sqlite_shell',
         '../tools/gn/gn.gyp:gn',
         '../tools/gn/gn.gyp:generate_test_gn_data',
         '../tools/gn/gn.gyp:gn_unittests',
@@ -164,7 +197,6 @@
         '../ui/display/display.gyp:display_unittests',
         '../ui/events/events.gyp:events_unittests',
         '../ui/gfx/gfx_tests.gyp:gfx_unittests',
-        '../ui/keyboard/keyboard.gyp:keyboard_unittests',
         '../ui/message_center/message_center.gyp:message_center_unittests',
         '../ui/snapshot/snapshot.gyp:snapshot_unittests',
         '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
@@ -174,28 +206,36 @@
         '../v8/tools/gyp/v8.gyp:postmortem-metadata',
       ],
       'conditions': [
+        ['clang==1', {
+          'dependencies': [
+            '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
+          ],
+        }],
+        ['disable_nacl==0 and disable_nacl_untrusted==0', {
+          'dependencies': [
+            '../components/nacl.gyp:nacl_loader_unittests',
+          ]
+        }],
         ['enable_extensions==1 and OS!="mac"', {
           'dependencies': [
             '../extensions/shell/app_shell.gyp:app_shell',
             '../extensions/shell/app_shell.gyp:app_shell_unittests',
           ],
         }],
-        ['OS!="win"', {
+        ['enable_mdns==1', {
           'dependencies': [
-            '../breakpad/breakpad.gyp:symupload',
+            '../chrome/chrome.gyp:service_discovery_sniffer',
+          ]
+        }],
+        ['remoting==1', {
+          'dependencies': [
+            '../remoting/remoting_all.gyp:remoting_all',
           ],
         }],
-        ['use_x11==1', {
+        ['remoting==1 and chromeos==0', {
           'dependencies': [
-            '../media/media.gyp:player_x11',
-            '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
-          ],
-          'conditions': [
-            ['target_arch!="arm"', {
-              'dependencies': [
-                '../gpu/tools/tools.gyp:compositor_model_bench',
-              ],
-            }],
+            '../remoting/remoting.gyp:remoting_me2me_host',
+            '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
           ],
         }],
         ['toolkit_views==1', {
@@ -211,11 +251,17 @@
             '../ash/ash.gyp:ash_unittests',
           ],
         }],
+        ['use_ash==1 or chromeos== 1', {
+          'dependencies': [
+            '../components/components.gyp:session_manager_component',
+          ]
+        }],
         ['use_aura==1', {
           'dependencies': [
             '../ui/aura/aura.gyp:aura_bench',
             '../ui/aura/aura.gyp:aura_demo',
             '../ui/aura/aura.gyp:aura_unittests',
+            '../ui/keyboard/keyboard.gyp:keyboard_unittests',
             '../ui/wm/wm.gyp:wm_unittests',
           ],
         }],
@@ -224,9 +270,18 @@
             '../ui/ozone/ozone.gyp:ozone',
           ],
         }],
-        ['OS=="win" or OS=="mac" or chromeos==1', {
+
+
+        ['use_x11==1', {
           'dependencies': [
-            '../rlz/rlz.gyp:rlz_lib',
+            '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+          ],
+          'conditions': [
+            ['target_arch!="arm"', {
+              'dependencies': [
+                '../gpu/tools/tools.gyp:compositor_model_bench',
+              ],
+            }],
           ],
         }],
         ['OS=="android"', {
@@ -275,6 +330,7 @@
             '../chrome/chrome.gyp:chromedriver',
             '../chrome/chrome.gyp:chromedriver_unitests',
             '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:performance_browser_tests',
             '../chrome/chrome.gyp:sync_integration_tests',
             '../chrome/chrome.gyp:unit_tests',
             '../extensions/extensions_tests.gyp:extensions_browsertests',
@@ -294,10 +350,38 @@
             '../url/url.gyp:url_unittests',
           ],
         }],
+        ['OS=="android" or OS=="linux"', {
+          'dependencies': [
+            '../net/net.gyp:disk_cache_memory_test',
+          ],
+        }],
+        ['chromeos==1', {
+          'dependencies': [
+            '../chromeos/chromeos.gyp:chromeos_unittests',
+            '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_unittests',
+          ]
+        }],
+        ['chromeos==1 or OS=="win" or OS=="mac"', {
+          'dependencies': [
+            '../rlz/rlz.gyp:rlz_id',
+            '../rlz/rlz.gyp:rlz_lib',
+            '../rlz/rlz.gyp:rlz_unittests',
+          ],
+        }],
+        ['OS=="android" or OS=="linux" or os_bsd==1', {
+          'dependencies': [
+            '../breakpad/breakpad.gyp:core-2-minidump',
+            '../breakpad/breakpad.gyp:microdump_stackwalk',
+            '../breakpad/breakpad.gyp:minidump_dump',
+            '../breakpad/breakpad.gyp:minidump_stackwalk',
+            '../breakpad/breakpad.gyp:symupload',
+            '../third_party/codesighs/codesighs.gyp:nm2tsv',
+          ],
+        }],
         ['OS=="linux"', {
           'dependencies': [
             '../breakpad/breakpad.gyp:breakpad_unittests',
-            '../breakpad/breakpad.gyp:dump_syms',
+            '../breakpad/breakpad.gyp:dump_syms#host',
             '../breakpad/breakpad.gyp:generate_test_dump',
             '../breakpad/breakpad.gyp:minidump-2-core',
             '../dbus/dbus.gyp:dbus_test_server',
@@ -306,6 +390,8 @@
             '../net/net.gyp:disk_cache_memory_test',
             '../net/net.gyp:flip_in_mem_edsm_server',
             '../net/net.gyp:flip_in_mem_edsm_server_unittests',
+            '../net/net.gyp:epoll_quic_client',
+            '../net/net.gyp:epoll_quic_server',
             '../net/net.gyp:hpack_example_generator',
             '../net/net.gyp:hpack_fuzz_mutator',
             '../net/net.gyp:hpack_fuzz_wrapper',
@@ -315,6 +401,7 @@
             '../sandbox/sandbox.gyp:chrome_sandbox',
             '../sandbox/sandbox.gyp:sandbox_linux_unittests',
             '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
+            '../third_party/sqlite/sqlite.gyp:sqlite_shell',
          ],
         }],
         ['OS=="mac"', {
@@ -372,22 +459,38 @@
         }],
         ['OS=="win"', {
           'dependencies': [
-            "//ui/metro_viewer",
+            '../base/base.gyp:pe_image_test',
+            '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests',
+            '../chrome_elf/chrome_elf.gyp:dll_hash_main',
+            '../components/components.gyp:wifi_test',
+            '../net/net.gyp:quic_client',
+            '../net/net.gyp:quic_server',
+            '../sandbox/sandbox.gyp:pocdll',
+            '../sandbox/sandbox.gyp:sandbox_poc',
+            '../sandbox/sandbox.gyp:sbox_integration_tests',
+            '../sandbox/sandbox.gyp:sbox_unittests',
+            '../sandbox/sandbox.gyp:sbox_validation_tests',
+            '../testing/gtest.gyp:gtest_main',
             '../third_party/codesighs/codesighs.gyp:msdump2symdb',
-          ],
-          'dependencies!': [
-            "//crypto:crypto_unittests",  # TODO(GYP)
-            "//net:net_unittests",  # TODO(GYP)
-          ],
-        }, {
-          'dependencies': [
-            '../third_party/codesighs/codesighs.gyp:nm2tsv',
+            '../third_party/codesighs/codesighs.gyp:msmap2tsv',
+            '../third_party/pdfium/samples/samples.gyp:pdfium_diff',
+            '../win8/win8.gyp:metro_viewer',
           ],
         }],
-        ['OS=="android" or OS=="linux"', {
-          'dependencies': [
-            '../net/net.gyp:disk_cache_memory_test',
-          ],
+      ],
+    },
+    {
+      'target_name': 'gyp_only',
+      'type': 'none',
+      'conditions': [
+        ['OS=="linux" or OS=="win"', {
+          'conditions': [
+            ['disable_nacl==0 and disable_nacl_untrusted==0', {
+              'dependencies': [
+                '../mojo/mojo_nacl.gyp:monacl_shell',  # This should not be built in chromium.
+              ]
+            }],
+          ]
         }],
       ],
     },
@@ -395,135 +498,172 @@
       'target_name': 'gyp_remaining',
       'type': 'none',
       'conditions': [
-        ['OS=="linux"', {
+        ['remoting==1', {
           'dependencies': [
-            '../chrome/chrome.gyp:performance_browser_tests',
-            '../cloud_print/cloud_print.gyp:cloud_print_unittests',
-            '../components/components.gyp:policy_templates',
-            '../components/components_tests.gyp:components_browsertests',
-            '../components/components_tests.gyp:components_perftests',
-            '../content/content.gyp:content_app_browser',
-            '../content/content.gyp:content_app_child',
-            '../content/content_shell_and_tests.gyp:content_gl_benchmark',
-            '../content/content_shell_and_tests.gyp:content_gl_tests',
-            '../courgette/courgette.gyp:courgette',
-            '../courgette/courgette.gyp:courgette_fuzz',
-            '../dbus/dbus.gyp:dbus_test_server',
-            '../device/device_tests.gyp:device_unittests',
-            '../gin/gin.gyp:gin_v8_snapshot_fingerprint',
-            '../gin/gin.gyp:gin_shell',
-            '../gpu/gpu.gyp:gl_tests',
-            '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
-            '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',
-            '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',
-            '../media/cast/cast.gyp:cast_benchmarks',
-            '../media/cast/cast.gyp:generate_barcode_video',
-            '../media/cast/cast.gyp:generate_timecode_audio',
-            '../media/cast/cast.gyp:tap_proxy',
-            '../mojo/mojo_base.gyp:mojo_application_chromium',
-            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
-            '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
-            '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
-            '../skia/skia.gyp:filter_fuzz_stub',
-            '../skia/skia.gyp:image_operations_bench',
-            '../sync/sync.gyp:run_sync_testserver',
-            '../sync/sync.gyp:sync_endtoend_tests',
-            '../sync/tools/sync_tools.gyp:sync_client',
-            '../sync/tools/sync_tools.gyp:sync_listen_notifications',
-            '../testing/gmock.gyp:gmock_main',
-            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
-            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
-            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../remoting/app_remoting_webapp.gyp:ar_sample_app',  # crbug.com/471916
+          ],
+        }],
+        ['test_isolation_mode!="noop"', {
+          'dependencies': [
+            '../base/base.gyp:base_unittests_run',
+            '../cc/cc_tests.gyp:cc_unittests_run',
+            '../chrome/chrome.gyp:browser_tests_run',
+            '../chrome/chrome.gyp:chrome_run',
+            '../chrome/chrome.gyp:interactive_ui_tests_run',
+            '../chrome/chrome.gyp:sync_integration_tests_run',
+            '../chrome/chrome.gyp:unit_tests_run',
+            '../components/components_tests.gyp:components_browsertests_run',
+            '../components/components_tests.gyp:components_unittests_run',
+            '../content/content_shell_and_tests.gyp:content_browsertests_run',
+            '../content/content_shell_and_tests.gyp:content_unittests_run',
+            '../crypto/crypto.gyp:crypto_unittests_run',
+            '../courgette/courgette.gyp:courgette_unittests_run',
+            '../gpu/gpu.gyp:gpu_unittests_run',
+            '../media/cast/cast.gyp:cast_unittests_run',
+            '../media/media.gyp:media_unittests_run',
+            '../net/net.gyp:net_unittests_run',
+            '../sql/sql.gyp:sql_unittests_run',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run',
+            '../ui/accessibility/accessibility.gyp:accessibility_unittests_run',
+            '../ui/app_list/app_list.gyp:app_list_unittests_run',
+            '../ui/events/events.gyp:events_unittests_run',
+            '../ui/message_center/message_center.gyp:message_center_unittests_run',
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
+          ],
+        }],
+        ['test_isolation_mode!="noop" and use_ash==1', {
+          'dependencies': [
+            '../ash/ash.gyp:ash_unittests_run',
+          ],
+        }],
+        ['test_isolation_mode!="noop" and OS=="linux"', {
+          'dependencies': [
+            '../sandbox/sandbox.gyp:sandbox_linux_unittests_run',
+          ],
+        }],
+        ['use_openssl==1', {
+          'dependencies': [
+            # TODO(GYP): All of these targets still need to be converted.
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ecdsa_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bn_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pqueue_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_digest_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_cipher_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_hkdf_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_constant_time_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_thread_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_base64_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_gcm_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bytestring_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_evp_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_dsa_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_rsa_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_hmac_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_aead_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ssl_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_err_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_lhash_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pbkdf_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_dh_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs12_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_example_mul',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_ec_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_bio_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs7_test',
+            '../third_party/boringssl/boringssl_tests.gyp:boringssl_unittests',
+          ],
+        }],
+        ['chromeos==1', {
+          'dependencies': [
+            '../content/content_shell_and_tests.gyp:video_encode_accelerator_unittest',
+          ],
+        }],
+        ['chromeos==1 and target_arch != "arm"', {
+          'dependencies': [
+            '../content/content_shell_and_tests.gyp:vaapi_jpeg_decoder_unittest',
+          ],
+        }],
+        ['chromeos==1 or OS=="win" or OS=="android"', {
+          'dependencies': [
+            '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest',
+          ],
+        }],
+        ['OS=="linux" or OS=="win"', {
+          'dependencies': [
+            # TODO(GYP): Figure out which of these run on android/mac/win/ios/etc.
+            '../net/net.gyp:net_docs',
+            '../remoting/app_remoting_test.gyp:ar_sample_test_driver',
+
+            # TODO(GYP): in progress - see tfarina.
             '../third_party/webrtc/tools/tools.gyp:frame_analyzer',
             '../third_party/webrtc/tools/tools.gyp:rgba_to_i420_converter',
-            '../tools/gn/gn.gyp:generate_test_gn_data',
-            '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache',
-            #'../tools/telemetry/telemetry.gyp:bitmaptools', TODO(GYP) should this be #host ?
-            '../ui/compositor/compositor.gyp:compositor_unittests',
-            '../ui/message_center/message_center.gyp:message_center_unittests',
-            '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
-            '../v8/tools/gyp/v8.gyp:v8_snapshot',
-            '../v8/tools/gyp/v8.gyp:postmortem-metadata',
-
-            # TODO(GYP) - list all of the examples explicitly.
-            '../ppapi/ppapi_internal.gyp:*',
           ],
-          'conditions': [
-            ['disable_nacl==0 and disable_nacl_untrusted==0', {
-              'dependencies': [
-                '../components/nacl.gyp:nacl_loader_unittests',
-                '../mojo/mojo_nacl.gyp:monacl_shell',  # TODO(GYP) This will be deleted; don't port
-                '../remoting/remoting.gyp:remoting_key_tester',
-              ]
-            }],
-            ['chromeos== 1 or use_ash==1', {
-              'dependencies': [
-                '../components/components.gyp:session_manager_component',
-              ],
-            }],
-            ['use_x11==1', {
-              'dependencies': [
-                '../gpu/tools/tools.gyp:compositor_model_bench',
-                '../media/media.gyp:player_x11',
-              ],
-            }],
-            ['remoting==1', {
-              'dependencies': [
-                '../remoting/app_remoting_webapp.gyp:ar_sample_app',
-                '../remoting/remoting.gyp:remoting_host',
-                '../remoting/remoting.gyp:remoting_it2me_native_messaging_host',
-                '../remoting/remoting.gyp:remoting_key_tester',
-                '../remoting/remoting.gyp:remoting_me2me_host',
-                '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
-                '../remoting/remoting.gyp:remoting_native_messaging_manifests',
-                '../remoting/remoting.gyp:remoting_perftests',
-                '../remoting/remoting.gyp:remoting_start_host',
-                '../remoting/remoting.gyp:remoting_unittests',
-              ],
-            }],
-            ['toolkit_views==1', {
-              'dependencies': [
-                '../ui/app_list/app_list.gyp:app_list_demo',
-              ],
-            }],
-            ['test_isolation_mode!="noop"', {
-              'dependencies': [
-                '../base/base.gyp:base_unittests_run',
-                '../cc/cc_tests.gyp:cc_unittests_run',
-                '../chrome/chrome.gyp:browser_tests_run',
-                '../chrome/chrome.gyp:chrome_run',
-                '../chrome/chrome.gyp:interactive_ui_tests_run',
-                '../chrome/chrome.gyp:sync_integration_tests_run',
-                '../chrome/chrome.gyp:unit_tests_run',
-                '../components/components_tests.gyp:components_browsertests_run',
-                '../components/components_tests.gyp:components_unittests_run',
-                '../content/content_shell_and_tests.gyp:content_browsertests_run',
-                '../content/content_shell_and_tests.gyp:content_unittests_run',
-                '../crypto/crypto.gyp:crypto_unittests_run',
-                '../courgette/courgette.gyp:courgette_unittests_run',
-                '../gpu/gpu.gyp:gpu_unittests_run',
-                '../media/cast/cast.gyp:cast_unittests_run',
-                '../media/media.gyp:media_unittests_run',
-                '../net/net.gyp:net_unittests_run',
-                '../sandbox/sandbox.gyp:sandbox_linux_unittests_run',
-                '../sql/sql.gyp:sql_unittests_run',
-                '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run',
-                '../ui/accessibility/accessibility.gyp:accessibility_unittests_run',
-                '../ui/app_list/app_list.gyp:app_list_unittests_run',
-                '../ui/events/events.gyp:events_unittests_run',
-                '../ui/message_center/message_center.gyp:message_center_unittests_run',
-                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
-              ],
-              'conditions': [
-                ['use_ash==1', {
-                  'dependencies': [
-                    '../ash/ash.gyp:ash_unittests_run',
-                  ],
-                }],
-              ],
-            }],
+        }],
+        ['OS=="win"', {
+          'dependencies': [
+            # TODO(GYP): All of these targets still need to be converted.
+            '../base/base.gyp:debug_message',
+            '../chrome/chrome.gyp:app_installer',
+            '../chrome/chrome.gyp:app_installer_unittests',
+            '../chrome/chrome.gyp:app_shim',
+            '../chrome/chrome.gyp:crash_service',
+            '../chrome/chrome.gyp:gcapi_dll',
+            '../chrome/chrome.gyp:gcapi_test',
+            '../chrome/chrome.gyp:installer_util_unittests',
+            '../chrome/chrome.gyp:pack_policy_templates',
+            '../chrome/chrome.gyp:sb_sigutil',
+            '../chrome/chrome.gyp:setup',
+            '../chrome/chrome.gyp:setup_unittests',
+            '../chrome/installer/mini_installer.gyp:mini_installer',
+            '../chrome/tools/crash_service/caps/caps.gyp:caps',
+            '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device',
+            '../cloud_print/gcp20/prototype/gcp20_device.gyp:gcp20_device_unittests',
+            '../cloud_print/service/service.gyp:cloud_print_service',
+            '../cloud_print/service/service.gyp:cloud_print_service_config',
+            '../cloud_print/service/service.gyp:cloud_print_service_setup',
+            '../cloud_print/virtual_driver/win/install/virtual_driver_install.gyp:virtual_driver_setup',
+            '../cloud_print/virtual_driver/win/virtual_driver.gyp:gcp_portmon',
+            '../content/content_shell_and_tests.gyp:content_shell_crash_service',
+            '../content/content_shell_and_tests.gyp:layout_test_helper',
+            '../gpu/gpu.gyp:angle_end2end_tests',
+            '../gpu/gpu.gyp:angle_perftests',
+            '../net/net.gyp:net_docs',
+            '../ppapi/ppapi_internal.gyp:ppapi_perftests',
+            '../remoting/app_remoting_test.gyp:ar_sample_test_driver',
+            '../remoting/remoting.gyp:remoting_breakpad_tester',
+            '../remoting/remoting.gyp:remoting_console',
+            '../remoting/remoting.gyp:remoting_desktop',
+            '../rlz/rlz.gyp:rlz',
+            '../tools/win/static_initializers/static_initializers.gyp:static_initializers',
           ],
         }],
+        ['OS=="win" and win_use_allocator_shim==1', {
+          'dependencies': [
+            '../base/allocator/allocator.gyp:allocator_unittests',
+          ]
+        }],
+        ['OS=="win" and target_arch=="ia32"', {
+          'dependencies': [
+            # TODO(GYP): All of these targets need to be ported over.
+            '../base/base.gyp:base_win64',
+            '../base/base.gyp:base_i18n_nacl_win64',
+            '../chrome/chrome.gyp:crash_service_win64',
+            '../chrome/chrome.gyp:launcher_support64',
+            '../components/components.gyp:breakpad_win64',
+            '../courgette/courgette.gyp:courgette64',
+            '../crypto/crypto.gyp:crypto_nacl_win64',
+            '../ipc/ipc.gyp:ipc_win64',
+            '../sandbox/sandbox.gyp:sandbox_win64',
+            '../cloud_print/virtual_driver/win/virtual_driver64.gyp:gcp_portmon64',
+            '../cloud_print/virtual_driver/win/virtual_driver64.gyp:virtual_driver_lib64',
+          ],
+        }],
+        ['OS=="win" and target_arch=="ia32" and configuration_policy==1', {
+          'dependencies': [
+            # TODO(GYP): All of these targets need to be ported over.
+            '../components/components.gyp:policy_win64',
+          ]
+        }],
       ],
     },
     {
@@ -533,7 +673,6 @@
       'type': 'none',
       'dependencies': [
         'All',
-        'aura_builder',
         'blink_tests',
         'chromium_builder_asan',
         'chromium_builder_chromedriver',
@@ -543,6 +682,22 @@
         'chromium_gpu_builder',
         'chromium_gpu_debug_builder',
       ],
+      'conditions': [
+        ['use_aura==1', {
+          'dependencies': [
+            'aura_builder',
+          ]
+        }],
+        ['OS=="win"', {
+          'dependencies': [
+            'chromium_builder',
+            'chromium_builder_dbg_drmemory_win',
+            'chromium_builder_nacl_sdk',
+            'chromium_builder_lkgr_drmemory_win',
+            'chromium_builder_dbg_tsan_win',
+          ],
+        }],
+      ],
     },
   ]
 }
diff --git a/build/grit_action.gypi b/build/grit_action.gypi
index 462fb4c..b24f0f8 100644
--- a/build/grit_action.gypi
+++ b/build/grit_action.gypi
@@ -50,11 +50,12 @@
   ],
   'inputs': [
     '<!@pymod_do_main(grit_info <@(grit_defines) <@(grit_additional_defines) '
-        '--inputs <(grit_grd_file) -f "<(grit_resource_ids)")',
+        '<@(grit_whitelist_flag) --inputs <(grit_grd_file) '
+        '-f "<(grit_resource_ids)")',
   ],
   'outputs': [
     '<!@pymod_do_main(grit_info <@(grit_defines) <@(grit_additional_defines) '
-        '--outputs \'<(grit_out_dir)\' '
+        '<@(grit_whitelist_flag) --outputs \'<(grit_out_dir)\' '
         '<(grit_grd_file) -f "<(grit_resource_ids)")',
   ],
   'action': ['<@(grit_cmd)',
diff --git a/build/gyp_chromium b/build/gyp_chromium
index 45f3206..4ed15ba 100755
--- a/build/gyp_chromium
+++ b/build/gyp_chromium
@@ -30,9 +30,6 @@
 # Add paths so that pymod_do_main(...) can import files.
 sys.path.insert(1, os.path.join(chrome_src, 'android_webview', 'tools'))
 sys.path.insert(1, os.path.join(chrome_src, 'build', 'android', 'gyp'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
-sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
 sys.path.insert(1, os.path.join(chrome_src, 'chrome', 'tools', 'build'))
 sys.path.insert(1, os.path.join(chrome_src, 'chromecast', 'tools', 'build'))
 sys.path.insert(1, os.path.join(chrome_src, 'native_client', 'build'))
@@ -42,6 +39,9 @@
 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'liblouis'))
 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit',
     'Source', 'build', 'scripts'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
+sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
 
 # On Windows, Psyco shortens warm runs of build/gyp_chromium by about
 # 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70
diff --git a/build/gyp_helper.py b/build/gyp_helper.py
index 9be2b9e..c840f2d 100644
--- a/build/gyp_helper.py
+++ b/build/gyp_helper.py
@@ -25,10 +25,12 @@
   supported_vars = (
       'CC',
       'CC_wrapper',
+      'CC.host_wrapper',
       'CHROMIUM_GYP_FILE',
       'CHROMIUM_GYP_SYNTAX_CHECK',
       'CXX',
       'CXX_wrapper',
+      'CXX.host_wrapper',
       'GYP_DEFINES',
       'GYP_GENERATOR_FLAGS',
       'GYP_CROSSCOMPILE',
diff --git a/build/host_jar.gypi b/build/host_jar.gypi
index 6ccc1bd..9c35177 100644
--- a/build/host_jar.gypi
+++ b/build/host_jar.gypi
@@ -3,7 +3,9 @@
 # found in the LICENSE file.
 
 # This file is meant to be included into a target to provide a rule to build
-# a JAR file for use on a host in a consistent manner.
+# a JAR file for use on a host in a consistent manner. If a main class is
+# specified, this file will also generate an executable to run the jar in the
+# output folder's /bin/ directory.
 #
 # To use this, create a gyp target with the following form:
 # {
@@ -69,9 +71,9 @@
             'java_sources!': ['<!@(find <@(excluded_src_paths) -name "*.java")']
           }],
           ['"<(jar_excluded_classes)" != ""', {
-            'extra_options': ['--excluded-classes=<(jar_excluded_classes)']
+            'extra_options': ['--jar-excluded-classes=<(jar_excluded_classes)']
           }],
-          ['">(main_class)" != ""', {
+          ['main_class != ""', {
             'extra_options': ['--main-class=>(main_class)']
           }]
         ],
@@ -97,6 +99,33 @@
         '^@(java_sources)',
       ],
     },
+  ],
+  'conditions': [
+    ['main_class != ""', {
+      'actions': [
+        {
+          'action_name': 'create_java_binary_script_<(_target_name)',
+          'message': 'Creating java binary script <(_target_name)',
+          'variables': {
+            'output': '<(PRODUCT_DIR)/bin/<(_target_name)',
+          },
+          'inputs': [
+            '<(DEPTH)/build/android/gyp/create_java_binary_script.py',
+            '<(jar_path)',
+          ],
+          'outputs': [
+            '<(output)',
+          ],
+          'action': [
+            'python', '<(DEPTH)/build/android/gyp/create_java_binary_script.py',
+            '--classpath=>(input_jars_paths)',
+            '--jar-path=<(jar_path)',
+            '--output=<(output)',
+            '--main-class=>(main_class)',
+          ]
+        }
+      ]
+    }]
   ]
 }
 
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index 53d9712..6473794 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -155,6 +155,12 @@
           linux-libc-dev-armhf-cross
           g++-arm-linux-gnueabihf"
 
+# Work around for dependency issue Ubuntu/Trusty: http://crbug.com/435056
+if [ "x$lsb_release" = "xtrusty" ]; then
+  arm_list+=" g++-4.8-multilib-arm-linux-gnueabihf
+              gcc-4.8-multilib-arm-linux-gnueabihf"
+fi
+
 # Packages to build NaCl, its toolchains, and its ports.
 naclports_list="ant autoconf bison cmake gawk intltool xutils-dev xsltproc"
 nacl_list="g++-mingw-w64-i686 lib32z1-dev
@@ -360,7 +366,7 @@
     sudo dpkg --add-architecture i386
   fi
 fi
-#sudo apt-get update
+sudo apt-get update
 
 # We initially run "apt-get" with the --reinstall option and parse its output.
 # This way, we can find all the packages that need to be newly installed
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 28407eb..18239b7 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -17,10 +17,12 @@
 IDR_DEFAULT_FAVICON_32
 IDR_DEFAULT_FAVICON_64
 IDR_DIR_HEADER_HTML
+IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL
 IDR_DISTILLER_CSS
 IDR_DISTILLER_JS
 IDR_DOM_DISTILLER_VIEWER_HTML
 IDR_DOM_DISTILLER_VIEWER_JS
+IDR_EXTRACT_PAGE_FEATURES_JS
 IDR_FLAGS_FAVICON
 IDR_FLAGS_HTML
 IDR_FLAGS_JS
@@ -98,7 +100,8 @@
 IDR_TOOLBAR_SHADOW_FULL_BLEED
 IDR_TRANSLATE_JS
 IDR_UBER_UTILS_JS
-IDR_WEBUI_I18N_TEMPLATE2_JS
+IDR_WEBUI_I18N_TEMPLATE_JS
+IDR_WEBUI_I18N_TEMPLATE_POLYMER_JS
 IDR_WEBUI_JSTEMPLATE_JS
 IDR_WEBUI_JS_LOAD_TIME_DATA
 IDS_ABOUT_MAC
@@ -304,6 +307,9 @@
 IDS_DELETE
 IDS_DISABLE_TOUCH_ADJUSTMENT_DESCRIPTION
 IDS_DISABLE_TOUCH_ADJUSTMENT_NAME
+IDS_DOM_DISTILLER_QUALITY_ANSWER_NO
+IDS_DOM_DISTILLER_QUALITY_ANSWER_YES
+IDS_DOM_DISTILLER_QUALITY_QUESTION
 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT
 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE
 IDS_DOM_DISTILLER_VIEWER_LOADING_STRING
@@ -348,6 +354,7 @@
 IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT
 IDS_ERRORPAGES_DETAILS_GONE
 IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED
+IDS_ERRORPAGES_DETAILS_ICANN_NAME_COLLISION
 IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR
 IDS_ERRORPAGES_DETAILS_INTERNET_DISCONNECTED
 IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED
@@ -426,6 +433,7 @@
 IDS_ERRORPAGES_SUMMARY_FORBIDDEN
 IDS_ERRORPAGES_SUMMARY_GATEWAY_TIMEOUT
 IDS_ERRORPAGES_SUMMARY_GONE
+IDS_ERRORPAGES_SUMMARY_ICANN_NAME_COLLISION
 IDS_ERRORPAGES_SUMMARY_INTERNAL_SERVER_ERROR
 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED
 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED_INSTRUCTIONS_TEMPLATE
@@ -514,8 +522,6 @@
 IDS_FLAGS_ENABLE
 IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_DESCRIPTION
 IDS_FLAGS_ENABLE_APPS_SHOW_ON_FIRST_PAINT_NAME
-IDS_FLAGS_ENABLE_CARRIER_SWITCHING
-IDS_FLAGS_ENABLE_CARRIER_SWITCHING_DESCRIPTION
 IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH
 IDS_FLAGS_ENABLE_CONTEXTUAL_SEARCH_DESCRIPTION
 IDS_FLAGS_ENABLE_DEFERRED_IMAGE_DECODING_DESCRIPTION
@@ -530,6 +536,8 @@
 IDS_FLAGS_ENABLE_EXPERIMENTAL_CANVAS_FEATURES_NAME
 IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_DESCRIPTION
 IDS_FLAGS_ENABLE_GESTURE_TAP_HIGHLIGHTING_NAME
+IDS_FLAGS_ENABLE_ICON_NTP_DESCRIPTION
+IDS_FLAGS_ENABLE_ICON_NTP_NAME
 IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_DESCRIPTION
 IDS_FLAGS_ENABLE_JAVASCRIPT_HARMONY_NAME
 IDS_FLAGS_ENABLE_NACL_DEBUG_DESCRIPTION
@@ -762,8 +770,6 @@
 IDS_NUMBERED_PROFILE_NAME
 IDS_OK
 IDS_OMNIBOX_EMPTY_HINT
-IDS_OMNIBOX_EMPTY_HINT_NO_DEFAULT_SEARCH_PROVIDER
-IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER
 IDS_ONE_CLICK_SIGNIN_CONFIRM_EMAIL_DIALOG_CANCEL_BUTTON
 IDS_OPEN_TABS_NOTYETSYNCED
 IDS_OPEN_TABS_PROMOCOMPUTER
@@ -852,8 +858,11 @@
 IDS_POLICY_INVALID_BOOKMARK
 IDS_POLICY_INVALID_PROXY_MODE_ERROR
 IDS_POLICY_INVALID_SEARCH_URL_ERROR
+IDS_POLICY_LABEL_ASSET_ID
 IDS_POLICY_LABEL_CLIENT_ID
+IDS_POLICY_LABEL_DIRECTORY_API_ID
 IDS_POLICY_LABEL_DOMAIN
+IDS_POLICY_LABEL_LOCATION
 IDS_POLICY_LABEL_REFRESH_INTERVAL
 IDS_POLICY_LABEL_STATUS
 IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH
@@ -863,6 +872,7 @@
 IDS_POLICY_LEVEL_RECOMMENDED
 IDS_POLICY_LIST_ENTRY_ERROR
 IDS_POLICY_NEVER_FETCHED
+IDS_POLICY_NOT_SPECIFIED
 IDS_POLICY_NOT_SPECIFIED_ERROR
 IDS_POLICY_NO_POLICIES_SET
 IDS_POLICY_OK
@@ -979,6 +989,7 @@
 IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE_V2
 IDS_SAFE_BROWSING_PRIVACY_POLICY_URL
 IDS_SAVE
+IDS_SEARCH_BOX_EMPTY_HINT
 IDS_SECURE_CONNECTION_EV
 IDS_SESSION_CRASHED_VIEW_MESSAGE
 IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON
@@ -1078,138 +1089,28 @@
 IDS_SYNC_UPGRADE_CLIENT
 IDS_SYSTEM_FLAGS_OWNER_ONLY
 IDS_TERMS_HTML
-IDS_TIME_DAYS_1ST_DEFAULT
-IDS_TIME_DAYS_1ST_FEW
-IDS_TIME_DAYS_1ST_MANY
-IDS_TIME_DAYS_1ST_SINGULAR
-IDS_TIME_DAYS_1ST_TWO
-IDS_TIME_DAYS_1ST_ZERO
-IDS_TIME_DAYS_DEFAULT
-IDS_TIME_DAYS_FEW
-IDS_TIME_DAYS_MANY
-IDS_TIME_DAYS_SINGULAR
-IDS_TIME_DAYS_TWO
-IDS_TIME_DAYS_ZERO
-IDS_TIME_ELAPSED_DAYS_DEFAULT
-IDS_TIME_ELAPSED_DAYS_FEW
-IDS_TIME_ELAPSED_DAYS_MANY
-IDS_TIME_ELAPSED_DAYS_SINGULAR
-IDS_TIME_ELAPSED_DAYS_TWO
-IDS_TIME_ELAPSED_DAYS_ZERO
-IDS_TIME_ELAPSED_HOURS_DEFAULT
-IDS_TIME_ELAPSED_HOURS_FEW
-IDS_TIME_ELAPSED_HOURS_MANY
-IDS_TIME_ELAPSED_HOURS_SINGULAR
-IDS_TIME_ELAPSED_HOURS_TWO
-IDS_TIME_ELAPSED_HOURS_ZERO
-IDS_TIME_ELAPSED_MINS_DEFAULT
-IDS_TIME_ELAPSED_MINS_FEW
-IDS_TIME_ELAPSED_MINS_MANY
-IDS_TIME_ELAPSED_MINS_SINGULAR
-IDS_TIME_ELAPSED_MINS_TWO
-IDS_TIME_ELAPSED_MINS_ZERO
-IDS_TIME_ELAPSED_SECS_DEFAULT
-IDS_TIME_ELAPSED_SECS_FEW
-IDS_TIME_ELAPSED_SECS_MANY
-IDS_TIME_ELAPSED_SECS_SINGULAR
-IDS_TIME_ELAPSED_SECS_TWO
-IDS_TIME_ELAPSED_SECS_ZERO
-IDS_TIME_HOURS_1ST_DEFAULT
-IDS_TIME_HOURS_1ST_FEW
-IDS_TIME_HOURS_1ST_MANY
-IDS_TIME_HOURS_1ST_SINGULAR
-IDS_TIME_HOURS_1ST_TWO
-IDS_TIME_HOURS_1ST_ZERO
-IDS_TIME_HOURS_2ND_DEFAULT
-IDS_TIME_HOURS_2ND_FEW
-IDS_TIME_HOURS_2ND_MANY
-IDS_TIME_HOURS_2ND_SINGULAR
-IDS_TIME_HOURS_2ND_TWO
-IDS_TIME_HOURS_2ND_ZERO
-IDS_TIME_HOURS_DEFAULT
-IDS_TIME_HOURS_FEW
-IDS_TIME_HOURS_MANY
-IDS_TIME_HOURS_SINGULAR
-IDS_TIME_HOURS_TWO
-IDS_TIME_HOURS_ZERO
-IDS_TIME_LONG_MINS_1ST_DEFAULT
-IDS_TIME_LONG_MINS_1ST_FEW
-IDS_TIME_LONG_MINS_1ST_MANY
-IDS_TIME_LONG_MINS_1ST_SINGULAR
-IDS_TIME_LONG_MINS_1ST_TWO
-IDS_TIME_LONG_MINS_1ST_ZERO
-IDS_TIME_LONG_MINS_2ND_DEFAULT
-IDS_TIME_LONG_MINS_2ND_FEW
-IDS_TIME_LONG_MINS_2ND_MANY
-IDS_TIME_LONG_MINS_2ND_SINGULAR
-IDS_TIME_LONG_MINS_2ND_TWO
-IDS_TIME_LONG_MINS_2ND_ZERO
-IDS_TIME_LONG_MINS_DEFAULT
-IDS_TIME_LONG_MINS_FEW
-IDS_TIME_LONG_MINS_MANY
-IDS_TIME_LONG_MINS_SINGULAR
-IDS_TIME_LONG_MINS_TWO
-IDS_TIME_LONG_MINS_ZERO
-IDS_TIME_LONG_SECS_2ND_DEFAULT
-IDS_TIME_LONG_SECS_2ND_FEW
-IDS_TIME_LONG_SECS_2ND_MANY
-IDS_TIME_LONG_SECS_2ND_SINGULAR
-IDS_TIME_LONG_SECS_2ND_TWO
-IDS_TIME_LONG_SECS_2ND_ZERO
-IDS_TIME_LONG_SECS_DEFAULT
-IDS_TIME_LONG_SECS_FEW
-IDS_TIME_LONG_SECS_MANY
-IDS_TIME_LONG_SECS_SINGULAR
-IDS_TIME_LONG_SECS_TWO
-IDS_TIME_LONG_SECS_ZERO
-IDS_TIME_MINS_DEFAULT
-IDS_TIME_MINS_FEW
-IDS_TIME_MINS_MANY
-IDS_TIME_MINS_SINGULAR
-IDS_TIME_MINS_TWO
-IDS_TIME_MINS_ZERO
-IDS_TIME_REMAINING_DAYS_DEFAULT
-IDS_TIME_REMAINING_DAYS_FEW
-IDS_TIME_REMAINING_DAYS_MANY
-IDS_TIME_REMAINING_DAYS_SINGULAR
-IDS_TIME_REMAINING_DAYS_TWO
-IDS_TIME_REMAINING_DAYS_ZERO
-IDS_TIME_REMAINING_HOURS_DEFAULT
-IDS_TIME_REMAINING_HOURS_FEW
-IDS_TIME_REMAINING_HOURS_MANY
-IDS_TIME_REMAINING_HOURS_SINGULAR
-IDS_TIME_REMAINING_HOURS_TWO
-IDS_TIME_REMAINING_HOURS_ZERO
-IDS_TIME_REMAINING_LONG_MINS_DEFAULT
-IDS_TIME_REMAINING_LONG_MINS_FEW
-IDS_TIME_REMAINING_LONG_MINS_MANY
-IDS_TIME_REMAINING_LONG_MINS_SINGULAR
-IDS_TIME_REMAINING_LONG_MINS_TWO
-IDS_TIME_REMAINING_LONG_MINS_ZERO
-IDS_TIME_REMAINING_LONG_SECS_DEFAULT
-IDS_TIME_REMAINING_LONG_SECS_FEW
-IDS_TIME_REMAINING_LONG_SECS_MANY
-IDS_TIME_REMAINING_LONG_SECS_SINGULAR
-IDS_TIME_REMAINING_LONG_SECS_TWO
-IDS_TIME_REMAINING_LONG_SECS_ZERO
-IDS_TIME_REMAINING_MINS_DEFAULT
-IDS_TIME_REMAINING_MINS_FEW
-IDS_TIME_REMAINING_MINS_MANY
-IDS_TIME_REMAINING_MINS_SINGULAR
-IDS_TIME_REMAINING_MINS_TWO
-IDS_TIME_REMAINING_MINS_ZERO
-IDS_TIME_REMAINING_SECS_DEFAULT
-IDS_TIME_REMAINING_SECS_FEW
-IDS_TIME_REMAINING_SECS_MANY
-IDS_TIME_REMAINING_SECS_SINGULAR
-IDS_TIME_REMAINING_SECS_TWO
-IDS_TIME_REMAINING_SECS_ZERO
-IDS_TIME_SECS_DEFAULT
-IDS_TIME_SECS_FEW
-IDS_TIME_SECS_MANY
-IDS_TIME_SECS_SINGULAR
-IDS_TIME_SECS_TWO
-IDS_TIME_SECS_ZERO
+IDS_TIME_DAYS
+IDS_TIME_DAYS_1ST
+IDS_TIME_ELAPSED_DAYS
+IDS_TIME_ELAPSED_HOURS
+IDS_TIME_ELAPSED_MINS
+IDS_TIME_ELAPSED_SECS
+IDS_TIME_HOURS
+IDS_TIME_HOURS_1ST
+IDS_TIME_HOURS_2ND
+IDS_TIME_LONG_MINS
+IDS_TIME_LONG_MINS_1ST
+IDS_TIME_LONG_MINS_2ND
+IDS_TIME_LONG_SECS
+IDS_TIME_LONG_SECS_2ND
+IDS_TIME_MINS
+IDS_TIME_REMAINING_DAYS
+IDS_TIME_REMAINING_HOURS
+IDS_TIME_REMAINING_LONG_MINS
+IDS_TIME_REMAINING_LONG_SECS
+IDS_TIME_REMAINING_MINS
+IDS_TIME_REMAINING_SECS
+IDS_TIME_SECS
 IDS_TOOLTIP_STAR
 IDS_TOUCH_EVENTS_DESCRIPTION
 IDS_TOUCH_EVENTS_NAME
diff --git a/build/isolate.gypi b/build/isolate.gypi
index 5fa1e67..7b050e2 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -61,9 +61,6 @@
         # Variables should use the -V FOO=<(FOO) form so frequent values,
         # like '0' or '1', aren't stripped out by GYP. Run 'isolate.py help' for
         # more details.
-        #
-        # This list needs to be kept in sync with the cmd line options
-        # in src/build/android/pylib/gtest/setup.py.
 
         # Path variables are used to replace file paths when loading a .isolate
         # file
@@ -74,12 +71,17 @@
         # the .isolate file but are not considered relative paths.
         '--extra-variable', 'version_full=<(version_full)',
 
+        # Note: This list must match DefaultConfigVariables()
+        # in build/android/pylib/utils/isolator.py
         '--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)',
         '--config-variable', 'OS=<(OS)',
         '--config-variable', 'asan=<(asan)',
+        '--config-variable', 'branding=<(branding)',
         '--config-variable', 'chromeos=<(chromeos)',
         '--config-variable', 'component=<(component)',
         '--config-variable', 'disable_nacl=<(disable_nacl)',
+        '--config-variable', 'enable_pepper_cdms=<(enable_pepper_cdms)',
+        '--config-variable', 'enable_plugins=<(enable_plugins)',
         '--config-variable', 'fastbuild=<(fastbuild)',
         '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
         # TODO(kbr): move this to chrome_tests.gypi:gles2_conform_tests_run
@@ -93,6 +95,8 @@
         '--config-variable', 'tsan=<(tsan)',
         '--config-variable', 'use_custom_libcxx=<(use_custom_libcxx)',
         '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
+        '--config-variable',
+        'use_prebuilt_instrumented_libraries=<(use_prebuilt_instrumented_libraries)',
         '--config-variable', 'use_openssl=<(use_openssl)',
         '--config-variable', 'use_ozone=<(use_ozone)',
         '--config-variable', 'use_x11=<(use_x11)',
diff --git a/build/jar_file_jni_generator.gypi b/build/jar_file_jni_generator.gypi
index 6f5d2f1..3d95b28 100644
--- a/build/jar_file_jni_generator.gypi
+++ b/build/jar_file_jni_generator.gypi
@@ -64,14 +64,4 @@
   # This target exports a hard dependency because it generates header
   # files.
   'hard_dependency': 1,
-  'conditions': [
-    ['android_webview_build==1', {
-      'variables': {
-        'native_exports%': '--native_exports',
-      },
-      'dependencies': [
-        '<(DEPTH)/build/android/android_exports.gyp:android_exports',
-      ],
-    }],
-  ],
 }
diff --git a/build/java.gypi b/build/java.gypi
index 061dff2..730fa22 100644
--- a/build/java.gypi
+++ b/build/java.gypi
@@ -77,6 +77,8 @@
     'lint_result': '<(intermediate_dir)/lint_result.xml',
     'lint_config': '<(intermediate_dir)/lint_config.xml',
     'never_lint%': 0,
+    'findbugs_stamp': '<(intermediate_dir)/findbugs.stamp',
+    'run_findbugs%': 0,
     'proguard_config%': '',
     'proguard_preprocess%': '0',
     'variables': {
@@ -217,6 +219,31 @@
         },
       ],
     }],
+    ['run_findbugs == 1', {
+      'actions': [
+        {
+          'action_name': 'findbugs_<(_target_name)',
+          'message': 'Running findbugs on <(_target_name)',
+          'inputs': [
+            '<(DEPTH)/build/android/findbugs_diff.py',
+            '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+            '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+            '>@(input_jars_paths)',
+            '<(jar_final_path)',
+            '<(compile_stamp)',
+          ],
+          'outputs': [
+            '<(findbugs_stamp)',
+          ],
+          'action': [
+            'python', '<(DEPTH)/build/android/findbugs_diff.py',
+            '--auxclasspath-gyp', '>(input_jars_paths)',
+            '--stamp', '<(findbugs_stamp)',
+            '<(jar_final_path)',
+          ],
+        },
+      ],
+    }],
   ],
   'actions': [
     {
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index c5e7ae3..56aefdf 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -103,6 +103,8 @@
     'lint_result': '<(intermediate_dir)/lint_result.xml',
     'lint_config': '<(intermediate_dir)/lint_config.xml',
     'never_lint%': 0,
+    'findbugs_stamp': '<(intermediate_dir)/findbugs.stamp',
+    'run_findbugs%': 0,
     'java_in_dir_suffix%': '/src',
     'instr_stamp': '<(intermediate_dir)/instr.stamp',
     'jar_stamp': '<(intermediate_dir)/jar.stamp',
@@ -558,6 +560,32 @@
         '<(DEPTH)/tools/android/android_tools.gyp:android_tools',
       ]
     }],
+    ['run_findbugs == 1', {
+      'actions': [
+        {
+          'action_name': 'findbugs_<(_target_name)',
+          'message': 'Running findbugs on <(_target_name)',
+          'inputs': [
+            '<(DEPTH)/build/android/findbugs_diff.py',
+            '<(DEPTH)/build/android/findbugs_filter/findbugs_exclude.xml',
+            '<(DEPTH)/build/android/pylib/utils/findbugs.py',
+            '>@(input_jars_paths)',
+            '<(jar_path)',
+            '<(compile_stamp)',
+          ],
+          'outputs': [
+            '<(findbugs_stamp)',
+          ],
+          'action': [
+            'python', '<(DEPTH)/build/android/findbugs_diff.py',
+            '--auxclasspath-gyp', '>(input_jars_paths)',
+            '--stamp', '<(findbugs_stamp)',
+            '<(jar_path)',
+          ],
+        },
+      ],
+    },
+    ]
   ],
   'dependencies': [
     '<(DEPTH)/tools/android/md5sum/md5sum.gyp:md5sum',
diff --git a/build/jni_generator.gypi b/build/jni_generator.gypi
index c2c71e7..7a9e333 100644
--- a/build/jni_generator.gypi
+++ b/build/jni_generator.gypi
@@ -83,15 +83,5 @@
   # This target exports a hard dependency because it generates header
   # files.
   'hard_dependency': 1,
-  'conditions': [
-    ['android_webview_build==1', {
-      'variables': {
-        'native_exports%': '--native_exports',
-      },
-      'dependencies': [
-        '<(DEPTH)/build/android/android_exports.gyp:android_exports',
-      ],
-    }],
-  ],
 }
 
diff --git a/build/linux/install-arm-sysroot.py b/build/linux/install-arm-sysroot.py
deleted file mode 100755
index 495fc75..0000000
--- a/build/linux/install-arm-sysroot.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import sys
-
-msg = '''\
-ERROR: This script has merged with install-debian.wheezy.sysroot.py.
-Please use that instead (with --arch=arm).
-'''
-sys.stderr.write(msg)
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 5333798..476476e 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -1124,6 +1124,7 @@
                      'spd_set_synthesis_voice',
                      'spd_list_modules',
                      'spd_set_output_module',
+                     'spd_set_language',
           ],
           'message': 'Generating libspeechd library loader',
           'process_outputs_as_sources': 1,
@@ -1180,8 +1181,7 @@
               'dependencies': [
                 '../../third_party/boringssl/boringssl.gyp:boringssl',
               ],
-            }],
-            ['use_openssl==0', {
+            }, {
               'dependencies': [
                 '../../net/third_party/nss/ssl.gyp:libssl',
               ],
@@ -1191,6 +1191,13 @@
                   # before other includes, as we are shadowing system headers.
                   '<(DEPTH)/net/third_party/nss/ssl',
                 ],
+              },
+            }],
+            # Link in the system NSS if it is used for either the internal
+            # crypto library (use_openssl==0) or platform certificate
+            # library (use_nss_certs==1).
+            ['use_openssl==0 or use_nss_certs==1', {
+              'direct_dependent_settings': {
                 'cflags': [
                   '<!@(<(pkg-config) --cflags nss)',
                 ],
@@ -1203,15 +1210,17 @@
                   '<!@(<(pkg-config) --libs-only-l nss | sed -e "s/-lssl3//")',
                 ],
               },
-            }],
-            ['use_openssl==0 and clang==1', {
-              'direct_dependent_settings': {
-                'cflags': [
-                  # There is a broken header guard in /usr/include/nss/secmod.h:
-                  # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
-                  '-Wno-header-guard',
-                ],
-              },
+              'conditions': [
+                ['clang==1', {
+                  'direct_dependent_settings': {
+                    'cflags': [
+                      # There is a broken header guard in /usr/include/nss/secmod.h:
+                      # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
+                      '-Wno-header-guard',
+                    ],
+                  },
+                }],
+              ],
             }],
           ]
         }],
diff --git a/build/linux/unbundle/libvpx.gyp b/build/linux/unbundle/libvpx.gyp
index cdcf6fa..75671c5 100644
--- a/build/linux/unbundle/libvpx.gyp
+++ b/build/linux/unbundle/libvpx.gyp
@@ -14,16 +14,17 @@
       'variables': {
         'headers_root_path': 'source/libvpx',
         'header_filenames': [
-          'vpx/vpx_codec_impl_bottom.h',
-          'vpx/vpx_image.h',
-          'vpx/vpx_decoder.h',
           'vpx/vp8.h',
-          'vpx/vpx_codec.h',
-          'vpx/vpx_codec_impl_top.h',
           'vpx/vp8cx.h',
-          'vpx/vpx_integer.h',
           'vpx/vp8dx.h',
+          'vpx/vpx_codec.h',
+          'vpx/vpx_codec_impl_bottom.h',
+          'vpx/vpx_codec_impl_top.h',
+          'vpx/vpx_decoder.h',
           'vpx/vpx_encoder.h',
+          'vpx/vpx_frame_buffer.h',
+          'vpx/vpx_image.h',
+          'vpx/vpx_integer.h',
         ],
       },
       'includes': [
diff --git a/build/protoc_java.gypi b/build/protoc_java.gypi
index 9ed597b..6fd80d8 100644
--- a/build/protoc_java.gypi
+++ b/build/protoc_java.gypi
@@ -50,6 +50,7 @@
     # Adding the |stamp_file| to |additional_input_paths| makes the actions in
     # the include of java.gypi depend on the genproto_java action.
     'additional_input_paths': ['<(stamp_file)'],
+    'run_findbugs': 0,
   },
   'actions': [
     {
diff --git a/build/sanitizers/asan_suppressions.cc b/build/sanitizers/asan_suppressions.cc
new file mode 100644
index 0000000..df94bc8
--- /dev/null
+++ b/build/sanitizers/asan_suppressions.cc
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains the default suppressions for AddressSanitizer.
+// It should only be used under very limited circumstances such as suppressing
+// a report caused by an interceptor call in a system-installed library.
+
+#if defined(ADDRESS_SANITIZER)
+
+// Please make sure the code below declares a single string variable
+// kASanDefaultSuppressions which contains ASan suppressions delimited by
+// newlines.
+char kASanDefaultSuppressions[] =
+// http://crbug.com/178677
+"interceptor_via_lib:libsqlite3.so\n"
+
+// PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS.
+
+// End of suppressions.
+;  // Please keep this semicolon.
+
+#endif  // ADDRESS_SANITIZER
diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc
index 33090fb..a659a22 100644
--- a/build/sanitizers/sanitizer_options.cc
+++ b/build/sanitizers/sanitizer_options.cc
@@ -36,8 +36,6 @@
 
 #if defined(ADDRESS_SANITIZER)
 // Default options for AddressSanitizer in various configurations:
-//   strict_memcmp=1 - disable the strict memcmp() checking
-//     (http://crbug.com/178677 and http://crbug.com/178404).
 //   malloc_context_size=5 - limit the size of stack traces collected by ASan
 //     for each malloc/free by 5 frames. These stack traces tend to accumulate
 //     very fast in applications using JIT (v8 in Chrome's case), see
@@ -52,8 +50,6 @@
 //     they reside in shared memory). This option is going to be deprecated in
 //     upstream AddressSanitizer and must not be used anywhere except the
 //     official builds.
-//   replace_intrin=0 - do not intercept memcpy(), memmove() and memset() to
-//     work around http://crbug.com/162461 (ASan report in OpenCL on Mac).
 //   check_printf=1 - check the memory accesses to printf (and other formatted
 //     output routines) arguments.
 //   use_sigaltstack=1 - handle signals on an alternate signal stack. Useful
@@ -66,32 +62,28 @@
 //     so the slow unwinder may not work properly.
 //   detect_stack_use_after_return=1 - use fake stack to delay the reuse of
 //     stack allocations and detect stack-use-after-return errors.
-//   detect_container_overflow=0 - do not detect overflows in containers
-//     until crbug.com/459632 is fixed.
 #if defined(OS_LINUX)
 #if defined(GOOGLE_CHROME_BUILD)
 // Default AddressSanitizer options for the official build. These do not affect
 // tests on buildbots (which don't set GOOGLE_CHROME_BUILD) or non-official
 // Chromium builds.
 const char kAsanDefaultOptions[] =
-    "legacy_pthread_cond=1 malloc_context_size=5 strict_memcmp=0 "
+    "legacy_pthread_cond=1 malloc_context_size=5 "
     "symbolize=false check_printf=1 use_sigaltstack=1 detect_leaks=0 "
-    "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
-    "detect_container_overflow=0 ";
+    "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1";
 #else
 // Default AddressSanitizer options for buildbots and non-official builds.
 const char *kAsanDefaultOptions =
-    "strict_memcmp=0 symbolize=false check_printf=1 use_sigaltstack=1 "
+    "symbolize=false check_printf=1 use_sigaltstack=1 "
     "detect_leaks=0 strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
-    "detect_stack_use_after_return=1 detect_container_overflow=0 ";
+    "detect_stack_use_after_return=1 ";
 #endif  // GOOGLE_CHROME_BUILD
 
 #elif defined(OS_MACOSX)
 const char *kAsanDefaultOptions =
-    "strict_memcmp=0 replace_intrin=0 check_printf=1 use_sigaltstack=1 "
+    "check_printf=1 use_sigaltstack=1 "
     "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 "
-    "detect_stack_use_after_return=1 detect_odr_violation=0 "
-    "detect_container_overflow=0 ";
+    "detect_stack_use_after_return=1 detect_odr_violation=0 ";
 static const char kNaClDefaultOptions[] = "handle_segv=0";
 static const char kNaClFlag[] = "--type=nacl-loader";
 #endif  // OS_LINUX
@@ -112,6 +104,12 @@
 #endif
   return kAsanDefaultOptions;
 }
+
+extern "C" char kASanDefaultSuppressions[];
+
+SANITIZER_HOOK_ATTRIBUTE const char *__asan_default_suppressions() {
+  return kASanDefaultSuppressions;
+}
 #endif  // OS_LINUX || OS_MACOSX
 #endif  // ADDRESS_SANITIZER
 
diff --git a/build/sanitizers/sanitizers.gyp b/build/sanitizers/sanitizers.gyp
index 4126d22..91dab8a 100644
--- a/build/sanitizers/sanitizers.gyp
+++ b/build/sanitizers/sanitizers.gyp
@@ -41,6 +41,11 @@
             'lsan_suppressions.cc',
           ],
         }],
+        ['asan==1', {
+          'sources': [
+            'asan_suppressions.cc',
+          ],
+        }],
       ],
       'cflags/': [
         ['exclude', '-fsanitize='],
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 76d2e1e..352b41f 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -63,6 +63,7 @@
 
 // http://crbug.com/158922
 "race:third_party/libvpx/source/libvpx/vp8/encoder/*\n"
+"race:third_party/libvpx/source/libvpx/vp9/encoder/*\n"
 
 // http://crbug.com/189177
 "race:thread_manager\n"
@@ -100,9 +101,6 @@
 // http://crbug.com/246968
 "race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n"
 
-// http://crbug.com/246970
-"race:webrtc::EventPosix::StartTimer\n"
-
 // http://crbug.com/246974
 "race:content::GpuWatchdogThread::CheckArmed\n"
 
@@ -124,12 +122,12 @@
 "race:base::PowerMonitor::RemoveObserver\n"
 "race:base::PowerMonitor::IsOnBatteryPower\n"
 
+// http://crbug.com/258935
+"race:base::Thread::StopSoon\n"
+
 // http://crbug.com/268941
 "race:tracked_objects::ThreadData::tls_index_\n"
 
-// http://crbug.com/270037
-"race:gLibCleanupFunctions\n"
-
 // http://crbug.com/272095
 "race:base::g_top_manager\n"
 
@@ -241,9 +239,6 @@
 // http://crbug.com/363999
 "race:v8::internal::EnterDebugger::*EnterDebugger\n"
 
-// http://crbug.com/364006
-"race:gfx::ImageFamily::~ImageFamily\n"
-
 // https://code.google.com/p/v8/issues/detail?id=3143
 "race:v8::internal::FLAG_track_double_fields\n"
 
@@ -290,9 +285,6 @@
 // http://crbug.com/425057
 "deadlock:webrtc::ViEChannelManagerScoped::ViEChannelManagerScoped\n"
 
-// https://crbug.com/433993
-"deadlock:content::WebRtcAudioDeviceImpl\n"
-
 // http://crbug.com/417193
 // Suppressing both AudioContext.{cpp,h}.
 "race:modules/webaudio/AudioContext\n"
@@ -303,6 +295,9 @@
 // https://crbug.com/430533
 "race:TileTaskGraphRunner::Run\n"
 
+// https://crbug.com/437044
+"race:SkEventTracer\n"
+
 // https://crbug.com/448203
 "race:blink::RemoteFrame::detach\n"
 
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index 92a088a..099b892 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -9,7 +9,7 @@
 }
 
 # This is the GN version of
-# //build/android/cpufeatures.gypi:cpufeatures
+# //build/android/ndk.gyp:cpu_features
 source_set("cpu_features") {
   sources = [
     "ndk/sources/android/cpufeatures/cpu-features.c",
@@ -65,6 +65,13 @@
   jar_path = "$android_sdk_root/extras/android/support/v7/mediarouter/libs/android-support-v7-mediarouter.jar"
 }
 
+android_java_prebuilt("android_support_v7_recyclerview_java") {
+  deps = [
+    ":android_support_v7_appcompat_java",
+  ]
+  jar_path = "$android_sdk_root/extras/android/support/v7/recyclerview/libs/android-support-v7-recyclerview.jar"
+}
+
 android_resources("google_play_services_default_resources") {
   v14_verify_only = true
   resource_dirs = [ "$android_sdk_root/extras/google/google_play_services/libproject/google-play-services_lib/res" ]
diff --git a/build/secondary/third_party/leveldatabase/BUILD.gn b/build/secondary/third_party/leveldatabase/BUILD.gn
deleted file mode 100644
index 067af30..0000000
--- a/build/secondary/third_party/leveldatabase/BUILD.gn
+++ /dev/null
@@ -1,338 +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.
-
-# Snappy is a compression library we use.
-# TODO(brettw) It's not clear why this needs to be parameterized.
-
-import("//testing/test.gni")
-
-use_snappy = true
-
-defines = [ "LEVELDB_PLATFORM_CHROMIUM=1" ]
-
-config("leveldatabase_config") {
-  include_dirs = [
-    ".",
-    "src",
-    "src/include",
-  ]
-}
-
-static_library("leveldatabase") {
-  sources = [
-    "env_chromium.cc",
-    "env_chromium.h",
-    "env_idb.h",
-    "port/port_chromium.cc",
-    "port/port_chromium.h",
-    "src/db/builder.cc",
-    "src/db/builder.h",
-    "src/db/db_impl.cc",
-    "src/db/db_impl.h",
-    "src/db/db_iter.cc",
-    "src/db/db_iter.h",
-    "src/db/dbformat.cc",
-    "src/db/dbformat.h",
-    "src/db/filename.cc",
-    "src/db/filename.h",
-    "src/db/log_format.h",
-    "src/db/log_reader.cc",
-    "src/db/log_reader.h",
-    "src/db/log_writer.cc",
-    "src/db/log_writer.h",
-    "src/db/memtable.cc",
-    "src/db/memtable.h",
-    "src/db/repair.cc",
-    "src/db/skiplist.h",
-    "src/db/snapshot.h",
-    "src/db/table_cache.cc",
-    "src/db/table_cache.h",
-    "src/db/version_edit.cc",
-    "src/db/version_edit.h",
-    "src/db/version_set.cc",
-    "src/db/version_set.h",
-    "src/db/write_batch.cc",
-    "src/db/write_batch_internal.h",
-    "src/helpers/memenv/memenv.cc",
-    "src/helpers/memenv/memenv.h",
-    "src/include/leveldb/cache.h",
-    "src/include/leveldb/comparator.h",
-    "src/include/leveldb/db.h",
-    "src/include/leveldb/env.h",
-    "src/include/leveldb/filter_policy.h",
-    "src/include/leveldb/iterator.h",
-    "src/include/leveldb/options.h",
-    "src/include/leveldb/slice.h",
-    "src/include/leveldb/status.h",
-    "src/include/leveldb/table.h",
-    "src/include/leveldb/table_builder.h",
-    "src/include/leveldb/write_batch.h",
-    "src/port/port.h",
-    "src/port/port_example.h",
-
-    #"src/port/port_posix.cc",  # We use the chromium port instead of this.
-    #"src/port/port_posix.h",
-    "src/table/block.cc",
-    "src/table/block.h",
-    "src/table/block_builder.cc",
-    "src/table/block_builder.h",
-    "src/table/filter_block.cc",
-    "src/table/filter_block.h",
-    "src/table/format.cc",
-    "src/table/format.h",
-    "src/table/iterator.cc",
-    "src/table/iterator_wrapper.h",
-    "src/table/merger.cc",
-    "src/table/merger.h",
-    "src/table/table.cc",
-    "src/table/table_builder.cc",
-    "src/table/two_level_iterator.cc",
-    "src/table/two_level_iterator.h",
-    "src/util/arena.cc",
-    "src/util/arena.h",
-    "src/util/bloom.cc",
-    "src/util/cache.cc",
-    "src/util/coding.cc",
-    "src/util/coding.h",
-    "src/util/comparator.cc",
-    "src/util/crc32c.cc",
-    "src/util/crc32c.h",
-    "src/util/env.cc",
-    "src/util/filter_policy.cc",
-    "src/util/hash.cc",
-    "src/util/hash.h",
-    "src/util/logging.cc",
-    "src/util/logging.h",
-    "src/util/mutexlock.h",
-    "src/util/options.cc",
-    "src/util/random.h",
-    "src/util/status.cc",
-  ]
-
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  public_configs = [ ":leveldatabase_config" ]
-
-  deps = [
-    "//base",
-    "//base/third_party/dynamic_annotations",
-    "//third_party/re2",
-  ]
-
-  if (use_snappy) {
-    defines += [ "USE_SNAPPY=1" ]
-    deps += [ "//third_party/snappy" ]
-  }
-}
-
-if (!is_android) {
-  test("env_chromium_unittests") {
-    sources = [
-      "env_chromium_unittest.cc",
-    ]
-    deps = [
-      ":leveldatabase",
-      "//base/test:test_support",
-      "//testing/gtest",
-    ]
-  }
-
-  static_library("leveldb_testutil") {
-    sources = [
-      "src/util/histogram.cc",
-      "src/util/histogram.h",
-      "src/util/testharness.cc",
-      "src/util/testharness.h",
-      "src/util/testutil.cc",
-      "src/util/testutil.h",
-    ]
-
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-
-    public_deps = [
-      ":leveldatabase",
-    ]
-    deps = [
-      "//base",
-    ]
-  }
-
-  test("leveldb_arena_test") {
-    sources = [
-      "src/util/arena_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_bloom_test") {
-    sources = [
-      "src/util/bloom_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_cache_test") {
-    sources = [
-      "src/util/cache_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_corruption_test") {
-    sources = [
-      "src/db/corruption_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_crc32c_test") {
-    sources = [
-      "src/util/crc32c_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_db_bench") {
-    sources = [
-      "src/db/db_bench.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_db_test") {
-    sources = [
-      "src/db/db_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_dbformat_test") {
-    sources = [
-      "src/db/dbformat_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_env_test") {
-    sources = [
-      "src/util/env_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_filename_test") {
-    sources = [
-      "src/db/filename_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_filter_block_test") {
-    sources = [
-      "src/table/filter_block_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_log_test") {
-    sources = [
-      "src/db/log_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_skiplist_test") {
-    sources = [
-      "src/db/skiplist_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_table_test") {
-    sources = [
-      "src/table/table_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_version_edit_test") {
-    sources = [
-      "src/db/version_edit_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-
-  test("leveldb_write_batch_test") {
-    sources = [
-      "src/db/write_batch_test.cc",
-    ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
-  }
-}
diff --git a/build/secondary/third_party/sfntly/BUILD.gn b/build/secondary/third_party/sfntly/BUILD.gn
deleted file mode 100644
index 111f1cd..0000000
--- a/build/secondary/third_party/sfntly/BUILD.gn
+++ /dev/null
@@ -1,131 +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.
-
-static_library("sfntly") {
-  sources = [
-    "cpp/src/sample/chromium/font_subsetter.cc",
-    "cpp/src/sample/chromium/font_subsetter.h",
-    "cpp/src/sample/chromium/subsetter_impl.cc",
-    "cpp/src/sample/chromium/subsetter_impl.h",
-    "cpp/src/sfntly/data/byte_array.cc",
-    "cpp/src/sfntly/data/byte_array.h",
-    "cpp/src/sfntly/data/font_data.cc",
-    "cpp/src/sfntly/data/font_data.h",
-    "cpp/src/sfntly/data/font_input_stream.cc",
-    "cpp/src/sfntly/data/font_input_stream.h",
-    "cpp/src/sfntly/data/font_output_stream.cc",
-    "cpp/src/sfntly/data/font_output_stream.h",
-    "cpp/src/sfntly/data/growable_memory_byte_array.cc",
-    "cpp/src/sfntly/data/growable_memory_byte_array.h",
-    "cpp/src/sfntly/data/memory_byte_array.cc",
-    "cpp/src/sfntly/data/memory_byte_array.h",
-    "cpp/src/sfntly/data/readable_font_data.cc",
-    "cpp/src/sfntly/data/readable_font_data.h",
-    "cpp/src/sfntly/data/writable_font_data.cc",
-    "cpp/src/sfntly/data/writable_font_data.h",
-    "cpp/src/sfntly/font.cc",
-    "cpp/src/sfntly/font.h",
-    "cpp/src/sfntly/font_factory.cc",
-    "cpp/src/sfntly/font_factory.h",
-    "cpp/src/sfntly/math/fixed1616.h",
-    "cpp/src/sfntly/math/font_math.h",
-    "cpp/src/sfntly/port/atomic.h",
-    "cpp/src/sfntly/port/config.h",
-    "cpp/src/sfntly/port/endian.h",
-    "cpp/src/sfntly/port/exception_type.h",
-    "cpp/src/sfntly/port/file_input_stream.cc",
-    "cpp/src/sfntly/port/file_input_stream.h",
-    "cpp/src/sfntly/port/input_stream.h",
-    "cpp/src/sfntly/port/lock.cc",
-    "cpp/src/sfntly/port/lock.h",
-    "cpp/src/sfntly/port/memory_input_stream.cc",
-    "cpp/src/sfntly/port/memory_input_stream.h",
-    "cpp/src/sfntly/port/memory_output_stream.cc",
-    "cpp/src/sfntly/port/memory_output_stream.h",
-    "cpp/src/sfntly/port/output_stream.h",
-    "cpp/src/sfntly/port/refcount.h",
-    "cpp/src/sfntly/port/type.h",
-    "cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/big_glyph_metrics.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_size_table.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_size_table.h",
-    "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/ebdt_table.cc",
-    "cpp/src/sfntly/table/bitmap/ebdt_table.h",
-    "cpp/src/sfntly/table/bitmap/eblc_table.cc",
-    "cpp/src/sfntly/table/bitmap/eblc_table.h",
-    "cpp/src/sfntly/table/bitmap/ebsc_table.cc",
-    "cpp/src/sfntly/table/bitmap/ebsc_table.h",
-    "cpp/src/sfntly/table/bitmap/glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/glyph_metrics.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format1.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format2.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format3.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format4.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format5.h",
-    "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/small_glyph_metrics.h",
-    "cpp/src/sfntly/table/byte_array_table_builder.cc",
-    "cpp/src/sfntly/table/byte_array_table_builder.h",
-    "cpp/src/sfntly/table/core/cmap_table.cc",
-    "cpp/src/sfntly/table/core/cmap_table.h",
-    "cpp/src/sfntly/table/core/font_header_table.cc",
-    "cpp/src/sfntly/table/core/font_header_table.h",
-    "cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_device_metrics_table.h",
-    "cpp/src/sfntly/table/core/horizontal_header_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_header_table.h",
-    "cpp/src/sfntly/table/core/horizontal_metrics_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_metrics_table.h",
-    "cpp/src/sfntly/table/core/maximum_profile_table.cc",
-    "cpp/src/sfntly/table/core/maximum_profile_table.h",
-    "cpp/src/sfntly/table/core/name_table.cc",
-    "cpp/src/sfntly/table/core/name_table.h",
-    "cpp/src/sfntly/table/core/os2_table.cc",
-    "cpp/src/sfntly/table/core/os2_table.h",
-    "cpp/src/sfntly/table/font_data_table.cc",
-    "cpp/src/sfntly/table/font_data_table.h",
-    "cpp/src/sfntly/table/generic_table_builder.cc",
-    "cpp/src/sfntly/table/generic_table_builder.h",
-    "cpp/src/sfntly/table/header.cc",
-    "cpp/src/sfntly/table/header.h",
-    "cpp/src/sfntly/table/subtable.cc",
-    "cpp/src/sfntly/table/subtable.h",
-    "cpp/src/sfntly/table/subtable_container_table.h",
-    "cpp/src/sfntly/table/table.cc",
-    "cpp/src/sfntly/table/table.h",
-    "cpp/src/sfntly/table/table_based_table_builder.cc",
-    "cpp/src/sfntly/table/table_based_table_builder.h",
-    "cpp/src/sfntly/table/truetype/glyph_table.cc",
-    "cpp/src/sfntly/table/truetype/glyph_table.h",
-    "cpp/src/sfntly/table/truetype/loca_table.cc",
-    "cpp/src/sfntly/table/truetype/loca_table.h",
-    "cpp/src/sfntly/tag.cc",
-    "cpp/src/sfntly/tag.h",
-  ]
-
-  defines = [ "SFNTLY_NO_EXCEPTION" ]
-  include_dirs = [ "cpp/src" ]
-
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  deps = [
-    "//third_party/icu:icuuc",
-  ]
-}
diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni
index 5d3b1e4..09a04c1 100644
--- a/build/secondary/tools/grit/grit_rule.gni
+++ b/build/secondary/tools/grit/grit_rule.gni
@@ -146,7 +146,7 @@
 if (use_nss_certs) {
   grit_defines += [
     "-D",
-    "use_nss",
+    "use_nss_certs",
   ]
 }
 
@@ -204,6 +204,12 @@
     "enable_extensions",
   ]
 }
+if (enable_media_router) {
+  grit_defines += [
+    "-D",
+    "enable_media_router",
+  ]
+}
 if (enable_plugins) {
   grit_defines += [
     "-D",
@@ -299,11 +305,14 @@
   assert(defined(invoker.source),
          "\"source\" must be defined for the grit template $target_name")
 
+  grit_inputs = [ invoker.source ]
+
   if (defined(invoker.resource_ids)) {
     resource_ids = invoker.resource_ids
   } else {
     resource_ids = grit_resource_id_file
   }
+  grit_inputs += [ resource_ids ]  # Script depends on ID file.
 
   if (defined(invoker.output_dir)) {
     output_dir = invoker.output_dir
@@ -331,8 +340,6 @@
     grit_flags = []  # These are optional so default to empty list.
   }
 
-  grit_inputs = [ invoker.source ]
-
   assert_files_flags = []
 
   # We want to make sure the declared outputs actually match what Grit is
@@ -371,20 +378,8 @@
     script = "//tools/grit/grit.py"
     inputs = grit_inputs
 
-    # TODO(knn): Remove this once grit has rolled to recognize the flag.
-    depend_on_stamp =
-        defined(invoker.depend_on_stamp) && invoker.depend_on_stamp
-    if (depend_on_stamp) {
-      # Need this for migrating existing targets without clobbering.
-      depfile = "$output_dir/${grit_output_name}_stamp.d"
-      outputs = [
-        "${depfile}.stamp",
-      ]
-    } else {
-      depfile = "$output_dir/${grit_output_name}.d"
-      outputs = []
-    }
-    outputs += grit_outputs
+    depfile = "$output_dir/${grit_output_name}_stamp.d"
+    outputs = [ "${depfile}.stamp" ] + grit_outputs
 
     args = [
       "-i",
@@ -398,18 +393,15 @@
       ]
     }
     args += [
-      "-o",
-      rebased_output_dir,
-      "--depdir",
-      ".",
-      "--depfile",
-      rebase_path(depfile, root_build_dir),
-      "--write-only-new=1",
-    ]
-    if (depend_on_stamp) {
-      args += [ "--depend-on-stamp" ]
-    }
-    args += grit_defines
+              "-o",
+              rebased_output_dir,
+              "--depdir",
+              ".",
+              "--depfile",
+              rebase_path(depfile, root_build_dir),
+              "--write-only-new=1",
+              "--depend-on-stamp",
+            ] + grit_defines
 
     # Add extra defines with -D flags.
     if (defined(invoker.defines)) {
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index 5f49f68..0192faa 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -211,12 +211,6 @@
       target_os = target_os
       target_cpu = target_cpu
 
-      # TODO(dpranke): These values are here for backwards compatibility and
-      # should be deleted when all of the builders and configs have been
-      # updated.
-      cpu_arch = current_cpu
-      os = current_os
-
       if (defined(invoker.is_clang)) {
         is_clang = invoker.is_clang
       }
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 18ee8b8..a4b8651 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -195,9 +195,6 @@
 
     toolchain_args() {
       current_os = invoker.toolchain_os
-
-      # TODO(dpranke): os is here for backwards compatibility.
-      os = current_os
     }
   }
 }
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index e9461a4..05406c3 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -101,7 +101,7 @@
       outputs = [
         "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
       ]
-      rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
+      rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
     }
 
     tool("rc") {
@@ -201,9 +201,6 @@
     # passed to the build. They are ignored when this is the default toolchain.
     toolchain_args() {
       current_cpu = invoker.current_cpu
-
-      # TODO(dpranke): cpu_arch is here for backwards compatibility.
-      cpu_arch = current_cpu
     }
   }
 }
diff --git a/build/util/lastchange.py b/build/util/lastchange.py
index d1c33e8..1a7f519 100755
--- a/build/util/lastchange.py
+++ b/build/util/lastchange.py
@@ -115,6 +115,7 @@
       for line in reversed(output.splitlines()):
         if line.startswith('Cr-Commit-Position:'):
           pos = line.rsplit()[-1].strip()
+          break
   if not pos:
     return VersionInfo('git', hsh)
   return VersionInfo('git', '%s-%s' % (hsh, pos))
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 79919df..b7bd765 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -126,7 +126,7 @@
   libs = []
 
   if (is_android) {
-    deps += [ "//testing/android:native_test_native_code" ]
+    deps += [ "//testing/android/native_test:native_test_native_code" ]
     libs += [ "android" ]
   }
 
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index af23813..a4fcc70 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4419,7 +4419,7 @@
         # Make this behavior consistent within Chromium, and avoid leaking GL
         # errors by generating the error in the command buffer instead of
         # letting the GL driver generate it.
-        code.append("base::IsNaN(%s)" % args[ndx].name)
+        code.append("std::isnan(%s)" % args[ndx].name)
       if len(code):
         file.Write("  if (%s) {\n" % " ||\n      ".join(code))
         file.Write(
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
index f0faded..e7a3a6c 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
@@ -90,7 +90,7 @@
   TransferThread() : base::Thread(kAsyncTransferThreadName) {
     Start();
 #if defined(OS_ANDROID) || defined(OS_LINUX)
-    SetPriority(base::kThreadPriority_Background);
+    SetPriority(base::ThreadPriority::BACKGROUND);
 #endif
   }
   ~TransferThread() override { Stop(); }
@@ -466,14 +466,14 @@
 void AsyncPixelTransferDelegateEGL::WaitForTransferCompletion() {
   if (state_->TransferIsInProgress()) {
 #if defined(OS_ANDROID) || defined(OS_LINUX)
-    g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Display);
+    g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::BACKGROUND);
 #endif
 
     state_->WaitForTransferCompletion();
     DCHECK(!state_->TransferIsInProgress());
 
 #if defined(OS_ANDROID) || defined(OS_LINUX)
-    g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Background);
+    g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::BACKGROUND);
 #endif
   }
 }
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
index 16089f6..47cdf9e 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
@@ -47,7 +47,7 @@
         initialized_(false) {
     Start();
 #if defined(OS_ANDROID) || defined(OS_LINUX)
-    SetPriority(base::kThreadPriority_Background);
+    SetPriority(base::ThreadPriority::BACKGROUND);
 #endif
   }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 0886768..efa9dbc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -17,7 +17,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
-#include "base/float_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/numerics/safe_math.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 9a27c2f..18b2808 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -2215,7 +2215,7 @@
       *static_cast<const gles2::cmds::LineWidth*>(cmd_data);
   (void)c;
   GLfloat width = static_cast<GLfloat>(c.width);
-  if (width <= 0.0f || base::IsNaN(width)) {
+  if (width <= 0.0f || std::isnan(width)) {
     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "LineWidth", "width out of range");
     return error::kNoError;
   }
diff --git a/mojo/common/task_tracker_unittest.cc b/mojo/common/task_tracker_unittest.cc
index d476554..77f7da8 100644
--- a/mojo/common/task_tracker_unittest.cc
+++ b/mojo/common/task_tracker_unittest.cc
@@ -34,7 +34,7 @@
   tracked_objects::ThreadData::Snapshot(&snapshot);
 
   // Nested one is ignored.
-  EXPECT_EQ(1U, snapshot.tasks.size());
+  EXPECT_EQ(1U, snapshot.phased_process_data_snapshots[0].tasks.size());
 }
 
 TEST_F(TaskTrackerTest, Twice) {
@@ -46,7 +46,7 @@
   tracked_objects::ProcessDataSnapshot snapshot;
   tracked_objects::ThreadData::Snapshot(&snapshot);
 
-  EXPECT_EQ(2U, snapshot.tasks.size());
+  EXPECT_EQ(2U, snapshot.phased_process_data_snapshots[0].tasks.size());
 }
 
 }  // namespace test
diff --git a/mojo/dart/embedder/BUILD.gn b/mojo/dart/embedder/BUILD.gn
index cf509aa..95fcc46 100644
--- a/mojo/dart/embedder/BUILD.gn
+++ b/mojo/dart/embedder/BUILD.gn
@@ -360,7 +360,7 @@
            "--output_bin",
            rebase_path(isolate_snapshot, root_build_dir),
            "--target_os",
-           os,
+           current_os,
            "--url_mapping=dart:mojo.builtin,$builtin_path",
            "--url_mapping=dart:mojo.internal,$internal_path",
            "--url_mapping=dart:mojo.io,$io_path",
diff --git a/mojo/public/tools/BUILD.gn b/mojo/public/tools/BUILD.gn
index 8b47bb9..9850a17 100644
--- a/mojo/public/tools/BUILD.gn
+++ b/mojo/public/tools/BUILD.gn
@@ -38,7 +38,7 @@
       ]
     } else {
       if (is_android) {
-        assert(cpu_arch == "arm",
+        assert(current_cpu == "arm",
                "Only arm version prebuilt netowrk_service.mojo is available.")
         sources = [
           "prebuilt/network_service/android-arm/$filename",
@@ -66,7 +66,7 @@
     } else {
       if (is_android) {
         assert(
-            cpu_arch == "arm",
+            target_cpu == "arm",
             "Only arm version prebuilt netowrk_service_apptests.mojo is available.")
         sources = [
           "prebuilt/network_service_apptests/android-arm/$filename",
diff --git a/mojo/tools/mopy/gn.py b/mojo/tools/mopy/gn.py
index f171281..1e519da 100644
--- a/mojo/tools/mopy/gn.py
+++ b/mojo/tools/mopy/gn.py
@@ -65,9 +65,9 @@
     gn_args["go_build_tool"] = config.values.get("go_build_tool")
 
   if config.target_os == Config.OS_ANDROID:
-    gn_args["os"] = "android"
+    gn_args["target_os"] = "android"
   elif config.target_os == Config.OS_CHROMEOS:
-    gn_args["os"] = "chromeos"
+    gn_args["target_os"] = "chromeos"
     gn_args["use_glib"] = False
     gn_args["use_system_harfbuzz"] = False
   elif config.target_os == Config.OS_LINUX:
@@ -114,7 +114,7 @@
   config_args["mojo_use_go"] = args.get("mojo_use_go", False)
   if config_args["mojo_use_go"]:
     config_args["go_build_tool"] = args.get("go_build_tool")
-  config_args["target_os"] = args.get("os")
+  config_args["target_os"] = args.get("target_os")
   config_args["target_cpu"] = args.get("target_cpu")
   config_args["dcheck_always_on"] = args.get("dcheck_always_on")
   return Config(**config_args)
diff --git a/mojo/tools/mopy/gn_unittest.py b/mojo/tools/mopy/gn_unittest.py
index 1aaaa6c..0e8768a 100644
--- a/mojo/tools/mopy/gn_unittest.py
+++ b/mojo/tools/mopy/gn_unittest.py
@@ -37,7 +37,7 @@
   def testGNToConfigToGN(self):
     """Tests that gn to config to gn is the identity"""
     configs_to_test = {
-      "os": [None, "android", "chromeos"],
+      "target_os": [None, "android", "chromeos"],
       "target_cpu": ["x86", "x64", "arm"],
       "is_debug": [False, True],
       "is_clang": [False, True],
@@ -49,10 +49,10 @@
     }
 
     for args in _iterate_over_config(configs_to_test):
-      if args.get('os', None) == "chromeos":
-        args['use_glib'] = False
-        args['use_system_harfbuzz'] = False
-      if args.get('os', None) is None and sys.platform[:5] == 'linux':
+      if args.get("target_os", None) == "chromeos":
+        args["use_glib"] = False
+        args["use_system_harfbuzz"] = False
+      if args.get("target_os", None) is None and sys.platform[:5] == "linux":
         args["use_aura"] = False
         args["use_glib"] = False
         args["use_system_harfbuzz"] = False
diff --git a/mojo/tools/roll/build_v8.patch b/mojo/tools/roll/build_v8.patch
index 7de0f0a..5575f24 100644
--- a/mojo/tools/roll/build_v8.patch
+++ b/mojo/tools/roll/build_v8.patch
@@ -1,13 +1,12 @@
 diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni
-index df6a4a3..05b673b 100644
+index db4ee4e..05b673b 100644
 --- a/build/module_args/v8.gni
 +++ b/build/module_args/v8.gni
-@@ -9,5 +9,7 @@ if (is_android) {
+@@ -9,4 +9,7 @@ if (is_android) {
  # TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456.
  enable_correct_v8_arch = false
  
--v8_use_external_startup_data =
--    !((is_android && is_android_webview_build) || is_chromeos || is_win)
+-v8_use_external_startup_data = !(is_chromeos || is_win)
 +# Many V8 users in mojo do not support external startup data for V8, so
 +# we disable it. If enabled, special care should be taken to ensure the
 +# appropriate startup data is correctly bundled for apps.
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index 211c22b..8496685 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -117,6 +117,7 @@
       "seccomp-bpf/errorcode_unittest.cc",
       "seccomp-bpf/sandbox_bpf_unittest.cc",
       "seccomp-bpf/syscall_unittest.cc",
+      "seccomp-bpf/trap_unittest.cc",
     ]
   }
   if (compile_credentials) {
@@ -147,7 +148,7 @@
     ":sandbox_linux_unittests_sources",
   ]
   if (is_android) {
-    deps += [ "//testing/android:native_test_native_code" ]
+    deps += [ "//testing/android/native_test:native_test_native_code" ]
   }
 }
 
@@ -288,15 +289,16 @@
 
 source_set("sandbox_services_headers") {
   sources = [
-    "system_headers/android_arm64_ucontext.h",
-    "system_headers/android_arm_ucontext.h",
-    "system_headers/android_futex.h",
-    "system_headers/android_i386_ucontext.h",
-    "system_headers/android_ucontext.h",
     "system_headers/arm64_linux_syscalls.h",
+    "system_headers/arm64_linux_ucontext.h",
     "system_headers/arm_linux_syscalls.h",
+    "system_headers/arm_linux_ucontext.h",
+    "system_headers/i386_linux_ucontext.h",
+    "system_headers/linux_futex.h",
     "system_headers/linux_seccomp.h",
+    "system_headers/linux_signal.h",
     "system_headers/linux_syscalls.h",
+    "system_headers/linux_ucontext.h",
     "system_headers/x86_32_linux_syscalls.h",
     "system_headers/x86_64_linux_syscalls.h",
   ]
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl.h b/sandbox/linux/bpf_dsl/bpf_dsl.h
index 63b095d..365e9b5 100644
--- a/sandbox/linux/bpf_dsl/bpf_dsl.h
+++ b/sandbox/linux/bpf_dsl/bpf_dsl.h
@@ -33,8 +33,8 @@
 //      class SillyPolicy : public Policy {
 //       public:
 //        SillyPolicy() {}
-//        virtual ~SillyPolicy() {}
-//        virtual ResultExpr EvaluateSyscall(int sysno) const override {
+//        ~SillyPolicy() override {}
+//        ResultExpr EvaluateSyscall(int sysno) const override {
 //          if (sysno == __NR_fcntl) {
 //            Arg<int> fd(0), cmd(1);
 //            Arg<unsigned long> flags(2);
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
index dba421f..398ec59 100644
--- a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
+++ b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
@@ -26,6 +26,7 @@
 #include "sandbox/linux/bpf_dsl/trap_registry.h"
 #include "sandbox/linux/bpf_dsl/verifier.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #define CASES SANDBOX_BPF_DSL_CASES
diff --git a/sandbox/linux/bpf_dsl/codegen.cc b/sandbox/linux/bpf_dsl/codegen.cc
index 793d95d..99b78ed 100644
--- a/sandbox/linux/bpf_dsl/codegen.cc
+++ b/sandbox/linux/bpf_dsl/codegen.cc
@@ -4,12 +4,11 @@
 
 #include "sandbox/linux/bpf_dsl/codegen.h"
 
-#include <linux/filter.h>
-
 #include <limits>
 #include <utility>
 
 #include "base/logging.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 
 // This CodeGen implementation strives for simplicity while still
 // generating acceptable BPF programs under typical usage patterns
diff --git a/sandbox/linux/bpf_dsl/codegen_unittest.cc b/sandbox/linux/bpf_dsl/codegen_unittest.cc
index 3abfc85..5961822 100644
--- a/sandbox/linux/bpf_dsl/codegen_unittest.cc
+++ b/sandbox/linux/bpf_dsl/codegen_unittest.cc
@@ -4,8 +4,6 @@
 
 #include "sandbox/linux/bpf_dsl/codegen.h"
 
-#include <linux/filter.h>
-
 #include <map>
 #include <utility>
 #include <vector>
@@ -13,6 +11,7 @@
 #include "base/macros.h"
 #include "base/md5.h"
 #include "base/strings/string_piece.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace sandbox {
@@ -63,7 +62,7 @@
   }
 
   std::string Base16() const {
-    return MD5DigestToBase16(digest_);
+    return base::MD5DigestToBase16(digest_);
   }
 
   base::MD5Digest digest_;
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.cc b/sandbox/linux/bpf_dsl/dump_bpf.cc
index 82c9852..d0c8f75 100644
--- a/sandbox/linux/bpf_dsl/dump_bpf.cc
+++ b/sandbox/linux/bpf_dsl/dump_bpf.cc
@@ -8,6 +8,7 @@
 
 #include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/linux/bpf_dsl/trap_registry.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
 
 namespace sandbox {
@@ -79,19 +80,22 @@
         }
         break;
       case BPF_ALU:
-        fprintf(stderr, BPF_OP(iter->code) == BPF_NEG
-            ? "A := -A\n" : "A := A %s 0x%x\n",
-            BPF_OP(iter->code) == BPF_ADD ? "+"  :
-            BPF_OP(iter->code) == BPF_SUB ? "-"  :
-            BPF_OP(iter->code) == BPF_MUL ? "*"  :
-            BPF_OP(iter->code) == BPF_DIV ? "/"  :
-            BPF_OP(iter->code) == BPF_MOD ? "%"  :
-            BPF_OP(iter->code) == BPF_OR  ? "|"  :
-            BPF_OP(iter->code) == BPF_XOR ? "^"  :
-            BPF_OP(iter->code) == BPF_AND ? "&"  :
-            BPF_OP(iter->code) == BPF_LSH ? "<<" :
-            BPF_OP(iter->code) == BPF_RSH ? ">>" : "???",
-            (int)iter->k);
+        if (BPF_OP(iter->code) == BPF_NEG) {
+          fprintf(stderr, "A := -A\n");
+        } else {
+          fprintf(stderr, "A := A %s 0x%x\n",
+                  BPF_OP(iter->code) == BPF_ADD ? "+"  :
+                  BPF_OP(iter->code) == BPF_SUB ? "-"  :
+                  BPF_OP(iter->code) == BPF_MUL ? "*"  :
+                  BPF_OP(iter->code) == BPF_DIV ? "/"  :
+                  BPF_OP(iter->code) == BPF_MOD ? "%"  :
+                  BPF_OP(iter->code) == BPF_OR  ? "|"  :
+                  BPF_OP(iter->code) == BPF_XOR ? "^"  :
+                  BPF_OP(iter->code) == BPF_AND ? "&"  :
+                  BPF_OP(iter->code) == BPF_LSH ? "<<" :
+                  BPF_OP(iter->code) == BPF_RSH ? ">>" : "???",
+                  (int)iter->k);
+        }
         break;
       default:
         fprintf(stderr, "???\n");
diff --git a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
index a26a166..a747770 100644
--- a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+++ b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
@@ -5,8 +5,6 @@
 #ifndef SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_
 #define SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_
 
-#include <asm/unistd.h>  // For __NR_SYSCALL_BASE
-
 #if defined(__x86_64__)
 
 #define MIN_SYSCALL         0u
@@ -25,15 +23,19 @@
 // and a "ghost syscall private to the kernel", cmpxchg,
 // at |__ARM_NR_BASE+0x00fff0|.
 // See </arch/arm/include/asm/unistd.h> in the Linux kernel.
-#define MIN_SYSCALL         ((unsigned int)__NR_SYSCALL_BASE)
+
+// __NR_SYSCALL_BASE is 0 in thumb and ARM EABI.
+#define MIN_SYSCALL         0u
 #define MAX_PUBLIC_SYSCALL  (MIN_SYSCALL + 1024u)
-#define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE)
+// __ARM_NR_BASE is __NR_SYSCALL_BASE + 0xf0000u
+#define MIN_PRIVATE_SYSCALL 0xf0000u
 #define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u)
-#define MIN_GHOST_SYSCALL   ((unsigned int)__ARM_NR_BASE + 0xfff0u)
+#define MIN_GHOST_SYSCALL   (MIN_PRIVATE_SYSCALL + 0xfff0u)
 #define MAX_SYSCALL         (MIN_GHOST_SYSCALL + 4u)
 
 #elif defined(__mips__) && (_MIPS_SIM == _ABIO32)
 
+#include <asm/unistd.h>  // for __NR_O32_Linux and __NR_Linux_syscalls
 #define MIN_SYSCALL         __NR_O32_Linux
 #define MAX_PUBLIC_SYSCALL  (MIN_SYSCALL + __NR_Linux_syscalls)
 #define MAX_SYSCALL         MAX_PUBLIC_SYSCALL
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index f508b30..d4d5280 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -5,7 +5,6 @@
 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
 
 #include <errno.h>
-#include <linux/filter.h>
 #include <sys/syscall.h>
 
 #include <limits>
@@ -21,6 +20,7 @@
 #include "sandbox/linux/bpf_dsl/syscall_set.h"
 #include "sandbox/linux/bpf_dsl/verifier.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h
index 7fd0e67..7f4866d 100644
--- a/sandbox/linux/bpf_dsl/seccomp_macros.h
+++ b/sandbox/linux/bpf_dsl/seccomp_macros.h
@@ -5,9 +5,6 @@
 #ifndef SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_
 #define SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_
 
-#include <asm/unistd.h>
-#include <linux/filter.h>
-
 #include <sys/cdefs.h>
 // Old Bionic versions do not have sys/user.h.  The if can be removed once we no
 // longer need to support these old Bionic versions.
diff --git a/sandbox/linux/bpf_dsl/verifier.cc b/sandbox/linux/bpf_dsl/verifier.cc
index adbc960..417c663 100644
--- a/sandbox/linux/bpf_dsl/verifier.cc
+++ b/sandbox/linux/bpf_dsl/verifier.cc
@@ -15,6 +15,7 @@
 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
 #include "sandbox/linux/bpf_dsl/syscall_set.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 4305b41..7724223 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -278,18 +278,18 @@
     { 'target_name': 'sandbox_services_headers',
       'type': 'none',
       'sources': [
-        'system_headers/android_arm64_ucontext.h',
-        'system_headers/android_arm_ucontext.h',
-        'system_headers/android_futex.h',
-        'system_headers/android_i386_ucontext.h',
-        'system_headers/android_mips_ucontext.h',
-        'system_headers/android_ucontext.h',
         'system_headers/arm64_linux_syscalls.h',
+        'system_headers/arm64_linux_ucontext.h',
         'system_headers/arm_linux_syscalls.h',
+        'system_headers/arm_linux_ucontext.h',
         'system_headers/capability.h',
+        'system_headers/i386_linux_ucontext.h',
+        'system_headers/linux_futex.h',
         'system_headers/linux_seccomp.h',
         'system_headers/linux_syscalls.h',
+        'system_headers/linux_ucontext.h',
         'system_headers/mips_linux_syscalls.h',
+        'system_headers/mips_linux_ucontext.h',
         'system_headers/x86_32_linux_syscalls.h',
         'system_headers/x86_64_linux_syscalls.h',
       ],
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index c558a0d..ce7817d 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -53,6 +53,7 @@
         'seccomp-bpf/errorcode_unittest.cc',
         'seccomp-bpf/sandbox_bpf_unittest.cc',
         'seccomp-bpf/syscall_unittest.cc',
+        'seccomp-bpf/trap_unittest.cc',
       ],
     }],
     [ 'compile_credentials==1', {
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index e6e8934..614849f 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/futex.h>
 #include <sched.h>
 #include <signal.h>
 #include <string.h>
@@ -32,7 +31,7 @@
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/services/thread_helpers.h"
-#include "sandbox/linux/system_headers/android_futex.h"
+#include "sandbox/linux/system_headers/linux_futex.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
 #include "sandbox/linux/tests/test_utils.h"
 #include "sandbox/linux/tests/unit_tests.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 21fd4d7..d449156 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -9,7 +9,6 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
-#include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "build/build_config.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
index 38e02bf..c64e994 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
@@ -5,7 +5,8 @@
 #ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SIGSYS_HANDLERS_H_
 #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SIGSYS_HANDLERS_H_
 
-#include "base/basictypes.h"
+#include <stdint.h>
+
 #include "build/build_config.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
 #include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index c081b29..282e727 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -7,10 +7,10 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <fcntl.h>
-#include <linux/futex.h>
 #include <linux/net.h>
 #include <sched.h>
 #include <signal.h>
+#include <stdint.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
@@ -21,7 +21,6 @@
 #include <time.h>
 #include <unistd.h>
 
-#include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/time/time.h"
@@ -30,12 +29,11 @@
 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/system_headers/linux_futex.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
 
 #if defined(OS_ANDROID)
 
-#include "sandbox/linux/system_headers/android_futex.h"
-
 #if !defined(F_DUPFD_CLOEXEC)
 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
 #endif
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
index 1dbd949..5ba6335 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
@@ -5,7 +5,7 @@
 #ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_SETS_H_
 #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_SETS_H_
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 #include "build/build_config.h"
 #include "sandbox/sandbox_export.h"
 
diff --git a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
index 1869913..7736c15 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
+++ b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
@@ -25,9 +25,9 @@
   explicit BPFTesterCompatibilityDelegate(TestFunction test_function)
       : aux_(), test_function_(test_function) {}
 
-  virtual ~BPFTesterCompatibilityDelegate() {}
+  ~BPFTesterCompatibilityDelegate() override {}
 
-  virtual scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
+  scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
     // The current method is guaranteed to only run in the child process
     // running the test. In this process, the current object is guaranteed
     // to live forever. So it's ok to pass aux_pointer_for_policy_ to
@@ -35,7 +35,7 @@
     return scoped_ptr<bpf_dsl::Policy>(new Policy(&aux_));
   }
 
-  virtual void RunTestFunction() override {
+  void RunTestFunction() override {
     // Run the actual test.
     // The current object is guaranteed to live forever in the child process
     // where this will run.
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests.h b/sandbox/linux/seccomp-bpf/bpf_tests.h
index 57de1dd..cc4debd 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests.h
+++ b/sandbox/linux/seccomp-bpf/bpf_tests.h
@@ -102,12 +102,12 @@
  public:
   explicit BPFTesterSimpleDelegate(void (*test_function)(void))
       : test_function_(test_function) {}
-  virtual ~BPFTesterSimpleDelegate() {}
+  ~BPFTesterSimpleDelegate() override {}
 
-  virtual scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
+  scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override {
     return scoped_ptr<bpf_dsl::Policy>(new PolicyClass());
   }
-  virtual void RunTestFunction() override {
+  void RunTestFunction() override {
     DCHECK(test_function_);
     test_function_();
   }
diff --git a/sandbox/linux/seccomp-bpf/die.cc b/sandbox/linux/seccomp-bpf/die.cc
index 777c9d1..3baf1f1 100644
--- a/sandbox/linux/seccomp-bpf/die.cc
+++ b/sandbox/linux/seccomp-bpf/die.cc
@@ -16,6 +16,8 @@
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "sandbox/linux/seccomp-bpf/syscall.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
 
 namespace sandbox {
 
@@ -32,7 +34,10 @@
   // to a defined state; but we have not way to verify whether we actually
   // succeeded in doing so. Nonetheless, triggering a fatal signal could help
   // us terminate.
-  signal(SIGSEGV, SIG_DFL);
+  struct sigaction sa = {};
+  sa.sa_handler = LINUX_SIG_DFL;
+  sa.sa_flags = LINUX_SA_RESTART;
+  sys_sigaction(LINUX_SIGSEGV, &sa, nullptr);
   Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0);
   if (*(volatile char*)0) {
   }
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index c96642e..239043e 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -11,7 +11,6 @@
 #endif
 
 #include <errno.h>
-#include <linux/filter.h>
 #include <sys/prctl.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -34,6 +33,7 @@
 #include "sandbox/linux/services/proc_util.h"
 #include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/services/thread_helpers.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
 
@@ -59,9 +59,40 @@
   return false;
 }
 
+// LG introduced a buggy syscall, sys_set_media_ext, with the same number as
+// seccomp. Return true if the current kernel has this buggy syscall.
+//
+// We want this to work with upcoming versions of seccomp, so we pass bogus
+// flags that are unlikely to ever be used by the kernel. A normal kernel would
+// return -EINVAL, but a buggy LG kernel would return 1.
+bool KernelHasLGBug() {
+#if defined(OS_ANDROID)
+  // sys_set_media will see this as NULL, which should be a safe (non-crashing)
+  // way to invoke it. A genuine seccomp syscall will see it as
+  // SECCOMP_SET_MODE_STRICT.
+  const unsigned int operation = 0;
+  // Chosen by fair dice roll. Guaranteed to be random.
+  const unsigned int flags = 0xf7a46a5c;
+  const int rv = sys_seccomp(operation, flags, nullptr);
+  // A genuine kernel would return -EINVAL (which would set rv to -1 and errno
+  // to EINVAL), or at the very least return some kind of error (which would
+  // set rv to -1). Any other behavior indicates that whatever code received
+  // our syscall was not the real seccomp.
+  if (rv != -1) {
+    return true;
+  }
+#endif  // defined(OS_ANDROID)
+
+  return false;
+}
+
 // Check if the kernel supports seccomp-filter via the seccomp system call
 // and the TSYNC feature to enable seccomp on all threads.
 bool KernelSupportsSeccompTsync() {
+  if (KernelHasLGBug()) {
+    return false;
+  }
+
   errno = 0;
   const int rv =
       sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, nullptr);
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
index cb051d2..321ea9a 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
@@ -5,13 +5,13 @@
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h"
 
 #include <fcntl.h>
-#include <linux/filter.h>
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/seccomp-bpf/die.h"
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/system_headers/linux_filter.h"
 #include "sandbox/linux/tests/unit_tests.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index 9fce1da..3b3c8db 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -4,10 +4,9 @@
 
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 
-#include <asm/unistd.h>
 #include <errno.h>
+#include <stdint.h>
 
-#include "base/basictypes.h"
 #include "base/logging.h"
 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
 
diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h
index dfb44eb..ccfc88d 100644
--- a/sandbox/linux/seccomp-bpf/syscall.h
+++ b/sandbox/linux/seccomp-bpf/syscall.h
@@ -9,13 +9,9 @@
 #include <stdint.h>
 
 #include "base/macros.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
 #include "sandbox/sandbox_export.h"
 
-// Android's signal.h doesn't define ucontext etc.
-#if defined(OS_ANDROID)
-#include "sandbox/linux/system_headers/android_ucontext.h"
-#endif
-
 namespace sandbox {
 
 // This purely static class can be used to perform system calls with some
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index 6bd3288..5fdee6c 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -13,7 +13,6 @@
 
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/posix/eintr_wrapper.h"
 #include "build/build_config.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index 145e624..79b7569 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -17,12 +17,9 @@
 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
 #include "sandbox/linux/seccomp-bpf/die.h"
 #include "sandbox/linux/seccomp-bpf/syscall.h"
+#include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
-
-// Android's signal.h doesn't define ucontext etc.
-#if defined(OS_ANDROID)
-#include "sandbox/linux/system_headers/android_ucontext.h"
-#endif
+#include "sandbox/linux/system_headers/linux_signal.h"
 
 namespace {
 
@@ -53,13 +50,13 @@
 // possibly even worse.
 bool GetIsInSigHandler(const ucontext_t* ctx) {
   // Note: on Android, sigismember does not take a pointer to const.
-  return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS);
+  return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), LINUX_SIGBUS);
 }
 
 void SetIsInSigHandler() {
   sigset_t mask;
-  if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) ||
-      sigprocmask(SIG_BLOCK, &mask, NULL)) {
+  if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGBUS) ||
+      sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) {
     SANDBOX_DIE("Failed to block SIGBUS");
   }
 }
@@ -82,10 +79,13 @@
       has_unsafe_traps_(false) {
   // Set new SIGSYS handler
   struct sigaction sa = {};
-  sa.sa_sigaction = SigSysAction;
-  sa.sa_flags = SA_SIGINFO | SA_NODEFER;
-  struct sigaction old_sa;
-  if (sigaction(SIGSYS, &sa, &old_sa) < 0) {
+  // In some toolchain, sa_sigaction is not declared in struct sigaction.
+  // So, here cast the pointer to the sa_handler's type. This works because
+  // |sa_handler| and |sa_sigaction| shares the same memory.
+  sa.sa_handler = reinterpret_cast<void (*)(int)>(SigSysAction);
+  sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER;
+  struct sigaction old_sa = {};
+  if (sys_sigaction(LINUX_SIGSYS, &sa, &old_sa) < 0) {
     SANDBOX_DIE("Failed to configure SIGSYS handler");
   }
 
@@ -99,8 +99,8 @@
 
   // Unmask SIGSYS
   sigset_t mask;
-  if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) ||
-      sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
+  if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGSYS) ||
+      sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) {
     SANDBOX_DIE("Failed to configure SIGSYS handler");
   }
 }
@@ -120,7 +120,7 @@
   return global_trap_;
 }
 
-void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) {
+void Trap::SigSysAction(int nr, LinuxSigInfo* info, void* void_context) {
   if (!global_trap_) {
     RAW_SANDBOX_DIE(
         "This can't happen. Found no global singleton instance "
@@ -129,7 +129,7 @@
   global_trap_->SigSys(nr, info, void_context);
 }
 
-void Trap::SigSys(int nr, siginfo_t* info, void* void_context) {
+void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) {
   // Signal handlers should always preserve "errno". Otherwise, we could
   // trigger really subtle bugs.
   const int old_errno = errno;
@@ -137,7 +137,7 @@
   // Various sanity checks to make sure we actually received a signal
   // triggered by a BPF filter. If something else triggered SIGSYS
   // (e.g. kill()), there is really nothing we can do with this signal.
-  if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
+  if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
       info->si_errno <= 0 ||
       static_cast<size_t>(info->si_errno) > trap_array_size_) {
     // ATI drivers seem to send SIGSYS, so this cannot be FATAL.
diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h
index 4073bfe..bbddeb7 100644
--- a/sandbox/linux/seccomp-bpf/trap.h
+++ b/sandbox/linux/seccomp-bpf/trap.h
@@ -5,13 +5,13 @@
 #ifndef SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__
 #define SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__
 
-#include <signal.h>
 #include <stdint.h>
 
 #include <map>
 
 #include "base/macros.h"
 #include "sandbox/linux/bpf_dsl/trap_registry.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
 #include "sandbox/sandbox_export.h"
 
 namespace sandbox {
@@ -57,11 +57,11 @@
   // break subsequent system calls that trigger a SIGSYS.
   ~Trap() = delete;
 
-  static void SigSysAction(int nr, siginfo_t* info, void* void_context);
+  static void SigSysAction(int nr, LinuxSigInfo* info, void* void_context);
 
   // Make sure that SigSys is not inlined in order to get slightly better crash
   // dumps.
-  void SigSys(int nr, siginfo_t* info, void* void_context)
+  void SigSys(int nr, LinuxSigInfo* info, void* void_context)
       __attribute__((noinline));
   // We have a global singleton that handles all of our SIGSYS traps. This
   // variable must never be deallocated after it has been set up initially, as
diff --git a/sandbox/linux/seccomp-bpf/trap_unittest.cc b/sandbox/linux/seccomp-bpf/trap_unittest.cc
new file mode 100644
index 0000000..3d95e34
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/trap_unittest.cc
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/linux/seccomp-bpf/trap.h"
+
+#include <signal.h>
+
+#include "sandbox/linux/tests/unit_tests.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+namespace {
+
+#if !defined(THREAD_SANITIZER)
+SANDBOX_TEST_ALLOW_NOISE(Trap, SigSysAction) {
+  // This creates a global Trap instance, and registers the signal handler
+  // (Trap::SigSysAction).
+  Trap::Registry();
+
+  // Send SIGSYS to self. If signal handler (SigSysAction) is not registered,
+  // the process will be terminated with status code -SIGSYS.
+  // Note that, SigSysAction handler would output an error message
+  // "Unexpected SIGSYS received." so it is necessary to allow the noise.
+  raise(SIGSYS);
+}
+#endif
+
+}  // namespace
+}  // namespace sandbox
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index 2e66d97..35bb4dc 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -6,13 +6,13 @@
 
 #include <errno.h>
 #include <signal.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -27,6 +27,7 @@
 #include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/services/thread_helpers.h"
 #include "sandbox/linux/system_headers/capability.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
 
 namespace sandbox {
 
@@ -40,8 +41,8 @@
 bool GetRESIds(uid_t* resuid, gid_t* resgid) {
   uid_t ruid, euid, suid;
   gid_t rgid, egid, sgid;
-  PCHECK(getresuid(&ruid, &euid, &suid) == 0);
-  PCHECK(getresgid(&rgid, &egid, &sgid) == 0);
+  PCHECK(sys_getresuid(&ruid, &euid, &suid) == 0);
+  PCHECK(sys_getresgid(&rgid, &egid, &sgid) == 0);
   const bool uids_are_equal = (ruid == euid) && (ruid == suid);
   const bool gids_are_equal = (rgid == egid) && (rgid == sgid);
   if (!uids_are_equal || !gids_are_equal) return false;
@@ -53,7 +54,7 @@
 const int kExitSuccess = 0;
 
 int ChrootToSelfFdinfo(void*) {
-  RAW_CHECK(chroot("/proc/self/fdinfo/") == 0);
+  RAW_CHECK(sys_chroot("/proc/self/fdinfo/") == 0);
 
   // CWD is essentially an implicit file descriptor, so be careful to not
   // leave it behind.
@@ -89,9 +90,10 @@
 #else
 #error "Unsupported architecture"
 #endif
+
   pid = clone(ChrootToSelfFdinfo, stack,
-              CLONE_VM | CLONE_VFORK | CLONE_FS | SIGCHLD, nullptr, nullptr,
-              nullptr, nullptr);
+              CLONE_VM | CLONE_VFORK | CLONE_FS | LINUX_SIGCHLD, nullptr,
+              nullptr, nullptr, nullptr);
   PCHECK(pid != -1);
 
   int status = -1;
@@ -110,23 +112,24 @@
          error == ENOSYS);
 }
 
-// Converts a LinuxCapability to the corresponding Linux CAP_XXX value.
-int LinuxCapabilityToKernelValue(LinuxCapability cap) {
+// Converts a Capability to the corresponding Linux CAP_XXX value.
+int CapabilityToKernelValue(Credentials::Capability cap) {
   switch (cap) {
-    case LinuxCapability::kCapSysChroot:
+    case Credentials::Capability::SYS_CHROOT:
       return CAP_SYS_CHROOT;
-    case LinuxCapability::kCapSysAdmin:
+    case Credentials::Capability::SYS_ADMIN:
       return CAP_SYS_ADMIN;
   }
 
-  LOG(FATAL) << "Invalid LinuxCapability: " << static_cast<int>(cap);
+  LOG(FATAL) << "Invalid Capability: " << static_cast<int>(cap);
   return 0;
 }
 
 }  // namespace.
 
+// static
 bool Credentials::DropAllCapabilities(int proc_fd) {
-  if (!SetCapabilities(proc_fd, std::vector<LinuxCapability>())) {
+  if (!SetCapabilities(proc_fd, std::vector<Capability>())) {
     return false;
   }
 
@@ -134,14 +137,40 @@
   return true;
 }
 
+// static
 bool Credentials::DropAllCapabilities() {
   base::ScopedFD proc_fd(ProcUtil::OpenProc());
   return Credentials::DropAllCapabilities(proc_fd.get());
 }
 
 // static
+bool Credentials::DropAllCapabilitiesOnCurrentThread() {
+  return SetCapabilitiesOnCurrentThread(std::vector<Capability>());
+}
+
+// static
+bool Credentials::SetCapabilitiesOnCurrentThread(
+    const std::vector<Capability>& caps) {
+  struct cap_hdr hdr = {};
+  hdr.version = _LINUX_CAPABILITY_VERSION_3;
+  struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
+
+  // Initially, cap has no capability flags set. Enable the effective and
+  // permitted flags only for the requested capabilities.
+  for (const Capability cap : caps) {
+    const int cap_num = CapabilityToKernelValue(cap);
+    const size_t index = CAP_TO_INDEX(cap_num);
+    const uint32_t mask = CAP_TO_MASK(cap_num);
+    data[index].effective |= mask;
+    data[index].permitted |= mask;
+  }
+
+  return sys_capset(&hdr, data) == 0;
+}
+
+// static
 bool Credentials::SetCapabilities(int proc_fd,
-                                  const std::vector<LinuxCapability>& caps) {
+                                  const std::vector<Capability>& caps) {
   DCHECK_LE(0, proc_fd);
 
 #if !defined(THREAD_SANITIZER)
@@ -150,21 +179,7 @@
   CHECK(ThreadHelpers::IsSingleThreaded(proc_fd));
 #endif
 
-  struct cap_hdr hdr = {};
-  hdr.version = _LINUX_CAPABILITY_VERSION_3;
-  struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
-
-  // Initially, cap has no capability flags set. Enable the effective and
-  // permitted flags only for the requested capabilities.
-  for (const LinuxCapability cap : caps) {
-    const int cap_num = LinuxCapabilityToKernelValue(cap);
-    const size_t index = CAP_TO_INDEX(cap_num);
-    const uint32_t mask = CAP_TO_MASK(cap_num);
-    data[index].effective |= mask;
-    data[index].permitted |= mask;
-  }
-
-  return sys_capset(&hdr, data) == 0;
+  return SetCapabilitiesOnCurrentThread(caps);
 }
 
 bool Credentials::HasAnyCapability() {
@@ -183,14 +198,14 @@
   return false;
 }
 
-bool Credentials::HasCapability(LinuxCapability cap) {
+bool Credentials::HasCapability(Capability cap) {
   struct cap_hdr hdr = {};
   hdr.version = _LINUX_CAPABILITY_VERSION_3;
   struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
 
   PCHECK(sys_capget(&hdr, data) == 0);
 
-  const int cap_num = LinuxCapabilityToKernelValue(cap);
+  const int cap_num = CapabilityToKernelValue(cap);
   const size_t index = CAP_TO_INDEX(cap_num);
   const uint32_t mask = CAP_TO_MASK(cap_num);
 
@@ -247,7 +262,7 @@
     DVLOG(1) << "uids or gids differ!";
     return false;
   }
-  int ret = unshare(CLONE_NEWUSER);
+  int ret = sys_unshare(CLONE_NEWUSER);
   if (ret) {
     const int unshare_errno = errno;
     VLOG(1) << "Looks like unprivileged CLONE_NEWUSER may not be available "
diff --git a/sandbox/linux/services/credentials.h b/sandbox/linux/services/credentials.h
index 83f2c70..0001dc7 100644
--- a/sandbox/linux/services/credentials.h
+++ b/sandbox/linux/services/credentials.h
@@ -14,26 +14,26 @@
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "sandbox/linux/system_headers/capability.h"
 #include "sandbox/sandbox_export.h"
 
 namespace sandbox {
 
-// For brevity, we only expose enums for the subset of capabilities we use.
-// This can be expanded as the need arises.
-enum class LinuxCapability {
-  kCapSysChroot,
-  kCapSysAdmin,
-};
-
 // This class should be used to manipulate the current process' credentials.
 // It is currently a stub used to manipulate POSIX.1e capabilities as
 // implemented by the Linux kernel.
 class SANDBOX_EXPORT Credentials {
  public:
+  // For brevity, we only expose enums for the subset of capabilities we use.
+  // This can be expanded as the need arises.
+  enum class Capability {
+    SYS_CHROOT,
+    SYS_ADMIN,
+  };
+
   // Drop all capabilities in the effective, inheritable and permitted sets for
   // the current thread. For security reasons, since capabilities are
   // per-thread, the caller is responsible for ensuring it is single-threaded
@@ -46,12 +46,20 @@
   // Sets the effective and permitted capability sets for the current thread to
   // the list of capabiltiies in |caps|. All other capability flags are cleared.
   static bool SetCapabilities(int proc_fd,
-                              const std::vector<LinuxCapability>& caps)
+                              const std::vector<Capability>& caps)
       WARN_UNUSED_RESULT;
 
+  // Versions of the above functions which do not check that the process is
+  // single-threaded. After calling these functions, capabilities of other
+  // threads will not be changed. This is dangerous, do not use unless you nkow
+  // what you are doing.
+  static bool DropAllCapabilitiesOnCurrentThread() WARN_UNUSED_RESULT;
+  static bool SetCapabilitiesOnCurrentThread(
+      const std::vector<Capability>& caps) WARN_UNUSED_RESULT;
+
   // Returns true if the current thread has either the effective, permitted, or
   // inheritable flag set for the given capability.
-  static bool HasCapability(LinuxCapability cap);
+  static bool HasCapability(Capability cap);
 
   // Return true iff there is any capability in any of the capabilities sets
   // of the current thread.
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc
index db19f6f..6b93c86 100644
--- a/sandbox/linux/services/credentials_unittest.cc
+++ b/sandbox/linux/services/credentials_unittest.cc
@@ -177,16 +177,17 @@
 
   base::ScopedFD proc_fd(ProcUtil::OpenProc());
 
-  CHECK(Credentials::HasCapability(LinuxCapability::kCapSysAdmin));
-  CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
+  CHECK(Credentials::HasCapability(Credentials::Capability::SYS_ADMIN));
+  CHECK(Credentials::HasCapability(Credentials::Capability::SYS_CHROOT));
 
-  const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
+  std::vector<Credentials::Capability> caps;
+  caps.push_back(Credentials::Capability::SYS_CHROOT);
   CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
 
-  CHECK(!Credentials::HasCapability(LinuxCapability::kCapSysAdmin));
-  CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
+  CHECK(!Credentials::HasCapability(Credentials::Capability::SYS_ADMIN));
+  CHECK(Credentials::HasCapability(Credentials::Capability::SYS_CHROOT));
 
-  const std::vector<LinuxCapability> no_caps;
+  const std::vector<Credentials::Capability> no_caps;
   CHECK(Credentials::SetCapabilities(proc_fd.get(), no_caps));
   CHECK(!Credentials::HasAnyCapability());
 }
@@ -198,10 +199,11 @@
 
   base::ScopedFD proc_fd(ProcUtil::OpenProc());
 
-  CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot));
+  CHECK(Credentials::HasCapability(Credentials::Capability::SYS_CHROOT));
   PCHECK(chroot("/") == 0);
 
-  const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
+  std::vector<Credentials::Capability> caps;
+  caps.push_back(Credentials::Capability::SYS_CHROOT);
   CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
   PCHECK(chroot("/") == 0);
 
@@ -216,7 +218,8 @@
 
   base::ScopedFD proc_fd(ProcUtil::OpenProc());
 
-  const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot};
+  std::vector<Credentials::Capability> caps;
+  caps.push_back(Credentials::Capability::SYS_CHROOT);
   CHECK(Credentials::SetCapabilities(proc_fd.get(), caps));
 
   ScopedCap actual_cap(cap_get_proc());
diff --git a/sandbox/linux/services/namespace_sandbox.cc b/sandbox/linux/services/namespace_sandbox.cc
index 0f371eb..2379644 100644
--- a/sandbox/linux/services/namespace_sandbox.cc
+++ b/sandbox/linux/services/namespace_sandbox.cc
@@ -5,6 +5,7 @@
 #include "sandbox/linux/services/namespace_sandbox.h"
 
 #include <sched.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -17,15 +18,22 @@
 #include "base/environment.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/launch.h"
 #include "base/process/process.h"
+#include "sandbox/linux/services/credentials.h"
 #include "sandbox/linux/services/namespace_utils.h"
 
 namespace sandbox {
 
 namespace {
 
+const char kSandboxUSERNSEnvironmentVarName[] = "SBX_USER_NS";
+const char kSandboxPIDNSEnvironmentVarName[] = "SBX_PID_NS";
+const char kSandboxNETNSEnvironmentVarName[] = "SBX_NET_NS";
+
+#if !defined(OS_NACL_NONSFI)
 class WriteUidGidMapDelegate : public base::LaunchOptions::PreExecDelegate {
  public:
   WriteUidGidMapDelegate()
@@ -58,12 +66,24 @@
   (*environ)[env_var] = value ? "1" : "";
 }
 
-const char kSandboxUSERNSEnvironmentVarName[] = "SBX_USER_NS";
-const char kSandboxPIDNSEnvironmentVarName[] = "SBX_PID_NS";
-const char kSandboxNETNSEnvironmentVarName[] = "SBX_NET_NS";
+// Linux supports up to 64 signals. This should be updated if that ever changes.
+int g_signal_exit_codes[64];
+
+void TerminationSignalHandler(int sig) {
+  // Return a special exit code so that the process is detected as terminated by
+  // a signal.
+  const size_t sig_idx = static_cast<size_t>(sig);
+  if (sig_idx < arraysize(g_signal_exit_codes)) {
+    _exit(g_signal_exit_codes[sig_idx]);
+  }
+
+  _exit(NamespaceSandbox::kDefaultExitCode);
+}
+#endif  // !defined(OS_NACL_NONSFI)
 
 }  // namespace
 
+#if !defined(OS_NACL_NONSFI)
 // static
 base::Process NamespaceSandbox::LaunchProcess(
     const base::CommandLine& cmdline,
@@ -111,6 +131,66 @@
 }
 
 // static
+pid_t NamespaceSandbox::ForkInNewPidNamespace(bool drop_capabilities_in_child) {
+  const pid_t pid =
+      base::ForkWithFlags(CLONE_NEWPID | SIGCHLD, nullptr, nullptr);
+  if (pid < 0) {
+    return pid;
+  }
+
+  if (pid == 0) {
+    DCHECK_EQ(1, getpid());
+    if (drop_capabilities_in_child) {
+      // Since we just forked, we are single-threaded, so this should be safe.
+      CHECK(Credentials::DropAllCapabilitiesOnCurrentThread());
+    }
+    return 0;
+  }
+
+  return pid;
+}
+
+// static
+void NamespaceSandbox::InstallDefaultTerminationSignalHandlers() {
+  static const int kDefaultTermSignals[] = {
+      SIGHUP, SIGINT, SIGABRT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2,
+  };
+
+  for (const int sig : kDefaultTermSignals) {
+    InstallTerminationSignalHandler(sig, kDefaultExitCode);
+  }
+}
+
+// static
+bool NamespaceSandbox::InstallTerminationSignalHandler(
+    int sig,
+    int exit_code) {
+  struct sigaction old_action;
+  PCHECK(sigaction(sig, nullptr, &old_action) == 0);
+
+  if (old_action.sa_flags & SA_SIGINFO &&
+      old_action.sa_sigaction != nullptr) {
+    return false;
+  } else if (old_action.sa_handler != SIG_DFL) {
+    return false;
+  }
+
+  const size_t sig_idx = static_cast<size_t>(sig);
+  CHECK_LT(sig_idx, arraysize(g_signal_exit_codes));
+
+  DCHECK_GE(exit_code, 0);
+  DCHECK_LT(exit_code, 256);
+
+  g_signal_exit_codes[sig_idx] = exit_code;
+
+  struct sigaction action = {};
+  action.sa_handler = &TerminationSignalHandler;
+  PCHECK(sigaction(sig, &action, nullptr) == 0);
+  return true;
+}
+#endif  // !defined(OS_NACL_NONSFI)
+
+// static
 bool NamespaceSandbox::InNewUserNamespace() {
   return getenv(kSandboxUSERNSEnvironmentVarName) != nullptr;
 }
diff --git a/sandbox/linux/services/namespace_sandbox.h b/sandbox/linux/services/namespace_sandbox.h
index b92f581..80097fb 100644
--- a/sandbox/linux/services/namespace_sandbox.h
+++ b/sandbox/linux/services/namespace_sandbox.h
@@ -5,6 +5,8 @@
 #ifndef SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_
 #define SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_
 
+#include <sys/types.h>
+
 #include <string>
 #include <vector>
 
@@ -35,6 +37,9 @@
 //    Credentials::DropAllCapabilities().
 class SANDBOX_EXPORT NamespaceSandbox {
  public:
+#if !defined(OS_NACL_NONSFI)
+  static const int kDefaultExitCode = 1;
+
   // Launch a new process inside its own user/PID/network namespaces (depending
   // on kernel support). Requires at a minimum that user namespaces are
   // supported (use Credentials::CanCreateProcessInNewUserNS to check this).
@@ -47,6 +52,39 @@
   static base::Process LaunchProcess(const std::vector<std::string>& argv,
                                      const base::LaunchOptions& options);
 
+  // Forks a process in its own PID namespace. The child process is the init
+  // process inside of the PID namespace, so if the child needs to fork further,
+  // it should call CreateInitProcessReaper, which turns the init process into a
+  // reaper process.
+  //
+  // Otherwise, the child should setup handlers for signals which should
+  // terminate the process using InstallDefaultTerminationSignalHandlers or
+  // InstallTerminationSignalHandler. This works around the fact that init
+  // processes ignore such signals unless they have an explicit handler set.
+  //
+  // This function requries CAP_SYS_ADMIN. If |drop_capabilities_in_child| is
+  // true, then capabilities are dropped in the child.
+  static pid_t ForkInNewPidNamespace(bool drop_capabilities_in_child);
+
+  // Installs a signal handler for:
+  //
+  // SIGHUP, SIGINT, SIGABRT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
+  //
+  // that exits with kDefaultExitCode. These are signals whose default action is
+  // to terminate the program (apart from SIGILL, SIGFPE, and SIGSEGV, which
+  // will still terminate the process if e.g. an illegal instruction is
+  // encountered, etc.).
+  //
+  // If any of these already had a signal handler installed, this function will
+  // not override them.
+  static void InstallDefaultTerminationSignalHandlers();
+
+  // Installs a signal handler for |sig| which exits with |exit_code|. If a
+  // signal handler was already present for |sig|, does nothing and returns
+  // false.
+  static bool InstallTerminationSignalHandler(int sig, int exit_code);
+#endif  // !defined(OS_NACL_NONSFI)
+
   // Returns whether the namespace sandbox created a new user, PID, and network
   // namespace. In particular, InNewUserNamespace should return true iff the
   // process was started via this class.
diff --git a/sandbox/linux/services/namespace_sandbox_unittest.cc b/sandbox/linux/services/namespace_sandbox_unittest.cc
index 8bb0bff..547ef67 100644
--- a/sandbox/linux/services/namespace_sandbox_unittest.cc
+++ b/sandbox/linux/services/namespace_sandbox_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "sandbox/linux/services/namespace_sandbox.h"
 
+#include <signal.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -118,6 +119,99 @@
   TestProc("NestedNamespaceSandbox");
 }
 
+const int kNormalExitCode = 0;
+const int kSignalTerminationExitCode = 255;
+
+// Ensure that CHECK(false) is distinguishable from _exit(kNormalExitCode).
+// Allowing noise since CHECK(false) will write a stack trace to stderr.
+SANDBOX_TEST_ALLOW_NOISE(ForkInNewPidNamespace, CheckDoesNotReturnZero) {
+  if (!Credentials::CanCreateProcessInNewUserNS()) {
+    return;
+  }
+
+  CHECK(sandbox::Credentials::MoveToNewUserNS());
+  const pid_t pid = NamespaceSandbox::ForkInNewPidNamespace(
+      /*drop_capabilities_in_child=*/true);
+  CHECK_GE(pid, 0);
+
+  if (pid == 0) {
+    CHECK(false);
+    _exit(kNormalExitCode);
+  }
+
+  int status;
+  PCHECK(waitpid(pid, &status, 0) == pid);
+  if (WIFEXITED(status)) {
+    CHECK_NE(kNormalExitCode, WEXITSTATUS(status));
+  }
+}
+
+SANDBOX_TEST(ForkInNewPidNamespace, BasicUsage) {
+  if (!Credentials::CanCreateProcessInNewUserNS()) {
+    return;
+  }
+
+  CHECK(sandbox::Credentials::MoveToNewUserNS());
+  const pid_t pid = NamespaceSandbox::ForkInNewPidNamespace(
+      /*drop_capabilities_in_child=*/true);
+  CHECK_GE(pid, 0);
+
+  if (pid == 0) {
+    CHECK_EQ(1, getpid());
+    CHECK(!Credentials::HasAnyCapability());
+    _exit(kNormalExitCode);
+  }
+
+  int status;
+  PCHECK(waitpid(pid, &status, 0) == pid);
+  CHECK(WIFEXITED(status));
+  CHECK_EQ(kNormalExitCode, WEXITSTATUS(status));
+}
+
+SANDBOX_TEST(ForkInNewPidNamespace, ExitWithSignal) {
+  if (!Credentials::CanCreateProcessInNewUserNS()) {
+    return;
+  }
+
+  CHECK(sandbox::Credentials::MoveToNewUserNS());
+  const pid_t pid = NamespaceSandbox::ForkInNewPidNamespace(
+      /*drop_capabilities_in_child=*/true);
+  CHECK_GE(pid, 0);
+
+  if (pid == 0) {
+    CHECK_EQ(1, getpid());
+    CHECK(!Credentials::HasAnyCapability());
+    CHECK(NamespaceSandbox::InstallTerminationSignalHandler(
+        SIGTERM, kSignalTerminationExitCode));
+    while (true) {
+      raise(SIGTERM);
+    }
+  }
+
+  int status;
+  PCHECK(waitpid(pid, &status, 0) == pid);
+  CHECK(WIFEXITED(status));
+  CHECK_EQ(kSignalTerminationExitCode, WEXITSTATUS(status));
+}
+
+volatile sig_atomic_t signal_handler_called;
+void ExitSuccessfully(int sig) {
+  signal_handler_called = 1;
+}
+
+SANDBOX_TEST(InstallTerminationSignalHandler, DoesNotOverrideExistingHandlers) {
+  struct sigaction action = {};
+  action.sa_handler = &ExitSuccessfully;
+  PCHECK(sigaction(SIGUSR1, &action, nullptr) == 0);
+
+  NamespaceSandbox::InstallDefaultTerminationSignalHandlers();
+  CHECK(!NamespaceSandbox::InstallTerminationSignalHandler(
+            SIGUSR1, kSignalTerminationExitCode));
+
+  raise(SIGUSR1);
+  CHECK_EQ(1, signal_handler_called);
+}
+
 }  // namespace
 
 }  // namespace sandbox
diff --git a/sandbox/linux/services/resource_limits.h b/sandbox/linux/services/resource_limits.h
index 488a5c5..3464dab 100644
--- a/sandbox/linux/services/resource_limits.h
+++ b/sandbox/linux/services/resource_limits.h
@@ -7,7 +7,6 @@
 
 #include <sys/resource.h>
 
-#include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/services/scoped_process.cc b/sandbox/linux/services/scoped_process.cc
index 4433201..65af487 100644
--- a/sandbox/linux/services/scoped_process.cc
+++ b/sandbox/linux/services/scoped_process.cc
@@ -12,7 +12,6 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
diff --git a/sandbox/linux/services/scoped_process.h b/sandbox/linux/services/scoped_process.h
index a28131e..bddbd55 100644
--- a/sandbox/linux/services/scoped_process.h
+++ b/sandbox/linux/services/scoped_process.h
@@ -5,8 +5,8 @@
 #ifndef SANDBOX_LINUX_SERVICES_SCOPED_PROCESS_H_
 #define SANDBOX_LINUX_SERVICES_SCOPED_PROCESS_H_
 
-#include "base/basictypes.h"
 #include "base/callback_forward.h"
+#include "base/macros.h"
 #include "base/process/process_handle.h"
 #include "sandbox/sandbox_export.h"
 
diff --git a/sandbox/linux/services/scoped_process_unittest.cc b/sandbox/linux/services/scoped_process_unittest.cc
index 82b85b9..8bd2847 100644
--- a/sandbox/linux/services/scoped_process_unittest.cc
+++ b/sandbox/linux/services/scoped_process_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "sandbox/linux/services/scoped_process.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -9,7 +11,6 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/file_util.h"
@@ -18,7 +19,6 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
-#include "sandbox/linux/services/scoped_process.h"
 #include "sandbox/linux/tests/unit_tests.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc
index 5a4045b..fdfcb94 100644
--- a/sandbox/linux/services/syscall_wrappers.cc
+++ b/sandbox/linux/services/syscall_wrappers.cc
@@ -12,11 +12,14 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <cstring>
 
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/third_party/valgrind/valgrind.h"
 #include "build/build_config.h"
+#include "sandbox/linux/system_headers/capability.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
 
 namespace sandbox {
@@ -45,6 +48,8 @@
     RAW_LOG(FATAL, "Invalid usage of sys_clone");
   }
 
+  if (ptid) MSAN_UNPOISON(ptid, sizeof(*ptid));
+  if (ctid) MSAN_UNPOISON(ctid, sizeof(*ctid));
   // See kernel/fork.c in Linux. There is different ordering of sys_clone
   // parameters depending on CONFIG_CLONE_BACKWARDS* configuration options.
 #if defined(ARCH_CPU_X86_64)
@@ -74,15 +79,154 @@
                   int resource,
                   const struct rlimit64* new_limit,
                   struct rlimit64* old_limit) {
-  return syscall(__NR_prlimit64, pid, resource, new_limit, old_limit);
+  int res = syscall(__NR_prlimit64, pid, resource, new_limit, old_limit);
+  if (res == 0 && old_limit) MSAN_UNPOISON(old_limit, sizeof(*old_limit));
+  return res;
 }
 
 int sys_capget(cap_hdr* hdrp, cap_data* datap) {
-  return syscall(__NR_capget, hdrp, datap);
+  int res = syscall(__NR_capget, hdrp, datap);
+  if (res == 0) {
+    if (hdrp) MSAN_UNPOISON(hdrp, sizeof(*hdrp));
+    if (datap) MSAN_UNPOISON(datap, sizeof(*datap));
+  }
+  return res;
 }
 
 int sys_capset(cap_hdr* hdrp, const cap_data* datap) {
   return syscall(__NR_capset, hdrp, datap);
 }
 
+int sys_getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) {
+  int res;
+#if defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARMEL)
+  // On 32-bit x86 or 32-bit arm, getresuid supports 16bit values only.
+  // Use getresuid32 instead.
+  res = syscall(__NR_getresuid32, ruid, euid, suid);
+#else
+  res = syscall(__NR_getresuid, ruid, euid, suid);
+#endif
+  if (res == 0) {
+    if (ruid) MSAN_UNPOISON(ruid, sizeof(*ruid));
+    if (euid) MSAN_UNPOISON(euid, sizeof(*euid));
+    if (suid) MSAN_UNPOISON(suid, sizeof(*suid));
+  }
+  return res;
+}
+
+int sys_getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) {
+  int res;
+#if defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARMEL)
+  // On 32-bit x86 or 32-bit arm, getresgid supports 16bit values only.
+  // Use getresgid32 instead.
+  res = syscall(__NR_getresgid32, rgid, egid, sgid);
+#else
+  res = syscall(__NR_getresgid, rgid, egid, sgid);
+#endif
+  if (res == 0) {
+    if (rgid) MSAN_UNPOISON(rgid, sizeof(*rgid));
+    if (egid) MSAN_UNPOISON(egid, sizeof(*egid));
+    if (sgid) MSAN_UNPOISON(sgid, sizeof(*sgid));
+  }
+  return res;
+}
+
+int sys_chroot(const char* path) {
+  return syscall(__NR_chroot, path);
+}
+
+int sys_unshare(int flags) {
+  return syscall(__NR_unshare, flags);
+}
+
+int sys_sigprocmask(int how, const sigset_t* set, decltype(nullptr) oldset) {
+  // In some toolchain (in particular Android and PNaCl toolchain),
+  // sigset_t is 32 bits, but Linux ABI requires 64 bits.
+  uint64_t linux_value = 0;
+  std::memcpy(&linux_value, set, std::min(sizeof(sigset_t), sizeof(uint64_t)));
+  return syscall(__NR_rt_sigprocmask, how, &linux_value, nullptr,
+                 sizeof(linux_value));
+}
+
+#if defined(MEMORY_SANITIZER) || \
+    (defined(ARCH_CPU_X86_64) && defined(__GNUC__) && !defined(__clang__))
+// If MEMORY_SANITIZER is enabled, it is necessary to call sigaction() here,
+// rather than the direct syscall (sys_sigaction() defined by ourselves).
+// It is because, if MEMORY_SANITIZER is enabled, sigaction is wrapped, and
+// |act->sa_handler| is injected in order to unpoisonize the memory passed via
+// callback's arguments. Please see msan_interceptors.cc for more details.
+// So, if the direct syscall is used, as MEMORY_SANITIZER does not know about
+// it, sigaction() invocation in other places would be broken (in more precise,
+// returned |oldact| would have a broken |sa_handler| callback).
+// Practically, it would break NaCl's signal handler installation.
+// cf) native_client/src/trusted/service_runtime/linux/nacl_signal.c.
+//
+// Also on x86_64 architecture, we need naked function for rt_sigreturn.
+// However, there is no simple way to define it with GCC. Note that the body
+// of function is actually very small (only two instructions), but we need to
+// define much debug information in addition, otherwise backtrace() used by
+// base::StackTrace would not work so that some tests would fail.
+int sys_sigaction(int signum,
+                  const struct sigaction* act,
+                  struct sigaction* oldact) {
+  return sigaction(signum, act, oldact);
+}
+#else
+// struct sigaction is different ABI from the Linux's.
+struct KernelSigAction {
+  void (*kernel_handler)(int);
+  uint32_t sa_flags;
+  void (*sa_restorer)(void);
+  uint64_t sa_mask;
+};
+
+// On X86_64 arch, it is necessary to set sa_restorer always.
+#if defined(ARCH_CPU_X86_64)
+#if !defined(SA_RESTORER)
+#define SA_RESTORER 0x04000000
+#endif
+
+// rt_sigreturn is a special system call that interacts with the user land
+// stack. Thus, here prologue must not be created, which implies syscall()
+// does not work properly, too. Note that rt_sigreturn will never return.
+static __attribute__((naked)) void sys_rt_sigreturn() {
+  // Just invoke rt_sigreturn system call.
+  asm volatile ("syscall\n"
+                :: "a"(__NR_rt_sigreturn));
+}
+#endif
+
+int sys_sigaction(int signum,
+                  const struct sigaction* act,
+                  struct sigaction* oldact) {
+  KernelSigAction kernel_act = {};
+  if (act) {
+    kernel_act.kernel_handler = act->sa_handler;
+    std::memcpy(&kernel_act.sa_mask, &act->sa_mask,
+                std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask)));
+    kernel_act.sa_flags = act->sa_flags;
+
+#if defined(ARCH_CPU_X86_64)
+    if (!(kernel_act.sa_flags & SA_RESTORER)) {
+      kernel_act.sa_flags |= SA_RESTORER;
+      kernel_act.sa_restorer = sys_rt_sigreturn;
+    }
+#endif
+  }
+
+  KernelSigAction kernel_oldact = {};
+  int result = syscall(__NR_rt_sigaction, signum, act ? &kernel_act : nullptr,
+                       oldact ? &kernel_oldact : nullptr, sizeof(uint64_t));
+  if (result == 0 && oldact) {
+    oldact->sa_handler = kernel_oldact.kernel_handler;
+    sigemptyset(&oldact->sa_mask);
+    std::memcpy(&oldact->sa_mask, &kernel_oldact.sa_mask,
+                std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask)));
+    oldact->sa_flags = kernel_oldact.sa_flags;
+  }
+  return result;
+}
+
+#endif  // defined(MEMORY_SANITIZER)
+
 }  // namespace sandbox
diff --git a/sandbox/linux/services/syscall_wrappers.h b/sandbox/linux/services/syscall_wrappers.h
index 28cc3a7..581425a 100644
--- a/sandbox/linux/services/syscall_wrappers.h
+++ b/sandbox/linux/services/syscall_wrappers.h
@@ -5,6 +5,7 @@
 #ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
 #define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
 
+#include <signal.h>
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -56,6 +57,27 @@
 SANDBOX_EXPORT int sys_capset(struct cap_hdr* hdrp,
                               const struct cap_data* datap);
 
+// Some libcs do not expose getresuid/getresgid wrappers.
+SANDBOX_EXPORT int sys_getresuid(uid_t* ruid, uid_t* euid, uid_t* suid);
+SANDBOX_EXPORT int sys_getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid);
+
+// Some libcs do not expose a chroot wrapper.
+SANDBOX_EXPORT int sys_chroot(const char* path);
+
+// Some libcs do not expose a unshare wrapper.
+SANDBOX_EXPORT int sys_unshare(int flags);
+
+// Some libcs do not expose a sigprocmask. Note that oldset must be a nullptr,
+// because of some ABI gap between toolchain's and Linux's.
+SANDBOX_EXPORT int sys_sigprocmask(int how,
+                                   const sigset_t* set,
+                                   decltype(nullptr) oldset);
+
+// Some libcs do not expose a sigaction().
+SANDBOX_EXPORT int sys_sigaction(int signum,
+                                 const struct sigaction* act,
+                                 struct sigaction* oldact);
+
 }  // namespace sandbox
 
 #endif  // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
diff --git a/sandbox/linux/services/syscall_wrappers_unittest.cc b/sandbox/linux/services/syscall_wrappers_unittest.cc
index a8b48fe..1878ff3 100644
--- a/sandbox/linux/services/syscall_wrappers_unittest.cc
+++ b/sandbox/linux/services/syscall_wrappers_unittest.cc
@@ -8,11 +8,13 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <cstring>
 
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/third_party/valgrind/valgrind.h"
 #include "build/build_config.h"
+#include "sandbox/linux/system_headers/linux_signal.h"
 #include "sandbox/linux/tests/test_utils.h"
 #include "sandbox/linux/tests/unit_tests.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -60,6 +62,38 @@
   EXPECT_EQ(kSuccessExit, WEXITSTATUS(status));
 }
 
+TEST(SyscallWrappers, GetRESUid) {
+  uid_t ruid, euid, suid;
+  uid_t sys_ruid, sys_euid, sys_suid;
+  ASSERT_EQ(0, getresuid(&ruid, &euid, &suid));
+  ASSERT_EQ(0, sys_getresuid(&sys_ruid, &sys_euid, &sys_suid));
+  EXPECT_EQ(ruid, sys_ruid);
+  EXPECT_EQ(euid, sys_euid);
+  EXPECT_EQ(suid, sys_suid);
+}
+
+TEST(SyscallWrappers, GetRESGid) {
+  gid_t rgid, egid, sgid;
+  gid_t sys_rgid, sys_egid, sys_sgid;
+  ASSERT_EQ(0, getresgid(&rgid, &egid, &sgid));
+  ASSERT_EQ(0, sys_getresgid(&sys_rgid, &sys_egid, &sys_sgid));
+  EXPECT_EQ(rgid, sys_rgid);
+  EXPECT_EQ(egid, sys_egid);
+  EXPECT_EQ(sgid, sys_sgid);
+}
+
+TEST(SyscallWrappers, LinuxSigSet) {
+  sigset_t sigset;
+  ASSERT_EQ(0, sigemptyset(&sigset));
+  ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGSEGV));
+  ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGBUS));
+  uint64_t linux_sigset = 0;
+  std::memcpy(&linux_sigset, &sigset,
+              std::min(sizeof(sigset), sizeof(linux_sigset)));
+  EXPECT_EQ((1ULL << (LINUX_SIGSEGV - 1)) | (1ULL << (LINUX_SIGBUS - 1)),
+            linux_sigset);
+}
+
 }  // namespace
 
 }  // namespace sandbox
diff --git a/sandbox/linux/services/thread_helpers.cc b/sandbox/linux/services/thread_helpers.cc
index f80c8a8..80766a9 100644
--- a/sandbox/linux/services/thread_helpers.cc
+++ b/sandbox/linux/services/thread_helpers.cc
@@ -13,7 +13,6 @@
 
 #include <string>
 
-#include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/scoped_file.h"
diff --git a/sandbox/linux/services/thread_helpers.h b/sandbox/linux/services/thread_helpers.h
index 2915784..f4abdff 100644
--- a/sandbox/linux/services/thread_helpers.h
+++ b/sandbox/linux/services/thread_helpers.h
@@ -5,7 +5,7 @@
 #ifndef SANDBOX_LINUX_SERVICES_THREAD_HELPERS_H_
 #define SANDBOX_LINUX_SERVICES_THREAD_HELPERS_H_
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 #include "sandbox/sandbox_export.h"
 
 namespace base { class Thread; }
diff --git a/sandbox/linux/services/thread_helpers_unittests.cc b/sandbox/linux/services/thread_helpers_unittests.cc
index 8886516..7357a0c 100644
--- a/sandbox/linux/services/thread_helpers_unittests.cc
+++ b/sandbox/linux/services/thread_helpers_unittests.cc
@@ -10,7 +10,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/posix/eintr_wrapper.h"
diff --git a/sandbox/linux/services/yama.h b/sandbox/linux/services/yama.h
index 20c28ba..e6c5c45 100644
--- a/sandbox/linux/services/yama.h
+++ b/sandbox/linux/services/yama.h
@@ -5,8 +5,7 @@
 #ifndef SANDBOX_LINUX_SERVICES_YAMA_H_
 #define SANDBOX_LINUX_SERVICES_YAMA_H_
 
-#include "base/basictypes.h"
-#include "base/process/process_handle.h"
+#include "base/macros.h"
 #include "sandbox/sandbox_export.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/syscall_broker/broker_process.h b/sandbox/linux/syscall_broker/broker_process.h
index c23ac3c..8a512a0 100644
--- a/sandbox/linux/syscall_broker/broker_process.h
+++ b/sandbox/linux/syscall_broker/broker_process.h
@@ -8,8 +8,8 @@
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/callback_forward.h"
+#include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/pickle.h"
 #include "base/process/process.h"
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc
index ee284f2..bd7ef27 100644
--- a/sandbox/linux/syscall_broker/broker_process_unittest.cc
+++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -17,7 +17,6 @@
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
diff --git a/sandbox/linux/system_headers/android_arm_ucontext.h b/sandbox/linux/system_headers/android_arm_ucontext.h
deleted file mode 100644
index a380499..0000000
--- a/sandbox/linux/system_headers/android_arm_ucontext.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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.
-
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
-
-#if !defined(__BIONIC_HAVE_UCONTEXT_T)
-#include <asm/sigcontext.h>
-
-// We also need greg_t for the sandbox, include it in this header as well.
-typedef unsigned long greg_t;
-
-//typedef unsigned long sigset_t;
-typedef struct ucontext {
-  unsigned long   uc_flags;
-  struct ucontext  *uc_link;
-  stack_t     uc_stack;
-  struct sigcontext uc_mcontext;
-  sigset_t    uc_sigmask;
-  /* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */
-  int     __not_used[32 - (sizeof (sigset_t) / sizeof (int))];
-  /* Last for extensibility.  Eight byte aligned because some
-     coprocessors require eight byte alignment.  */
-  unsigned long   uc_regspace[128] __attribute__((__aligned__(8)));
-} ucontext_t;
-
-#else
-#include <sys/ucontext.h>
-#endif  // __BIONIC_HAVE_UCONTEXT_T
-
-#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_ucontext.h b/sandbox/linux/system_headers/android_ucontext.h
deleted file mode 100644
index 8e873be..0000000
--- a/sandbox/linux/system_headers/android_ucontext.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
-
-#if defined(__ANDROID__)
-
-#if defined(__arm__)
-#include "sandbox/linux/system_headers/android_arm_ucontext.h"
-#elif defined(__i386__)
-#include "sandbox/linux/system_headers/android_i386_ucontext.h"
-#elif defined(__x86_64__)
-#include "sandbox/linux/system_headers/android_x86_64_ucontext.h"
-#elif defined(__mips__)
-#include "sandbox/linux/system_headers/android_mips_ucontext.h"
-#elif defined(__aarch64__)
-#include "sandbox/linux/system_headers/android_arm64_ucontext.h"
-#else
-#error "No support for your architecture in Android header"
-#endif
-
-#else  // __ANDROID__
-#error "Android header file included on non Android."
-#endif  // __ANDROID__
-
-#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_arm64_ucontext.h b/sandbox/linux/system_headers/arm64_linux_ucontext.h
similarity index 78%
rename from sandbox/linux/system_headers/android_arm64_ucontext.h
rename to sandbox/linux/system_headers/arm64_linux_ucontext.h
index df2b66a..46e0407 100644
--- a/sandbox/linux/system_headers/android_arm64_ucontext.h
+++ b/sandbox/linux/system_headers/arm64_linux_ucontext.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
 
 #if !defined(__BIONIC_HAVE_UCONTEXT_T)
 #include <asm/sigcontext.h>
@@ -26,4 +26,4 @@
 #include <sys/ucontext.h>
 #endif  // __BIONIC_HAVE_UCONTEXT_T
 
-#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/arm_linux_syscalls.h b/sandbox/linux/system_headers/arm_linux_syscalls.h
index b11041d..bfd5342 100644
--- a/sandbox/linux/system_headers/arm_linux_syscalls.h
+++ b/sandbox/linux/system_headers/arm_linux_syscalls.h
@@ -10,8 +10,10 @@
 #error "Including header on wrong architecture"
 #endif
 
-// __NR_SYSCALL_BASE, __ARM_NR_BASE are defined in <asm/unistd.h>.
-#include <asm/unistd.h>
+#if !defined(__NR_SYSCALL_BASE)
+// On ARM EABI arch, __NR_SYSCALL_BASE is 0.
+#define __NR_SYSCALL_BASE 0
+#endif
 
 // This syscall list has holes, because ARM EABI makes some syscalls obsolete.
 
@@ -1380,6 +1382,10 @@
 #endif
 
 // ARM private syscalls.
+#if !defined(__ARM_NR_BASE)
+#define __ARM_NR_BASE (__NR_SYSCALL_BASE + 0xF0000)
+#endif
+
 #if !defined(__ARM_NR_breakpoint)
 #define __ARM_NR_breakpoint (__ARM_NR_BASE+1)
 #endif
@@ -1406,4 +1412,3 @@
 #endif
 
 #endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_
-
diff --git a/sandbox/linux/system_headers/arm_linux_ucontext.h b/sandbox/linux/system_headers/arm_linux_ucontext.h
new file mode 100644
index 0000000..0eb723a
--- /dev/null
+++ b/sandbox/linux/system_headers/arm_linux_ucontext.h
@@ -0,0 +1,67 @@
+// 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.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
+
+#if !defined(__BIONIC_HAVE_UCONTEXT_T)
+#if !defined(__native_client_nonsfi__)
+#include <asm/sigcontext.h>
+#else
+// In PNaCl toolchain, sigcontext and stack_t is not defined. So here declare
+// them.
+struct sigcontext {
+  unsigned long trap_no;
+  unsigned long error_code;
+  unsigned long oldmask;
+  unsigned long arm_r0;
+  unsigned long arm_r1;
+  unsigned long arm_r2;
+  unsigned long arm_r3;
+  unsigned long arm_r4;
+  unsigned long arm_r5;
+  unsigned long arm_r6;
+  unsigned long arm_r7;
+  unsigned long arm_r8;
+  unsigned long arm_r9;
+  unsigned long arm_r10;
+  unsigned long arm_fp;
+  unsigned long arm_ip;
+  unsigned long arm_sp;
+  unsigned long arm_lr;
+  unsigned long arm_pc;
+  unsigned long arm_cpsr;
+  unsigned long fault_address;
+};
+
+typedef struct sigaltstack {
+  void* ss_sp;
+  int ss_flags;
+  size_t ss_size;
+} stack_t;
+
+#endif
+
+// We also need greg_t for the sandbox, include it in this header as well.
+typedef unsigned long greg_t;
+
+// typedef unsigned long sigset_t;
+typedef struct ucontext {
+  unsigned long uc_flags;
+  struct ucontext* uc_link;
+  stack_t uc_stack;
+  struct sigcontext uc_mcontext;
+  sigset_t uc_sigmask;
+  /* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */
+  int __not_used[32 - (sizeof(sigset_t) / sizeof(int))];
+  /* Last for extensibility.  Eight byte aligned because some
+     coprocessors require eight byte alignment.  */
+  unsigned long uc_regspace[128] __attribute__((__aligned__(8)));
+} ucontext_t;
+
+#else
+#include <sys/ucontext.h>
+#endif  // __BIONIC_HAVE_UCONTEXT_T
+
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_i386_ucontext.h b/sandbox/linux/system_headers/i386_linux_ucontext.h
similarity index 81%
rename from sandbox/linux/system_headers/android_i386_ucontext.h
rename to sandbox/linux/system_headers/i386_linux_ucontext.h
index 868016b..61d9f7a 100644
--- a/sandbox/linux/system_headers/android_i386_ucontext.h
+++ b/sandbox/linux/system_headers/i386_linux_ucontext.h
@@ -11,7 +11,16 @@
 // except we do use sigset_t for uc_sigmask instead of a custom type.
 
 #if !defined(__BIONIC_HAVE_UCONTEXT_T)
+#if !defined(__native_client_nonsfi__)
 #include <asm/sigcontext.h>
+#else
+// In PNaCl toolchain, sigcontext is not defined. So here declare it.
+typedef struct sigaltstack {
+  void* ss_sp;
+  int ss_flags;
+  size_t ss_size;
+} stack_t;
+#endif
 
 /* 80-bit floating-point register */
 struct _libc_fpreg {
@@ -68,7 +77,12 @@
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  sigset_t uc_sigmask;
+  // Android and PNaCl toolchain's sigset_t has only 32 bits, though Linux
+  // ABI requires 64 bits.
+  union {
+    sigset_t uc_sigmask;
+    uint32_t kernel_sigmask[2];
+  };
   struct _libc_fpstate __fpregs_mem;
 } ucontext_t;
 
diff --git a/sandbox/linux/system_headers/linux_filter.h b/sandbox/linux/system_headers/linux_filter.h
new file mode 100644
index 0000000..b23b6eb
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_filter.h
@@ -0,0 +1,140 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_
+
+#include <stdint.h>
+
+// The following structs and macros are taken from linux/filter.h,
+// as some toolchain does not expose them.
+struct sock_filter {
+  uint16_t code;
+  uint8_t jt;
+  uint8_t jf;
+  uint32_t k;
+};
+
+struct sock_fprog {
+  uint16_t len;
+  struct sock_filter *filter;
+};
+
+#ifndef BPF_CLASS
+#define BPF_CLASS(code) ((code) & 0x07)
+#endif
+
+#ifndef BPF_LD
+#define BPF_LD 0x00
+#endif
+
+#ifndef BPF_ALU
+#define BPF_ALU 0x04
+#endif
+
+#ifndef BPF_JMP
+#define BPF_JMP 0x05
+#endif
+
+#ifndef BPF_RET
+#define BPF_RET 0x06
+#endif
+
+#ifndef BPF_SIZE
+#define BPF_SIZE(code) ((code) & 0x18)
+#endif
+
+#ifndef BPF_W
+#define BPF_W 0x00
+#endif
+
+#ifndef BPF_MODE
+#define BPF_MODE(code) ((code) & 0xe0)
+#endif
+
+#ifndef BPF_ABS
+#define BPF_ABS 0x20
+#endif
+
+#ifndef BPF_OP
+#define BPF_OP(code) ((code) & 0xf0)
+#endif
+
+#ifndef BPF_ADD
+#define BPF_ADD 0x00
+#endif
+
+#ifndef BPF_SUB
+#define BPF_SUB 0x10
+#endif
+
+#ifndef BPF_MUL
+#define BPF_MUL 0x20
+#endif
+
+#ifndef BPF_DIV
+#define BPF_DIV 0x30
+#endif
+
+#ifndef BPF_OR
+#define BPF_OR 0x40
+#endif
+
+#ifndef BPF_AND
+#define BPF_AND 0x50
+#endif
+
+#ifndef BPF_LSH
+#define BPF_LSH 0x60
+#endif
+
+#ifndef BPF_RSH
+#define BPF_RSH 0x70
+#endif
+
+#ifndef BPF_NEG
+#define BPF_NEG 0x80
+#endif
+
+#ifndef BPF_MOD
+#define BPF_MOD 0x90
+#endif
+
+#ifndef BPF_XOR
+#define BPF_XOR 0xA0
+#endif
+
+#ifndef BPF_JA
+#define BPF_JA 0x00
+#endif
+
+#ifndef BPF_JEQ
+#define BPF_JEQ 0x10
+#endif
+
+#ifndef BPF_JGT
+#define BPF_JGT 0x20
+#endif
+
+#ifndef BPF_JGE
+#define BPF_JGE 0x30
+#endif
+
+#ifndef BPF_JSET
+#define BPF_JSET 0x40
+#endif
+
+#ifndef BPF_SRC
+#define BPF_SRC(code) ((code) & 0x08)
+#endif
+
+#ifndef BPF_K
+#define BPF_K 0x00
+#endif
+
+#ifndef BPF_MAXINSNS
+#define BPF_MAXINSNS 4096
+#endif
+
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_
diff --git a/sandbox/linux/system_headers/android_futex.h b/sandbox/linux/system_headers/linux_futex.h
similarity index 88%
rename from sandbox/linux/system_headers/android_futex.h
rename to sandbox/linux/system_headers/linux_futex.h
index 11b766f..91733a8 100644
--- a/sandbox/linux/system_headers/android_futex.h
+++ b/sandbox/linux/system_headers/linux_futex.h
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
+
+#include <linux/futex.h>
 
 #if !defined(FUTEX_WAIT)
 #define FUTEX_WAIT 0
@@ -77,4 +79,4 @@
 #define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
 #endif
 
-#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
diff --git a/sandbox/linux/system_headers/linux_seccomp.h b/sandbox/linux/system_headers/linux_seccomp.h
index 40029c8..3deb3d2 100644
--- a/sandbox/linux/system_headers/linux_seccomp.h
+++ b/sandbox/linux/system_headers/linux_seccomp.h
@@ -5,8 +5,6 @@
 #ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_
 #define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_
 
-#include <linux/filter.h>
-
 // The Seccomp2 kernel ABI is not part of older versions of glibc.
 // As we can't break compilation with these versions of the library,
 // we explicitly define all missing symbols.
@@ -67,13 +65,6 @@
 #define IPC_64                   0x0100
 #endif
 
-#ifndef BPF_MOD
-#define BPF_MOD                    0x90
-#endif
-#ifndef BPF_XOR
-#define BPF_XOR                    0xA0
-#endif
-
 // In order to build will older tool chains, we currently have to avoid
 // including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on
 // our own definitions of the seccomp kernel ABI.
diff --git a/sandbox/linux/system_headers/linux_signal.h b/sandbox/linux/system_headers/linux_signal.h
new file mode 100644
index 0000000..5db7fc5
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_signal.h
@@ -0,0 +1,73 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_
+
+// NOTE: On some toolchains, signal related ABI is incompatible with Linux's
+// (not undefined, but defined different values and in different memory
+// layouts). So, fill the gap here.
+
+#if defined(__native_client_nonsfi__)
+#if !defined(__i386__) && !defined(__arm__)
+#error "Unsupported platform"
+#endif
+
+#include <signal.h>
+
+#define LINUX_SIGBUS 7    // 10 in PNaCl toolchain.
+#define LINUX_SIGSEGV 11  // 11 in PNaCl toolchain. Defined for consistency.
+#define LINUX_SIGCHLD 17  // 20 in PNaCl toolchain.
+#define LINUX_SIGSYS 31   // 12 in PNaCl toolchain.
+
+#define LINUX_SIG_BLOCK 0    // 1 in PNaCl toolchain.
+#define LINUX_SIG_UNBLOCK 1  // 2 in PNaCl toolchain.
+
+#define LINUX_SA_SIGINFO 4           // 2 in PNaCl toolchain.
+#define LINUX_SA_NODEFER 0x40000000  // Undefined in PNaCl toolchain.
+#define LINUX_SA_RESTART 0x10000000  // Undefined in PNaCl toolchain.
+
+#define LINUX_SIG_DFL 0  // In PNaCl toolchain, unneeded cast is applied.
+
+struct LinuxSigInfo {
+  int si_signo;
+  int si_errno;
+  int si_code;
+
+  // Extra data is followed by the |si_code|. The length depends on the
+  // signal number.
+  char _sifields[1];
+};
+
+#include "sandbox/linux/system_headers/linux_ucontext.h"
+
+#else  // !defined(__native_client_nonsfi__)
+
+// Just alias the toolchain's value.
+#include <signal.h>
+
+#define LINUX_SIGBUS SIGBUS
+#define LINUX_SIGSEGV SIGSEGV
+#define LINUX_SIGCHLD SIGCHLD
+#define LINUX_SIGSYS SIGSYS
+
+#define LINUX_SIG_BLOCK SIG_BLOCK
+#define LINUX_SIG_UNBLOCK SIG_UNBLOCK
+
+#define LINUX_SA_SIGINFO SA_SIGINFO
+#define LINUX_SA_NODEFER SA_NODEFER
+#define LINUX_SA_RESTART SA_RESTART
+
+#define LINUX_SIG_DFL SIG_DFL
+
+typedef siginfo_t LinuxSigInfo;
+
+#if defined(__ANDROID__)
+// Android's signal.h doesn't define ucontext etc.
+#include "sandbox/linux/system_headers/linux_ucontext.h"
+#endif  // defined(__ANDROID__)
+
+#endif  // !defined(__native_client_nonsfi__)
+
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_
diff --git a/sandbox/linux/system_headers/linux_ucontext.h b/sandbox/linux/system_headers/linux_ucontext.h
new file mode 100644
index 0000000..ea4d8a6
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_ucontext.h
@@ -0,0 +1,28 @@
+// Copyright (c) 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.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
+
+#if defined(__ANDROID__) || defined(__native_client_nonsfi__)
+
+#if defined(__arm__)
+#include "sandbox/linux/system_headers/arm_linux_ucontext.h"
+#elif defined(__i386__)
+#include "sandbox/linux/system_headers/i386_linux_ucontext.h"
+#elif defined(__x86_64__)
+#include "sandbox/linux/system_headers/x86_64_linux_ucontext.h"
+#elif defined(__mips__)
+#include "sandbox/linux/system_headers/mips_linux_ucontext.h"
+#elif defined(__aarch64__)
+#include "sandbox/linux/system_headers/arm64_linux_ucontext.h"
+#else
+#error "No support for your architecture in Android or PNaCl header"
+#endif
+
+#else  // defined(__ANDROID__) || defined(__native_client_nonsfi__)
+#error "The header file included on non Android and non PNaCl."
+#endif  // defined(__ANDROID__) || defined(__native_client_nonsfi__)
+
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_mips_ucontext.h b/sandbox/linux/system_headers/mips_linux_ucontext.h
similarity index 86%
rename from sandbox/linux/system_headers/android_mips_ucontext.h
rename to sandbox/linux/system_headers/mips_linux_ucontext.h
index ec3aa63..27b3763 100644
--- a/sandbox/linux/system_headers/android_mips_ucontext.h
+++ b/sandbox/linux/system_headers/mips_linux_ucontext.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
 
 // This is mostly copied from breakpad (common/android/include/sys/ucontext.h),
 // except we do use sigset_t for uc_sigmask instead of a custom type.
@@ -48,4 +48,4 @@
 #include <sys/ucontext.h>
 #endif  // __BIONIC_HAVE_UCONTEXT_T
 
-#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_x86_64_ucontext.h b/sandbox/linux/system_headers/x86_64_linux_ucontext.h
similarity index 89%
rename from sandbox/linux/system_headers/android_x86_64_ucontext.h
rename to sandbox/linux/system_headers/x86_64_linux_ucontext.h
index 778e6d0..57b8919 100644
--- a/sandbox/linux/system_headers/android_x86_64_ucontext.h
+++ b/sandbox/linux/system_headers/x86_64_linux_ucontext.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
-#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
 
 // We do something compatible with glibc. Hopefully, at some point Android will
 // provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined.
@@ -85,4 +85,4 @@
 #include <sys/ucontext.h>
 #endif  // __BIONIC_HAVE_UCONTEXT_T
 
-#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
+#endif  // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/tests/sandbox_test_runner.h b/sandbox/linux/tests/sandbox_test_runner.h
index 3504126..3155b74 100644
--- a/sandbox/linux/tests/sandbox_test_runner.h
+++ b/sandbox/linux/tests/sandbox_test_runner.h
@@ -5,7 +5,7 @@
 #ifndef SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_H_
 #define SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_H_
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 
 namespace sandbox {
 
diff --git a/sandbox/linux/tests/sandbox_test_runner_function_pointer.h b/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
index f2554f7..cadd07c 100644
--- a/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
+++ b/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
@@ -5,7 +5,7 @@
 #ifndef SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_FUNCTION_POINTER_H_
 #define SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_FUNCTION_POINTER_H_
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 #include "sandbox/linux/tests/sandbox_test_runner.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/tests/test_utils.cc b/sandbox/linux/tests/test_utils.cc
index 6000b8a..747bad2 100644
--- a/sandbox/linux/tests/test_utils.cc
+++ b/sandbox/linux/tests/test_utils.cc
@@ -10,7 +10,6 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 
diff --git a/sandbox/linux/tests/test_utils.h b/sandbox/linux/tests/test_utils.h
index 1d9eb79..7cf9749 100644
--- a/sandbox/linux/tests/test_utils.h
+++ b/sandbox/linux/tests/test_utils.h
@@ -7,7 +7,7 @@
 
 #include <sys/types.h>
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 
 namespace sandbox {
 
diff --git a/sandbox/linux/tests/unit_tests.h b/sandbox/linux/tests/unit_tests.h
index bf0a44f..5a7116e 100644
--- a/sandbox/linux/tests/unit_tests.h
+++ b/sandbox/linux/tests/unit_tests.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SANDBOX_LINUX_TESTS_UNIT_TESTS_H__
-#define SANDBOX_LINUX_TESTS_UNIT_TESTS_H__
+#ifndef SANDBOX_LINUX_TESTS_UNIT_TESTS_H_
+#define SANDBOX_LINUX_TESTS_UNIT_TESTS_H_
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 #include "build/build_config.h"
 #include "sandbox/linux/tests/sandbox_test_runner_function_pointer.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -198,4 +198,4 @@
 
 }  // namespace
 
-#endif  // SANDBOX_LINUX_TESTS_UNIT_TESTS_H__
+#endif  // SANDBOX_LINUX_TESTS_UNIT_TESTS_H_
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java b/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
index f160260..18e4050 100644
--- a/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
+++ b/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
@@ -40,7 +40,7 @@
      * Initializes Java-side utils.
      */
     private void initializeJavaUtils() {
-        PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
+        PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX, getApplicationContext());
     }
 
     /**
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 807b8da..e130479 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -13,7 +13,7 @@
 }
 
 skia_support_gpu = !is_ios
-skia_support_pdf = !is_ios && (enable_basic_printing || enable_print_preview)
+skia_support_pdf = false
 
 # The list of Skia defines that are to be set for chromium.
 gypi_skia_defines =
diff --git a/skia/ext/SkDiscardableMemory_chrome.cc b/skia/ext/SkDiscardableMemory_chrome.cc
index 5bb6928..1a98720 100644
--- a/skia/ext/SkDiscardableMemory_chrome.cc
+++ b/skia/ext/SkDiscardableMemory_chrome.cc
@@ -14,7 +14,7 @@
 }
 
 void* SkDiscardableMemoryChrome::data() {
-  return discardable_->Memory();
+  return discardable_->data();
 }
 
 void SkDiscardableMemoryChrome::unlock() {
diff --git a/sky/engine/bindings/BUILD.gn b/sky/engine/bindings/BUILD.gn
index 0e8edf2..b7dbafe 100644
--- a/sky/engine/bindings/BUILD.gn
+++ b/sky/engine/bindings/BUILD.gn
@@ -89,7 +89,7 @@
     "--output_bin",
     rebase_path(isolate_snapshot, root_build_dir),
     "--target_os",
-    os,
+    target_os,
     "--url_mapping=dart:sky,$dart_sky_path",
     "--url_mapping=dart:mojo.internal,$internal_path",
     "--url_mapping=dart:sky_builtin,$builtin_path",
diff --git a/sky/shell/org/domokit/sky/shell/SkyApplication.java b/sky/shell/org/domokit/sky/shell/SkyApplication.java
index 54798de..0fd9294 100644
--- a/sky/shell/org/domokit/sky/shell/SkyApplication.java
+++ b/sky/shell/org/domokit/sky/shell/SkyApplication.java
@@ -39,7 +39,7 @@
     }
 
     private void initializeJavaUtils() {
-        PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
+        PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX, getApplicationContext());
     }
 
     private void initializeNative() {
diff --git a/testing/android/junit/BUILD.gn b/testing/android/junit/BUILD.gn
index f80d0b5..d479629 100644
--- a/testing/android/junit/BUILD.gn
+++ b/testing/android/junit/BUILD.gn
@@ -8,20 +8,17 @@
 
 # GYP: //testing/android/junit_test.gyp:junit_test_support
 java_library("junit_test_support") {
+  testonly = true
   DEPRECATED_java_in_dir = "java/src"
   deps = [
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
     "//third_party/robolectric:robolectric_java",
+    "//third_party/robolectric:android-all-4.3_r2-robolectric-0",
   ]
 }
 
 # GYP: //testing/android/junit_test.gyp:junit_unit_tests
-java_binary("junit_unittests") {
-  deps = [
-    ":junit_test_support",
-    "//third_party/junit",
-  ]
-  main_class = "org.chromium.testing.local.JunitTestMain"
+junit_binary("junit_unittests") {
   DEPRECATED_java_in_dir = "javatests/src"
 }
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JsonListener.java b/testing/android/junit/java/src/org/chromium/testing/local/JsonListener.java
new file mode 100644
index 0000000..3d501b3
--- /dev/null
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JsonListener.java
@@ -0,0 +1,54 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.testing.local;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+/** A json RunListener that creates a Json file with test run information.
+ */
+public class JsonListener extends RunListener {
+
+    private final JsonLogger mJsonLogger;
+    private long mTestStartTimeMillis;
+    private boolean mCurrentTestPassed;
+
+    public JsonListener(JsonLogger jsonLogger) {
+        mJsonLogger = jsonLogger;
+    }
+
+    /** Called after all tests run.
+     */
+    @Override
+    public void testRunFinished(Result r) throws Exception {
+        mJsonLogger.writeJsonToFile();
+    }
+
+    /** Called when a test is about to start.
+     */
+    @Override
+    public void testStarted(Description d) throws Exception {
+        mCurrentTestPassed = true;
+        mTestStartTimeMillis = System.currentTimeMillis();
+    }
+
+    /** Called when a test has just finished.
+     */
+    @Override
+    public void testFinished(Description d) throws Exception {
+        long testElapsedTimeMillis = System.currentTimeMillis() - mTestStartTimeMillis;
+        mJsonLogger.addTestResultInfo(d, mCurrentTestPassed, testElapsedTimeMillis);
+    }
+
+    /** Called when a test fails.
+     */
+    @Override
+    public void testFailure(Failure f) throws Exception {
+        mCurrentTestPassed = false;
+    }
+}
+
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JsonLogger.java b/testing/android/junit/java/src/org/chromium/testing/local/JsonLogger.java
new file mode 100644
index 0000000..c253ba3
--- /dev/null
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JsonLogger.java
@@ -0,0 +1,89 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.testing.local;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.runner.Description;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+/**
+ *  Creates json file with junit test information. Format of the json file mirrors the
+ *  json generated by build/android/pylib/results/json_results.py.
+ */
+public class JsonLogger {
+
+    private final JSONObject mBaseJsonObject;
+    private final JSONObject mBaseTestInfoJsonObject;
+    private final File mOutputFile;
+
+    public JsonLogger(File outputFile) {
+        mBaseJsonObject = new JSONObject();
+        mBaseTestInfoJsonObject = new JSONObject();
+        mOutputFile = outputFile;
+
+        try {
+            mBaseJsonObject.put("global_tags", new JSONArray());
+            mBaseJsonObject.put("all_tests", new JSONArray());
+            mBaseJsonObject.put("disabled_tests", new JSONArray());
+            mBaseJsonObject.put("per_iteration_data",
+                                new JSONArray().put(mBaseTestInfoJsonObject));
+        } catch (JSONException e) {
+            System.err.println("Unable to create json output.");
+        }
+    }
+
+    /**
+     *  Add the results of a test run to the json output.
+     */
+    public void addTestResultInfo(Description test, boolean passed, long elapsedTimeMillis) {
+        JSONObject testInfoJsonObject = new JSONObject();
+
+        try {
+            testInfoJsonObject.put("status", (passed ? "SUCCESS" : "FAILURE"));
+            testInfoJsonObject.put("elapsed_time_ms", elapsedTimeMillis);
+            testInfoJsonObject.put("output_snippet", "");
+            testInfoJsonObject.put("output_snippet_base64", "");
+            testInfoJsonObject.put("losless_snippet", "");
+
+            if (mBaseTestInfoJsonObject.optJSONArray(testName(test)) == null) {
+                mBaseTestInfoJsonObject.put(testName(test), new JSONArray());
+                mBaseJsonObject.getJSONArray("all_tests").put(testName(test));
+            }
+            mBaseTestInfoJsonObject.getJSONArray(testName(test)).put(testInfoJsonObject);
+        } catch (JSONException e) {
+            System.err.println("Unable to log test to json output: " + testName(test));
+        }
+    }
+
+    /**
+     *  Writes the json output to a file.
+     */
+    public void writeJsonToFile() {
+        try {
+            PrintStream stream = new PrintStream(new FileOutputStream(mOutputFile));
+            try {
+                stream.print(mBaseJsonObject);
+            } finally {
+                try {
+                    stream.close();
+                } catch (RuntimeException e) {
+                    System.err.println("Unable to close output file: " + mOutputFile.getPath());
+                }
+            }
+        } catch (FileNotFoundException e) {
+            System.err.println("File not found: " + mOutputFile.getPath());
+        }
+    }
+
+    private String testName(Description test) {
+        return test.getClassName() + "#" + test.getMethodName();
+    }
+}
\ No newline at end of file
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java
index 9de7874..20c5a65 100644
--- a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestArgParser.java
@@ -4,17 +4,23 @@
 
 package org.chromium.testing.local;
 
+import java.io.File;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.regex.Pattern;
 
 /**
  *  Parses command line arguments for JunitTestMain.
  */
 public class JunitTestArgParser {
 
+    private static final Pattern COLON = Pattern.compile(":");
+
     private final Set<String> mPackageFilters;
     private final Set<Class<?>> mRunnerFilters;
     private final Set<String> mGtestFilters;
+    private File mJsonOutput;
+    private String[] mTestJars;
 
     public static JunitTestArgParser parse(String[] args) {
 
@@ -38,6 +44,12 @@
                     } else if ("gtest-filter".equals(argName)) {
                         // Read the command line argument after the flag.
                         parsed.addGtestFilter(args[++i]);
+                    } else if ("json-results-file".equals(argName)) {
+                        // Read the command line argument after the flag.
+                        parsed.setJsonOutputFile(args[++i]);
+                    } else if ("test-jars".equals(argName)) {
+                        // Read the command line argument after the flag.
+                        parsed.setTestJars(args[++i]);
                     } else {
                         System.out.println("Ignoring flag: \"" + argName + "\"");
                     }
@@ -60,6 +72,7 @@
         mPackageFilters = new HashSet<String>();
         mRunnerFilters = new HashSet<Class<?>>();
         mGtestFilters = new HashSet<String>();
+        mJsonOutput = null;
     }
 
     public Set<String> getPackageFilters() {
@@ -74,6 +87,14 @@
         return mGtestFilters;
     }
 
+    public File getJsonOutputFile() {
+        return mJsonOutput;
+    }
+
+    public String[] getTestJars() {
+        return mTestJars;
+    }
+
     private void addPackageFilter(String packageFilter) {
         mPackageFilters.add(packageFilter);
     }
@@ -86,5 +107,11 @@
         mGtestFilters.add(gtestFilter);
     }
 
-}
+    private void setJsonOutputFile(String path) {
+        mJsonOutput = new File(path);
+    }
 
+    private void setTestJars(String jars) {
+        mTestJars = COLON.split(jars);
+    }
+}
\ No newline at end of file
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java
index d9c468d..f32579b 100644
--- a/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java
+++ b/testing/android/junit/java/src/org/chromium/testing/local/JunitTestMain.java
@@ -9,8 +9,9 @@
 import org.junit.runner.RunWith;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.LinkedList;
+import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.regex.Pattern;
@@ -32,10 +33,19 @@
     /**
      *  Finds all classes on the class path annotated with RunWith.
      */
-    public static Class[] findClassesFromClasspath() {
+    public static Class[] findClassesFromClasspath(String[] testJars) {
         String[] jarPaths = COLON.split(System.getProperty("java.class.path"));
-        LinkedList<Class> classes = new LinkedList<Class>();
-        for (String jp : jarPaths) {
+        List<String> testJarPaths = new ArrayList<String>(testJars.length);
+        for (String testJar: testJars) {
+            for (String jarPath: jarPaths) {
+                if (jarPath.endsWith(testJar)) {
+                    testJarPaths.add(jarPath);
+                    break;
+                }
+            }
+        }
+        List<Class> classes = new ArrayList<Class>();
+        for (String jp : testJarPaths) {
             try {
                 JarFile jf = new JarFile(jp);
                 for (Enumeration<JarEntry> eje = jf.entries(); eje.hasMoreElements();) {
@@ -48,7 +58,7 @@
                     cn = FORWARD_SLASH.matcher(cn).replaceAll(".");
                     Class<?> c = classOrNull(cn);
                     if (c != null && c.isAnnotationPresent(RunWith.class)) {
-                        classes.push(c);
+                        classes.add(c);
                     }
                 }
                 jf.close();
@@ -76,10 +86,13 @@
         JunitTestArgParser parser = JunitTestArgParser.parse(args);
 
         JUnitCore core = new JUnitCore();
-        GtestLogger logger = new GtestLogger(System.out);
-        core.addListener(new GtestListener(logger));
-        Class[] classes = findClassesFromClasspath();
-        Request testRequest = Request.classes(new GtestComputer(logger), classes);
+        GtestLogger gtestLogger = new GtestLogger(System.out);
+        core.addListener(new GtestListener(gtestLogger));
+        JsonLogger jsonLogger = new JsonLogger(parser.getJsonOutputFile());
+        core.addListener(new JsonListener(jsonLogger));
+        Class[] classes = findClassesFromClasspath(parser.getTestJars());
+        Request testRequest = Request.classes(new GtestComputer(gtestLogger), classes);
+
         for (String packageFilter : parser.getPackageFilters()) {
             testRequest = testRequest.filterWith(new PackageFilter(packageFilter));
         }
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java b/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
index 293525e..cf6202b 100644
--- a/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
+++ b/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
@@ -8,13 +8,10 @@
 
 import org.robolectric.AndroidManifest;
 import org.robolectric.DependencyResolver;
-import org.robolectric.LocalDependencyResolver;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.SdkConfig;
 import org.robolectric.annotation.Config;
 
-import java.io.File;
-
 /**
  * A custom Robolectric Junit4 Test Runner. This test runner will load the
  * "real" android jars from a local directory rather than use Maven to fetch
@@ -32,13 +29,7 @@
 
     @Override
     protected final DependencyResolver getJarResolver() {
-        String dependencyDir = System.getProperty("robolectric.dependency.dir");
-        if (dependencyDir == null) {
-            throw new IllegalStateException("robolectric.dependency.dir not specified. Make sure"
-                    + " you are setting the robolectric.dependency.dir system property to the"
-                    + " directory containing Robolectric's runtime dependency jars.");
-        }
-        return new LocalDependencyResolver(new File(dependencyDir));
+        return new RobolectricClasspathDependencyResolver();
     }
 
     @Override
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/RobolectricClasspathDependencyResolver.java b/testing/android/junit/java/src/org/chromium/testing/local/RobolectricClasspathDependencyResolver.java
new file mode 100644
index 0000000..47bc1ba
--- /dev/null
+++ b/testing/android/junit/java/src/org/chromium/testing/local/RobolectricClasspathDependencyResolver.java
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.testing.local;
+
+import org.robolectric.DependencyJar;
+import org.robolectric.DependencyResolver;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.regex.Pattern;
+
+/**
+ * A Robolectric dependency resolver that looks for the Robolectric dependencies
+ * in the Java classpath.
+ */
+public class RobolectricClasspathDependencyResolver implements DependencyResolver {
+    private static final Pattern COLON = Pattern.compile(":");
+    private final String[] mClassPathJars;
+
+    /**
+     * Creates a {@link ClasspathDependencyResolver}.
+     */
+    public RobolectricClasspathDependencyResolver() {
+        mClassPathJars = COLON.split(System.getProperty("java.class.path"));
+    }
+
+    /**
+     * Returns the {@link URL} for a Robolectric dependency. It looks through the jars
+     * in the classpath to find the dependency's filepath.
+     */
+    @Override
+    public URL getLocalArtifactUrl(DependencyJar dependency) {
+        // Jar filenames are constructed identically to how they are built in Robolectric's
+        // own LocalDependencyResolver.
+        String dependencyJar = dependency.getArtifactId() + "-" + dependency.getVersion() + "."
+                + dependency.getType();
+
+        for (String jarPath : mClassPathJars) {
+            if (jarPath.endsWith(dependencyJar)) {
+                return fileToUrl(new File(jarPath));
+            }
+        }
+        throw new IllegalStateException(
+                String.format("Robolectric jar %s was not found in classpath.", dependencyJar));
+    }
+
+    /**
+     * Returns the {@link URL} for a list of Robolectric dependencies.
+     */
+    @Override
+    public URL[] getLocalArtifactUrls(DependencyJar... dependencies) {
+        URL[] urls = new URL[dependencies.length];
+
+        for (int i = 0; i < dependencies.length; i++) {
+            urls[i] = getLocalArtifactUrl(dependencies[i]);
+        }
+
+        return urls;
+    }
+
+    private static URL fileToUrl(File file) {
+        try {
+            return file.toURI().toURL();
+        } catch (MalformedURLException e) {
+            throw new IllegalArgumentException(
+                    String.format("File \"%s\" cannot be represented as a URL: %s", file, e));
+        }
+    }
+}
\ No newline at end of file
diff --git a/testing/android/native_test.gyp b/testing/android/native_test.gyp
index 632d687..b26e01e 100644
--- a/testing/android/native_test.gyp
+++ b/testing/android/native_test.gyp
@@ -12,9 +12,9 @@
           'message': 'building native pieces of native test package',
           'type': 'static_library',
           'sources': [
-            'native_test_jni_onload.cc',
-            'native_test_launcher.cc',
-            'native_test_launcher.h',
+            'native_test/native_test_jni_onload.cc',
+            'native_test/native_test_launcher.cc',
+            'native_test/native_test_launcher.h',
           ],
           'dependencies': [
             '../../base/base.gyp:base',
@@ -30,7 +30,7 @@
           'target_name': 'native_test_jni_headers',
           'type': 'none',
           'sources': [
-            'java/src/org/chromium/native_test/ChromeNativeTestActivity.java'
+            'native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java'
           ],
           'variables': {
             'jni_gen_package': 'testing',
@@ -42,8 +42,8 @@
           'target_name': 'native_test_util',
           'type': 'static_library',
           'sources': [
-            'native_test_util.cc',
-            'native_test_util.h',
+            'native_test/native_test_util.cc',
+            'native_test/native_test_util.h',
           ],
           'dependencies': [
             '../../base/base.gyp:base',
diff --git a/testing/android/BUILD.gn b/testing/android/native_test/BUILD.gn
similarity index 100%
rename from testing/android/BUILD.gn
rename to testing/android/native_test/BUILD.gn
diff --git a/testing/android/README.chromium b/testing/android/native_test/README.chromium
similarity index 100%
rename from testing/android/README.chromium
rename to testing/android/native_test/README.chromium
diff --git a/testing/android/java/AndroidManifest.xml b/testing/android/native_test/java/AndroidManifest.xml
similarity index 95%
rename from testing/android/java/AndroidManifest.xml
rename to testing/android/native_test/java/AndroidManifest.xml
index 8cc36b2..244f116 100644
--- a/testing/android/java/AndroidManifest.xml
+++ b/testing/android/native_test/java/AndroidManifest.xml
@@ -10,7 +10,7 @@
       android:versionCode="1"
       android:versionName="1.0">
 
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
+    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
 
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.INTERNET"/>
diff --git a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
similarity index 97%
rename from testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
rename to testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
index 4aafa7c..4a74877 100644
--- a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
+++ b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
@@ -43,7 +43,7 @@
         CommandLine.init(new String[]{});
 
         // Needed by path_utils_unittest.cc
-        PathUtils.setPrivateDataDirectorySuffix("chrome");
+        PathUtils.setPrivateDataDirectorySuffix("chrome", getApplicationContext());
 
         ResourceExtractor resourceExtractor = ResourceExtractor.get(getApplicationContext());
         resourceExtractor.setExtractAllPaksAndV8SnapshotForTesting();
diff --git a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
similarity index 100%
rename from testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
rename to testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
diff --git a/testing/android/native_test_jni_onload.cc b/testing/android/native_test/native_test_jni_onload.cc
similarity index 93%
rename from testing/android/native_test_jni_onload.cc
rename to testing/android/native_test/native_test_jni_onload.cc
index de42356..041aa74 100644
--- a/testing/android/native_test_jni_onload.cc
+++ b/testing/android/native_test/native_test_jni_onload.cc
@@ -5,7 +5,7 @@
 #include "base/android/base_jni_onload.h"
 #include "base/android/jni_android.h"
 #include "base/bind.h"
-#include "testing/android/native_test_launcher.h"
+#include "testing/android/native_test/native_test_launcher.h"
 
 namespace {
 
diff --git a/testing/android/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc
similarity index 98%
rename from testing/android/native_test_launcher.cc
rename to testing/android/native_test/native_test_launcher.cc
index 4cc87d2..51edf36 100644
--- a/testing/android/native_test_launcher.cc
+++ b/testing/android/native_test/native_test_launcher.cc
@@ -26,7 +26,7 @@
 #include "base/strings/stringprintf.h"
 #include "gtest/gtest.h"
 #include "jni/ChromeNativeTestActivity_jni.h"
-#include "testing/android/native_test_util.h"
+#include "testing/android/native_test/native_test_util.h"
 
 using testing::native_test_util::ArgsToArgv;
 using testing::native_test_util::ParseArgsFromCommandLineFile;
diff --git a/testing/android/native_test_launcher.h b/testing/android/native_test/native_test_launcher.h
similarity index 100%
rename from testing/android/native_test_launcher.h
rename to testing/android/native_test/native_test_launcher.h
diff --git a/testing/android/native_test_util.cc b/testing/android/native_test/native_test_util.cc
similarity index 95%
rename from testing/android/native_test_util.cc
rename to testing/android/native_test/native_test_util.cc
index 885f297..2eaf971 100644
--- a/testing/android/native_test_util.cc
+++ b/testing/android/native_test/native_test_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "testing/android/native_test_util.h"
+#include "testing/android/native_test/native_test_util.h"
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
diff --git a/testing/android/native_test_util.h b/testing/android/native_test/native_test_util.h
similarity index 100%
rename from testing/android/native_test_util.h
rename to testing/android/native_test/native_test_util.h
diff --git a/testing/buildbot/PRESUBMIT.py b/testing/buildbot/PRESUBMIT.py
new file mode 100644
index 0000000..a74562a
--- /dev/null
+++ b/testing/buildbot/PRESUBMIT.py
@@ -0,0 +1,24 @@
+# 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.
+
+"""Enforces json format.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into depot_tools.
+"""
+
+
+def CommonChecks(input_api, output_api):
+  args = [input_api.python_executable, 'manage.py', '--check']
+  cmd = input_api.Command(
+      name='manage', cmd=args, kwargs={}, message=output_api.PresubmitError)
+  return input_api.RunTests([cmd])
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return CommonChecks(input_api, output_api)
diff --git a/testing/buildbot/chromium.chrome.json b/testing/buildbot/chromium.chrome.json
index 2c63c08..0967ef4 100644
--- a/testing/buildbot/chromium.chrome.json
+++ b/testing/buildbot/chromium.chrome.json
@@ -1,2 +1 @@
-{
-}
+{}
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 64f2cd5..e7df4ed 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1,291 +1,599 @@
 {
-  "Linux ChromiumOS Tests (1)": {
-    "gtest_tests": [
+  "Linux ChromiumOS GN": {
+    "additional_compile_targets": [
       "accessibility_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        }
-      },
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
       "cacheinvalidation_unittests",
+      "chromedriver_unittests",
       "chromeos_unittests",
+      "components_browsertests",
       "components_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
       "dbus_unittests",
+      "device_unittests",
       "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
       "extensions_unittests",
       "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
       "google_apis_unittests",
       "gpu_unittests",
-      "url_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "interactive_ui_tests",
+      "ipc_tests",
       "jingle_unittests",
-      "device_unittests",
       "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "net_unittests",
       "ppapi_unittests",
       "printing_unittests",
       "remoting_unittests",
-      {
-        "test": "sandbox_linux_unittests",
-        "args": ["--test-launcher-print-test-stdio=always"]
-      },
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_unit_tests",
       "ui_base_unittests",
       "ui_chromeos_unittests",
       "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
       "views_unittests",
-      "wm_unittests",
-      "aura_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
       {
-        "test": "ash_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "app_list_unittests",
-      "message_center_unittests",
-      "compositor_unittests",
-      "events_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "Linux ChromiumOS GN (dbg)": {
+    "additional_compile_targets": [
+      "net_unittests"
+    ],
+    "gtest_tests": [
       {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "nacl_loader_unittests",
-      "app_shell_unittests",
-      "chromevox_tests",
-      {
-        "test": "extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "skia_unittests"
+        "test": "base_unittests"
+      }
     ]
   },
   "Linux ChromiumOS Ozone Tests (1)": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "app_shell_unittests",
-      "ash_unittests",
-      "aura_unittests",
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "chromeos_unittests",
-      "chromevox_tests",
-      "components_unittests",
       {
-        "test": "content_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chromeos_unittests"
+      },
+      {
+        "test": "chromevox_tests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "content_browsertests"
       },
-      "content_unittests",
       {
-        "test": "crypto_unittests",
+        "test": "content_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
-      "dbus_unittests",
-      "device_unittests",
-      "display_unittests",
-      "events_unittests",
       {
-        "test": "extensions_browsertests",
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "extensions_browsertests"
       },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
       {
-        "test": "interactive_ui_tests",
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 3
-        }
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      "message_center_unittests",
-      "nacl_loader_unittests",
       {
-        "test": "net_unittests",
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "net_unittests"
       },
-      "ozone_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
       {
-        "test": "sandbox_linux_unittests",
-        "args": ["--test-launcher-print-test-stdio=always"]
+        "test": "ozone_unittests"
       },
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "ui_chromeos_unittests",
-      "ui_touch_selection_unittests",
       {
-        "test": "unit_tests",
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_chromeos_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "unit_tests"
       },
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests"
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ]
+  },
+  "Linux ChromiumOS Tests (1)": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 5
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chromeos_unittests"
+      },
+      {
+        "test": "chromevox_tests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_chromeos_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ]
   },
   "Linux ChromiumOS Tests (dbg)(1)": {
     "gtest_tests": [
-      "accessibility_unittests",
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
-      "cacheinvalidation_unittests",
-      "chromeos_unittests",
-      "components_unittests",
       {
-        "test": "crypto_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
-      "dbus_unittests",
-      "extensions_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
       {
-        "test": "content_unittests",
+        "test": "app_shell_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "ash_unittests"
       },
-      "device_unittests",
-      "display_unittests",
-      "media_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
       {
-        "test": "sandbox_linux_unittests",
-        "args": ["--test-launcher-print-test-stdio=always"]
+        "test": "aura_unittests"
       },
-      "ui_base_unittests",
-      "ui_chromeos_unittests",
-      "ui_touch_selection_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "aura_unittests",
       {
-        "test": "ash_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
-      },
-      "app_list_unittests",
-      "message_center_unittests",
-      "compositor_unittests",
-      "events_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "base_unittests"
       },
       {
-        "test": "browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
+        },
+        "test": "browser_tests"
       },
-      "app_shell_unittests",
       {
-        "test": "content_browsertests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chromeos_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "extensions_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
-      "gcm_unit_tests",
-      "skia_unittests",
       {
-        "test": "interactive_ui_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 3
-        }
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_chromeos_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
       }
     ]
   }
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 8a47be4..3b3c8fe 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -1,55 +1,199 @@
 {
-  "Linux Trusty": {
+  "Browser Side Navigation Linux": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "app_shell_unittests",
-      "aura_unittests",
-      "interactive_ui_tests",
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "compositor_unittests",
-      "crypto_unittests",
-      "dbus_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "events_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "unit_tests",
-      "views_unittests",
-      "wm_unittests",
-      "sql_unittests",
-      "browser_tests",
-      "content_browsertests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests"
+      {
+        "args": [
+          "--enable-browser-side-navigation",
+          "--gtest_filter=-BatteryMonitorImplTest.BatteryManagerDefaultValues:BatteryMonitorImplTest.BatteryManagerResolvePromise:BatteryMonitorImplTest.BatteryManagerWithEventListener:BookmarkletTest.DocumentWrite:BookmarkletTest.NonEmptyResult:BookmarkletTest.Redirect:BookmarkletTest.RedirectVoided:ChildProcessLauncherBrowserTest.ChildSpawnFail:CrossProcessFrameTreeBrowserTest.CreateCrossProcessSubframeProxies:CrossProcessFrameTreeBrowserTest.OriginSetOnCrossProcessNavigations:CrossSiteRedirectorBrowserTest.VerifyCrossSiteRedirectURL:CrossSiteTransferTest.NoLeakOnCrossSiteCancel:CrossSiteTransferTest.ReplaceEntryCrossProcessThenTransfer:CrossSiteTransferTest.ReplaceEntryCrossProcessTwice:CrossSiteTransferTest.ReplaceEntryInProcessThenTranfers:DatabaseTest.ReloadPage:DeviceInertialSensorBrowserTest.LightOneOffInfintyTest:DeviceInertialSensorBrowserTest.LightTest:DeviceInertialSensorBrowserTest.MotionNullTest:DeviceInertialSensorBrowserTest.MotionTest:DeviceInertialSensorBrowserTest.OrientationNullTest:DeviceInertialSensorBrowserTest.OrientationTest:DOMStorageBrowserTest.SanityCheck:DOMStorageBrowserTest.SanityCheckIncognito:DownloadContentTest.CancelAtFinalRename:DownloadContentTest.CancelAtRelease:DownloadContentTest.CancelInterruptedDownload:DownloadContentTest.CancelResumingDownload:DownloadContentTest.DownloadCancelled:DownloadContentTest.DownloadGZipWithNoContent:DownloadContentTest.DownloadOctetStream:DownloadContentTest.MultiDownload:DownloadContentTest.RemoveDownload:DownloadContentTest.RemoveResumingDownload:DownloadContentTest.ResumeInterruptedDownload:DownloadContentTest.ResumeInterruptedDownloadBadPrecondition:DownloadContentTest.ResumeInterruptedDownloadNoRange:DownloadContentTest.ResumeInterruptedDownloadNoVerifiers:DownloadContentTest.ResumeWithDeletedFile:DownloadContentTest.ResumeWithFileFinalRenameError:DownloadContentTest.ResumeWithFileInitError:DownloadContentTest.ResumeWithFileIntermediateRenameError:DownloadContentTest.ShutdownAtRelease:DownloadContentTest.ShutdownInProgress:File/MediaTest.VideoBearOpusOgg/0:File/MediaTest.VideoBearOpusWebm/0:File/MediaTest.VideoBearSilentTheora/0:File/MediaTest.VideoBearSilentWebm/0:File/MediaTest.VideoBearTheora/0:File/MediaTest.VideoBearWavAlaw/0:File/MediaTest.VideoBearWavMulaw/0:File/MediaTest.VideoBearWavPcm/0:File/MediaTest.VideoBearWavPcm192kHz/0:File/MediaTest.VideoBearWavPcm3kHz/0:File/MediaTest.VideoBearWebm/0:File/MediaTest.VideoTulipWebm/0:FileSystemBrowserTest.CreateTest:FileSystemBrowserTest.RequestTest:FileSystemBrowserTestWithLowQuota.QuotaTest:FrameTreeBrowserTest.FrameTreeAfterCrash:FrameTreeBrowserTest.SandboxFlagsSetForChildFrames:IndexedDBBrowserTest.BlobsCountAgainstQuota:IndexedDBBrowserTest.CallbackAccounting:IndexedDBBrowserTest.CanDeleteWhenOverQuotaTest:IndexedDBBrowserTest.ConnectionsClosedOnTabClose:IndexedDBBrowserTest.CursorPrefetch:IndexedDBBrowserTest.CursorTest:IndexedDBBrowserTest.CursorTestIncognito:IndexedDBBrowserTest.DatabaseTest:IndexedDBBrowserTest.DeleteCompactsBackingStore:IndexedDBBrowserTest.DeleteForOriginDeletesBlobs:IndexedDBBrowserTest.DiskFullOnCommit:IndexedDBBrowserTest.DoesntHangTest:IndexedDBBrowserTest.EmptyBlob:IndexedDBBrowserTest.ForceCloseEventTest:IndexedDBBrowserTest.IndexTest:IndexedDBBrowserTest.KeyPathTest:IndexedDBBrowserTest.KeyTypesTest:IndexedDBBrowserTest.LevelDBLogFileTest:IndexedDBBrowserTest.NullKeyPathPersistence:IndexedDBBrowserTest.ObjectStoreTest:IndexedDBBrowserTest.PRE_NullKeyPathPersistence:IndexedDBBrowserTest.PRE_PRE_VersionChangeCrashResilience:IndexedDBBrowserTest.PRE_VersionChangeCrashResilience:IndexedDBBrowserTest.TransactionGetTest:IndexedDBBrowserTest.TransactionTest:IndexedDBBrowserTest.VersionChangeCrashResilience:IndexedDBBrowserTestSingleProcess.RenderThreadShutdownTest:IndexedDBBrowserTestWithCorruptLevelDB.DestroyTest:IndexedDBBrowserTestWithGCExposed.BlobDidAck:IndexedDBBrowserTestWithGCExposed.BlobDidAckPrefetch:IndexedDBBrowserTestWithGCExposed.DatabaseCallbacksTest:IndexedDBBrowserTestWithLowQuota.QuotaTest:IndexedDBBrowserTestWithMissingSSTFile.DestroyTest:IndexedDBBrowserTestWithVersion0Schema.MigrationTest:IndexedDBBrowserTestWithVersion123456Schema.DestroyTest:IndexedDBBrowserTestWithVersion987654SSVData.DestroyTest:ManifestBrowserTest.DummyManifest:ManifestBrowserTest.DynamicManifest:ManifestBrowserTest.ParseErrorManifest:ManifestBrowserTest.ParsingErrorsManifest:MediaCanPlayTypeTest.CodecSupportTest_Avc1Variants:MediaCanPlayTypeTest.CodecSupportTest_Avc3Variants:MediaCanPlayTypeTest.CodecSupportTest_AvcLevels:MediaCanPlayTypeTest.CodecSupportTest_HLS:MediaCanPlayTypeTest.CodecSupportTest_mp3:MediaCanPlayTypeTest.CodecSupportTest_mp4:MediaCanPlayTypeTest.CodecSupportTest_Mp4aVariants:MediaCanPlayTypeTest.CodecSupportTest_ogg:MediaCanPlayTypeTest.CodecSupportTest_wav:MediaCanPlayTypeTest.CodecSupportTest_webm:MediaTest.Navigate:NavigationControllerBrowserTest.CorrectLengthWithCurrentItemReplacement:NavigationControllerBrowserTest.CorrectLengthWithNewTabNavigatingFromWebUI:NavigationControllerBrowserTest.DontIgnoreBackAfterNavEntryLimit:NavigationControllerBrowserTest.ErrorPageReplacement:NavigationControllerBrowserTest.NavigationTypeClassification_ClientSideRedirect:NavigationControllerBrowserTest.NavigationTypeClassification_ExistingPage:NavigationControllerBrowserTest.NavigationTypeClassification_InPage:NavigationControllerBrowserTest.NavigationTypeClassification_NewAndAutoSubframe:NavigationControllerBrowserTest.NavigationTypeClassification_NewPage:NavigationControllerBrowserTest.SubframeOnEmptyPage:OutOfProcessPPAPITest.InputEvent:OutOfProcessPPAPITest.MediaStreamAudioTrack:OutOfProcessPPAPITest.MediaStreamVideoTrack:RendererAccessibilityTest.AccessibilityMessagesQueueWhileSwappedOut:RenderFrameHostImplBrowserTest.IsFocused_AtLoad:RenderFrameHostImplBrowserTest.IsFocused_Widget:RenderFrameHostManagerTest.BackForwardNotStale:RenderFrameHostManagerTest.ClickLinkAfter204Error:RenderFrameHostManagerTest.DisownSubframeOpener:RenderFrameHostManagerTest.DontPreemptNavigationWithFrameTreeUpdate:RenderFrameHostManagerTest.ForceSwapAfterWebUIBindings:RenderFrameHostManagerTest.IgnoreRendererDebugURLsWhenCrashed:RenderFrameHostManagerTest.NoScriptAccessAfterSwapOut:RenderFrameHostManagerTest.RendererDebugURLsDontSwap:RenderFrameHostManagerTest.RestoreFileAccessForHistoryNavigation:RenderFrameHostManagerTest.RestoreSubframeFileAccessForHistoryNavigation:RenderFrameHostManagerTest.ShowLoadingURLUntilSpoof:RenderViewImplTest.DecideNavigationPolicy:RenderViewImplTest.InsertCharacters:RenderViewImplTest.NavigateFrame:RenderViewImplTest.NavigationStartOverride:RenderViewImplTest.OnHandleKeyboardEvent:RenderViewImplTest.OnNavigationHttpPost:RenderViewImplTest.ReloadWhileSwappedOut:RenderViewImplTest.StaleNavigationsIgnored:RenderViewImplTest.TestBackForward:ResourceDispatcherHostBrowserTest.CrossSiteAfterCrash:ResourceDispatcherHostBrowserTest.CrossSiteNoUnloadOn204:ResourceFetcherTests.ResourceFetcher404:ResourceFetcherTests.ResourceFetcherDeletedInCallback:ResourceFetcherTests.ResourceFetcherDidFail:ResourceFetcherTests.ResourceFetcherDownload:ResourceFetcherTests.ResourceFetcherPost:ResourceFetcherTests.ResourceFetcherSetHeader:ResourceFetcherTests.ResourceFetcherTimeout:SecurityExploitBrowserTest.AttemptDuplicateRenderViewHost:SecurityExploitBrowserTest.AttemptDuplicateRenderWidgetHost:SecurityExploitBrowserTest.InterstitialCommandFromUnderlyingContent:ServiceWorkerBrowserTest.CrossSiteTransfer:ServiceWorkerBrowserTest.ImportsBustMemcache:ServiceWorkerBrowserTest.Reload:ServiceWorkerBrowserTest.ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure:ServiceWorkerBrowserTest.ResponseFromHTTPSServiceWorkerIsMarkedAsSecure:SessionHistoryTest.BasicBackForward:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FragmentBackForward:SessionHistoryTest.FrameBackForward:SessionHistoryTest.FrameFormBackForward:SessionHistoryTest.HistoryLength:SessionHistoryTest.JavascriptHistory:SessionHistoryTest.LocationChangeInSubframe:SessionHistoryTest.LocationReplace:SitePerProcessAccessibilityBrowserTest.CrossSiteIframeAccessibility:SitePerProcessBrowserTest.CleanupCrossSiteIframe:SitePerProcessBrowserTest.CompositorFrameSwapped:SitePerProcessBrowserTest.CreateProxiesForNewFrames:SitePerProcessBrowserTest.CrossSiteDidStopLoading:SitePerProcessBrowserTest.CrossSiteIframe:SitePerProcessBrowserTest.DynamicSandboxFlags:SitePerProcessBrowserTest.DynamicSandboxFlagsRemoteToLocal:SitePerProcessBrowserTest.KillingRendererClearsDescendantProxies:SitePerProcessBrowserTest.NavigateRemoteFrame:SitePerProcessBrowserTest.NavigateRemoteFrameToBlankAndDataURLs:SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess:SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcessWithSubtree:SitePerProcessBrowserTest.NavigateWithSiblingRemoteFrame:SitePerProcessBrowserTest.OriginReplication:SitePerProcessBrowserTest.ProxyCreationSkipsSubtree:SitePerProcessBrowserTest.RFPHDestruction:SitePerProcessBrowserTest.RestrictFrameDetach:SitePerProcessBrowserTest.SandboxFlagsReplication:SitePerProcessBrowserTest.SubframePostMessage:SitePerProcessDevToolsBrowserTest.CrossSiteIframeAgentHost:SpeechRecognitionBrowserTest.OneShotRecognition:StatsTableBrowserTest.StartWithStatTable:TransitionBrowserTest.NormalNavigationNotDeferred:TransitionBrowserTest.TransitionNavigationDataIsCleared:TransitionBrowserTest.TransitionNavigationIsDeferred:WebContentsImplBrowserTest.ClearNonVisiblePendingOnFail:WebContentsImplBrowserTest.GetSizeForNewRenderView:WebContentsViewAuraTest.ScreenshotForSwappedOutRenderViews:WebUIMojoTest.EndToEndPing:WorkerTest.IncognitoSharedWorkers:WorkerTest.MultipleSharedWorkers:WorkerTest.MultipleWorkers:WorkerTest.PassMessagePortToSharedWorker:WorkerTest.PassMessagePortToSharedWorkerDontWaitForConnect:WorkerTest.SharedWorkerTlsClientAuth:WorkerTest.SingleSharedWorker:WorkerTest.SingleWorker:WorkerTest.WorkerTlsClientAuth"
+        ],
+        "test": "content_browsertests"
+      },
+      {
+        "args": [
+          "--enable-browser-side-navigation",
+          "--gtest_filter=-NavigationControllerTest.CopyRestoredStateAndNavigate:NavigationControllerTest.LoadURL_AbortDoesntCancelPending:NavigationControllerTest.LoadURL_IgnorePreemptsPending:NavigationControllerTest.ShowRendererURLAfterFailUntilModified:NavigationControllerTest.ShowRendererURLInNewTabUntilModified:RenderFrameHostManagerTest.CancelPendingProperlyDeletesOrSwaps:RenderFrameHostManagerTest.NavigateWithEarlyClose:RenderFrameHostManagerTest.PageDoesBackAndReload:RenderViewHostTest.ResetUnloadOnReload:ResourceDispatcherHostTest.TransferNavigationHtml:ResourceDispatcherHostTest.TransferNavigationText:ResourceDispatcherHostTest.TransferNavigationWithProcessCrash:ResourceDispatcherHostTest.TransferNavigationWithTwoRedirects:ResourceDispatcherHostTest.TransferTwoNavigationsHtml:WebContentsImplTest.ActiveContentsCountChangeBrowsingInstance:WebContentsImplTest.CrossSiteNavigationBackPreempted:WebContentsImplTest.CrossSiteNavigationPreempted:WebContentsImplTest.CrossSiteNotPreemptedDuringBeforeUnload:WebContentsImplTest.NoEarlyStop:WebContentsImplTest.ShowInterstitialCrashRendererThenGoBack:WebContentsImplTest.ShowInterstitialFromBrowserNewNavigationProceed:WebContentsImplTest.ShowInterstitialThenGoBack"
+        ],
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "Cast Linux": {
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_base_unittests"
+      },
+      {
+        "test": "cast_media_unittests"
+      },
+      {
+        "test": "cast_shell_browser_test"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "url_unittests"
+      }
+    ]
+  },
+  "Chromium Mac 10.10": {
+    "gtest_tests": [
+      {
+        "test": "accessibility_unittests"
+      },
+      {
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_mac_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
     ],
     "scripts": [
       {
@@ -66,57 +210,1845 @@
       }
     ]
   },
-  "Linux Trusty (dbg)": {
+  "ClangToTLinux tester": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "app_shell_unittests",
-      "aura_unittests",
-      "interactive_ui_tests",
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "compositor_unittests",
-      "crypto_unittests",
-      "dbus_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "events_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "unit_tests",
-      "views_unittests",
-      "wm_unittests",
-      "sql_unittests",
-      "browser_tests",
-      "content_browsertests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests"
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "nacl_integration",
+        "script": "nacl_integration.py"
+      }
+    ]
+  },
+  "ClangToTLinuxASan tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 5
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 4
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
+    ]
+  },
+  "ClangToTMac tester": {
+    "gtest_tests": [
+      {
+        "test": "accessibility_unittests"
+      },
+      {
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_mac_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "telemetry_unittests",
+        "script": "telemetry_unittests.py"
+      },
+      {
+        "name": "telemetry_perf_unittests",
+        "script": "telemetry_perf_unittests.py"
+      },
+      {
+        "name": "nacl_integration",
+        "script": "nacl_integration.py"
+      }
+    ]
+  },
+  "ClangToTMacASan tester": {
+    "gtest_tests": [
+      {
+        "test": "accessibility_unittests"
+      },
+      {
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_mac_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "telemetry_unittests",
+        "script": "telemetry_unittests.py"
+      },
+      {
+        "name": "telemetry_perf_unittests",
+        "script": "telemetry_perf_unittests.py"
+      },
+      {
+        "name": "nacl_integration",
+        "script": "nacl_integration.py"
+      }
+    ]
+  },
+  "CrWinAsan tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinAsan(dll) tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinClang tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinClang(dbg) tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinClang(shared) tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinClang64 tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinClang64(dbg) tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinClang64(dll) tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "CrWinClangLLD tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "Linux ARM Cross-Compile": {
+    "compile_targets": [
+      "browser_tests_run"
+    ],
+    "gtest_tests": [
+      {
+        "test": "browser_tests"
+      }
+    ]
+  },
+  "Linux Trusty": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ],
     "scripts": [
       {
@@ -135,55 +2067,324 @@
   },
   "Linux Trusty (32)": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "app_shell_unittests",
-      "aura_unittests",
-      "interactive_ui_tests",
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "compositor_unittests",
-      "crypto_unittests",
-      "dbus_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "events_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "unit_tests",
-      "views_unittests",
-      "wm_unittests",
-      "sql_unittests",
-      "browser_tests",
-      "content_browsertests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests"
+      {
+        "test": "accessibility_unittests"
+      },
+      {
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "telemetry_unittests",
+        "script": "telemetry_unittests.py"
+      },
+      {
+        "name": "telemetry_perf_unittests",
+        "script": "telemetry_perf_unittests.py"
+      },
+      {
+        "name": "nacl_integration",
+        "script": "nacl_integration.py"
+      }
+    ]
+  },
+  "Linux Trusty (dbg)": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ],
     "scripts": [
       {
@@ -202,121 +2403,153 @@
   },
   "Linux Trusty (dbg)(32)": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "app_shell_unittests",
-      "aura_unittests",
-      "interactive_ui_tests",
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "compositor_unittests",
-      "crypto_unittests",
-      "dbus_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "events_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "unit_tests",
-      "views_unittests",
-      "wm_unittests",
-      "sql_unittests",
-      "browser_tests",
-      "content_browsertests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests"
-    ],
-    "scripts": [
       {
-        "name": "telemetry_unittests",
-        "script": "telemetry_unittests.py"
+        "test": "accessibility_unittests"
       },
       {
-        "name": "telemetry_perf_unittests",
-        "script": "telemetry_perf_unittests.py"
+        "test": "app_list_unittests"
       },
       {
-        "name": "nacl_integration",
-        "script": "nacl_integration.py"
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
       }
-    ]
-  },
-  "Linux ARM Cross-Compile": {
-    "compile_targets": [
-      "browser_tests_run"
-    ],
-    "gtest_tests": [
-      "browser_tests"
-    ]
-  },
-  "Chromium Mac 10.10": {
-    "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "content_browsertests",
-      "content_unittests",
-      "crypto_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "gpu_unittests",
-      "google_apis_unittests",
-      "interactive_ui_tests",
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      "message_center_unittests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_mac_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_integration_tests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "unit_tests",
-      "url_unittests",
-      "browser_tests"
     ],
     "scripts": [
       {
@@ -335,818 +2568,62 @@
   },
   "Site Isolation Linux": {
     "gtest_tests": [
-      { "test": "content_unittests", "args": ["--site-per-process"] },
-      { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] },
-      { "test": "unit_tests", "args": ["--site-per-process"] },
-      { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] }
+      {
+        "args": [
+          "--site-per-process",
+          "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ActiveTab:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*"
+        ],
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--site-per-process",
+          "--gtest_filter=-*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"
+        ],
+        "test": "content_browsertests"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "test": "content_unittests"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "test": "unit_tests"
+      }
     ]
   },
   "Site Isolation Win": {
     "gtest_tests": [
-      { "test": "content_unittests", "args": ["--site-per-process"] },
-      { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] },
-      { "test": "unit_tests", "args": ["--site-per-process"] },
-      { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] }
-    ]
-  },
-  "Browser Side Navigation Linux": {
-    "gtest_tests": [
-      { "test": "content_unittests", "args": ["--enable-browser-side-navigation", "--gtest_filter=-ResourceDispatcherHostTest.TransferNavigationHtml:ResourceDispatcherHostTest.TransferNavigationText:ResourceDispatcherHostTest.TransferNavigationWithProcessCrash:ResourceDispatcherHostTest.TransferNavigationWithTwoRedirects:ResourceDispatcherHostTest.TransferTwoNavigationsHtml:RenderFrameHostManagerTest.CancelPendingProperlyDeletesOrSwaps:WebContentsImplTest.CrossSiteNotPreemptedDuringBeforeUnload"] },
-      { "test": "content_browsertests", "args": ["--enable-browser-side-navigation"] }
-    ]
-  },
-  "CrWinClang tester": {
-    "gtest_tests": [
       {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "args": [
+          "--site-per-process",
+          "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ActiveTab:ExtensionApiTest.ChromeRuntimeOpenOptionsPage:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*"
+        ],
+        "test": "browser_tests"
       },
       {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
+        "args": [
+          "--site-per-process",
+          "--gtest_filter=-*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"
+        ],
+        "test": "content_browsertests"
       },
       {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinClang(dbg) tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "args": [
+          "--site-per-process"
+        ],
+        "test": "content_unittests"
       },
       {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinClang(shared) tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinClang64 tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinClang64(dbg) tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinClang64(dll) tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinClangLLD tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      "unit_tests",
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      "browser_tests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinAsan tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      "unit_tests",
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      "browser_tests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "CrWinAsan(dll) tester": {
-    "gtest_tests": [
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chrome_elf_unittests",
-      "components_unittests",
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "skia_unittests",
-      "unit_tests",
-      "sql_unittests",
-      "ui_base_unittests",
-      "views_unittests",
-      "browser_tests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests"
-    ]
-  },
-  "ClangToTLinux tester": {
-    "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "app_shell_unittests",
-      "aura_unittests",
-      "interactive_ui_tests",
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "compositor_unittests",
-      "crypto_unittests",
-      "dbus_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "events_unittests",
-      "media_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      "unit_tests",
-      "views_unittests",
-      "wm_unittests",
-      "sql_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "content_browsertests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "nacl_integration",
-        "script": "nacl_integration.py"
+        "args": [
+          "--site-per-process"
+        ],
+        "test": "unit_tests"
       }
     ]
-  },
-  "ClangToTLinuxASan tester": {
-    "gtest_tests": [
-      "accessibility_unittests",
-      "extensions_browsertests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        }
-      },
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "components_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 4
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      },
-      "url_unittests"
-    ]
-  },
-  "Cast Linux": {
-    "gtest_tests": [
-      "base_unittests",
-      "cacheinvalidation_unittests",
-      "cast_media_unittests",
-      "cast_shell_browser_test",
-      "content_unittests",
-      "crypto_unittests",
-      "gpu_unittests",
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      "net_unittests",
-      "sandbox_linux_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "url_unittests"
-    ]
   }
 }
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 48ed324..88acb35 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -1,123 +1,142 @@
 {
-  "Linux Tests": {
+  "Android GN": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
+    ],
+    "gtest_tests": []
+  },
+  "Android Tests": {
+    "scripts": [
+      {
+        "name": "webview_licenses",
+        "script": "webview_licenses.py"
+      }
+    ]
+  },
+  "Android Tests (dbg)": {
+    "scripts": [
+      {
+        "name": "webview_licenses",
+        "script": "webview_licenses.py"
+      }
+    ]
+  },
+  "Linux Clang (dbg)": {
     "gtest_tests": [
       {
-        "test": "accessibility_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "test": "app_list_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "app_shell_unittests"
       },
-      "app_shell_unittests",
+      {
+        "test": "base_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gn_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "unit_tests"
+      }
+    ]
+  },
+  "Linux GN": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
       "aura_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        }
-      },
+      "browser_tests",
       "cacheinvalidation_unittests",
-      {
-        "test": "cast_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "cc_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "cast_unittests",
+      "cc_unittests",
       "chromedriver_unittests",
-      {
-        "test": "components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "compositor_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
       "dbus_unittests",
       "device_unittests",
       "display_unittests",
-      {
-        "test": "events_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "events_unittests",
+      "extensions_browsertests",
       "extensions_unittests",
       "gcm_unit_tests",
-      {
-        "test": "gfx_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "gfx_unittests",
+      "gn_unittests",
       "google_apis_unittests",
-      {
-        "test": "gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "gpu_unittests",
+      "interactive_ui_tests",
       "ipc_mojo_unittests",
       "ipc_tests",
       "jingle_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "media_unittests",
       "mojo_common_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
@@ -125,46 +144,318 @@
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
       "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "net_unittests",
       "ppapi_unittests",
       "printing_unittests",
       "remoting_unittests",
       "sandbox_linux_unittests",
+      "skia_unittests",
       "sql_unittests",
-      {
-        "test": "ui_base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "ui_touch_selection_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "sync_integration_tests",
       "sync_unit_tests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
       "url_unittests",
       "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "Linux GN (dbg)": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "Linux Tests": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 5
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cast_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "gn_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ],
     "scripts": [
       {
@@ -193,338 +484,235 @@
       }
     ]
   },
-  "Linux Tests (dbg)(1)(32)": {
-    "gtest_tests": [
-      {
-        "test": "accessibility_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "app_list_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "app_shell_unittests",
-      "aura_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      "cacheinvalidation_unittests",
-      {
-        "test": "cast_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "cc_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "chromedriver_unittests",
-      {
-        "test": "components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "compositor_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "dbus_unittests",
-      "device_unittests",
-      "display_unittests",
-      {
-        "test": "events_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      {
-        "test": "gfx_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "google_apis_unittests",
-      {
-        "test": "gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ipc_mojo_unittests",
-      "ipc_tests",
-      "jingle_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "sql_unittests",
-      {
-        "test": "ui_base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "ui_touch_selection_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sync_unit_tests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "nacl_integration",
-        "script": "nacl_integration.py"
-      }
-    ]
-  },
   "Linux Tests (dbg)(1)": {
     "gtest_tests": [
       {
-        "test": "accessibility_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "test": "app_list_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
-      "app_shell_unittests",
-      "aura_unittests",
       {
-        "test": "base_unittests",
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "base_unittests"
       },
       {
-        "test": "browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
       {
-        "test": "cast_unittests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cast_unittests"
       },
       {
-        "test": "cc_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cc_unittests"
       },
-      "chromedriver_unittests",
       {
-        "test": "components_unittests",
+        "test": "chromedriver_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "components_unittests"
       },
-      "compositor_unittests",
       {
-        "test": "content_browsertests",
+        "test": "compositor_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
       {
-        "test": "crypto_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
-      "dbus_unittests",
-      "device_unittests",
-      "display_unittests",
       {
-        "test": "events_unittests",
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "events_unittests"
       },
       {
-        "test": "extensions_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "extensions_browsertests"
       },
-      "extensions_unittests",
-      "gcm_unit_tests",
       {
-        "test": "gfx_unittests",
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "gfx_unittests"
       },
-      "google_apis_unittests",
       {
-        "test": "gpu_unittests",
+        "test": "gn_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "gpu_unittests"
       },
       {
-        "test": "interactive_ui_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 3
-        }
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_mojo_unittests",
-      "ipc_tests",
-      "jingle_unittests",
       {
-        "test": "media_unittests",
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "media_unittests"
       },
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
       {
-        "test": "net_unittests",
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "net_unittests"
       },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
       {
-        "test": "sandbox_linux_unittests",
-        "args": ["--test-launcher-print-test-stdio=always"]
+        "test": "ppapi_unittests"
       },
-      "sql_unittests",
       {
-        "test": "ui_base_unittests",
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "sync_integration_tests"
       },
       {
-        "test": "ui_touch_selection_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "sync_unit_tests"
       },
       {
-        "test": "sync_integration_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "ui_base_unittests"
       },
-      "sync_unit_tests",
       {
-        "test": "unit_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "ui_touch_selection_unittests"
       },
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ],
     "scripts": [
       {
@@ -541,48 +729,236 @@
       }
     ]
   },
-  "Linux Clang (dbg)": {
+  "Linux Tests (dbg)(1)(32)": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_shell_unittests",
-      "base_unittests",
-      "components_unittests",
-      "content_unittests",
-      "crypto_unittests",
-      "device_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "google_apis_unittests",
-      "ipc_mojo_unittests",
-      "ipc_tests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      "sandbox_linux_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "unit_tests",
-      "skia_unittests"
-    ]
-  },
-  "Android Tests (dbg)": {
-    "scripts": [
       {
-        "name": "check_licenses",
-        "script": "webview_licenses.py"
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cast_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "gn_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
       }
-    ]
-  },
-  "Android Tests": {
+    ],
     "scripts": [
       {
-        "name": "check_licenses",
-        "script": "webview_licenses.py"
+        "name": "nacl_integration",
+        "script": "nacl_integration.py"
       }
     ]
   }
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index a5de375..8883601 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -1,149 +1,263 @@
 {
-  "Mac10.6 Tests": {
-    "gtest_tests": [
-      {
-        "test": "accessibility_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "app_list_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
+  "Mac GN": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "base_unittests",
       "cacheinvalidation_unittests",
-      {
-        "test": "cast_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "cc_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "cast_unittests",
+      "cc_unittests",
       "chromedriver_unittests",
-      {
-        "test": "components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
+      "crypto_unittests",
       "gcm_unit_tests",
-      {
-        "test": "gfx_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "google_apis_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "gn_unittests",
+      "gpu_unittests",
       "ipc_tests",
       "jingle_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "message_center_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "media_unittests",
       "mojo_common_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
       "ppapi_unittests",
       "printing_unittests",
-      "remoting_unittests",
-      "sandbox_mac_unittests",
+      "skia_unittests",
       "sql_unittests",
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
       "sync_unit_tests",
+      "ui_base_unittests",
+      "url_unittests"
+    ],
+    "gtest_tests": [
       {
-        "test": "ui_base_unittests",
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "Mac GN (dbg)": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "base_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "crypto_unittests",
+      "gcm_unit_tests",
+      "gn_unittests",
+      "gpu_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "url_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "Mac10.6 Tests": {
+    "gtest_tests": [
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "test": "unit_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
-      "url_unittests",
-      "skia_unittests"
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cast_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_mac_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
     ],
     "scripts": [
       {
@@ -163,142 +277,186 @@
   "Mac10.8 Tests": {
     "gtest_tests": [
       {
-        "test": "accessibility_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "test": "app_list_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "base_unittests"
       },
       {
-        "test": "browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
-      },
-      "cacheinvalidation_unittests",
-      {
-        "test": "cast_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "browser_tests"
       },
       {
-        "test": "cc_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "chromedriver_unittests",
-      {
-        "test": "components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "cacheinvalidation_unittests"
       },
       {
-        "test": "content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cast_unittests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cc_unittests"
       },
       {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      {
-        "test": "gfx_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "chromedriver_unittests"
       },
       {
-        "test": "gpu_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
-      },
-      "google_apis_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ipc_tests",
-      "jingle_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "components_unittests"
       },
       {
-        "test": "message_center_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
-      },
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_mac_unittests",
-      "sql_unittests",
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sync_unit_tests",
-      {
-        "test": "ui_base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "unit_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
-      "url_unittests",
-      "skia_unittests"
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_mac_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
     ],
     "scripts": [
       {
@@ -318,142 +476,186 @@
   "Mac10.9 Tests": {
     "gtest_tests": [
       {
-        "test": "accessibility_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "test": "app_list_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "base_unittests"
       },
       {
-        "test": "browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
-      },
-      "cacheinvalidation_unittests",
-      {
-        "test": "cast_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "browser_tests"
       },
       {
-        "test": "cc_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "chromedriver_unittests",
-      {
-        "test": "components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "cacheinvalidation_unittests"
       },
       {
-        "test": "content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cast_unittests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cc_unittests"
       },
       {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      {
-        "test": "gfx_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "chromedriver_unittests"
       },
       {
-        "test": "gpu_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
-      },
-      "google_apis_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ipc_tests",
-      "jingle_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "components_unittests"
       },
       {
-        "test": "message_center_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
-      },
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_mac_unittests",
-      "sql_unittests",
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sync_unit_tests",
-      {
-        "test": "ui_base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "unit_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
-      "url_unittests",
-      "skia_unittests"
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_mac_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
     ],
     "scripts": [
       {
@@ -473,143 +675,187 @@
   "Mac10.9 Tests (dbg)": {
     "gtest_tests": [
       {
-        "test": "accessibility_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "test": "app_list_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "base_unittests"
       },
       {
-        "test": "browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
       {
-        "test": "cast_unittests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cast_unittests"
       },
       {
-        "test": "cc_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cc_unittests"
       },
-      "chromedriver_unittests",
       {
-        "test": "components_unittests",
+        "test": "chromedriver_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "components_unittests"
       },
       {
-        "test": "content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
       {
-        "test": "crypto_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
-      "extensions_unittests",
-      "gcm_unit_tests",
       {
-        "test": "gfx_unittests",
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "gfx_unittests"
       },
       {
-        "test": "gpu_unittests",
+        "test": "google_apis_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "gpu_unittests"
       },
-      "google_apis_unittests",
       {
-        "test": "interactive_ui_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
-      },
-      "ipc_tests",
-      "jingle_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "interactive_ui_tests"
       },
       {
-        "test": "message_center_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_mac_unittests",
-      "sql_unittests",
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sync_unit_tests",
-      {
-        "test": "ui_base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "ipc_tests"
       },
       {
-        "test": "unit_tests",
+        "test": "jingle_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "media_unittests"
       },
-      "url_unittests",
-      "skia_unittests"
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_mac_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      }
     ],
     "scripts": [
       {
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json
index 644bd9e..dc1a9d7 100644
--- a/testing/buildbot/chromium.memory.fyi.json
+++ b/testing/buildbot/chromium.memory.fyi.json
@@ -1,209 +1,484 @@
 {
-  "Linux MSan Tests": {
-    "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "aura_unittests",
-      "base_unittests",
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        }
-      },
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "compositor_unittests",
-      "content_browsertests",
-      "content_unittests",
-      "crypto_unittests",
-      "dbus_unittests",
-      "device_unittests",
-      "display_unittests",
-      "events_unittests",
-      "extensions_browsertests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ipc_mojo_unittests",
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "unit_tests",
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests"
-    ]
-  },
   "Linux ChromeOS MSan Tests": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "aura_unittests",
-      "base_unittests",
       {
-        "test": "browser_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 5
-        }
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      "compositor_unittests",
-      "content_browsertests",
-      "content_unittests",
-      "crypto_unittests",
-      "dbus_unittests",
-      "device_unittests",
-      "display_unittests",
-      "events_unittests",
-      "extensions_browsertests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
       {
-        "test": "interactive_ui_tests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_mojo_unittests",
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      "net_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "unit_tests",
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests"
+      {
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ]
+  },
+  "Linux MSan Tests": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 5
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ]
   },
   "Linux TSan Tests": {
+    "disabled_tests": {
+      "app_shell_browsertests": "http://crbug.com/455633",
+      "browser_tests": "Too many errors, clean content_browsertests first. http://crbug.com/368525",
+      "cc_unittests": "http://crbug.com/437454",
+      "interactive_ui_tests": "http://crbug.com/455679"
+    },
     "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      "aura_unittests",
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
       {
-        "test": "content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
       {
-        "test": "content_unittests",
+        "test": "aura_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "base_unittests"
       },
-      "crypto_unittests",
-      "dbus_unittests",
-      "device_unittests",
-      "display_unittests",
-      "events_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "ipc_mojo_unittests",
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      "mojo_common_unittests",
       {
-        "test": "net_unittests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 4
-        }
+        },
+        "test": "net_unittests"
       },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
       {
-        "test": "unit_tests",
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "unit_tests"
       },
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests"
-    ],
-    "disabled_tests": {
-      "app_shell_browsertests": "http://crbug.com/455633",
-      "cc_unittests": "http://crbug.com/437454",
-      "browser_tests":
-        "Too many errors, clean content_browsertests first. http://crbug.com/368525",
-      "interactive_ui_tests": "http://crbug.com/455679"
-    }
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ]
   }
 }
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 87a67e4..dcdfe7c 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -1,335 +1,527 @@
 {
   "Linux ASan LSan Tests (1)": {
     "gtest_tests": [
-      "accessibility_unittests",
-      "extensions_browsertests",
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "test": "browser_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
-          "shards": 5
-        }
+          "shards": 10
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "cc_unittests",
-      "components_unittests",
       {
-        "test": "content_browsertests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
       {
-        "test": "crypto_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
-      "device_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
       {
-        "test": "interactive_ui_tests",
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
         "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+          "can_use_on_swarming_builders": true,
+          "shards": 3
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
       {
-        "test": "net_unittests",
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 4
-        }
+        },
+        "test": "net_unittests"
       },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
       {
-        "test": "unit_tests",
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "unit_tests"
       },
-      "url_unittests"
+      {
+        "test": "url_unittests"
+      }
     ]
   },
   "Linux ASan Tests (sandboxed)": {
     "gtest_tests": [
       {
-        "test": "browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 5
-        }
+        },
+        "test": "browser_tests"
       },
       {
-        "test": "content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "interactive_ui_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "interactive_ui_tests"
+      }
+    ]
+  },
+  "Linux Chromium OS ASan LSan Tests (1)": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cast_unittests"
+      },
+      {
+        "test": "chromeos_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 4
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_chromeos_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      }
+    ]
+  },
+  "Mac ASan 64 Tests (1)": {
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 20
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
       }
     ]
   },
   "Mac ASan Tests (1)": {
     "gtest_tests": [
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "base_unittests"
       },
       {
-        "test": "browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
       {
-        "test": "content_browsertests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
       {
-        "test": "crypto_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
-      "gcm_unit_tests",
-      "gpu_unittests",
       {
-        "test": "interactive_ui_tests",
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
       {
-        "test": "net_unittests",
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "url_unittests"
-    ]
-  },
-  "Mac ASan 64 Tests (1)": {
-    "gtest_tests": [
-      "base_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "net_unittests"
       },
       {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 20
-        }
-      },
-      "cacheinvalidation_unittests",
-      "cc_unittests",
-      "chromedriver_unittests",
-      "components_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
+        "test": "ppapi_unittests"
       },
       {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "printing_unittests"
       },
       {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "gcm_unit_tests",
-      "gpu_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      },
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "url_unittests"
-    ]
-  },
-  "Linux Chromium OS ASan LSan Tests (1)": {
-    "gtest_tests": [
-      "accessibility_unittests",
-      "app_list_unittests",
-      {
-        "test": "ash_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "aura_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "remoting_unittests"
       },
       {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      "cacheinvalidation_unittests",
-      "cast_unittests",
-      "chromeos_unittests",
-      "compositor_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "sql_unittests"
       },
       {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "sync_unit_tests"
       },
-      "components_unittests",
       {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "ui_base_unittests"
       },
-      "device_unittests",
-      "display_unittests",
-      "events_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "gpu_unittests",
-      "google_apis_unittests",
       {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      },
-      "ipc_tests",
-      "jingle_unittests",
-      "media_unittests",
-      "message_center_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 4
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "skia_unittests",
-      "sql_unittests",
-      "sync_unit_tests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      },
-      "ui_base_unittests",
-      "ui_chromeos_unittests",
-      "ui_touch_selection_unittests",
-      "url_unittests",
-      "views_unittests"
+        "test": "url_unittests"
+      }
     ]
   }
 }
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index ec70b5b..f3ad4ca 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1,87 +1,23 @@
 {
-  "Linux Perf (3)": {
-    "scripts": [
-      {
-        "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests", "--test-launcher-print-test-stdio=always"]
-      }
-    ]
-  },
-  "Android Nexus4 Perf": {
+  "Android MotoE Perf": {
     "scripts": [
       {
         "name": "host_info",
         "script": "host_info.py"
       },
       {
+        "args": [
+          "gpu_perftests"
+        ],
         "name": "gpu_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["gpu_perftests"]
+        "script": "gtest_perf_test.py"
       },
       {
+        "args": [
+          "cc_perftests"
+        ],
         "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests"]
-      }
-    ]
-  },
-  "Android Nexus5 Perf": {
-    "scripts": [
-      {
-        "name": "host_info",
-        "script": "host_info.py"
-      },
-      {
-        "name": "gpu_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["gpu_perftests"]
-      },
-      {
-        "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests"]
-      }
-    ]
-  },
-  "Android Nexus6 Perf": {
-    "scripts": [
-      {
-        "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests"]
-      }
-    ]
-  },
-  "Android Nexus7v2 Perf": {
-    "scripts": [
-      {
-        "name": "host_info",
-        "script": "host_info.py"
-      },
-      {
-        "name": "gpu_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["gpu_perftests"]
-      },
-      {
-        "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests"]
-      }
-    ]
-  },
-  "Android Nexus9 Perf": {
-    "scripts": [
-      {
-        "name": "gpu_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["gpu_perftests"]
-      },
-      {
-        "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests"]
+        "script": "gtest_perf_test.py"
       }
     ]
   },
@@ -92,72 +28,326 @@
         "script": "host_info.py"
       },
       {
+        "args": [
+          "gpu_perftests"
+        ],
         "name": "gpu_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["gpu_perftests"]
+        "script": "gtest_perf_test.py"
       },
       {
+        "args": [
+          "cc_perftests"
+        ],
         "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests"]
+        "script": "gtest_perf_test.py"
       }
     ]
   },
-  "Android One Perf": {
-    "scripts": [
-    ]
-  },
-  "Android MotoE Perf": {
+  "Android Nexus4 Perf": {
     "scripts": [
       {
         "name": "host_info",
         "script": "host_info.py"
       },
       {
+        "args": [
+          "gpu_perftests"
+        ],
         "name": "gpu_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["gpu_perftests"]
+        "script": "gtest_perf_test.py"
       },
       {
+        "args": [
+          "cc_perftests"
+        ],
         "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests"]
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Android Nexus5 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      },
+      {
+        "args": [
+          "gpu_perftests"
+        ],
+        "name": "gpu_perftests",
+        "script": "gtest_perf_test.py"
+      },
+      {
+        "args": [
+          "cc_perftests"
+        ],
+        "name": "cc_perftests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Android Nexus6 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      },
+      {
+        "args": [
+          "cc_perftests"
+        ],
+        "name": "cc_perftests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Android Nexus7v2 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      },
+      {
+        "args": [
+          "gpu_perftests"
+        ],
+        "name": "gpu_perftests",
+        "script": "gtest_perf_test.py"
+      },
+      {
+        "args": [
+          "cc_perftests"
+        ],
+        "name": "cc_perftests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Android Nexus9 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      },
+      {
+        "args": [
+          "gpu_perftests"
+        ],
+        "name": "gpu_perftests",
+        "script": "gtest_perf_test.py"
+      },
+      {
+        "args": [
+          "cc_perftests"
+        ],
+        "name": "cc_perftests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Android One Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      }
+    ]
+  },
+  "Linux Perf (3)": {
+    "scripts": [
+      {
+        "args": [
+          "cc_perftests",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "name": "cc_perftests",
+        "script": "gtest_perf_test.py"
       }
     ]
   },
   "Mac 10.8 Perf (1)": {
     "scripts": [
       {
-	"name": "gpu_perftests",
-	"script": "gtest_perf_test.py",
-	"args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
+        "args": [
+          "gpu_perftests",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "name": "gpu_perftests",
+        "script": "gtest_perf_test.py"
       }
     ]
   },
   "Mac 10.8 Perf (3)": {
     "scripts": [
       {
+        "args": [
+          "cc_perftests",
+          "--test-launcher-print-test-stdio=always"
+        ],
         "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests", "--test-launcher-print-test-stdio=always"]
+        "script": "gtest_perf_test.py"
+      },
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
       }
     ]
   },
   "Mac 10.9 Perf (1)": {
     "scripts": [
       {
-	"name": "gpu_perftests",
-	"script": "gtest_perf_test.py",
-	"args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
+        "args": [
+          "gpu_perftests",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "name": "gpu_perftests",
+        "script": "gtest_perf_test.py"
       }
     ]
   },
   "Mac 10.9 Perf (3)": {
     "scripts": [
       {
+        "args": [
+          "cc_perftests",
+          "--test-launcher-print-test-stdio=always"
+        ],
         "name": "cc_perftests",
-        "script": "gtest_perf_test.py",
-        "args": ["cc_perftests", "--test-launcher-print-test-stdio=always"]
+        "script": "gtest_perf_test.py"
+      },
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Win 7 ATI GPU Perf": {
+    "scripts": [
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Win 7 Intel GPU Perf": {
+    "scripts": [
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Win 7 Low-End Perf (2)": {
+    "scripts": [
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Win 7 Nvidia GPU Perf": {
+    "scripts": [
+      {
+        "args": [
+          "angle_perftests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=DrawCallPerf*",
+          "--test-launcher-jobs=1"
+        ],
+        "name": "angle_perftests",
+        "script": "gtest_perf_test.py"
+      },
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Win 7 Perf (3)": {
+    "scripts": [
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Win 7 x64 Perf (2)": {
+    "scripts": [
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
+      }
+    ]
+  },
+  "Win 8 Perf (2)": {
+    "scripts": [
+      {
+        "args": [
+          "performance_browser_tests",
+          "--test-launcher-print-test-stdio=always",
+          "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*",
+          "--test-launcher-jobs=1",
+          "--enable-gpu"
+        ],
+        "name": "performance_browser_tests",
+        "script": "gtest_perf_test.py"
       }
     ]
   }
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json
index 9933e3b..5742add 100644
--- a/testing/buildbot/chromium.webkit.json
+++ b/testing/buildbot/chromium.webkit.json
@@ -1,208 +1,506 @@
 {
-  "WebKit XP": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
+  "Android GN": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
     ],
-    "scripts": [
+    "gtest_tests": []
+  },
+  "Android GN (dbg)": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
+    ],
+    "gtest_tests": []
+  },
+  "Linux ChromiumOS Tests (1)": {
+    "gtest_tests": [
       {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 5
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chromeos_unittests"
+      },
+      {
+        "test": "chromevox_tests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
       }
     ]
   },
-  "WebKit Win7": {
+  "Linux ChromiumOS Tests (2)": {
+    "gtest_tests": []
+  },
+  "Linux ChromiumOS Tests (dbg)(1)": {
     "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
       {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
       },
       {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 20
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "test": "chromeos_unittests"
+      },
+      {
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "dbus_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "display_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 3
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
       }
     ]
   },
-  "WebKit Win7 (dbg)": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
+  "Linux ChromiumOS Tests (dbg)(2)": {
+    "gtest_tests": []
+  },
+  "Linux ChromiumOS Tests (dbg)(3)": {
+    "gtest_tests": []
+  },
+  "Linux GN": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "nacl_loader_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
     ],
-    "scripts": [
+    "gtest_tests": [
       {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
+        "test": "base_unittests"
       }
     ]
   },
-  "WebKit Mac10.6": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
+  "Linux GN (dbg)": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
     ],
-    "scripts": [
-      {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
-      }
-    ]
-  },
-  "WebKit Mac10.7": {
     "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
       {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
-      }
-    ]
-  },
-  "WebKit Mac10.8": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
-      }
-    ]
-  },
-  "WebKit Mac10.8 (retina)": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
-      }
-    ]
-  },
-  "WebKit Mac10.9": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
-      }
-    ]
-  },
-  "WebKit Mac10.6 (dbg)": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
-      }
-    ]
-  },
-  "WebKit Mac10.7 (dbg)": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
-      },
-      {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
+        "test": "base_unittests"
       }
     ]
   },
   "WebKit Linux": {
     "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
-    ],
-    "scripts": [
       {
-        "name": "webkit_lint",
-        "script": "webkit_lint.py"
+        "test": "blink_heap_unittests"
       },
       {
-        "name": "webkit_python_tests",
-        "script": "webkit_python_tests.py"
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
       }
-    ]
-  },
-  "WebKit Linux 32": {
-    "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
     ],
     "scripts": [
       {
@@ -217,10 +515,18 @@
   },
   "WebKit Linux (dbg)": {
     "gtest_tests": [
-      "blink_heap_unittests",
-      "blink_platform_unittests",
-      "webkit_unit_tests",
-      "wtf_unittests"
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
     ],
     "scripts": [
       {
@@ -233,216 +539,498 @@
       }
     ]
   },
-  "Linux ChromiumOS Tests (1)": {
+  "WebKit Linux 32": {
     "gtest_tests": [
-      "accessibility_unittests",
       {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "blink_heap_unittests"
       },
       {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chromeos_unittests",
-      "components_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "blink_platform_unittests"
       },
       {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "webkit_unit_tests"
       },
       {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "dbus_unittests",
-      "display_unittests",
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
       {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "jingle_unittests",
-      "content_unittests",
-      "device_unittests",
-      "media_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "aura_unittests",
-      {
-        "test": "ash_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "app_list_unittests",
-      "message_center_unittests",
-      "compositor_unittests",
-      "events_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "nacl_loader_unittests",
-      "app_shell_unittests",
-      "chromevox_tests",
-      {
-        "test": "extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "skia_unittests"
-    ]
-  },
-  "Linux ChromiumOS Tests (2)": {
-    "gtest_tests": [
-    ]
-  },
-  "Linux ChromiumOS Tests (dbg)(1)": {
-    "gtest_tests": [
-      "accessibility_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "cacheinvalidation_unittests",
-      "chromeos_unittests",
-      "components_unittests",
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "dbus_unittests",
-      "extensions_unittests",
-      "google_apis_unittests",
-      "gpu_unittests",
-      "url_unittests",
-      "jingle_unittests",
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "display_unittests",
-      "media_unittests",
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sandbox_linux_unittests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "aura_unittests",
-      {
-        "test": "ash_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "app_list_unittests",
-      "message_center_unittests",
-      "compositor_unittests",
-      "events_unittests",
-      "ipc_tests",
-      "sync_unit_tests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
       },
       {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 20
-        }
-      },
-      "app_shell_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      },
-      {
-        "test": "extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "gcm_unit_tests",
-      "skia_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 3
-        }
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
       }
     ]
   },
-  "Linux ChromiumOS Tests (dbg)(2)": {
+  "WebKit Linux Leak": {
     "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
     ]
   },
-  "Linux ChromiumOS Tests (dbg)(3)": {
+  "WebKit Linux Oilpan": {
     "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Linux Oilpan (dbg)": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Linux Oilpan Leak": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac Oilpan": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac Oilpan (dbg)": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.6": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.6 (dbg)": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.7": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.7 (dbg)": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.8": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.8 (retina)": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.9": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Win Oilpan": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Win Oilpan (dbg)": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Win7": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Win7 (dbg)": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit XP": {
+    "gtest_tests": [
+      {
+        "test": "blink_heap_unittests"
+      },
+      {
+        "test": "blink_platform_unittests"
+      },
+      {
+        "test": "webkit_unit_tests"
+      },
+      {
+        "test": "wtf_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
     ]
   }
 }
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 3f69a8e..ca0ab23 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -1,141 +1,456 @@
 {
-  "XP Tests (1)": {
+  "Vista Tests (1)": {
     "gtest_tests": [
-      "accessibility_unittests",
       {
-        "test": "base_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
-      "app_shell_unittests",
-      "aura_unittests",
       {
-        "test": "browser_tests",
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
       {
-        "test": "cast_unittests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cast_unittests"
       },
       {
-        "test": "cc_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cc_unittests"
       },
-      "chromedriver_unittests",
-      "chrome_elf_unittests",
       {
-        "test": "components_browsertests",
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "components_unittests"
       },
       {
-        "test": "components_unittests",
+        "test": "compositor_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
-      "compositor_unittests",
       {
-        "test": "content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "courgette_unittests"
       },
       {
-        "test": "courgette_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
       {
-        "test": "crypto_unittests",
+        "test": "events_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "extensions_browsertests"
       },
-      "events_unittests",
       {
-        "test": "extensions_browsertests",
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "gpu_unittests"
       },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
       {
-        "test": "gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
+        "test": "installer_util_unittests"
       },
-      "installer_util_unittests",
       {
-        "test": "interactive_ui_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_mojo_unittests",
-      "ipc_tests",
-      "jingle_unittests",
       {
-        "test": "media_unittests",
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "media_unittests"
       },
-      "nacl_loader_unittests",
       {
-        "test": "net_unittests",
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "net_unittests"
       },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "sql_unittests",
       {
-        "test": "sync_integration_tests",
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "sync_integration_tests"
       },
-      "sync_unit_tests",
       {
-        "test": "unit_tests",
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "unit_tests"
       },
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ],
+    "scripts": []
+  },
+  "Win 7 Tests x64 (1)": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "test": "app_installer_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "app_list_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cast_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "device_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "keyboard_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "media_unittests"
+      },
+      {
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ],
     "scripts": [
       {
@@ -152,466 +467,368 @@
       }
     ]
   },
-  "Vista Tests (1)": {
-    "gtest_tests": [
+  "Win x64 GN": {
+    "additional_compile_targets": [
       "accessibility_unittests",
+      "app_list_unittests",
       "app_shell_unittests",
+      "ash_unittests",
       "aura_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
       "cacheinvalidation_unittests",
-      {
-        "test": "cast_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "cc_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "chromedriver_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
       "chrome_elf_unittests",
-      {
-        "test": "components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
       "compositor_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
       "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
       "gcm_unit_tests",
       "gfx_unittests",
       "google_apis_unittests",
-      {
-        "test": "gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      },
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
       "ipc_tests",
       "jingle_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
       "mojo_common_unittests",
       "mojo_public_bindings_unittests",
       "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
       "ppapi_unittests",
       "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
       "sbox_integration_tests",
+      "sbox_unittests",
       "sbox_validation_tests",
+      "skia_unittests",
       "sql_unittests",
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
+      "sync_integration_tests",
       "sync_unit_tests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
       "ui_base_unittests",
       "ui_touch_selection_unittests",
       "url_unittests",
       "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
+      "wm_unittests"
     ],
-    "scripts": [
+    "gtest_tests": [
       {
-        "name": "telemetry_unittests",
-        "script": "telemetry_unittests.py"
-      },
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "Win x64 GN (dbg)": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "app_shell_unittests",
+      "ash_unittests",
+      "aura_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
+      "chrome_elf_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "compositor_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "sbox_integration_tests",
+      "sbox_unittests",
+      "sbox_validation_tests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
       {
-        "name": "telemetry_perf_unittests",
-        "script": "telemetry_perf_unittests.py"
+        "test": "base_unittests"
       }
     ]
   },
   "Win7 Tests (1)": {
     "gtest_tests": [
-      "app_installer_unittests",
-      "app_list_unittests",
-      "accessibility_unittests",
       {
-        "test": "ash_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
-      "app_shell_unittests",
-      "aura_unittests",
       {
-        "test": "base_unittests",
+        "test": "app_installer_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "app_list_unittests"
       },
       {
-        "test": "browser_tests",
+        "test": "app_shell_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
-        }
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
       {
-        "test": "cast_unittests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cast_unittests"
       },
       {
-        "test": "cc_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cc_unittests"
       },
-      "chromedriver_unittests",
-      "chrome_elf_unittests",
-      "components_browsertests",
       {
-        "test": "components_unittests",
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "test": "components_browsertests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "components_unittests"
       },
-      "compositor_unittests",
       {
-        "test": "content_browsertests",
+        "test": "compositor_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
       {
-        "test": "courgette_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "courgette_unittests"
       },
       {
-        "test": "crypto_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
-      "device_unittests",
-      "events_unittests",
       {
-        "test": "extensions_browsertests",
+        "test": "device_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "extensions_browsertests"
       },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
       {
-        "test": "gpu_unittests",
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "gpu_unittests"
       },
-      "installer_util_unittests",
       {
-        "test": "interactive_ui_tests",
+        "test": "installer_util_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_tests",
-      "jingle_unittests",
-      "keyboard_unittests",
       {
-        "test": "media_unittests",
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "test": "keyboard_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "media_unittests"
       },
-      "message_center_unittests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
       {
-        "test": "net_unittests",
+        "test": "message_center_unittests"
+      },
+      {
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "net_unittests"
       },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "sql_unittests",
       {
-        "test": "sync_integration_tests",
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "sync_integration_tests"
       },
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
       {
-        "test": "unit_tests",
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
-      },
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
-    ],
-    "scripts": [
-      {
-        "name": "telemetry_unittests",
-        "script": "telemetry_unittests.py"
+        },
+        "test": "unit_tests"
       },
       {
-        "name": "telemetry_perf_unittests",
-        "script": "telemetry_perf_unittests.py"
+        "test": "url_unittests"
       },
       {
-        "name": "nacl_integration",
-        "script": "nacl_integration.py"
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
       }
-    ]
-  },
-  "Win 7 Tests x64 (1)": {
-    "gtest_tests": [
-      "accessibility_unittests",
-      {
-        "test": "base_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        }
-      },
-      "app_installer_unittests",
-      "app_list_unittests",
-      "app_shell_unittests",
-      {
-        "test": "ash_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "aura_unittests",
-      "cacheinvalidation_unittests",
-      {
-        "test": "cast_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "cc_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "chromedriver_unittests",
-      "chrome_elf_unittests",
-      "components_browsertests",
-      {
-        "test": "components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "compositor_unittests",
-      {
-        "test": "content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "courgette_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "test": "crypto_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "device_unittests",
-      "events_unittests",
-      {
-        "test": "extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "extensions_unittests",
-      "gcm_unit_tests",
-      "gfx_unittests",
-      "google_apis_unittests",
-      {
-        "test": "gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "installer_util_unittests",
-      {
-        "test": "interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      },
-      "ipc_tests",
-      "jingle_unittests",
-      "keyboard_unittests",
-      {
-        "test": "media_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "message_center_unittests",
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
-      {
-        "test": "net_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      {
-        "test": "sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "sql_unittests",
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
-      {
-        "test": "unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
     ],
     "scripts": [
       {
@@ -630,146 +847,217 @@
   },
   "Win7 Tests (dbg)(1)": {
     "gtest_tests": [
-      "accessibility_unittests",
       {
-        "test": "ash_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "accessibility_unittests"
       },
-      "app_shell_unittests",
-      "aura_unittests",
       {
-        "test": "base_unittests",
+        "test": "app_shell_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "ash_unittests"
       },
       {
-        "test": "browser_tests",
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 20
-        }
+        },
+        "test": "browser_tests"
       },
-      "cacheinvalidation_unittests",
       {
-        "test": "cast_unittests",
+        "test": "cacheinvalidation_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cast_unittests"
       },
       {
-        "test": "cc_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "cc_unittests"
       },
-      "chromedriver_unittests",
-      "chrome_elf_unittests",
       {
-        "test": "components_unittests",
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "components_unittests"
       },
-      "compositor_unittests",
       {
-        "test": "content_browsertests",
+        "test": "compositor_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "content_browsertests"
       },
       {
-        "test": "content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "content_unittests"
       },
       {
-        "test": "courgette_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "courgette_unittests"
       },
       {
-        "test": "crypto_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "crypto_unittests"
       },
-      "events_unittests",
       {
-        "test": "extensions_browsertests",
+        "test": "events_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "extensions_browsertests"
       },
-      "extensions_unittests",
-      "gcm_unit_tests",
       {
-        "test": "gpu_unittests",
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "gpu_unittests"
       },
-      "installer_util_unittests",
       {
-        "test": "interactive_ui_tests",
+        "test": "installer_util_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 4
-        }
+        },
+        "test": "interactive_ui_tests"
       },
-      "ipc_tests",
-      "jingle_unittests",
       {
-        "test": "media_unittests",
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "media_unittests"
       },
-      "mojo_common_unittests",
-      "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
-      "mojo_public_system_unittests",
-      "mojo_public_utility_unittests",
-      "mojo_system_unittests",
-      "nacl_loader_unittests",
       {
-        "test": "net_unittests",
+        "test": "mojo_common_unittests"
+      },
+      {
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "test": "mojo_public_environment_unittests"
+      },
+      {
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "test": "mojo_public_utility_unittests"
+      },
+      {
+        "test": "mojo_system_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "net_unittests"
       },
-      "ppapi_unittests",
-      "printing_unittests",
-      "remoting_unittests",
-      "sbox_unittests",
-      "sbox_integration_tests",
-      "sbox_validation_tests",
-      "sql_unittests",
       {
-        "test": "sync_integration_tests",
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
-        }
+        },
+        "test": "sync_integration_tests"
       },
-      "sync_unit_tests",
-      "ui_base_unittests",
-      "ui_touch_selection_unittests",
       {
-        "test": "unit_tests",
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
-        }
+        },
+        "test": "unit_tests"
       },
-      "url_unittests",
-      "views_unittests",
-      "wm_unittests",
-      "skia_unittests"
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
     ],
     "scripts": [
       {
@@ -784,14 +1072,372 @@
   },
   "Win8 Aura": {
     "gtest_tests": [
-      "views_unittests",
-      "wm_unittests",
-      "aura_unittests",
+      {
+        "test": "ash_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "test": "content_browsertests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ]
+  },
+  "Win8 GN": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "app_shell_unittests",
       "ash_unittests",
+      "aura_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
+      "chrome_elf_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
       "compositor_unittests",
       "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
       "events_unittests",
-      "ui_touch_selection_unittests"
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "sbox_integration_tests",
+      "sbox_unittests",
+      "sbox_validation_tests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "Win8 GN (dbg)": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "app_shell_unittests",
+      "ash_unittests",
+      "aura_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
+      "chrome_elf_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "compositor_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "sbox_integration_tests",
+      "sbox_unittests",
+      "sbox_validation_tests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "XP Tests (1)": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "accessibility_unittests"
+      },
+      {
+        "test": "app_shell_unittests"
+      },
+      {
+        "test": "aura_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 10
+        },
+        "test": "browser_tests"
+      },
+      {
+        "test": "cacheinvalidation_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cast_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "test": "chrome_elf_unittests"
+      },
+      {
+        "test": "chromedriver_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "components_unittests"
+      },
+      {
+        "test": "compositor_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "courgette_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      },
+      {
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "extensions_browsertests"
+      },
+      {
+        "test": "extensions_unittests"
+      },
+      {
+        "test": "gcm_unit_tests"
+      },
+      {
+        "test": "gfx_unittests"
+      },
+      {
+        "test": "google_apis_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "test": "installer_util_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 2
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "test": "ipc_mojo_unittests"
+      },
+      {
+        "test": "ipc_tests"
+      },
+      {
+        "test": "jingle_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "media_unittests"
+      },
+      {
+        "test": "nacl_loader_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "net_unittests"
+      },
+      {
+        "test": "ppapi_unittests"
+      },
+      {
+        "test": "printing_unittests"
+      },
+      {
+        "test": "remoting_unittests"
+      },
+      {
+        "test": "sbox_integration_tests"
+      },
+      {
+        "test": "sbox_unittests"
+      },
+      {
+        "test": "sbox_validation_tests"
+      },
+      {
+        "test": "skia_unittests"
+      },
+      {
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "test": "sync_unit_tests"
+      },
+      {
+        "test": "ui_base_unittests"
+      },
+      {
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "unit_tests"
+      },
+      {
+        "test": "url_unittests"
+      },
+      {
+        "test": "views_unittests"
+      },
+      {
+        "test": "wm_unittests"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "telemetry_unittests",
+        "script": "telemetry_unittests.py"
+      },
+      {
+        "name": "telemetry_perf_unittests",
+        "script": "telemetry_perf_unittests.py"
+      },
+      {
+        "name": "nacl_integration",
+        "script": "nacl_integration.py"
+      }
     ]
   }
 }
diff --git a/testing/buildbot/chromium_memory_trybot.json b/testing/buildbot/chromium_memory_trybot.json
index c794785..c58d2de 100644
--- a/testing/buildbot/chromium_memory_trybot.json
+++ b/testing/buildbot/chromium_memory_trybot.json
@@ -2,109 +2,113 @@
   "gtest_tests": [
     "accessibility_unittests",
     {
-      "test": "base_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "base_unittests"
     },
     {
-      "test": "browser_tests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 10
-      }
+      },
+      "test": "browser_tests"
     },
     "cacheinvalidation_unittests",
     {
-      "test": "cc_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "cc_unittests"
     },
     {
-      "test": "components_browsertests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "components_browsertests"
     },
     {
-      "test": "components_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "components_unittests"
     },
     {
-      "test": "content_browsertests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "content_browsertests"
     },
     {
-      "test": "content_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "content_unittests"
     },
     {
-      "test": "crypto_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "crypto_unittests"
     },
     "device_unittests",
     {
-      "test": "display_unittests",
-      "platforms": ["linux"]
+      "platforms": [
+        "linux"
+      ],
+      "test": "display_unittests"
     },
     "extensions_unittests",
     "gcm_unit_tests",
     "gfx_unittests",
     "google_apis_unittests",
     {
-      "test": "gpu_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "gpu_unittests"
     },
     {
-      "test": "interactive_ui_tests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 3
-      }
+      },
+      "test": "interactive_ui_tests"
     },
     "ipc_tests",
     "jingle_unittests",
     {
-      "test": "media_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "media_unittests"
     },
     {
-      "test": "net_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 2
-      }
+      },
+      "test": "net_unittests"
     },
     "ppapi_unittests",
     "printing_unittests",
     "remoting_unittests",
     {
-      "test": "sandbox_linux_unittests",
-      "platforms": ["linux"]
+      "platforms": [
+        "linux"
+      ],
+      "test": "sandbox_linux_unittests"
     },
     "skia_unittests",
     "sql_unittests",
     "sync_unit_tests",
     "ui_base_unittests",
     {
-      "test": "unit_tests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 2
-      }
+      },
+      "test": "unit_tests"
     },
     "url_unittests"
   ]
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json
index 065de53..d42d551 100644
--- a/testing/buildbot/chromium_trybot.json
+++ b/testing/buildbot/chromium_trybot.json
@@ -2,25 +2,32 @@
   "compile_targets": [
     "all"
   ],
+  "filter_compile_builders": [
+    "win_chromium_compile_dbg",
+    "win_chromium_rel_swarming",
+    "win_chromium_x64_rel_swarming",
+    "win8_chromium_rel"
+  ],
   "gtest_tests": [
     {
-      "test": "accessibility_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "accessibility_unittests"
     },
     {
-      "test": "app_installer_unittests",
-      "platforms": ["win"]
+      "platforms": [
+        "win"
+      ],
+      "test": "app_installer_unittests"
     },
     {
-      "test": "app_list_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "app_list_unittests"
     },
     {
-      "test": "ash_unittests",
       "chromium_configs": [
         "chromium_chromeos",
         "chromium_chromeos_clang",
@@ -28,155 +35,183 @@
       ],
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "ash_unittests"
     },
     {
-      "test": "ash_unittests",
-      "platforms": ["win"],
+      "platforms": [
+        "win"
+      ],
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "ash_unittests"
     },
     {
-      "test": "base_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "base_unittests"
     },
     {
-      "test": "browser_tests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 8
-      }
+      },
+      "test": "browser_tests"
     },
     "cacheinvalidation_unittests",
     {
-      "test": "cast_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "cast_unittests"
     },
     {
-      "test": "cc_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "cc_unittests"
     },
     "chromedriver_unittests",
     {
-      "test": "chromevox_tests",
       "chromium_configs": [
         "chromium_chromeos",
         "chromium_chromeos_clang",
         "chromium_chromeos_ozone"
-      ]
+      ],
+      "test": "chromevox_tests"
     },
     {
-      "test": "chrome_elf_unittests",
-      "platforms": ["win"]
+      "platforms": [
+        "win"
+      ],
+      "test": "chrome_elf_unittests"
     },
     {
-      "test": "components_browsertests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "components_browsertests"
     },
     {
-      "test": "components_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "components_unittests"
     },
     {
-      "test": "compositor_unittests",
-      "platforms": ["linux", "win"]
+      "platforms": [
+        "linux",
+        "win"
+      ],
+      "test": "compositor_unittests"
     },
     {
-      "test": "courgette_unittests",
       "can_use_on_swarming_builders": true,
-      "platforms": ["win"]
+      "platforms": [
+        "win"
+      ],
+      "test": "courgette_unittests"
     },
     {
-      "test": "content_browsertests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "content_browsertests"
     },
     {
-      "test": "content_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "content_unittests"
     },
     {
-      "test": "crypto_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "crypto_unittests"
     },
     {
-      "test": "dbus_unittests",
-      "platforms": ["linux"]
+      "platforms": [
+        "linux"
+      ],
+      "test": "dbus_unittests"
     },
     "device_unittests",
     {
-      "test": "events_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "events_unittests"
     },
     {
-      "test": "extensions_unittests",
-      "platforms": ["win", "mac", "linux"]
+      "platforms": [
+        "win",
+        "mac",
+        "linux"
+      ],
+      "test": "extensions_unittests"
     },
     "gcm_unit_tests",
     {
-      "test": "gfx_unittests",
+      "chromium_configs": [
+        "chromium_chromeos",
+        "chromium_chromeos_clang",
+        "chromium_chromeos_ozone"
+      ],
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "gfx_unittests"
     },
     "google_apis_unittests",
     {
-      "test": "gpu_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "gpu_unittests"
     },
     {
-      "test": "interactive_ui_tests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 3
-      }
+      },
+      "test": "interactive_ui_tests"
     },
     {
-      "test": "installer_util_unittests",
-      "platforms": ["win"]
+      "platforms": [
+        "win"
+      ],
+      "test": "installer_util_unittests"
     },
     {
-      "test": "ipc_mojo_unittests",
-      "platforms": ["linux"]
+      "platforms": [
+        "linux"
+      ],
+      "test": "ipc_mojo_unittests"
     },
     "ipc_tests",
     "jingle_unittests",
     {
-      "test": "keyboard_unittests",
-      "platforms": ["linux", "win"]
+      "platforms": [
+        "linux",
+        "win"
+      ],
+      "test": "keyboard_unittests"
     },
     "media_perftests",
     {
-      "test": "media_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "media_unittests"
     },
     {
-      "test": "message_center_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "message_center_unittests"
     },
     "mojo_common_unittests",
     "mojo_public_bindings_unittests",
@@ -186,127 +221,153 @@
     "mojo_system_unittests",
     "nacl_loader_unittests",
     {
-      "test": "net_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "net_unittests"
     },
     "ppapi_unittests",
     "printing_unittests",
     "remoting_unittests",
     {
-      "test": "sbox_integration_tests",
-      "platforms": ["win"]
+      "platforms": [
+        "win"
+      ],
+      "test": "sbox_integration_tests"
     },
     {
-      "test": "sbox_validation_tests",
-      "platforms": ["win"]
+      "platforms": [
+        "win"
+      ],
+      "test": "sbox_validation_tests"
     },
     {
-      "test": "sbox_unittests",
-      "platforms": ["win"]
+      "platforms": [
+        "win"
+      ],
+      "test": "sbox_unittests"
     },
     "sql_unittests",
     {
-      "test": "sync_integration_tests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 3
-      }
+      },
+      "test": "sync_integration_tests"
     },
     "sync_unit_tests",
     {
-      "test": "ui_base_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "ui_base_unittests"
     },
     {
-      "test": "ui_touch_selection_unittests",
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "ui_touch_selection_unittests"
     },
     {
-      "test": "unit_tests",
       "swarming": {
         "can_use_on_swarming_builders": true,
         "shards": 2
-      }
+      },
+      "test": "unit_tests"
     },
     {
-      "test": "ui_chromeos_unittests",
-      "platforms": ["linux"],
       "chromium_configs": [
         "chromium_chromeos",
         "chromium_chromeos_clang",
         "chromium_chromeos_ozone"
-      ]
+      ],
+      "platforms": [
+        "linux"
+      ],
+      "test": "ui_chromeos_unittests"
     },
     "url_unittests",
     "skia_unittests",
     {
-      "test": "wm_unittests",
-      "platforms": ["linux", "win"]
+      "platforms": [
+        "linux",
+        "win"
+      ],
+      "test": "wm_unittests"
     },
     {
-      "test": "extensions_browsertests",
-      "platforms": ["linux", "win"],
+      "platforms": [
+        "linux",
+        "win"
+      ],
       "swarming": {
         "can_use_on_swarming_builders": true
-      }
+      },
+      "test": "extensions_browsertests"
     },
     {
-      "test": "app_shell_unittests",
-      "platforms": ["linux", "win"]
+      "platforms": [
+        "linux",
+        "win"
+      ],
+      "test": "app_shell_unittests"
     },
     {
-      "test": "aura_unittests",
-      "platforms": ["linux", "win"]
+      "platforms": [
+        "linux",
+        "win"
+      ],
+      "test": "aura_unittests"
     },
     {
-      "test": "views_unittests",
-      "platforms": ["linux", "win"]
+      "platforms": [
+        "linux",
+        "win"
+      ],
+      "test": "views_unittests"
     },
     {
-      "test": "sandbox_linux_unittests",
-      "platforms": ["linux"],
-      "args": ["--test-launcher-print-test-stdio=always"]
+      "args": [
+        "--test-launcher-print-test-stdio=always"
+      ],
+      "platforms": [
+        "linux"
+      ],
+      "test": "sandbox_linux_unittests"
     },
     {
-      "test": "sandbox_mac_unittests",
-      "platforms": ["mac"]
+      "platforms": [
+        "mac"
+      ],
+      "test": "sandbox_mac_unittests"
     },
     {
-      "test": "chromeos_unittests",
-      "platforms": ["linux"],
       "chromium_configs": [
         "chromium_chromeos",
         "chromium_chromeos_clang",
         "chromium_chromeos_ozone"
-      ]
+      ],
+      "platforms": [
+        "linux"
+      ],
+      "test": "chromeos_unittests"
     },
     {
-      "test": "display_unittests",
-      "platforms": ["linux"]
+      "platforms": [
+        "linux"
+      ],
+      "test": "display_unittests"
     },
     {
-      "test": "ozone_unittests",
-      "platforms": ["linux"],
-      "chromium_configs": ["chromium_chromeos_ozone"]
+      "chromium_configs": [
+        "chromium_chromeos_ozone"
+      ],
+      "platforms": [
+        "linux"
+      ],
+      "test": "ozone_unittests"
     }
   ],
-
-  "non_filter_builders": [
-  ],
-
-  "non_filter_tests_builders": [
-  ],
-
-  "filter_compile_builders": [
-    "win_chromium_compile_dbg",
-    "win_chromium_rel_swarming",
-    "win_chromium_x64_rel_swarming",
-    "win8_chromium_rel"
-  ]
+  "non_filter_builders": [],
+  "non_filter_tests_builders": []
 }
diff --git a/testing/buildbot/client.v8.json b/testing/buildbot/client.v8.json
new file mode 100644
index 0000000..2f43da0
--- /dev/null
+++ b/testing/buildbot/client.v8.json
@@ -0,0 +1,64 @@
+{
+  "V8 Android GN (dbg)": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
+    ],
+    "gtest_tests": []
+  },
+  "V8 Linux GN": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "nacl_loader_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": []
+  }
+}
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
new file mode 100755
index 0000000..bc362fd
--- /dev/null
+++ b/testing/buildbot/manage.py
@@ -0,0 +1,193 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Toolbox to manage all the json files in this directory.
+
+It can reformat them in their canonical format or ensures they are well
+formatted.
+"""
+
+import argparse
+import collections
+import glob
+import json
+import os
+import subprocess
+import sys
+
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR))
+sys.path.insert(0, os.path.join(SRC_DIR, 'third_party', 'colorama', 'src'))
+
+import colorama
+
+
+SKIP = {
+  # These are not 'builders'.
+  'compile_targets', 'gtest_tests', 'filter_compile_builders',
+  'non_filter_builders', 'non_filter_tests_builders',
+
+  # These are not supported on Swarming yet.
+  # http://crbug.com/472205
+  'Chromium Mac 10.10',
+  # http://crbug.com/441429
+  'Linux Trusty (32)', 'Linux Trusty (dbg)(32)',
+
+  # One off builders. Note that Swarming does support ARM.
+  'Linux ARM Cross-Compile',
+  'Site Isolation Linux',
+  'Site Isolation Win',
+}
+
+
+def upgrade_test(test):
+  """Converts from old style string to new style dict."""
+  if isinstance(test, basestring):
+    return {'test': test}
+  assert isinstance(test, dict)
+  return test
+
+
+def get_isolates():
+  """Returns the list of all isolate files."""
+  files = subprocess.check_output(['git', 'ls-files'], cwd=SRC_DIR).splitlines()
+  return [os.path.basename(f) for f in files if f.endswith('.isolate')]
+
+
+def main():
+  colorama.init()
+  parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__)
+  group = parser.add_mutually_exclusive_group(required=True)
+  group.add_argument(
+      '-c', '--check', action='store_true', help='Only check the files')
+  group.add_argument(
+      '--convert', action='store_true',
+      help='Convert a test to run on Swarming everywhere')
+  group.add_argument(
+      '--remaining', action='store_true',
+      help='Count the number of tests not yet running on Swarming')
+  group.add_argument(
+      '-w', '--write', action='store_true', help='Rewrite the files')
+  parser.add_argument(
+      'test_name', nargs='?',
+      help='The test name to print which configs to update; only to be used '
+           'with --remaining')
+  args = parser.parse_args()
+
+  if args.convert or args.remaining:
+    isolates = get_isolates()
+
+  if args.convert:
+    if not args.test_name:
+      parser.error('A test name is required with --convert')
+    if args.test_name + '.isolate' not in isolates:
+      parser.error('Create %s.isolate first' % args.test_name)
+
+  # Stats when running in --remaining mode;
+  tests_location = collections.defaultdict(
+      lambda: {
+        'count_run_local': 0, 'count_run_on_swarming': 0, 'local_configs': {}
+      })
+
+  result = 0
+  for filepath in glob.glob(os.path.join(THIS_DIR, '*.json')):
+    filename = os.path.basename(filepath)
+    with open(filepath) as f:
+      content = f.read()
+    try:
+      config = json.loads(content)
+    except ValueError as e:
+      print "Exception raised while checking %s: %s" % (filepath, e)
+      raise
+    for builder, data in sorted(config.iteritems()):
+      if builder in SKIP:
+        # Oddities.
+        continue
+
+      if not isinstance(data, dict):
+        print('%s: %s is broken: %s' % (filename, builder, data))
+        continue
+
+      if 'gtest_tests' in data:
+        config[builder]['gtest_tests'] = sorted(
+          (upgrade_test(l) for l in data['gtest_tests']),
+          key=lambda x: x['test'])
+
+        if args.remaining:
+          for test in data['gtest_tests']:
+            name = test['test']
+            if test.get('swarming', {}).get('can_use_on_swarming_builders'):
+              tests_location[name]['count_run_on_swarming'] += 1
+            else:
+              tests_location[name]['count_run_local'] += 1
+              tests_location[name]['local_configs'].setdefault(
+                  filename, []).append(builder)
+        elif args.convert:
+          for test in data['gtest_tests']:
+            if test['test'] != args.test_name:
+              continue
+            test.setdefault('swarming', {})
+            if not test['swarming'].get('can_use_on_swarming_builders'):
+              print('- %s: %s' % (filename, builder))
+              test['swarming']['can_use_on_swarming_builders'] = True
+
+    expected = json.dumps(
+        config, sort_keys=True, indent=2, separators=(',', ': ')) + '\n'
+    if content != expected:
+      result = 1
+      if args.write or args.convert:
+        with open(filepath, 'wb') as f:
+          f.write(expected)
+        if args.write:
+          print('Updated %s' % filename)
+      else:
+        print('%s is not in canonical format' % filename)
+
+  if args.remaining:
+    if args.test_name:
+      if args.test_name not in tests_location:
+        print('Unknown test %s' % args.test_name)
+        return 1
+      for config, builders in sorted(
+          tests_location[args.test_name]['local_configs'].iteritems()):
+        print('%s:' % config)
+        for builder in sorted(builders):
+          print('  %s' % builder)
+    else:
+      l = max(map(len, tests_location))
+      print('%-*s%sLocal       %sSwarming  %sMissing isolate' %
+          (l, 'Test', colorama.Fore.RED, colorama.Fore.GREEN,
+            colorama.Fore.MAGENTA))
+      total_local = 0
+      total_swarming = 0
+      for name, location in sorted(tests_location.iteritems()):
+        if not location['count_run_on_swarming']:
+          c = colorama.Fore.RED
+        elif location['count_run_local']:
+          c = colorama.Fore.YELLOW
+        else:
+          c = colorama.Fore.GREEN
+        total_local += location['count_run_local']
+        total_swarming += location['count_run_on_swarming']
+        missing_isolate = ''
+        if name + '.isolate' not in isolates:
+          missing_isolate = colorama.Fore.MAGENTA + '*'
+        print('%s%-*s %4d           %4d    %s' %
+            (c, l, name, location['count_run_local'],
+              location['count_run_on_swarming'], missing_isolate))
+
+      total = total_local + total_swarming
+      p_local = 100. * total_local / total
+      p_swarming = 100. * total_swarming / total
+      print('%s%-*s %4d (%4.1f%%)   %4d (%4.1f%%)' %
+          (colorama.Fore.WHITE, l, 'Total:', total_local, p_local,
+            total_swarming, p_swarming))
+      print('%-*s                %4d' % (l, 'Total executions:', total))
+  return result
+
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json
index ed45362..f5c6710 100644
--- a/testing/buildbot/trybot_analyze_config.json
+++ b/testing/buildbot/trybot_analyze_config.json
@@ -1,4 +1,9 @@
 {
+  "android_webview": {
+    "exclusions": [
+      "android_webview/.*"
+    ]
+  },
   "base": {
     "exclusions": [
       ".*isolate",
@@ -16,11 +21,6 @@
       "tools/whitespace.txt"
     ]
   },
-  "android_webview": {
-    "exclusions": [
-      "android_webview/.*"
-    ]
-  },
   "chromium": {
     "exclusions": [
       "chrome/test/data/.*",
@@ -37,6 +37,7 @@
       "third_party/zlib/google/test/data/.*",
       "tools/clang/scripts/update.py",
       "tools/clang/scripts/update.sh",
+      "tools/mb/.*",
       "tools/metrics/histograms/histograms.xml",
       "tools/perf/.*",
       "tools/telemetry/.*"
diff --git a/testing/buildbot/tryserver.blink.json b/testing/buildbot/tryserver.blink.json
new file mode 100644
index 0000000..fe4d275
--- /dev/null
+++ b/testing/buildbot/tryserver.blink.json
@@ -0,0 +1,65 @@
+{
+  "android_chromium_gn_compile_rel": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
+    ],
+    "gtest_tests": []
+  },
+  "linux_chromium_gn_rel": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "chromedriver_unittests",
+      "chromeos_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_chromeos_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  }
+}
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json
index 2c63c08..6d3c6d4 100644
--- a/testing/buildbot/tryserver.chromium.linux.json
+++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -1,2 +1,200 @@
 {
+  "android_chromium_gn_compile_dbg": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
+    ],
+    "gtest_tests": []
+  },
+  "android_chromium_gn_compile_rel": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
+    ],
+    "gtest_tests": []
+  },
+  "linux_chromium_gn_chromeos_dbg": {
+    "additional_compile_targets": [
+      "net_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "linux_chromium_gn_chromeos_rel": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "chromedriver_unittests",
+      "chromeos_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_chromeos_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "linux_chromium_gn_dbg": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "linux_chromium_gn_rel": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "nacl_loader_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  }
 }
diff --git a/testing/buildbot/tryserver.chromium.mac.json b/testing/buildbot/tryserver.chromium.mac.json
index 2c63c08..4a46f9a 100644
--- a/testing/buildbot/tryserver.chromium.mac.json
+++ b/testing/buildbot/tryserver.chromium.mac.json
@@ -1,2 +1,72 @@
 {
+  "mac_chromium_gn_dbg": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "base_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "crypto_unittests",
+      "gcm_unit_tests",
+      "gn_unittests",
+      "gpu_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "url_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "mac_chromium_gn_rel": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "base_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "crypto_unittests",
+      "gcm_unit_tests",
+      "gn_unittests",
+      "gpu_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "url_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  }
 }
diff --git a/testing/buildbot/tryserver.chromium.perf.json b/testing/buildbot/tryserver.chromium.perf.json
index 2c63c08..0967ef4 100644
--- a/testing/buildbot/tryserver.chromium.perf.json
+++ b/testing/buildbot/tryserver.chromium.perf.json
@@ -1,2 +1 @@
-{
-}
+{}
diff --git a/testing/buildbot/tryserver.chromium.win.json b/testing/buildbot/tryserver.chromium.win.json
index 2c63c08..6710973 100644
--- a/testing/buildbot/tryserver.chromium.win.json
+++ b/testing/buildbot/tryserver.chromium.win.json
@@ -1,2 +1,250 @@
 {
+  "win8_chromium_gn_dbg": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "app_shell_unittests",
+      "ash_unittests",
+      "aura_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
+      "chrome_elf_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "compositor_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "sbox_integration_tests",
+      "sbox_unittests",
+      "sbox_validation_tests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "win8_chromium_gn_rel": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "app_shell_unittests",
+      "ash_unittests",
+      "aura_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
+      "chrome_elf_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "compositor_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "sbox_integration_tests",
+      "sbox_unittests",
+      "sbox_validation_tests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "win_chromium_gn_x64_dbg": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "app_shell_unittests",
+      "ash_unittests",
+      "aura_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
+      "chrome_elf_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "compositor_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "sbox_integration_tests",
+      "sbox_unittests",
+      "sbox_validation_tests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  },
+  "win_chromium_gn_x64_rel": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "app_shell_unittests",
+      "ash_unittests",
+      "aura_unittests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chrome",
+      "chrome_elf_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "compositor_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "courgette_unittests",
+      "crypto_unittests",
+      "device_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "keyboard_unittests",
+      "media_unittests",
+      "message_center_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "sbox_integration_tests",
+      "sbox_unittests",
+      "sbox_validation_tests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "test": "base_unittests"
+      }
+    ]
+  }
 }
diff --git a/testing/buildbot/tryserver.v8.json b/testing/buildbot/tryserver.v8.json
new file mode 100644
index 0000000..a92d05d
--- /dev/null
+++ b/testing/buildbot/tryserver.v8.json
@@ -0,0 +1,64 @@
+{
+  "v8_android_chromium_gn_dbg": {
+    "additional_compile_targets": [
+      "chrome_shell_apk"
+    ],
+    "gtest_tests": []
+  },
+  "v8_linux_chromium_gn_rel": {
+    "additional_compile_targets": [
+      "accessibility_unittests",
+      "app_list_unittests",
+      "aura_unittests",
+      "browser_tests",
+      "cacheinvalidation_unittests",
+      "cast_unittests",
+      "cc_unittests",
+      "chromedriver_unittests",
+      "components_browsertests",
+      "components_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "crypto_unittests",
+      "dbus_unittests",
+      "device_unittests",
+      "display_unittests",
+      "events_unittests",
+      "extensions_browsertests",
+      "extensions_unittests",
+      "gcm_unit_tests",
+      "gfx_unittests",
+      "gn_unittests",
+      "google_apis_unittests",
+      "gpu_unittests",
+      "interactive_ui_tests",
+      "ipc_mojo_unittests",
+      "ipc_tests",
+      "jingle_unittests",
+      "media_unittests",
+      "mojo_common_unittests",
+      "mojo_public_bindings_unittests",
+      "mojo_public_environment_unittests",
+      "mojo_public_system_unittests",
+      "mojo_public_utility_unittests",
+      "mojo_system_unittests",
+      "nacl_loader_unittests",
+      "net_unittests",
+      "ppapi_unittests",
+      "printing_unittests",
+      "remoting_unittests",
+      "sandbox_linux_unittests",
+      "skia_unittests",
+      "sql_unittests",
+      "sync_integration_tests",
+      "sync_unit_tests",
+      "ui_base_unittests",
+      "ui_touch_selection_unittests",
+      "unit_tests",
+      "url_unittests",
+      "views_unittests",
+      "wm_unittests"
+    ],
+    "gtest_tests": []
+  }
+}
diff --git a/testing/chromoting/browser_test_commands_linux.txt b/testing/chromoting/browser_test_commands_linux.txt
index 95f076f..c9ecb29 100644
--- a/testing/chromoting/browser_test_commands_linux.txt
+++ b/testing/chromoting/browser_test_commands_linux.txt
@@ -14,4 +14,5 @@
 /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Cancel_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
 /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Update_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
 /usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=RemoteDesktopBrowserTest.MANUAL_Invalid_PIN --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123457 --override-user-data-dir=/tmp/chromoting_test_profile
-/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=FullscreenBrowserTest.MANUAL_Me2Me_Bump_Scroll --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
\ No newline at end of file
+/usr/bin/python ../xvfb.py #PROD_DIR# #PROD_DIR#/browser_tests --gtest_filter=FullscreenBrowserTest.MANUAL_Me2Me_Bump_Scroll --run-manual --ui-test-action-timeout=100000 --webapp-unpacked=#PROD_DIR#/remoting/remoting.webapp.v2 --extension-name=Chromoting --accounts-file=../../remoting/tools/internal/test_accounts.json --account-type=gmail --me2me-pin=123456 --override-user-data-dir=/tmp/chromoting_test_profile
+cd ../../remoting/internal/config && /usr/bin/python ./is_valid_json.py
\ No newline at end of file
diff --git a/testing/chromoting/browser_tests_launcher.py b/testing/chromoting/browser_tests_launcher.py
index a265f56..2fceb7c 100644
--- a/testing/chromoting/browser_tests_launcher.py
+++ b/testing/chromoting/browser_tests_launcher.py
@@ -21,15 +21,19 @@
 CRD_ID = 'chrome-remote-desktop'  # Used in a few file/folder names
 CHROMOTING_HOST_PATH = '/opt/google/chrome-remote-desktop/chrome-remote-desktop'
 TEST_FAILURE = False
+FAILING_TESTS = ''
+HOST_READY_INDICATOR = 'Host ready to receive connections.'
 
 
 def LaunchBTCommand(command):
-  global TEST_FAILURE
+  global TEST_FAILURE, FAILING_TESTS
   results = RunCommandInSubProcess(command)
 
   # Check that the test passed.
   if SUCCESS_INDICATOR not in results:
     TEST_FAILURE = True
+    # Add this command-line to list of tests that failed.
+    FAILING_TESTS += command
 
 
 def RunCommandInSubProcess(command):
@@ -43,17 +47,16 @@
 
   cmd_line = [command]
   try:
-    p = subprocess.Popen(cmd_line, stdout=subprocess.PIPE, shell=True)
-    results, error = p.communicate()
+    results = subprocess.check_output(cmd_line, stderr=subprocess.STDOUT,
+                                      shell=True)
   except subprocess.CalledProcessError, e:
-    raise Exception('Exception %s running command %s\nError: %s' %
-                    (e, command, error))
-  else:
+    results = e.output
+  finally:
     print results
   return results
 
 
-def TestCleanUp(user_profile_dir):
+def TestMachineCleanup(user_profile_dir):
   """Cleans up test machine so as not to impact other tests.
 
   Args:
@@ -81,6 +84,9 @@
 
   Args:
     cfg_file: location of test account's host-config file.
+
+  Raises:
+    Exception: if host did not start properly.
   """
 
   # First get home directory on current machine.
@@ -98,8 +104,31 @@
       config_file_src,
       os.path.join(default_config_file_location, default_config_file_name))
 
-  # Finally, start chromoting host.
-  RunCommandInSubProcess(CHROMOTING_HOST_PATH + ' --start')
+  # Make sure chromoting host is running.
+  if not RestartMe2MeHost():
+    # Host start failed. Don't run any tests.
+    raise Exception('Host restart failed.')
+
+
+def RestartMe2MeHost():
+  """Stops and starts the Me2Me host on the test machine.
+
+  Waits to confirm that host is ready to receive connections before returning.
+
+  Returns:
+    True: if HOST_READY_INDICATOR is found in stdout, indicating host is ready.
+    False: if HOST_READY_INDICATOR not found in stdout.
+  """
+
+  # Stop chromoting host.
+  RunCommandInSubProcess(CHROMOTING_HOST_PATH + ' --stop')
+  # Start chromoting host.
+  results = RunCommandInSubProcess(CHROMOTING_HOST_PATH + ' --start')
+  # Confirm that the start process completed, and we got:
+  # "Host ready to receive connections." in the log.
+  if HOST_READY_INDICATOR not in results:
+    return False
+  return True
 
 
 def SetupUserProfileDir(me2me_manifest_file, it2me_manifest_file,
@@ -133,7 +162,45 @@
     shutil.copyfile(manifest_file_src, manifest_file_dest)
 
 
-def main():
+def main(args):
+
+  InitialiseTestMachineForLinux(args.cfg_file)
+
+  with open(args.commands_file) as f:
+    for line in f:
+      # Reset the user profile directory to start each test with a clean slate.
+      SetupUserProfileDir(args.me2me_manifest_file, args.it2me_manifest_file,
+                          args.user_profile_dir)
+
+      # Replace the PROD_DIR value in the command-line with
+      # the passed in value.
+      line = line.replace(PROD_DIR_ID, args.prod_dir)
+      # Launch specified command line for test.
+      LaunchBTCommand(line)
+      # After each test, stop+start me2me host process.
+      if not RestartMe2MeHost():
+        # Host restart failed. Don't run any more tests.
+        raise Exception('Host restart failed.')
+
+  # All tests completed. Include host-logs in the test results.
+  host_log_contents = ''
+  # There should be only 1 log file, as we delete logs on test completion.
+  # Loop through matching files, just in case there are more.
+  for log_file in glob.glob('/tmp/chrome_remote_desktop_*'):
+    with open(log_file, 'r') as log:
+      host_log_contents += '\nHOST LOG %s\n CONTENTS:\n%s' % (
+          log_file, log.read())
+  print host_log_contents
+
+  # Was there any test failure?
+  if TEST_FAILURE:
+    print '++++++++++AT LEAST 1 TEST FAILED++++++++++'
+    print FAILING_TESTS.rstrip('\n')
+    print '++++++++++++++++++++++++++++++++++++++++++'
+    raise Exception('At least one test failed.')
+
+if __name__ == '__main__':
+
   parser = argparse.ArgumentParser()
   parser.add_argument('-f', '--commands_file',
                       help='path to file listing commands to be launched.')
@@ -148,36 +215,9 @@
   parser.add_argument(
       '-u', '--user_profile_dir',
       help='path to user-profile-dir, used by connect-to-host tests.')
-
-  args = parser.parse_args()
-
-  InitialiseTestMachineForLinux(args.cfg_file)
-
-  with open(args.commands_file) as f:
-    for line in f:
-      # Reset the user profile directory to start each test with a clean slate.
-      SetupUserProfileDir(args.me2me_manifest_file, args.it2me_manifest_file,
-                          args.user_profile_dir)
-
-      # Replace the PROD_DIR value in the command-line with
-      # the passed in value.
-      line = line.replace(PROD_DIR_ID, args.prod_dir)
-      LaunchBTCommand(line)
-
-  # Was there any test failure?
-  if TEST_FAILURE:
-    # Obtain contents of Chromoting host logs.
-    log_contents = ''
-    # There should be only 1 log file, as we delete logs on test completion.
-    # Loop through matching files, just in case there are more.
-    for log_file in glob.glob('/tmp/chrome_remote_desktop_*'):
-      with open(log_file, 'r') as log:
-        log_contents += '\nHOST LOG %s\n CONTENTS:\n%s' % (log_file, log.read())
-    print log_contents
-    raise Exception('At least one test failed.')
-
-  # Now, stop host, and cleanup user-profile-dir
-  TestCleanUp(args.user_profile_dir)
-
-if __name__ == '__main__':
-  main()
+  command_line_args = parser.parse_args()
+  try:
+    main(command_line_args)
+  finally:
+    # Stop host and cleanup user-profile-dir.
+    TestMachineCleanup(command_line_args.user_profile_dir)
diff --git a/testing/chromoting/chromoting_integration_tests.isolate b/testing/chromoting/chromoting_integration_tests.isolate
index 8dcbe5d..0bf8b7a 100644
--- a/testing/chromoting/chromoting_integration_tests.isolate
+++ b/testing/chromoting/chromoting_integration_tests.isolate
@@ -31,6 +31,10 @@
           '<(PRODUCT_DIR)/remoting/com.google.chrome.remote_desktop.json',
           '<(PRODUCT_DIR)/remoting/com.google.chrome.remote_assistance.json',
           '<(PRODUCT_DIR)/remoting-me2me-host.deb',
+          '<(PRODUCT_DIR)/nacl_helper',
+          '<(PRODUCT_DIR)/nacl_helper_bootstrap',
+          '<(PRODUCT_DIR)/pnacl/',
+          '../../remoting/internal/config/',
         ],
       },
     }],
diff --git a/testing/chromoting/dependencies.gypi b/testing/chromoting/dependencies.gypi
new file mode 100644
index 0000000..10013d3
--- /dev/null
+++ b/testing/chromoting/dependencies.gypi
@@ -0,0 +1,25 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is meant to be included by chromoting's integration_tests.
+
+{
+  'dependencies': [
+    '../../chrome/chrome.gyp:browser_tests',
+    '../../remoting/remoting.gyp:remoting_webapp_v1',
+    '../../remoting/remoting.gyp:remoting_webapp_v2',
+  ],
+  'type': 'none',
+  'includes': [
+    '../../build/isolate.gypi',
+  ],
+  'conditions': [
+    ['OS=="linux"', {
+      'dependencies': [
+        '../../remoting/remoting.gyp:remoting_me2me_host_archive',
+        '../../remoting/internal/app_remoting_all.gyp:app_remoting_all_apps',
+      ],
+    }],  # OS=="linux"
+  ],
+}
diff --git a/testing/chromoting/integration_tests.gyp b/testing/chromoting/integration_tests.gyp
index b50c3c6..c3f7912 100644
--- a/testing/chromoting/integration_tests.gyp
+++ b/testing/chromoting/integration_tests.gyp
@@ -2,58 +2,28 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# TODO: Factor out all of the common items across the test targets into a
-# single .gypi file that can be included by each test target.
-
 {
   'conditions': [
     ['archive_chromoting_tests==1', {
       'targets': [
         {
           'target_name': 'chromoting_integration_tests_run',
-          'type': 'none',
-          'dependencies': [
-            '../../chrome/chrome.gyp:browser_tests',
-            '../../remoting/remoting.gyp:remoting_webapp_v1',
-            '../../remoting/remoting.gyp:remoting_webapp_v2',
-          ],
           'includes': [
-            '../../build/isolate.gypi',
+            './dependencies.gypi',
           ],
           'sources': [
             'chromoting_integration_tests.isolate',
           ],
-          'conditions': [
-            ['OS=="linux"', {
-              'dependencies': [
-                '../../remoting/remoting.gyp:remoting_me2me_host_archive',
-                '../../remoting/webapp/app_remoting/internal/app_remoting_all.gyp:app_remoting_all_apps',
-              ],
-            }],  # OS=="linux"
-          ],
         },  # target_name: 'chromoting_integration_tests_run'
         {
           'target_name': 'chromoting_multi_machine_example_test',
-          'type': 'none',
-          'dependencies': [
-            '../../chrome/chrome.gyp:browser_tests',
-            '../../remoting/remoting.gyp:remoting_webapp_v1',
-            '../../remoting/remoting.gyp:remoting_webapp_v2',
-          ],
           'includes': [
-            '../../build/isolate.gypi',
+            './dependencies.gypi',
           ],
           'sources': [
             'multi_machine_example/example_test_controller.isolate',
             'multi_machine_example/example_task.isolate',
           ],
-          'conditions': [
-            ['OS=="linux"', {
-              'dependencies': [
-                '../../remoting/remoting.gyp:remoting_me2me_host_archive',
-              ],
-            }],  # OS=="linux"
-          ],
         },  # target_name: 'chromoting_multi_machine_example_test'
       ],
     }],
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json
index 8c0a2e7..aefd3c7 100644
--- a/testing/commit_queue/config.json
+++ b/testing/commit_queue/config.json
@@ -1,14 +1,10 @@
 {
     "commit_burst_delay": 60,
     "commit_user": "commit-bot@chromium.org",
-    "committer_project": "chromium",
     "cq_status_url": "https://chromium-cq-status.appspot.com",
     "git_repo_url": "https://chromium.googlesource.com/chromium/src",
     "hide_ref_in_committed_msg": true,
     "max_commit_burst": 2,
-    "project_bases": [
-        ".*"
-    ],
     "project_bases_legacy": [
         "^svn\\:\\/\\/svn\\.chromium\\.org\\/chrome/trunk/src(|/.*)$",
         "^svn\\:\\/\\/chrome\\-svn\\/chrome/trunk/src(|/.*)$",
@@ -26,8 +22,6 @@
     "skip_throttle_users": [
         "commit-bot@chromium.org"
     ],
-    "tree_status_url": "https://chromium-status.appspot.com",
-    "tryserver_url": "http://build.chromium.org/p/tryserver.chromium/",
     "use_buildbucket_for_tryjobs": true,
     "verifiers_no_patch": {
         "experimental_try_job_verifier": {
@@ -39,12 +33,6 @@
                             "android_amp_rel_tests_recipe": [
                                 "defaulttests"
                             ],
-                            "cast_shell": [
-                                "defaulttests"
-                            ],
-                            "cast_shell_apk": [
-                                "defaulttests"
-                            ],
                             "linux_arm_compile": [
                                 "defaulttests"
                             ],
@@ -94,8 +82,12 @@
                 }
             }
         },
-        "reviewer_lgtm_verifier": {},
-        "tree_status_verifier": {},
+        "reviewer_lgtm_verifier": {
+            "committer_project": "chromium"
+        },
+        "tree_status_verifier": {
+            "tree_status_url": "https://chromium-status.appspot.com"
+        },
         "try_job_verifier": {
             "launched": {
                 "tryserver.chromium.linux": {
@@ -111,7 +103,13 @@
                     "android_clang_dbg_recipe": [
                         "defaulttests"
                     ],
-                    "android_compile_rel": [
+                    "android_compile_dbg": [
+                        "defaulttests"
+                    ],
+                    "cast_shell_android": [
+                        "defaulttests"
+                    ],
+                    "cast_shell_linux": [
                         "defaulttests"
                     ],
                     "chromium_presubmit": [
@@ -181,5 +179,6 @@
                 }
             }
         }
-    }
+    },
+    "version": 1
 }
diff --git a/testing/iossim/OWNERS b/testing/iossim/OWNERS
index 7f8c2f8..1b3348e 100644
--- a/testing/iossim/OWNERS
+++ b/testing/iossim/OWNERS
@@ -1,3 +1,2 @@
-lliabraa@chromium.org
 rohitrao@chromium.org
 stuartmorgan@chromium.org
diff --git a/testing/iossim/iossim.mm b/testing/iossim/iossim.mm
index 83cfe92..2f2af8d 100644
--- a/testing/iossim/iossim.mm
+++ b/testing/iossim/iossim.mm
@@ -850,7 +850,8 @@
   NSString* appPath = nil;
   NSString* appName = nil;
   NSString* sdkVersion = nil;
-  NSString* deviceName = IsRunningWithXcode6OrLater() ? @"iPhone 5" : @"iPhone";
+  NSString* deviceName =
+      IsRunningWithXcode6OrLater() ? @"iPhone 5s" : @"iPhone";
   NSString* simHomePath = nil;
   NSMutableArray* appArgs = [NSMutableArray array];
   NSMutableDictionary* appEnv = [NSMutableDictionary dictionary];
diff --git a/testing/legion/common_lib.py b/testing/legion/common_lib.py
index c752e0f..6e7954b 100644
--- a/testing/legion/common_lib.py
+++ b/testing/legion/common_lib.py
@@ -26,7 +26,7 @@
     argparse.ArgumentError if the --verbosity arg is incorrect.
   """
   parser = argparse.ArgumentParser()
-  logging_action = parser.add_argument('--verbosity', default='ERROR')
+  logging_action = parser.add_argument('--verbosity', default='INFO')
   args, _ = parser.parse_known_args()
   if args.verbosity not in LOGGING_LEVELS:
     raise argparse.ArgumentError(
@@ -40,4 +40,4 @@
   """Connect to an RPC server."""
   addr = 'http://%s:%d' % (server, SERVER_PORT)
   logging.debug('Connecting to RPC server at %s', addr)
-  return xmlrpclib.Server(addr)
+  return xmlrpclib.Server(addr, allow_none=True)
diff --git a/testing/legion/examples/hello_world/controller_test.py b/testing/legion/examples/hello_world/controller_test.py
index 37afcef..8253e9e 100755
--- a/testing/legion/examples/hello_world/controller_test.py
+++ b/testing/legion/examples/hello_world/controller_test.py
@@ -9,74 +9,69 @@
 task machines, waiting for them, and running RPC calls on them.
 """
 
-# Map the legion directory so we can import the host controller.
-import sys
-sys.path.append('../../')
-
 import argparse
 import logging
+import os
+import sys
 import time
 
-import test_controller
+# Map the testing directory so we can import legion.legion_test.
+TESTING_DIR = os.path.join(
+    os.path.dirname(os.path.abspath(__file__)),
+    '..', '..', '..', '..', 'testing')
+sys.path.append(TESTING_DIR)
+
+from legion import legion_test_case
 
 
-class ExampleTestController(test_controller.TestController):
+class ExampleTestController(legion_test_case.TestCase):
   """A simple example controller for a test."""
 
-  def __init__(self):
-    super(ExampleTestController, self).__init__()
-    self.task1 = None
-    self.task2 = None
+  @classmethod
+  def CreateTestTask(cls):
+    """Create a new task."""
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--task-hash')
+    parser.add_argument('--os', default='Ubuntu-14.04')
+    args, _ = parser.parse_known_args()
 
-  def CreateTask(self, isolated_hash):
-    """Create a task object and set the proper values."""
-    task = self.CreateNewTask(
-        isolated_hash=isolated_hash,
-        dimensions={'os': 'Ubuntu-14.04', 'pool': 'Legion'}, priority=200,
-        idle_timeout_secs=90, connection_timeout_secs=90,
-        verbosity=logging.INFO,
-        run_id=1)
+    task = cls.CreateTask(
+        isolated_hash=args.task_hash,
+        dimensions={'os': args.os},
+        idle_timeout_secs=90,
+        connection_timeout_secs=90,
+        verbosity=logging.DEBUG)
     task.Create()
     return task
 
-  def SetUp(self):
-    """Create the task machines and wait until they connect.
+  @classmethod
+  def setUpClass(cls):
+    """Creates the task machines and waits until they connect."""
+    cls.task1 = cls.CreateTestTask()
+    cls.task2 = cls.CreateTestTask()
+    cls.task1.WaitForConnection()
+    cls.task2.WaitForConnection()
 
-    In this call the actual creation of the task machines is done in parallel
-    by the system. The WaitForConnect calls are performed in series but will
-    return as soon as the tasks connect.
-    """
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--task-hash')
-    args, _ = parser.parse_known_args()
+  def testCallEcho(self):
+    """Tests rpc.Echo on a task."""
+    logging.info('Calling Echo on %s', self.task2.name)
+    self.assertEqual(self.task2.rpc.Echo('foo'), 'echo foo')
 
-    self.task1 = self.CreateTask(args.task_hash)
-    self.task2 = self.CreateTask(args.task_hash)
-    self.task1.WaitForConnection()
-    self.task2.WaitForConnection()
+  def testLaunchTaskBinary(self):
+    """Call task_test.py 'name' on the tasks."""
+    self.VerifyTaskBinaryLaunched(self.task1)
+    self.VerifyTaskBinaryLaunched(self.task2)
 
-  def RunTest(self):
-    """Main method to run the test code."""
-    self.CallEcho(self.task1)
-    self.CallEcho(self.task2)
-    self.CallTaskTest(self.task1)
-    self.CallTaskTest(self.task2)
-
-  def CallEcho(self, task):
-    """Call rpc.Echo on a task."""
-    logging.info('Calling Echo on %s', task.name)
-    logging.info(task.rpc.Echo(task.name))
-
-  def CallTaskTest(self, task):
-    """Call task_test.py name on a task."""
-    logging.info('Calling Subprocess to run "./task_test.py %s"', task.name)
-    proc = task.rpc.subprocess.Popen(['./task_test.py', task.name])
-    task.rpc.subprocess.Wait(proc)
-    retcode = task.rpc.subprocess.GetReturncode(proc)
-    stdout = task.rpc.subprocess.ReadStdout(proc)
-    stderr = task.rpc.subprocess.ReadStderr(proc)
-    logging.info('retcode: %s, stdout: %s, stderr: %s', retcode, stdout, stderr)
+  def VerifyTaskBinaryLaunched(self, task):
+    logging.info(
+        'Calling Process to run "./task_test.py %s"', task.name)
+    proc = task.Process(['./task_test.py', task.name])
+    proc.Wait()
+    self.assertEqual(proc.GetReturncode(), 0)
+    self.assertIn(task.name, proc.ReadStdout())
+    self.assertEquals(proc.ReadStderr(), '')
+    proc.Delete()
 
 
 if __name__ == '__main__':
-  ExampleTestController().RunController()
+  legion_test_case.main()
diff --git a/testing/legion/examples/subprocess/subprocess_test.py b/testing/legion/examples/subprocess/subprocess_test.py
index 1a28ddd..cea871a 100755
--- a/testing/legion/examples/subprocess/subprocess_test.py
+++ b/testing/legion/examples/subprocess/subprocess_test.py
@@ -5,85 +5,91 @@
 
 """A host test module demonstrating interacting with remote subprocesses."""
 
-# Map the legion directory so we can import the host controller.
-import sys
-sys.path.append('../../')
-
 import argparse
 import logging
+import os
+import sys
 import time
 import xmlrpclib
 
-import test_controller
+# Map the testing directory so we can import legion.legion_test.
+TESTING_DIR = os.path.join(
+    os.path.dirname(os.path.abspath(__file__)),
+    '..', '..', '..', '..', 'testing')
+sys.path.append(TESTING_DIR)
+
+from legion import legion_test_case
 
 
-class ExampleTestController(test_controller.TestController):
+class ExampleTestController(legion_test_case.TestCase):
   """An example controller using the remote subprocess functions."""
 
-  def __init__(self):
-    super(ExampleTestController, self).__init__()
-    self.task = None
-
-  def SetUp(self):
+  @classmethod
+  def setUpClass(cls):
     """Creates the task machine and waits until it connects."""
     parser = argparse.ArgumentParser()
     parser.add_argument('--task-hash')
+    parser.add_argument('--os', default='Ubuntu-14.04')
     args, _ = parser.parse_known_args()
 
-    self.task = self.CreateNewTask(
+    cls.task = cls.CreateTask(
         isolated_hash=args.task_hash,
-        dimensions={'os': 'Ubuntu-14.04', 'pool': 'Chromoting'},
-        idle_timeout_secs=90, connection_timeout_secs=90,
+        dimensions={'os': args.os},
+        idle_timeout_secs=90,
+        connection_timeout_secs=90,
         verbosity=logging.DEBUG)
-    self.task.Create()
-    self.task.WaitForConnection()
+    cls.task.Create()
+    cls.task.WaitForConnection()
 
-  def RunTest(self):
-    """Main method to run the test code."""
-    self.TestLs()
-    self.TestTerminate()
-    self.TestMultipleProcesses()
+  def testMultipleProcesses(self):
+    """Tests that processes can be run and controlled simultaneously."""
+    start = time.time()
+    logging.info('Starting "sleep 10" and "sleep 20"')
+    sleep10 = self.task.Process(['sleep', '10'])
+    sleep20 = self.task.Process(['sleep', '20'])
 
-  def TestMultipleProcesses(self):
+    logging.info('Waiting for sleep 10 to finish and verifying timing')
+    sleep10.Wait()
+    elapsed = time.time() - start
+    self.assertGreaterEqual(elapsed, 10)
+    self.assertLess(elapsed, 11)
+
+    logging.info('Waiting for sleep 20 to finish and verifying timing')
+    sleep20.Wait()
+    elapsed = time.time() - start
+    self.assertGreaterEqual(elapsed, 20)
+
+    sleep10.Delete()
+    sleep20.Delete()
+
+  def testTerminate(self):
+    """Tests that a process can be correctly terminated."""
     start = time.time()
 
-    sleep20 = self.task.rpc.subprocess.Process(['sleep', '20'])
-    self.task.rpc.subprocess.Start(sleep20)
-    sleep10 = self.task.rpc.subprocess.Process(['sleep', '10'])
-    self.task.rpc.subprocess.Start(sleep10)
-
-    self.task.rpc.subprocess.Wait(sleep10)
-    elapsed = time.time() - start
-    assert elapsed >= 10 and elapsed < 11
-
-    self.task.rpc.subprocess.Wait(sleep20)
-    elapsed = time.time() - start
-    assert elapsed >= 20
-
-    self.task.rpc.subprocess.Delete(sleep20)
-    self.task.rpc.subprocess.Delete(sleep10)
-
-  def TestTerminate(self):
-    start = time.time()
-    proc = self.task.rpc.subprocess.Process(['sleep', '20'])
-    self.task.rpc.subprocess.Start(proc)
-    self.task.rpc.subprocess.Terminate(proc)
+    logging.info('Starting "sleep 20"')
+    sleep20 = self.task.Process(['sleep', '20'])
+    logging.info('Calling Terminate()')
+    sleep20.Terminate()
     try:
-      self.task.rpc.subprocess.Wait(proc)
+      logging.info('Trying to wait for sleep 20 to complete')
+      sleep20.Wait()
     except xmlrpclib.Fault:
       pass
     finally:
-      self.task.rpc.subprocess.Delete(proc)
-    assert time.time() - start < 20
+      sleep20.Delete()
+    logging.info('Checking to make sure sleep 20 was actually terminated')
+    self.assertLess(time.time() - start, 20)
 
-  def TestLs(self):
-    proc = self.task.rpc.subprocess.Process(['ls'])
-    self.task.rpc.subprocess.Start(proc)
-    self.task.rpc.subprocess.Wait(proc)
-    assert self.task.rpc.subprocess.GetReturncode(proc) == 0
-    assert 'task.isolate' in self.task.rpc.subprocess.ReadStdout(proc)
-    self.task.rpc.subprocess.Delete(proc)
+  def testLs(self):
+    """Tests that the returned results from a process are correct."""
+    logging.info('Calling "ls"')
+    ls = self.task.Process(['ls'])
+    logging.info('Trying to wait for ls to complete')
+    ls.Wait()
+    logging.info('Checking that ls completed and returned the correct results')
+    self.assertEqual(ls.GetReturncode(), 0)
+    self.assertIn('task.isolate', ls.ReadStdout())
 
 
 if __name__ == '__main__':
-  ExampleTestController().RunController()
+  legion_test_case.main()
diff --git a/testing/legion/legion.isolate b/testing/legion/legion.isolate
index 774b27a..18e0b3b 100644
--- a/testing/legion/legion.isolate
+++ b/testing/legion/legion.isolate
@@ -7,7 +7,9 @@
     'files': [
       '__init__.py',
       'common_lib.py',
+      'legion_test_case.py',
       'legion.isolate',
+      'process.py',
       'rpc_methods.py',
       'rpc_server.py',
       'run_task.py',
diff --git a/testing/legion/legion_test_case.py b/testing/legion/legion_test_case.py
new file mode 100644
index 0000000..9514e8e
--- /dev/null
+++ b/testing/legion/legion_test_case.py
@@ -0,0 +1,135 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Adds unittest-esque functionality to Legion."""
+
+import argparse
+import logging
+import sys
+import unittest
+
+#pylint: disable=relative-import
+import common_lib
+import task_controller
+import task_registration_server
+
+BANNER_WIDTH = 80
+
+
+class TestCase(unittest.TestCase):
+  """Test case class with added Legion support."""
+
+  _registration_server = None
+  _initialized = False
+
+  @classmethod
+  def __new__(cls, *args, **kwargs):
+    """Initialize the class and return a new instance."""
+    cls._InitializeClass()
+    return super(TestCase, cls).__new__(*args, **kwargs)
+
+  def __init__(self, test_name='runTest'):
+    super(TestCase, self).__init__(test_name)
+    method = getattr(self, test_name, None)
+    if method:
+      # Install the _RunTest method
+      self._TestMethod = method
+      setattr(self, test_name, self._RunTest)
+
+  def _RunTest(self):
+    """Runs the test method and provides banner info and error reporting."""
+    self._LogInfoBanner(self._testMethodName, self.shortDescription())
+    try:
+      return self._TestMethod()
+    except:
+      exc_info = sys.exc_info()
+      logging.error('', exc_info=exc_info)
+      raise exc_info[0], exc_info[1], exc_info[2]
+
+  @classmethod
+  def _InitializeClass(cls):
+    """Handles class level initialization.
+
+    There are 2 types of setup/teardown methods that always need to be run:
+    1) Framework level setup/teardown
+    2) Test case level setup/teardown
+
+    This method installs handlers in place of setUpClass and tearDownClass that
+    will ensure both types of setup/teardown methods are called correctly.
+    """
+    if cls._initialized:
+      return
+    cls._OriginalSetUpClassMethod = cls.setUpClass
+    cls.setUpClass = cls._HandleSetUpClass
+    cls._OriginalTearDownClassMethod = cls.tearDownClass
+    cls.tearDownClass = cls._HandleTearDownClass
+    cls._initialized = True
+
+  @classmethod
+  def _LogInfoBanner(cls, method_name, method_doc=None):
+    """Formats and logs test case information."""
+    logging.info('*' * BANNER_WIDTH)
+    logging.info(method_name.center(BANNER_WIDTH))
+    if method_doc:
+      for line in method_doc.split('\n'):
+        logging.info(line.center(BANNER_WIDTH))
+    logging.info('*' * BANNER_WIDTH)
+
+  @classmethod
+  def CreateTask(cls, *args, **kwargs):
+    """Convenience method to create a new task."""
+    task = task_controller.TaskController(*args, **kwargs)
+    cls._registration_server.RegisterTaskCallback(
+        task.otp, task.OnConnect)
+    return task
+
+  @classmethod
+  def _SetUpFramework(cls):
+    """Perform the framework-specific setup operations."""
+    cls._registration_server = (
+        task_registration_server.TaskRegistrationServer())
+    cls._registration_server.Start()
+
+  @classmethod
+  def _TearDownFramework(cls):
+    """Perform the framework-specific teardown operations."""
+    if cls._registration_server:
+      cls._registration_server.Shutdown()
+    task_controller.TaskController.ReleaseAllTasks()
+
+  @classmethod
+  def _HandleSetUpClass(cls):
+    """Performs common class-level setup operations.
+
+    This method performs test-wide setup such as starting the registration
+    server and then calls the original setUpClass method."""
+    try:
+      common_lib.InitLogging()
+      cls._LogInfoBanner('setUpClass', 'Performs class level setup.')
+      cls._SetUpFramework()
+      cls._OriginalSetUpClassMethod()
+    except:
+      # Make sure we tear down in case of any exceptions
+      cls._HandleTearDownClass(setup_failed=True)
+      exc_info = sys.exc_info()
+      logging.error('', exc_info=exc_info)
+      raise exc_info[0], exc_info[1], exc_info[2]
+
+  @classmethod
+  def _HandleTearDownClass(cls, setup_failed=False):
+    """Performs common class-level tear down operations.
+
+    This method calls the original tearDownClass then performs test-wide
+    tear down such as stopping the registration server.
+    """
+    cls._LogInfoBanner('tearDownClass', 'Performs class level tear down.')
+    try:
+      if not setup_failed:
+        cls._OriginalTearDownClassMethod()
+    finally:
+      cls._TearDownFramework()
+
+
+def main():
+  unittest.main(verbosity=0, argv=sys.argv[:1])
diff --git a/testing/legion/process.py b/testing/legion/process.py
new file mode 100644
index 0000000..356db61
--- /dev/null
+++ b/testing/legion/process.py
@@ -0,0 +1,247 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""RPC compatible subprocess-type module.
+
+This module defined both a task-side process class as well as a controller-side
+process wrapper for easier access and usage of the task-side process.
+"""
+
+import logging
+import subprocess
+import sys
+import threading
+
+#pylint: disable=relative-import
+import common_lib
+
+# Map swarming_client to use subprocess42
+sys.path.append(common_lib.SWARMING_DIR)
+
+from utils import subprocess42
+
+
+class ControllerProcessWrapper(object):
+  """Controller-side process wrapper class.
+
+  This class provides a more intuitive interface to task-side processes
+  than calling the methods directly using the RPC object.
+  """
+
+  def __init__(self, rpc, cmd, verbose=False, detached=False, cwd=None):
+    self._rpc = rpc
+    self._id = rpc.subprocess.Process(cmd)
+    if verbose:
+      self._rpc.subprocess.SetVerbose(self._id)
+    if detached:
+      self._rpc.subprocess.SetDetached(self._id)
+    if cwd:
+      self._rpc.subprocess.SetCwd(self._rpc, cwd)
+    self._rpc.subprocess.Start(self._id)
+
+  def Terminate(self):
+    logging.debug('Terminating process %s', self._id)
+    return self._rpc.subprocess.Terminate(self._id)
+
+  def Kill(self):
+    logging.debug('Killing process %s', self._id)
+    self._rpc.subprocess.Kill(self._id)
+
+  def Delete(self):
+    return self._rpc.subprocess.Delete(self._id)
+
+  def GetReturncode(self):
+    return self._rpc.subprocess.GetReturncode(self._id)
+
+  def ReadStdout(self):
+    """Returns all stdout since the last call to ReadStdout.
+
+    This call allows the user to read stdout while the process is running.
+    However each call will flush the local stdout buffer. In order to make
+    multiple calls to ReadStdout and to retain the entire output the results
+    of this call will need to be buffered in the calling code.
+    """
+    return self._rpc.subprocess.ReadStdout(self._id)
+
+  def ReadStderr(self):
+    """Returns all stderr read since the last call to ReadStderr.
+
+    See ReadStdout for additional details.
+    """
+    return self._rpc.subprocess.ReadStderr(self._id)
+
+  def ReadOutput(self):
+    """Returns the (stdout, stderr) since the last Read* call.
+
+    See ReadStdout for additional details.
+    """
+    return self._rpc.subprocess.ReadOutput(self._id)
+
+  def Wait(self):
+    return self._rpc.subprocess.Wait(self._id)
+
+  def Poll(self):
+    return self._rpc.subprocess.Poll(self._id)
+
+  def GetPid(self):
+    return self._rpc.subprocess.GetPid(self._id)
+
+
+
+class Process(object):
+  """Implements a task-side non-blocking subprocess.
+
+  This non-blocking subprocess allows the caller to continue operating while
+  also able to interact with this subprocess based on a key returned to
+  the caller at the time of creation.
+
+  Creation args are set via Set* methods called after calling Process but
+  before calling Start. This is due to a limitation of the XML-RPC
+  implementation not supporting keyword arguments.
+  """
+
+  _processes = {}
+  _process_next_id = 0
+  _creation_lock = threading.Lock()
+
+  def __init__(self, cmd):
+    self.stdout = ''
+    self.stderr = ''
+    self.cmd = cmd
+    self.proc = None
+    self.cwd = None
+    self.verbose = False
+    self.detached = False
+    self.data_lock = threading.Lock()
+
+  def __str__(self):
+    return '%r, cwd=%r, verbose=%r, detached=%r' % (
+        self.cmd, self.cwd, self.verbose, self.detached)
+
+  def _reader(self):
+    for pipe, data in self.proc.yield_any():
+      with self.data_lock:
+        if pipe == 'stdout':
+          self.stdout += data
+          if self.verbose:
+            sys.stdout.write(data)
+        else:
+          self.stderr += data
+          if self.verbose:
+            sys.stderr.write(data)
+
+  @classmethod
+  def KillAll(cls):
+    for key in cls._processes:
+      cls.Kill(key)
+
+  @classmethod
+  def Process(cls, cmd):
+    with cls._creation_lock:
+      key = 'Process%d' % cls._process_next_id
+      cls._process_next_id += 1
+    logging.debug('Creating process %s with cmd %r', key, cmd)
+    process = cls(cmd)
+    cls._processes[key] = process
+    return key
+
+  def _Start(self):
+    logging.info('Starting process %s', self)
+    self.proc = subprocess42.Popen(self.cmd, stdout=subprocess42.PIPE,
+                                   stderr=subprocess42.PIPE,
+                                   detached=self.detached, cwd=self.cwd)
+    threading.Thread(target=self._reader).start()
+
+  @classmethod
+  def Start(cls, key):
+    cls._processes[key]._Start()
+
+  @classmethod
+  def SetCwd(cls, key, cwd):
+    """Sets the process's cwd."""
+    logging.debug('Setting %s cwd to %s', key, cwd)
+    cls._processes[key].cwd = cwd
+
+  @classmethod
+  def SetDetached(cls, key):
+    """Creates a detached process."""
+    logging.debug('Setting %s.detached = True', key)
+    cls._processes[key].detached = True
+
+  @classmethod
+  def SetVerbose(cls, key):
+    """Sets the stdout and stderr to be emitted locally."""
+    logging.debug('Setting %s.verbose = True', key)
+    cls._processes[key].verbose = True
+
+  @classmethod
+  def Terminate(cls, key):
+    logging.debug('Terminating process %s', key)
+    cls._processes[key].proc.terminate()
+
+  @classmethod
+  def Kill(cls, key):
+    logging.debug('Killing process %s', key)
+    cls._processes[key].proc.kill()
+
+  @classmethod
+  def Delete(cls, key):
+    if cls.GetReturncode(key) is None:
+      logging.warning('Killing %s before deleting it', key)
+      cls.Kill(key)
+    logging.debug('Deleting process %s', key)
+    cls._processes.pop(key)
+
+  @classmethod
+  def GetReturncode(cls, key):
+    return cls._processes[key].proc.returncode
+
+  @classmethod
+  def ReadStdout(cls, key):
+    """Returns all stdout since the last call to ReadStdout.
+
+    This call allows the user to read stdout while the process is running.
+    However each call will flush the local stdout buffer. In order to make
+    multiple calls to ReadStdout and to retain the entire output the results
+    of this call will need to be buffered in the calling code.
+    """
+    proc = cls._processes[key]
+    with proc.data_lock:
+      # Perform a "read" on the stdout data
+      stdout = proc.stdout
+      proc.stdout = ''
+    return stdout
+
+  @classmethod
+  def ReadStderr(cls, key):
+    """Returns all stderr read since the last call to ReadStderr.
+
+    See ReadStdout for additional details.
+    """
+    proc = cls._processes[key]
+    with proc.data_lock:
+      # Perform a "read" on the stderr data
+      stderr = proc.stderr
+      proc.stderr = ''
+    return stderr
+
+  @classmethod
+  def ReadOutput(cls, key):
+    """Returns the (stdout, stderr) since the last Read* call.
+
+    See ReadStdout for additional details.
+    """
+    return cls.ReadStdout(key), cls.ReadStderr(key)
+
+  @classmethod
+  def Wait(cls, key):
+    return cls._processes[key].proc.wait()
+
+  @classmethod
+  def Poll(cls, key):
+    return cls._processes[key].proc.poll()
+
+  @classmethod
+  def GetPid(cls, key):
+    return cls._processes[key].proc.pid
diff --git a/testing/legion/rpc_methods.py b/testing/legion/rpc_methods.py
index 1a59f28..24d0312 100644
--- a/testing/legion/rpc_methods.py
+++ b/testing/legion/rpc_methods.py
@@ -4,18 +4,13 @@
 
 """Defines the task RPC methods."""
 
+import logging
 import os
 import sys
-import logging
 import threading
 
 #pylint: disable=relative-import
-import common_lib
-
-# Map swarming_client to use subprocess42
-sys.path.append(common_lib.SWARMING_DIR)
-
-from utils import subprocess42
+import process
 
 
 class RPCMethods(object):
@@ -25,7 +20,7 @@
 
   def __init__(self, server):
     self._server = server
-    self.subprocess = Subprocess
+    self.subprocess = process.Process
 
   def _dispatch(self, method, params):
     obj = self
@@ -54,161 +49,3 @@
     """
     t = threading.Thread(target=self._server.shutdown)
     t.start()
-
-
-class Subprocess(object):
-  """Implements a server-based non-blocking subprocess.
-
-  This non-blocking subprocess allows the caller to continue operating while
-  also able to interact with this subprocess based on a key returned to
-  the caller at the time of creation.
-
-  Creation args are set via Set* methods called after calling Process but
-  before calling Start. This is due to a limitation of the XML-RPC
-  implementation not supporting keyword arguments.
-  """
-
-  _processes = {}
-  _process_next_id = 0
-  _creation_lock = threading.Lock()
-
-  def __init__(self, cmd):
-    self.stdout = ''
-    self.stderr = ''
-    self.cmd = cmd
-    self.proc = None
-    self.cwd = None
-    self.verbose = False
-    self.detached = False
-    self.data_lock = threading.Lock()
-
-  def __str__(self):
-    return '%r, cwd=%r, verbose=%r, detached=%r' % (
-        self.cmd, self.cwd, self.verbose, self.detached)
-
-  def _reader(self):
-    for pipe, data in self.proc.yield_any():
-      with self.data_lock:
-        if pipe == 'stdout':
-          self.stdout += data
-          if self.verbose:
-            sys.stdout.write(data)
-        else:
-          self.stderr += data
-          if self.verbose:
-            sys.stderr.write(data)
-
-  @classmethod
-  def KillAll(cls):
-    for key in cls._processes:
-      cls.Kill(key)
-
-  @classmethod
-  def Process(cls, cmd):
-    with cls._creation_lock:
-      key = 'Process%d' % cls._process_next_id
-      cls._process_next_id += 1
-    logging.debug('Creating process %s', key)
-    process = cls(cmd)
-    cls._processes[key] = process
-    return key
-
-  def _Start(self):
-    logging.info('Starting process %s', self)
-    self.proc = subprocess42.Popen(self.cmd, stdout=subprocess42.PIPE,
-                                   stderr=subprocess42.PIPE,
-                                   detached=self.detached, cwd=self.cwd)
-    threading.Thread(target=self._reader).start()
-
-  @classmethod
-  def Start(cls, key):
-    cls._processes[key]._Start()
-
-  @classmethod
-  def SetCwd(cls, key, cwd):
-    """Sets the process's cwd."""
-    logging.debug('Setting %s cwd to %s', key, cwd)
-    cls._processes[key].cwd = cwd
-
-  @classmethod
-  def SetDetached(cls, key):
-    """Creates a detached process."""
-    logging.debug('Setting %s to run detached', key)
-    cls._processes[key].detached = True
-
-  @classmethod
-  def SetVerbose(cls, key):
-    """Sets the stdout and stderr to be emitted locally."""
-    logging.debug('Setting %s to be verbose', key)
-    cls._processes[key].verbose = True
-
-  @classmethod
-  def Terminate(cls, key):
-    logging.debug('Terminating process %s', key)
-    cls._processes[key].proc.terminate()
-
-  @classmethod
-  def Kill(cls, key):
-    logging.debug('Killing process %s', key)
-    cls._processes[key].proc.kill()
-
-  @classmethod
-  def Delete(cls, key):
-    if cls.GetReturncode(key) is None:
-      logging.warning('Killing %s before deleting it', key)
-      cls.Kill(key)
-    logging.debug('Deleting process %s', key)
-    cls._processes.pop(key)
-
-  @classmethod
-  def GetReturncode(cls, key):
-    return cls._processes[key].proc.returncode
-
-  @classmethod
-  def ReadStdout(cls, key):
-    """Returns all stdout since the last call to ReadStdout.
-
-    This call allows the user to read stdout while the process is running.
-    However each call will flush the local stdout buffer. In order to make
-    multiple calls to ReadStdout and to retain the entire output the results
-    of this call will need to be buffered in the calling code.
-    """
-    proc = cls._processes[key]
-    with proc.data_lock:
-      # Perform a "read" on the stdout data
-      stdout = proc.stdout
-      proc.stdout = ''
-    return stdout
-
-  @classmethod
-  def ReadStderr(cls, key):
-    """Returns all stderr read since the last call to ReadStderr.
-
-    See ReadStdout for additional details.
-    """
-    proc = cls._processes[key]
-    with proc.data_lock:
-      # Perform a "read" on the stderr data
-      stderr = proc.stderr
-      proc.stderr = ''
-    return stderr
-
-  @classmethod
-  def ReadOutput(cls, key):
-    """Returns the (stdout, stderr) since the last Read* call.
-
-    See ReadStdout for additional details.
-    """
-    return cls.ReadStdout(key), cls.ReadStderr(key)
-
-  @classmethod
-  def Wait(cls, key):
-    return cls._processes[key].proc.wait()
-
-  @classmethod
-  def Poll(cls, key):
-    return cls._processes[key].proc.poll()
-
-  @classmethod
-  def GetPid(cls, key):
-    return cls._processes[key].proc.pid
diff --git a/testing/legion/task_controller.py b/testing/legion/task_controller.py
index df9ddbd..9514f44 100644
--- a/testing/legion/task_controller.py
+++ b/testing/legion/task_controller.py
@@ -17,6 +17,7 @@
 
 #pylint: disable=relative-import
 import common_lib
+import process
 
 ISOLATE_PY = os.path.join(common_lib.SWARMING_DIR, 'isolate.py')
 SWARMING_PY = os.path.join(common_lib.SWARMING_DIR, 'swarming.py')
@@ -125,6 +126,10 @@
     for task in cls._tasks:
       task.Release()
 
+  def Process(self, cmd, verbose=False, detached=False, cwd=None):
+    return process.ControllerProcessWrapper(
+        self.rpc, cmd, verbose, detached, cwd)
+
   def _CreateOTP(self):
     """Creates the OTP."""
     controller_name = socket.gethostname()
diff --git a/testing/legion/task_registration_server.py b/testing/legion/task_registration_server.py
index 52ba727..fe92dcd 100644
--- a/testing/legion/task_registration_server.py
+++ b/testing/legion/task_registration_server.py
@@ -39,7 +39,7 @@
 
   def Start(self):
     """Starts the registration server."""
-    logging.debug('Starting task registration server')
+    logging.info('Starting task registration server')
     self._rpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer(
         (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT),
         allow_none=True, logRequests=False)
@@ -51,5 +51,5 @@
   def Shutdown(self):
     """Shuts the discovery server down."""
     if self._thread and self._thread.is_alive():
-      logging.debug('Shutting down task registration server')
+      logging.info('Shutting down task registration server')
       self._rpc_server.shutdown()
diff --git a/testing/scripts/gtest_perf_test.py b/testing/scripts/gtest_perf_test.py
index 6243a79..af4380f 100755
--- a/testing/scripts/gtest_perf_test.py
+++ b/testing/scripts/gtest_perf_test.py
@@ -11,6 +11,10 @@
 import common
 
 
+def IsWindows():
+  return sys.platform == 'cygwin' or sys.platform.startswith('win')
+
+
 def main_run(args):
   filter_tests = []
   if args.filter_file:
@@ -19,6 +23,8 @@
   perf_id = args.properties.get('perf-id')
   script_args = args.args
   test_suite = script_args[0]
+  if IsWindows():
+    script_args[0] += '.exe'
 
   with common.temporary_file() as tempfile_path:
     gtest_args = [
diff --git a/testing/test.gni b/testing/test.gni
index 3afb9f7..ec56f01 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -67,7 +67,7 @@
       }
       deps = []
       if (!defined(invoker.use_launcher) || invoker.use_launcher) {
-        deps += [ "//testing/android:native_test_native_code" ]
+        deps += [ "//testing/android/native_test:native_test_native_code" ]
       }
       if (defined(invoker.deps)) {
         deps += invoker.deps
diff --git a/testing/xvfb.py b/testing/xvfb.py
index ce53099..e7280f4 100755
--- a/testing/xvfb.py
+++ b/testing/xvfb.py
@@ -50,7 +50,7 @@
     xvfb_path: Path to Xvfb.
   """
   cmd = [xvfb_path, display, '-screen', '0', '1024x768x24', '-ac',
-         '-nolisten', 'tcp']
+         '-nolisten', 'tcp', '-dpi', '96']
   try:
     proc = subprocess.Popen(
         cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
diff --git a/third_party/junit/BUILD.gn b/third_party/junit/BUILD.gn
new file mode 100644
index 0000000..babe0f2
--- /dev/null
+++ b/third_party/junit/BUILD.gn
@@ -0,0 +1,20 @@
+# 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("//build/config/android/rules.gni")
+
+# GYP: //third_party/junit.gyp:hamcrest_jar
+java_prebuilt("hamcrest") {
+  jar_path = "src/lib/hamcrest-core-1.1.jar"
+}
+
+# GYP: //third_party/junit.gyp:junit_jar
+java_library("junit") {
+  chromium_code = false
+  testonly = true
+  deps = [
+    ":hamcrest",
+  ]
+  DEPRECATED_java_in_dir = "src/src/main/java"
+}
diff --git a/third_party/junit/LICENSE b/third_party/junit/LICENSE
new file mode 100644
index 0000000..1aba77a
--- /dev/null
+++ b/third_party/junit/LICENSE
@@ -0,0 +1,218 @@
+JUnit
+
+Common Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+      a) in the case of the initial Contributor, the initial code and
+         documentation distributed under this Agreement, and
+      b) in the case of each subsequent Contributor:
+
+      i) changes to the Program, and
+
+      ii) additions to the Program;
+
+      where such changes and/or additions to the Program originate from and are
+distributed by that particular Contributor. A Contribution 'originates' from a
+Contributor if it was added to the Program by such Contributor itself or anyone
+acting on such Contributor's behalf. Contributions do not include additions to
+the Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii) are
+not derivative works of the Program. 
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+
+      a) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free copyright license to
+reproduce, prepare derivative works of, publicly display, publicly perform,
+distribute and sublicense the Contribution of such Contributor, if any, and
+such derivative works, in source code and object code form.
+
+      b) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free patent license under
+Licensed Patents to make, use, sell, offer to sell, import and otherwise
+transfer the Contribution of such Contributor, if any, in source code and
+object code form. This patent license shall apply to the combination of the
+Contribution and the Program if, at the time the Contribution is added by the
+Contributor, such addition of the Contribution causes such combination to be
+covered by the Licensed Patents. The patent license shall not apply to any
+other combinations which include the Contribution. No hardware per se is
+licensed hereunder. 
+
+      c) Recipient understands that although each Contributor grants the
+licenses to its Contributions set forth herein, no assurances are provided by
+any Contributor that the Program does not infringe the patent or other
+intellectual property rights of any other entity. Each Contributor disclaims
+any liability to Recipient for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a condition to
+exercising the rights and licenses granted hereunder, each Recipient hereby
+assumes sole responsibility to secure any other intellectual property rights
+needed, if any. For example, if a third party patent license is required to
+allow Recipient to distribute the Program, it is Recipient's responsibility to
+acquire that license before distributing the Program.
+
+      d) Each Contributor represents that to its knowledge it has sufficient
+copyright rights in its Contribution, if any, to grant the copyright license
+set forth in this Agreement. 
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+      a) it complies with the terms and conditions of this Agreement; and
+
+      b) its license agreement:
+
+      i) effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose; 
+
+      ii) effectively excludes on behalf of all Contributors all liability for
+damages, including direct, indirect, special, incidental and consequential
+damages, such as lost profits; 
+
+      iii) states that any provisions which differ from this Agreement are
+offered by that Contributor alone and not by any other party; and
+
+      iv) states that source code for the Program is available from such
+Contributor, and informs licensees how to obtain it in a reasonable manner on
+or through a medium customarily used for software exchange. 
+
+When the Program is made available in source code form:
+
+      a) it must be made available under this Agreement; and 
+
+      b) a copy of this Agreement must be included with each copy of the
+Program. 
+
+Contributors may not remove or alter any copyright notices contained within the
+Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its exercise
+of rights under this Agreement, including but not limited to the risks and
+costs of program errors, compliance with applicable laws, damage to or loss of
+data, programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with respect to
+a patent applicable to software (including a cross-claim or counterclaim in a
+lawsuit), then any patent licenses granted by that Contributor to such
+Recipient under this Agreement shall terminate as of the date such litigation
+is filed. In addition, if Recipient institutes patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's rights
+granted under Section 2(b) shall terminate as of the date such litigation is
+filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+IBM is the initial Agreement Steward. IBM may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial
+in any resulting litigation. 
+
diff --git a/third_party/junit/OWNERS b/third_party/junit/OWNERS
new file mode 100644
index 0000000..212ffdf
--- /dev/null
+++ b/third_party/junit/OWNERS
@@ -0,0 +1,3 @@
+jbudorick@chromium.org
+klundberg@chromium.org
+
diff --git a/third_party/junit/README.chromium b/third_party/junit/README.chromium
new file mode 100644
index 0000000..5a1651b
--- /dev/null
+++ b/third_party/junit/README.chromium
@@ -0,0 +1,10 @@
+Name: JUnit
+URL: http://junit.org
+Version: 4.10
+License: Common Public License 1.0
+License File: NOT_SHIPPED
+Security Critical: no
+License Android Compatible: yes
+Description: JUnit is a java unit testing library.
+Local Modifications: None
+
diff --git a/third_party/junit/junit.gyp b/third_party/junit/junit.gyp
new file mode 100644
index 0000000..c797e06
--- /dev/null
+++ b/third_party/junit/junit.gyp
@@ -0,0 +1,34 @@
+# 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.
+
+{
+  'targets': [
+    {
+      # GN: //third_party/junit:hamcrest
+      'target_name': 'hamcrest_jar',
+      'type': 'none',
+      'variables': {
+        'jar_path': 'src/lib/hamcrest-core-1.1.jar',
+      },
+      'includes': [
+        '../../build/host_prebuilt_jar.gypi',
+      ]
+    },
+    {
+      # GN: //third_party/junit:junit
+      'target_name': 'junit_jar',
+      'type': 'none',
+      'dependencies': [
+        'hamcrest_jar',
+      ],
+      'variables': {
+        'src_paths': [ 'src/src/main/java' ],
+      },
+      'includes': [
+        '../../build/host_jar.gypi',
+      ],
+    },
+  ],
+}
+
diff --git a/third_party/libevent/event-config.h b/third_party/libevent/event-config.h
index 2e564db..c5c0e75 100644
--- a/third_party/libevent/event-config.h
+++ b/third_party/libevent/event-config.h
@@ -6,17 +6,17 @@
 // event-config.h depending on your platform.
 
 #if defined(__native_client_nonsfi__)
-#include "nacl_nonsfi/event-config.h"
+#include "third_party/libevent/nacl_nonsfi/event-config.h"
 #elif defined(__APPLE__)
-#include "mac/event-config.h"
+#include "third_party/libevent/mac/event-config.h"
 #elif defined(ANDROID)
-#include "android/event-config.h"
+#include "third_party/libevent/android/event-config.h"
 #elif defined(__linux__)
-#include "linux/event-config.h"
+#include "third_party/libevent/linux/event-config.h"
 #elif defined(__FreeBSD__)
-#include "freebsd/event-config.h"
+#include "third_party/libevent/freebsd/event-config.h"
 #elif defined(__sun)
-#include "solaris/event-config.h"
+#include "third_party/libevent/solaris/event-config.h"
 #else
 #error generate event-config.h for your platform
 #endif
diff --git a/third_party/libevent/libevent.gyp b/third_party/libevent/libevent.gyp
index a785d34..656dd63 100644
--- a/third_party/libevent/libevent.gyp
+++ b/third_party/libevent/libevent.gyp
@@ -27,6 +27,9 @@
       'defines': [
         'HAVE_CONFIG_H',
       ],
+      'include_dirs': [
+        '../..',
+      ],
       'conditions': [
         # libevent has platform-specific implementation files.  Since its
         # native build uses autoconf, platform-specific config.h files are
diff --git a/third_party/libevent/libevent_nacl_nonsfi.gyp b/third_party/libevent/libevent_nacl_nonsfi.gyp
index 704de10..37a78ad 100644
--- a/third_party/libevent/libevent_nacl_nonsfi.gyp
+++ b/third_party/libevent/libevent_nacl_nonsfi.gyp
@@ -40,9 +40,6 @@
             'build_pnacl_newlib': 0,
             'build_nonsfi_helper': 1,
           },
-          'dependencies': [
-            '../../native_client/tools.gyp:prep_toolchain',
-          ],
         },
       ],
     }],
diff --git a/third_party/libxml/DEPS b/third_party/libxml/DEPS
new file mode 100644
index 0000000..6dcfa15
--- /dev/null
+++ b/third_party/libxml/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  '+libxml',
+]
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
index bfdff5b..f12d267 100644
--- a/third_party/libxml/README.chromium
+++ b/third_party/libxml/README.chromium
@@ -29,6 +29,7 @@
 - Add helper classes in chromium/libxml_utils.cc and chromium/include/libxml/libxml_utils.h.
 - Add a tweak to limit problems caused by excessive strings and buffers.
 - Change the xmlNs struct a little bit, so it looks like it has no children
+- Prevent snprintf from being defined as _snprintf on VS 2015.
 if treated as a generic xmlNode object.
 - Fix pretty harmless use-after-free in generate-id function.
 - Merge a clang warning fix http://git.gnome.org/browse/libxml2/commit/?id=713434d2309da469d64b35e163ea6556dadccada
diff --git a/third_party/libxml/patches/snprintf_config b/third_party/libxml/patches/snprintf_config
new file mode 100644
index 0000000..9d1ca62
--- /dev/null
+++ b/third_party/libxml/patches/snprintf_config
@@ -0,0 +1,14 @@
+diff --git a/third_party/libxml/win32/config.h b/third_party/libxml/win32/config.h
+index 3fc9be5..5112ce6 100644
+--- a/third_party/libxml/win32/config.h
++++ b/third_party/libxml/win32/config.h
+@@ -95,7 +95,9 @@ static int isnan (double d) {
+ 
+ #if defined(_MSC_VER)
+ #define mkdir(p,m) _mkdir(p)
++#if _MSC_VER < 1900
+ #define snprintf _snprintf
++#endif
+ #if _MSC_VER < 1500
+ #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
+ #endif
diff --git a/third_party/libxml/patches/snprintf_win32config b/third_party/libxml/patches/snprintf_win32config
new file mode 100644
index 0000000..3fec790
--- /dev/null
+++ b/third_party/libxml/patches/snprintf_win32config
@@ -0,0 +1,14 @@
+diff --git a/third_party/libxml/src/include/win32config.h b/third_party/libxml/src/include/win32config.h
+index 3fc9be5..5112ce6 100644
+--- a/third_party/libxml/src/include/win32config.h
++++ b/third_party/libxml/src/include/win32config.h
+@@ -95,7 +95,9 @@ static int isnan (double d) {
+ 
+ #if defined(_MSC_VER)
+ #define mkdir(p,m) _mkdir(p)
++#if _MSC_VER < 1900
+ #define snprintf _snprintf
++#endif
+ #if _MSC_VER < 1500
+ #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
+ #endif
diff --git a/third_party/libxml/src/include/win32config.h b/third_party/libxml/src/include/win32config.h
index 3fc9be5..5112ce6 100644
--- a/third_party/libxml/src/include/win32config.h
+++ b/third_party/libxml/src/include/win32config.h
@@ -95,7 +95,9 @@
 
 #if defined(_MSC_VER)
 #define mkdir(p,m) _mkdir(p)
+#if _MSC_VER < 1900
 #define snprintf _snprintf
+#endif
 #if _MSC_VER < 1500
 #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
 #endif
diff --git a/third_party/libxml/win32/config.h b/third_party/libxml/win32/config.h
index 3fc9be5..5112ce6 100644
--- a/third_party/libxml/win32/config.h
+++ b/third_party/libxml/win32/config.h
@@ -95,7 +95,9 @@
 
 #if defined(_MSC_VER)
 #define mkdir(p,m) _mkdir(p)
+#if _MSC_VER < 1900
 #define snprintf _snprintf
+#endif
 #if _MSC_VER < 1500
 #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
 #endif
diff --git a/third_party/mockito/BUILD.gn b/third_party/mockito/BUILD.gn
new file mode 100644
index 0000000..2f03b7c
--- /dev/null
+++ b/third_party/mockito/BUILD.gn
@@ -0,0 +1,28 @@
+# 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("//build/config/android/rules.gni")
+
+# GYP: //third_party/mockito.gyp:cglib_and_asm_jar
+java_prebuilt("cglib_and_asm_java") {
+  jar_path = "src/lib/repackaged/cglib-and-asm-1.0.jar"
+}
+
+# GYP: //third_party/mockito.gyp:objenesis_jar
+java_prebuilt("objenesis_java") {
+  jar_path = "src/lib/run/objenesis-2.1.jar"
+}
+
+# GYP: //third_party/mockito.gyp:mockito_jar
+java_library("mockito_java") {
+  chromium_code = false
+  testonly = true
+  deps = [
+    ":cglib_and_asm_java",
+    ":objenesis_java",
+    "../junit:junit",
+    "../junit:hamcrest",
+  ]
+  DEPRECATED_java_in_dir = "src/src"
+}
diff --git a/third_party/mockito/LICENSE b/third_party/mockito/LICENSE
new file mode 100644
index 0000000..5a311f7
--- /dev/null
+++ b/third_party/mockito/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/mockito/OWNERS b/third_party/mockito/OWNERS
new file mode 100644
index 0000000..bd675fb
--- /dev/null
+++ b/third_party/mockito/OWNERS
@@ -0,0 +1,2 @@
+jbudorick@chromium.org
+klundberg@chromium.org
diff --git a/third_party/mockito/README.chromium b/third_party/mockito/README.chromium
new file mode 100644
index 0000000..1d932ad
--- /dev/null
+++ b/third_party/mockito/README.chromium
@@ -0,0 +1,9 @@
+Name: Mockito
+URL: https://code.google.com/p/mockito
+Version: 1.10.5
+License: MIT
+License File: NOT_SHIPPED
+Security Critical: no
+License Android Compatible: yes
+Description: Mockito is a java mocking framework.
+Local Modifications: None
diff --git a/third_party/mockito/mockito.gyp b/third_party/mockito/mockito.gyp
new file mode 100644
index 0000000..d9a9db2
--- /dev/null
+++ b/third_party/mockito/mockito.gyp
@@ -0,0 +1,47 @@
+# 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.
+
+{
+  'targets': [
+    {
+      # GN: //third_party/mockito:cglib_and_asm_java
+      'target_name': 'cglib_and_asm_jar',
+      'type': 'none',
+      'variables': {
+        'jar_path': 'src/lib/repackaged/cglib-and-asm-1.0.jar',
+      },
+      'includes': [
+        '../../build/host_prebuilt_jar.gypi',
+      ]
+    },
+    {
+      # GN: //third_party/mockito:objenesis_java
+      'target_name': 'objenesis_jar',
+      'type': 'none',
+      'variables': {
+        'jar_path': 'src/lib/run/objenesis-2.1.jar',
+      },
+      'includes': [
+        '../../build/host_prebuilt_jar.gypi',
+      ]
+    },
+    {
+      # GN: //third_party/mockito:mockito_java
+      'target_name': 'mockito_jar',
+      'type': 'none',
+      'dependencies': [
+        'cglib_and_asm_jar',
+        'objenesis_jar',
+        '../junit/junit.gyp:junit_jar',
+      ],
+      'variables': {
+        'src_paths': [ 'src/src' ],
+      },
+      'includes': [
+        '../../build/host_jar.gypi',
+      ],
+    },
+  ],
+}
+
diff --git a/third_party/modp_b64/DEPS b/third_party/modp_b64/DEPS
new file mode 100644
index 0000000..8061b5a
--- /dev/null
+++ b/third_party/modp_b64/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  '+build',
+]
\ No newline at end of file
diff --git a/third_party/modp_b64/modp_b64_nacl.gyp b/third_party/modp_b64/modp_b64_nacl.gyp
index cd0d210..e2f4a25 100644
--- a/third_party/modp_b64/modp_b64_nacl.gyp
+++ b/third_party/modp_b64/modp_b64_nacl.gyp
@@ -16,9 +16,6 @@
         'build_newlib': 1,
         'build_pnacl_newlib': 1,
       },
-      'dependencies': [
-        '<(DEPTH)/native_client/tools.gyp:prep_toolchain',
-      ],
       'sources': [
         'modp_b64.cc',
         'modp_b64.h',
diff --git a/third_party/robolectric/BUILD.gn b/third_party/robolectric/BUILD.gn
new file mode 100644
index 0000000..211c3d6
--- /dev/null
+++ b/third_party/robolectric/BUILD.gn
@@ -0,0 +1,31 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+# GYP: //third_party/robolectric/robolectric.gyp:android-all-4.3_r2-robolectric-0
+java_prebuilt("android-all-4.3_r2-robolectric-0") {
+  jar_path = "lib/android-all-4.3_r2-robolectric-0.jar"
+}
+
+# GYP: //third_party/robolectric/robolectric.gyp:tagsoup-1.2
+java_prebuilt("tagsoup-1.2") {
+  jar_path = "lib/tagsoup-1.2.jar"
+}
+
+# GYP: //third_party/robolectric/robolectric.gyp:json-20080701
+java_prebuilt("json-20080701") {
+  jar_path = "lib/json-20080701.jar"
+}
+
+# GYP: //third_party/robolectric/robolectric.gyp:robolectric_jar
+java_prebuilt("robolectric_java") {
+  testonly = true
+  jar_path = "lib/robolectric-2.4-jar-with-dependencies.jar"
+  deps = [
+    ":android-all-4.3_r2-robolectric-0",
+    ":tagsoup-1.2",
+    ":json-20080701",
+  ]
+}
diff --git a/third_party/robolectric/LICENSE b/third_party/robolectric/LICENSE
new file mode 100644
index 0000000..f433b1a
--- /dev/null
+++ b/third_party/robolectric/LICENSE
@@ -0,0 +1,177 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/third_party/robolectric/OWNERS b/third_party/robolectric/OWNERS
new file mode 100644
index 0000000..bd675fb
--- /dev/null
+++ b/third_party/robolectric/OWNERS
@@ -0,0 +1,2 @@
+jbudorick@chromium.org
+klundberg@chromium.org
diff --git a/third_party/robolectric/README.chromium b/third_party/robolectric/README.chromium
new file mode 100644
index 0000000..10aeba3
--- /dev/null
+++ b/third_party/robolectric/README.chromium
@@ -0,0 +1,11 @@
+Name: Robolectric 
+URL: http://robolectric.org
+Version: 2.4
+License: Apache 2.0 
+License File: NOT_SHIPPED
+Security Critical: no
+License Android Compatible: yes
+Description: Robolectric is a unit test framework for Android. To update the
+robolectric jars, go to robolectric.org/download and follow link to
+robolectric-X.X.X-jar-with-dependencies.jar.
+Local Modifications: None
diff --git a/third_party/robolectric/lib b/third_party/robolectric/lib
new file mode 160000
index 0000000..6b63c99
--- /dev/null
+++ b/third_party/robolectric/lib
@@ -0,0 +1 @@
+Subproject commit 6b63c99a8b6967acdb42cbed0adb067c80efc810
diff --git a/third_party/robolectric/licenses/extreme.indiana.edu.license.txt b/third_party/robolectric/licenses/extreme.indiana.edu.license.txt
new file mode 100644
index 0000000..c743155
--- /dev/null
+++ b/third_party/robolectric/licenses/extreme.indiana.edu.license.txt
@@ -0,0 +1,47 @@
+Indiana University Extreme! Lab Software License
+
+Version 1.1.1
+
+Copyright (c) 2002 Extreme! Lab, Indiana University. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions 
+are met:
+
+1. Redistributions of source code must retain the above copyright notice, 
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright 
+   notice, this list of conditions and the following disclaimer in 
+   the documentation and/or other materials provided with the distribution.
+
+3. The end-user documentation included with the redistribution, if any, 
+   must include the following acknowledgment:
+
+  "This product includes software developed by the Indiana University 
+  Extreme! Lab (http://www.extreme.indiana.edu/)."
+
+Alternately, this acknowledgment may appear in the software itself, 
+if and wherever such third-party acknowledgments normally appear.
+
+4. The names "Indiana Univeristy" and "Indiana Univeristy Extreme! Lab" 
+must not be used to endorse or promote products derived from this 
+software without prior written permission. For written permission, 
+please contact http://www.extreme.indiana.edu/.
+
+5. Products derived from this software may not use "Indiana Univeristy" 
+name nor may "Indiana Univeristy" appear in their name, without prior 
+written permission of the Indiana University.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHORS, COPYRIGHT HOLDERS OR ITS CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/third_party/robolectric/licenses/javolution.license.txt b/third_party/robolectric/licenses/javolution.license.txt
new file mode 100644
index 0000000..0633749
--- /dev/null
+++ b/third_party/robolectric/licenses/javolution.license.txt
@@ -0,0 +1,23 @@
+Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+Copyright (c) 2006, Javolution (http://javolution.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/robolectric/licenses/pivotal.labs.license.txt b/third_party/robolectric/licenses/pivotal.labs.license.txt
new file mode 100644
index 0000000..c9dccb8
--- /dev/null
+++ b/third_party/robolectric/licenses/pivotal.labs.license.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2010 Xtreme Labs and Pivotal Labs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/robolectric/robolectric.gyp b/third_party/robolectric/robolectric.gyp
new file mode 100644
index 0000000..7c3d785
--- /dev/null
+++ b/third_party/robolectric/robolectric.gyp
@@ -0,0 +1,58 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      # GN: //third_party/robolectric:android-all-4.3_r2-robolectric-0
+      'target_name': 'android-all-4.3_r2-robolectric-0',
+      'type': 'none',
+      'variables': {
+        'jar_path': 'lib/android-all-4.3_r2-robolectric-0.jar',
+      },
+      'includes': [
+        '../../build/host_prebuilt_jar.gypi',
+      ]
+    },
+    {
+      # GN: //third_party/robolectric:tagsoup-1.2
+      'target_name': 'tagsoup-1.2',
+      'type': 'none',
+      'variables': {
+        'jar_path': 'lib/tagsoup-1.2.jar',
+      },
+      'includes': [
+        '../../build/host_prebuilt_jar.gypi',
+      ]
+    },
+    {
+      # GN: //third_party/robolectric:json-20080701
+      'target_name': 'json-20080701',
+      'type': 'none',
+      'variables': {
+        'jar_path': 'lib/json-20080701.jar',
+      },
+      'includes': [
+        '../../build/host_prebuilt_jar.gypi',
+      ]
+    },
+    {
+      # GN: //third_party/robolectric:robolectric_java
+      'target_name': 'robolectric_jar',
+      'type': 'none',
+      'dependencies': [
+        'android-all-4.3_r2-robolectric-0',
+        'tagsoup-1.2',
+        'json-20080701',
+      ],
+      'variables': {
+        'jar_path': 'lib/robolectric-2.4-jar-with-dependencies.jar',
+      },
+      'includes': [
+        '../../build/host_prebuilt_jar.gypi',
+      ]
+    },
+  ],
+}
+
diff --git a/third_party/tcmalloc/DEPS b/third_party/tcmalloc/DEPS
new file mode 100644
index 0000000..b0a0897
--- /dev/null
+++ b/third_party/tcmalloc/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+  '+base',
+  '+build',
+  '+gperftools',
+  '+tests',
+  '+../config.h',
+]
diff --git a/third_party/tcmalloc/vendor/packages/deb.sh b/third_party/tcmalloc/vendor/packages/deb.sh
deleted file mode 100644
index 31b423c..0000000
--- a/third_party/tcmalloc/vendor/packages/deb.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/bash -e
-
-# This takes one commandline argument, the name of the package.  If no
-# name is given, then we'll end up just using the name associated with
-# an arbitrary .tar.gz file in the rootdir.  That's fine: there's probably
-# only one.
-#
-# Run this from the 'packages' directory, just under rootdir
-
-## Set LIB to lib if exporting a library, empty-string else
-LIB=
-#LIB=lib
-
-PACKAGE="$1"
-VERSION="$2"
-
-# We can only build Debian packages, if the Debian build tools are installed
-if [ \! -x /usr/bin/debuild ]; then
-  echo "Cannot find /usr/bin/debuild. Not building Debian packages." 1>&2
-  exit 0
-fi
-
-# Double-check we're in the packages directory, just under rootdir
-if [ \! -r ../Makefile -a \! -r ../INSTALL ]; then
-  echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
-  echo "Also, you must run \"make dist\" before running this script." 1>&2
-  exit 0
-fi
-
-# Find the top directory for this package
-topdir="${PWD%/*}"
-
-# Find the tar archive built by "make dist"
-archive="${PACKAGE}-${VERSION}"
-archive_with_underscore="${PACKAGE}_${VERSION}"
-if [ -z "${archive}" ]; then
-  echo "Cannot find ../$PACKAGE*.tar.gz. Run \"make dist\" first." 1>&2
-  exit 0
-fi
-
-# Create a pristine directory for building the Debian package files
-trap 'rm -rf '`pwd`/tmp'; exit $?' EXIT SIGHUP SIGINT SIGTERM
-
-rm -rf tmp
-mkdir -p tmp
-cd tmp
-
-# Debian has very specific requirements about the naming of build
-# directories, and tar archives. It also wants to write all generated
-# packages to the parent of the source directory. We accommodate these
-# requirements by building directly from the tar file.
-ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive}.orig.tar.gz"
-# Some version of debuilder want foo.orig.tar.gz with _ between versions.
-ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive_with_underscore}.orig.tar.gz"
-tar zfx "${LIB}${archive}.orig.tar.gz"
-[ -n "${LIB}" ] && mv "${archive}" "${LIB}${archive}"
-cd "${LIB}${archive}"
-# This is one of those 'specific requirements': where the deb control files live
-cp -a "packages/deb" "debian"
-
-# Now, we can call Debian's standard build tool
-debuild -uc -us
-cd ../..                            # get back to the original top-level dir
-
-# We'll put the result in a subdirectory that's named after the OS version
-# we've made this .deb file for.
-destdir="debian-$(cat /etc/debian_version 2>/dev/null || echo UNKNOWN)"
-
-rm -rf "$destdir"
-mkdir -p "$destdir"
-mv $(find tmp -mindepth 1 -maxdepth 1 -type f) "$destdir"
-
-echo
-echo "The Debian package files are located in $PWD/$destdir"
diff --git a/third_party/tcmalloc/vendor/packages/deb/README b/third_party/tcmalloc/vendor/packages/deb/README
deleted file mode 100644
index 57becfd..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/README
+++ /dev/null
@@ -1,7 +0,0 @@
-The list of files here isn't complete.  For a step-by-step guide on
-how to set this package up correctly, check out
-    http://www.debian.org/doc/maint-guide/
-
-Most of the files that are in this directory are boilerplate.
-However, you may need to change the list of binary-arch dependencies
-in 'rules'.
diff --git a/third_party/tcmalloc/vendor/packages/deb/changelog b/third_party/tcmalloc/vendor/packages/deb/changelog
deleted file mode 100644
index dad1d5f..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/changelog
+++ /dev/null
@@ -1,196 +0,0 @@
-gperftools (2.0-1) unstable; urgency=low
-
-  * New upstream release.
-  * Package renamed from google-perftools to gperftools.
-
- -- Google Inc. and others <google-perftools@googlegroups.com>  Fri, 03 Feb 2012 15:40:45 -0800
-
-google-perftools (1.10-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 31 Jan 2012 10:43:50 -0800
-
-google-perftools (1.9-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Thu, 22 Dec 2011 16:22:45 -0800
-
-google-perftools (1.8-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Fri, 15 Jul 2011 16:10:51 -0700
-
-google-perftools (1.7-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Fri, 04 Feb 2011 15:54:31 -0800
-
-google-perftools (1.6-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Thu, 05 Aug 2010 12:48:03 -0700
-
-google-perftools (1.5-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 19 Jan 2010 14:46:12 -0800
-
-google-perftools (1.4-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Thu, 10 Sep 2009 13:51:15 -0700
-
-google-perftools (1.3-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 09 Jun 2009 18:19:06 -0700
-
-google-perftools (1.2-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Fri, 17 Apr 2009 16:40:48 -0700
-
-google-perftools (1.1-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Wed, 11 Mar 2009 11:25:34 -0700
-
-google-perftools (1.0-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 06 Jan 2009 13:58:56 -0800
-	
-google-perftools (1.0rc1-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Thu, 11 Dec 2008 16:01:32 -0800
-	
-google-perftools (0.99.1-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Sat, 20 Sep 2008 09:37:18 -0700
-	
-google-perftools (0.99-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Thu, 18 Sep 2008 16:00:27 -0700
-	
-google-perftools (0.98-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Mon, 09 Jun 2008 16:47:03 -0700
-	
-google-perftools (0.97-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Mon, 21 Apr 2008 15:20:52 -0700
-	
-google-perftools (0.96-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 18 Mar 2008 14:30:44 -0700
-	
-google-perftools (0.95-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 12 Feb 2008 12:28:32 -0800
-
-google-perftools (0.94-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Thu, 29 Nov 2007 07:59:43 -0800
-
-google-perftools (0.93-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Fri, 17 Aug 2007 12:32:56 -0700
-
-google-perftools (0.92-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 17 Jul 2007 22:26:27 -0700
-
-google-perftools (0.91-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Wed, 18 Apr 2007 16:43:55 -0700
-
-google-perftools (0.90-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Fri, 13 Apr 2007 14:50:51 -0700
-
-google-perftools (0.8-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Wed, 14 Jun 2006 15:11:14 -0700
-
-google-perftools (0.7-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Thu, 13 Apr 2006 20:59:09 -0700
-
-google-perftools (0.6-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Fri, 27 Jan 2006 14:04:27 -0800
-
-google-perftools (0.5-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Mon, Nov 14 17:28:59 2005 -0800
-
-google-perftools (0.4-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Wed, 26 Oct 2005 15:19:16 -0700
-
-google-perftools (0.3-1) unstable; urgency=low
-
-  * New upstream release.
-  
- -- Google Inc. <opensource@google.com>  Fri, 24 Jun 2005 18:02:26 -0700
-
-google-perftools (0.2-1) unstable; urgency=low
-
-  * New upstream release.
-
- -- Google Inc. <opensource@google.com>  Tue, 31 May 2005 08:14:38 -0700
-
-google-perftools (0.1-1) unstable; urgency=low
-
-  * Initial release.
-    The google-perftools package contains some utilities to improve
-    and analyze the performance of C++ programs.  This includes an
-    optimized thread-caching malloc() and cpu and heap profiling
-    utilities.
-
- -- Google Inc. <opensource@google.com>  Fri, 11 Mar 2005 08:07:33 -0800
diff --git a/third_party/tcmalloc/vendor/packages/deb/compat b/third_party/tcmalloc/vendor/packages/deb/compat
deleted file mode 100644
index b8626c4..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/compat
+++ /dev/null
@@ -1 +0,0 @@
-4
diff --git a/third_party/tcmalloc/vendor/packages/deb/control b/third_party/tcmalloc/vendor/packages/deb/control
deleted file mode 100644
index a553594..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/control
+++ /dev/null
@@ -1,25 +0,0 @@
-Source: gperftools
-Priority: optional
-Maintainer: Google Inc. and others <google-perftools@googlegroups.com>
-Build-Depends: debhelper (>= 4.0.0), binutils
-Standards-Version: 3.6.1
-
-Package: libgperftools-dev
-Section: libdevel
-Architecture: any
-Depends: libgperftools0 (= ${Source-Version})
-Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc
- The gperftools package contains some utilities to improve and
- analyze the performance of C++ programs.  This includes an optimized
- thread-caching malloc() and cpu and heap profiling utilities.  The
- devel package contains static and debug libraries and header files
- for developing applications that use the gperftools package.
-
-Package: libgperftools0
-Section: libs
-Architecture: any
-Depends: ${shlibs:Depends}
-Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc
- The gperftools package contains some utilities to improve and
- analyze the performance of C++ programs.  This includes an optimized
- thread-caching malloc() and cpu and heap profiling utilities.
diff --git a/third_party/tcmalloc/vendor/packages/deb/copyright b/third_party/tcmalloc/vendor/packages/deb/copyright
deleted file mode 100644
index 1a11eb7..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/copyright
+++ /dev/null
@@ -1,35 +0,0 @@
-This package was debianized by Craig Silverstein <google-perftools@googlegroups.com>
-on Fri, 03 Feb 2012 15:40:45 -0800.
-
-It was downloaded from http://code.google.com/p/gperftools/downloads/list
-
-Upstream Author: google-perftools@googlegroups.com
-
-Copyright (c) 2005, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-    * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/tcmalloc/vendor/packages/deb/docs b/third_party/tcmalloc/vendor/packages/deb/docs
deleted file mode 100644
index df891c9..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/docs
+++ /dev/null
@@ -1,47 +0,0 @@
-AUTHORS
-COPYING
-ChangeLog
-INSTALL
-NEWS
-README
-TODO
-doc/cpuprofile.html
-doc/cpuprofile-fileformat.html
-doc/designstyle.css
-doc/heap-example1.png
-doc/heap_checker.html
-doc/heapprofile.html
-doc/index.html
-doc/overview.gif
-doc/pageheap.gif
-doc/pprof-test-big.gif
-doc/pprof-test.gif
-doc/pprof-vsnprintf-big.gif
-doc/pprof-vsnprintf.gif
-doc/pprof.1
-doc/pprof_remote_servers.html
-doc/spanmap.gif
-doc/t-test1.times.txt
-doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
-doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
-doc/tcmalloc-opspersec.vs.size.1.threads.png
-doc/tcmalloc-opspersec.vs.size.12.threads.png
-doc/tcmalloc-opspersec.vs.size.16.threads.png
-doc/tcmalloc-opspersec.vs.size.2.threads.png
-doc/tcmalloc-opspersec.vs.size.20.threads.png
-doc/tcmalloc-opspersec.vs.size.3.threads.png
-doc/tcmalloc-opspersec.vs.size.4.threads.png
-doc/tcmalloc-opspersec.vs.size.5.threads.png
-doc/tcmalloc-opspersec.vs.size.8.threads.png
-doc/tcmalloc.html
-doc/threadheap.gif
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs b/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs
deleted file mode 100644
index 8f88347..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs
+++ /dev/null
@@ -1,5 +0,0 @@
-usr/lib
-usr/lib/pkgconfig
-usr/include
-usr/include/google
-usr/include/gperftools
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install b/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install
deleted file mode 100644
index e863529..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install
+++ /dev/null
@@ -1,12 +0,0 @@
-usr/include/google/*
-usr/include/gperftools/*
-usr/lib/lib*.so
-usr/lib/lib*.a
-usr/lib/*.la
-usr/lib/pkgconfig/*.pc
-debian/tmp/usr/include/google/*
-debian/tmp/usr/include/gperftools/*
-debian/tmp/usr/lib/lib*.so
-debian/tmp/usr/lib/lib*.a
-debian/tmp/usr/lib/*.la
-debian/tmp/usr/lib/pkgconfig/*.pc
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
deleted file mode 100644
index 14f5b95..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/lib
-usr/bin
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install
deleted file mode 100644
index 047eed5..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install
+++ /dev/null
@@ -1,4 +0,0 @@
-usr/lib/lib*.so.*
-usr/bin/pprof*
-debian/tmp/usr/lib/lib*.so.*
-debian/tmp/usr/bin/pprof*
diff --git a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
deleted file mode 100644
index 08d1476..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
+++ /dev/null
@@ -1 +0,0 @@
-doc/pprof.1
diff --git a/third_party/tcmalloc/vendor/packages/deb/rules b/third_party/tcmalloc/vendor/packages/deb/rules
deleted file mode 100644
index f520bef..0000000
--- a/third_party/tcmalloc/vendor/packages/deb/rules
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-
-CFLAGS = -Wall -g
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -O0
-else
-	CFLAGS += -O2
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
-	INSTALL_PROGRAM += -s
-endif
-
-# shared library versions, option 1
-#version=2.0.5
-#major=2
-# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
-version=`ls src/.libs/lib*.so.* | \
- awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
-major=`ls src/.libs/lib*.so.* | \
- awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
-
-config.status: configure
-	dh_testdir
-	# Add here commands to configure the package.
-	CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
-
-
-build: build-stamp
-build-stamp:  config.status
-	dh_testdir
-
-	# Add here commands to compile the package.
-	$(MAKE)
-
-	touch build-stamp
-
-clean:
-	dh_testdir
-	dh_testroot
-	rm -f build-stamp 
-
-	# Add here commands to clean up after the build process.
-	-$(MAKE) distclean
-ifneq "$(wildcard /usr/share/misc/config.sub)" ""
-	cp -f /usr/share/misc/config.sub config.sub
-endif
-ifneq "$(wildcard /usr/share/misc/config.guess)" ""
-	cp -f /usr/share/misc/config.guess config.guess
-endif
-
-
-	dh_clean 
-
-install: build
-	dh_testdir
-	dh_testroot
-	dh_clean -k 
-	dh_installdirs
-
-	# Add here commands to install the package into debian/tmp
-	$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
-
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
-	dh_testdir
-	dh_testroot
-	dh_installchangelogs ChangeLog
-	dh_installdocs
-	dh_installexamples
-	dh_install --sourcedir=debian/tmp
-#	dh_installmenu
-#	dh_installdebconf	
-#	dh_installlogrotate
-#	dh_installemacsen
-#	dh_installpam
-#	dh_installmime
-#	dh_installinit
-#	dh_installcron
-#	dh_installinfo
-	dh_installman
-	dh_link
-	dh_strip
-	dh_compress
-	dh_fixperms
-#	dh_perl
-#	dh_python
-	dh_makeshlibs
-	dh_installdeb
-	dh_shlibdeps
-	dh_gencontrol
-	dh_md5sums
-	dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install 
diff --git a/third_party/tcmalloc/vendor/packages/rpm.sh b/third_party/tcmalloc/vendor/packages/rpm.sh
deleted file mode 100644
index 448a032..0000000
--- a/third_party/tcmalloc/vendor/packages/rpm.sh
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/bin/sh -e
-
-# Run this from the 'packages' directory, just under rootdir
-
-# We can only build rpm packages, if the rpm build tools are installed
-if [ \! -x /usr/bin/rpmbuild ]
-then
-  echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2
-  exit 0
-fi
-
-# Check the commandline flags
-PACKAGE="$1"
-VERSION="$2"
-fullname="${PACKAGE}-${VERSION}"
-archive=../$fullname.tar.gz
-
-if [ -z "$1" -o -z "$2" ]
-then
-  echo "Usage: $0 <package name> <package version>" 1>&2
-  exit 0
-fi
-
-# Double-check we're in the packages directory, just under rootdir
-if [ \! -r ../Makefile -a \! -r ../INSTALL ]
-then
-  echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
-  echo "Also, you must run \"make dist\" before running this script." 1>&2
-  exit 0
-fi
-
-if [ \! -r "$archive" ]
-then
-  echo "Cannot find $archive. Run \"make dist\" first." 1>&2
-  exit 0
-fi
-
-# Create the directory where the input lives, and where the output should live
-RPM_SOURCE_DIR="/tmp/rpmsource-$fullname"
-RPM_BUILD_DIR="/tmp/rpmbuild-$fullname"
-
-trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM
-
-rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR"
-mkdir "$RPM_SOURCE_DIR"
-mkdir "$RPM_BUILD_DIR"
-
-cp "$archive" "$RPM_SOURCE_DIR"
-
-# rpmbuild -- as far as I can tell -- asks the OS what CPU it has.
-# This may differ from what kind of binaries gcc produces.  dpkg
-# does a better job of this, so if we can run 'dpkg --print-architecture'
-# to get the build CPU, we use that in preference of the rpmbuild
-# default.
-target=`dpkg --print-architecture 2>/dev/null || echo ""`
-if [ -n "$target" ]
-then
-   target=" --target $target"
-fi
-
-rpmbuild -bb rpm/rpm.spec $target \
-  --define "NAME $PACKAGE" \
-  --define "VERSION $VERSION" \
-  --define "_sourcedir $RPM_SOURCE_DIR" \
-  --define "_builddir $RPM_BUILD_DIR" \
-  --define "_rpmdir $RPM_SOURCE_DIR"
-
-# We put the output in a directory based on what system we've built for
-destdir=rpm-unknown
-if [ -r /etc/issue ]
-then
-   grep "Red Hat.*release 7" /etc/issue >/dev/null 2>&1 && destdir=rh7
-   grep "Red Hat.*release 8" /etc/issue >/dev/null 2>&1 && destdir=rh8
-   grep "Red Hat.*release 9" /etc/issue >/dev/null 2>&1 && destdir=rh9
-   grep "Fedora Core.*release 1" /etc/issue >/dev/null 2>&1 && destdir=fc1
-   grep "Fedora Core.*release 2" /etc/issue >/dev/null 2>&1 && destdir=fc2
-   grep "Fedora Core.*release 3" /etc/issue >/dev/null 2>&1 && destdir=fc3
-fi
-
-rm -rf "$destdir"
-mkdir -p "$destdir"
-# We want to get not only the main package but devel etc, hence the middle *
-mv "$RPM_SOURCE_DIR"/*/"${PACKAGE}"-*"${VERSION}"*.rpm "$destdir"
-
-echo
-echo "The rpm package file(s) are located in $PWD/$destdir"
diff --git a/third_party/tcmalloc/vendor/packages/rpm/rpm.spec b/third_party/tcmalloc/vendor/packages/rpm/rpm.spec
deleted file mode 100644
index bb9a4ee..0000000
--- a/third_party/tcmalloc/vendor/packages/rpm/rpm.spec
+++ /dev/null
@@ -1,77 +0,0 @@
-%define	RELEASE	1
-%define rel     %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
-%define	prefix	/usr
-
-Name: %NAME
-Summary: Performance tools for C++
-Version: %VERSION
-Release: %rel
-Group: Development/Libraries
-URL: http://code.google.com/p/gperftools/
-License: BSD
-Vendor: Google Inc. and others
-Packager: Google Inc. and others <google-perftools@googlegroups.com>
-Source: http://%{NAME}.googlecode.com/files/%{NAME}-%{VERSION}.tar.gz
-Distribution: Redhat 7 and above.
-Buildroot: %{_tmppath}/%{name}-root
-Prefix: %prefix
-
-%description
-The %name packages contains some utilities to improve and analyze the
-performance of C++ programs.  This includes an optimized thread-caching
-malloc() and cpu and heap profiling utilities.
-
-%package devel
-Summary: Performance tools for C++
-Group: Development/Libraries
-Requires: %{NAME} = %{VERSION}
-
-%description devel
-The %name-devel package contains static and debug libraries and header
-files for developing applications that use the %name package.
-
-%changelog
-	* Mon Apr 20 2009  <opensource@google.com>
-	- Change build rule to use a configure line more like '%configure'
-	- Change install to use DESTDIR instead of prefix for configure
-	- Use wildcards for doc/ and lib/ directories
-
-	* Fri Mar 11 2005  <opensource@google.com>
-	- First draft
-
-%prep
-%setup
-
-%build
-# I can't use '% configure', because it defines -m32 which breaks some
-# of the low-level atomicops files in this package.  But I do take
-# as much from % configure (in /usr/lib/rpm/macros) as I can.
-./configure --prefix=%{_prefix} --exec-prefix=%{_exec_prefix} --bindir=%{_bindir} --sbindir=%{_sbindir} --sysconfdir=%{_sysconfdir} --datadir=%{_datadir} --includedir=%{_includedir} --libdir=%{_libdir} --libexecdir=%{_libexecdir} --localstatedir=%{_localstatedir} --sharedstatedir=%{_sharedstatedir} --mandir=%{_mandir} --infodir=%{_infodir}
-make
-
-%install
-rm -rf $RPM_BUILD_ROOT
-make DESTDIR=$RPM_BUILD_ROOT install
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-
-%docdir %{prefix}/share/doc/%{NAME}-%{VERSION}
-%{prefix}/share/doc/%{NAME}-%{VERSION}/*
-
-%{_libdir}/*.so.*
-%{_bindir}/pprof
-%{_mandir}/man1/pprof.1*
-
-%files devel
-%defattr(-,root,root)
-
-%{_includedir}/google
-%{_includedir}/gperftools
-%{_libdir}/*.a
-%{_libdir}/*.la
-%{_libdir}/*.so
-%{_libdir}/pkgconfig/*.pc
diff --git a/tools/android/checkstyle/checkstyle.py b/tools/android/checkstyle/checkstyle.py
index 99a9fc9..44e1ecf 100644
--- a/tools/android/checkstyle/checkstyle.py
+++ b/tools/android/checkstyle/checkstyle.py
@@ -13,7 +13,7 @@
     os.path.join(os.path.dirname(__file__),
                  os.pardir, os.pardir, os.pardir))
 CHECKSTYLE_ROOT = os.path.join(CHROMIUM_SRC, 'third_party', 'checkstyle',
-                               'checkstyle-6.1-all.jar')
+                               'checkstyle-6.5-all.jar')
 
 
 def RunCheckstyle(input_api, output_api, style_file, black_list=None):
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml
index c43f779..9e56dd9 100644
--- a/tools/android/checkstyle/chromium-style-5.0.xml
+++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -101,8 +101,10 @@
       <property name="severity" value="error"/>
     </module>
     <module name="NeedBraces">
-      <property name="severity" value="info"/>
-      <property name="tokens" value="LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
+      <message key="needBraces" value="if, for, while, and do require curly braces unless they are single-line statements."/>
+      <property name="severity" value="error"/>
+      <property name="tokens" value="LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, LITERAL_IF"/>
+      <property name="allowSingleLineStatement" value="true"/>
     </module>
     <module name="EmptyBlock">
       <property name="severity" value="error"/>
diff --git a/tools/android/findbugs_plugin/findbugs.xml b/tools/android/findbugs_plugin/findbugs.xml
index 43b1f34..a1c4b5e 100644
--- a/tools/android/findbugs_plugin/findbugs.xml
+++ b/tools/android/findbugs_plugin/findbugs.xml
@@ -11,8 +11,8 @@
         provider="chromium"
         website="http://code.google.com/p/chromium/wiki/UseFindBugsForAndroid">
         <Detector class="org.chromium.tools.findbugs.plugin.SynchronizedThisDetector" reports="CHROMIUM_SYNCHRONIZED_THIS" />
-        <BugPattern type="CHROMIUM_SYNCHRONIZED_THIS" abbrev="CST" category="CORRECTNESS"/>
+        <BugPattern type="CHROMIUM_SYNCHRONIZED_THIS" abbrev="CHROMIUM" category="CORRECTNESS"/>
 
         <Detector class="org.chromium.tools.findbugs.plugin.SynchronizedMethodDetector" reports="CHROMIUM_SYNCHRONIZED_METHOD" />
-        <BugPattern type="CHROMIUM_SYNCHRONIZED_METHOD" abbrev="CSM" category="CORRECTNESS"/>
+        <BugPattern type="CHROMIUM_SYNCHRONIZED_METHOD" abbrev="CHROMIUM" category="CORRECTNESS"/>
 </FindbugsPlugin>
diff --git a/tools/android/findbugs_plugin/findbugs_plugin.gyp b/tools/android/findbugs_plugin/findbugs_plugin.gyp
index 16d06e6..440d779 100644
--- a/tools/android/findbugs_plugin/findbugs_plugin.gyp
+++ b/tools/android/findbugs_plugin/findbugs_plugin.gyp
@@ -9,6 +9,7 @@
          'type': 'none',
          'variables': {
            'java_in_dir': 'test/java/',
+            'run_findbugs': 0,
          },
          'includes': [ '../../../build/java.gypi' ],
       }
diff --git a/tools/android/findbugs_plugin/lib/chromiumPlugin.jar b/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
index 6ccf61b..451566d 100644
--- a/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
+++ b/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
Binary files differ
diff --git a/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py b/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py
index a570cdb..e36fe8e 100755
--- a/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py
+++ b/tools/android/findbugs_plugin/test/run_findbugs_plugin_tests.py
@@ -14,7 +14,7 @@
 # remove the expected result of exsting tests.
 
 
-import optparse
+import argparse
 import os
 import sys
 
@@ -26,28 +26,79 @@
 from pylib.utils import findbugs
 
 
+_EXPECTED_WARNINGS = set([
+    findbugs.FindBugsWarning(
+        bug_type='CHROMIUM_SYNCHRONIZED_THIS',
+        start_line=15,
+        end_line=15,
+        file_name='SimpleSynchronizedThis.java',
+        message=(
+            "Shouldn't use synchronized(this)",
+            'In class org.chromium.tools.findbugs.plugin.'
+                + 'SimpleSynchronizedThis',
+            'In method org.chromium.tools.findbugs.plugin.'
+                + 'SimpleSynchronizedThis.synchronizedThis()',
+            'At SimpleSynchronizedThis.java:[line 15]',
+        )),
+    findbugs.FindBugsWarning(
+        bug_type='CHROMIUM_SYNCHRONIZED_METHOD',
+        start_line=14,
+        end_line=14,
+        file_name='SimpleSynchronizedStaticMethod.java',
+        message=(
+            "Shouldn't use synchronized method",
+            'In class org.chromium.tools.findbugs.plugin.'
+                + 'SimpleSynchronizedStaticMethod',
+            'In method org.chromium.tools.findbugs.plugin.'
+                + 'SimpleSynchronizedStaticMethod.synchronizedStaticMethod()',
+            'At SimpleSynchronizedStaticMethod.java:[line 14]',
+        )),
+    findbugs.FindBugsWarning(
+        bug_type='CHROMIUM_SYNCHRONIZED_METHOD',
+        start_line=15,
+        end_line=15,
+        file_name='SimpleSynchronizedMethod.java',
+        message=(
+            "Shouldn't use synchronized method",
+            'In class org.chromium.tools.findbugs.plugin.'
+                + 'SimpleSynchronizedMethod',
+            'In method org.chromium.tools.findbugs.plugin.'
+                + 'SimpleSynchronizedMethod.synchronizedMethod()',
+            'At SimpleSynchronizedMethod.java:[line 15]',
+        )),
+])
+
+
 def main(argv):
-  parser = findbugs.GetCommonParser()
 
-  options, _ = parser.parse_args()
+  parser = argparse.ArgumentParser()
+  parser.add_argument(
+      '-l', '--release-build', action='store_true', dest='release',
+      help='Run the release build of the findbugs plugin test.')
+  args = parser.parse_args()
 
-  if not options.known_bugs:
-    options.known_bugs = os.path.join(constants.DIR_SOURCE_ROOT, 'tools',
-                                      'android', 'findbugs_plugin', 'test',
-                                      'expected_result.txt')
+  test_jar_path = os.path.join(
+      constants.GetOutDirectory(
+          'Release' if args.release else 'Debug'),
+      'lib.java', 'findbugs_plugin_test.jar')
 
-  if not options.only_analyze:
-    options.only_analyze = 'org.chromium.tools.findbugs.plugin.*'
+  findbugs_command, findbugs_warnings = findbugs.Run(
+      None, 'org.chromium.tools.findbugs.plugin.*', None, None, None,
+      [test_jar_path])
 
-  # crbug.com/449101
-  # Temporary workaround to have the Android Clang Builder (dbg) bot
-  # pass the findbugs_tests step.
-  if not options.exclude:
-    options.exclude = os.path.join(constants.DIR_SOURCE_ROOT, 'build',
-                                   'android', 'findbugs_filter',
-                                   'findbugs_exclude.xml')
+  missing_warnings = _EXPECTED_WARNINGS.difference(findbugs_warnings)
+  if missing_warnings:
+    print 'Missing warnings:'
+    for w in missing_warnings:
+      print '%s' % str(w)
 
-  return findbugs.Run(options)
+  unexpected_warnings = findbugs_warnings.difference(_EXPECTED_WARNINGS)
+  if unexpected_warnings:
+    print 'Unexpected warnings:'
+    for w in unexpected_warnings:
+      print '%s' % str(w)
+
+  return len(unexpected_warnings) + len(missing_warnings)
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv))
diff --git a/tools/clang/blink_gc_plugin/Edge.h b/tools/clang/blink_gc_plugin/Edge.h
index 7659968..2ea8e54 100644
--- a/tools/clang/blink_gc_plugin/Edge.h
+++ b/tools/clang/blink_gc_plugin/Edge.h
@@ -39,14 +39,14 @@
 class RecursiveEdgeVisitor : public EdgeVisitor {
  public:
   // Overrides that recursively walk the edges and record the path.
-  virtual void VisitValue(Value*) override;
-  virtual void VisitRawPtr(RawPtr*) override;
-  virtual void VisitRefPtr(RefPtr*) override;
-  virtual void VisitOwnPtr(OwnPtr*) override;
-  virtual void VisitMember(Member*) override;
-  virtual void VisitWeakMember(WeakMember*) override;
-  virtual void VisitPersistent(Persistent*) override;
-  virtual void VisitCollection(Collection*) override;
+  void VisitValue(Value*) override;
+  void VisitRawPtr(RawPtr*) override;
+  void VisitRefPtr(RefPtr*) override;
+  void VisitOwnPtr(OwnPtr*) override;
+  void VisitMember(Member*) override;
+  void VisitWeakMember(WeakMember*) override;
+  void VisitPersistent(Persistent*) override;
+  void VisitCollection(Collection*) override;
 
  protected:
   typedef std::deque<Edge*> Context;
diff --git a/tools/clang/blink_gc_plugin/JsonWriter.h b/tools/clang/blink_gc_plugin/JsonWriter.h
index 54a87aa..09504b3 100644
--- a/tools/clang/blink_gc_plugin/JsonWriter.h
+++ b/tools/clang/blink_gc_plugin/JsonWriter.h
@@ -7,66 +7,75 @@
 
 #include "llvm/Support/raw_ostream.h"
 
+// TODO(hans): Remove this #ifdef after Clang is rolled past r234897.
+#ifdef LLVM_FORCE_HEAD_REVISION
+#define JSON_WRITER_STREAM std::unique_ptr<llvm::raw_ostream>
+#else
+#define JSON_WRITER_STREAM llvm::raw_fd_ostream*
+#endif
+
 // Helper to write information for the points-to graph.
 class JsonWriter {
  public:
-  static JsonWriter* from(llvm::raw_fd_ostream* os) {
-    return os ? new JsonWriter(os) : 0;
+  static JsonWriter* from(JSON_WRITER_STREAM os) {
+    return os ? new JsonWriter(std::move(os)) : 0;
   }
+#ifndef LLVM_FORCE_HEAD_REVISION
   ~JsonWriter() {
-    os_.close();
+    delete os_;
   }
+#endif
   void OpenList() {
     Separator();
-    os_ << "[";
+    *os_ << "[";
     state_.push(false);
   }
   void OpenList(const std::string key) {
     Write(key);
-    os_ << ":";
+    *os_ << ":";
     OpenList();
   }
   void CloseList() {
-    os_ << "]";
+    *os_ << "]";
     state_.pop();
   }
   void OpenObject() {
     Separator();
-    os_ << "{";
+    *os_ << "{";
     state_.push(false);
   }
   void CloseObject() {
-    os_ << "}\n";
+    *os_ << "}\n";
     state_.pop();
   }
   void Write(const size_t val) {
     Separator();
-    os_ << val;
+    *os_ << val;
   }
   void Write(const std::string val) {
     Separator();
-    os_ << "\"" << val << "\"";
+    *os_ << "\"" << val << "\"";
   }
   void Write(const std::string key, const size_t val) {
     Separator();
-    os_ << "\"" << key << "\":" << val;
+    *os_ << "\"" << key << "\":" << val;
   }
   void Write(const std::string key, const std::string val) {
     Separator();
-    os_ << "\"" << key << "\":\"" << val << "\"";
+    *os_ << "\"" << key << "\":\"" << val << "\"";
   }
  private:
-  JsonWriter(llvm::raw_fd_ostream* os) : os_(*os) {}
+  JsonWriter(JSON_WRITER_STREAM os) : os_(std::move(os)) {}
   void Separator() {
     if (state_.empty())
       return;
     if (state_.top()) {
-      os_ << ",";
+      *os_ << ",";
       return;
     }
     state_.top() = true;
   }
-  llvm::raw_fd_ostream& os_;
+  JSON_WRITER_STREAM os_;
   std::stack<bool> state_;
 };
 
diff --git a/tools/clang/plugins/CMakeLists.txt b/tools/clang/plugins/CMakeLists.txt
index d17de19..e4eea86 100644
--- a/tools/clang/plugins/CMakeLists.txt
+++ b/tools/clang/plugins/CMakeLists.txt
@@ -1,15 +1,33 @@
-add_llvm_loadable_module(libFindBadConstructs
-                         ChromeClassTester.cpp
-                         FindBadConstructsAction.cpp
-                         FindBadConstructsConsumer.cpp
-                        )
+set(plugin_sources
+  ChromeClassTester.cpp
+  FindBadConstructsAction.cpp
+  FindBadConstructsConsumer.cpp)
 
-add_dependencies(libFindBadConstructs clang)
+if(WIN32)
+  # Clang doesn't support loadable modules on Windows. Unfortunately, building
+  # the plugin as a static library and linking clang against it doesn't work.
+  # Since clang doesn't reference any symbols in our static library, the linker
+  # strips it out completely.
+  # Instead, we rely on the fact that the SOURCES property of a target is no
+  # read-only after CMake 3.1 and use it to compile the plugin directly into
+  # clang...
+  cmake_minimum_required(VERSION 3.1)
+  # Paths must be absolute, since we're modifying a target in another directory.
+  set(absolute_sources "")
+  foreach(source ${plugin_sources})
+    list(APPEND absolute_sources ${CMAKE_CURRENT_SOURCE_DIR}/${source})
+  endforeach()
+  set_property(TARGET clang APPEND PROPERTY SOURCES ${absolute_sources})
+else()
+  add_llvm_loadable_module(libFindBadConstructs ${plugin_sources})
+  add_dependencies(libFindBadConstructs clang)
 
-cr_install(TARGETS libFindBadConstructs LIBRARY DESTINATION lib)
+  cr_install(TARGETS libFindBadConstructs LIBRARY DESTINATION lib)
 
-cr_add_test(plugins_test
-  ${CMAKE_CURRENT_SOURCE_DIR}/tests/test.sh
-  ${CMAKE_BINARY_DIR}/bin/clang
-  $<TARGET_FILE:libFindBadConstructs>
-  )
+  # TODO(dcheng): Rewrite the test framework so it works on Windows too.
+  cr_add_test(plugins_test
+    ${CMAKE_CURRENT_SOURCE_DIR}/tests/test.sh
+    ${CMAKE_BINARY_DIR}/bin/clang
+    $<TARGET_FILE:libFindBadConstructs>
+    )
+endif()
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index 48d6a73..931da02 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -7,26 +7,20 @@
 
 #include "ChromeClassTester.h"
 
-#include <sys/param.h>
+#include <algorithm>
 
 #include "clang/AST/AST.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 
+#ifdef LLVM_ON_UNIX
+#include <sys/param.h>
+#endif
+
 using namespace clang;
 
 namespace {
 
-bool starts_with(const std::string& one, const std::string& two) {
-  return one.compare(0, two.size(), two) == 0;
-}
-
-std::string lstrip(const std::string& one, const std::string& two) {
-  if (starts_with(one, two))
-    return one.substr(two.size());
-  return one;
-}
-
 bool ends_with(const std::string& one, const std::string& two) {
   if (two.size() > one.size())
     return false;
@@ -101,14 +95,67 @@
   std::string err;
   err = "[chromium-style] ";
   err += raw_error;
+  // TODO(dcheng): Re-enable -Werror for these diagnostics on Windows once all
+  // the pre-existing warnings are cleaned up. https://crbug.com/467287
   DiagnosticIDs::Level level =
+#if !defined(LLVM_ON_WIN32)
       diagnostic().getWarningsAsErrors() ?
       DiagnosticIDs::Error :
+#endif
       DiagnosticIDs::Warning;
   unsigned id = diagnostic().getDiagnosticIDs()->getCustomDiagID(level, err);
   DiagnosticBuilder builder = diagnostic().Report(full, id);
 }
 
+bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
+  if (instance().getSourceManager().isInSystemHeader(loc))
+    return true;
+
+  std::string filename;
+  if (!GetFilename(loc, &filename)) {
+    // If the filename cannot be determined, simply treat this as a banned
+    // location, instead of going through the full lookup process.
+    return true;
+  }
+
+  // We need to special case scratch space; which is where clang does its
+  // macro expansion. We explicitly want to allow people to do otherwise bad
+  // things through macros that were defined due to third party libraries.
+  if (filename == "<scratch space>")
+    return true;
+
+  // Don't complain about autogenerated protobuf files.
+  if (ends_with(filename, ".pb.h")) {
+    return true;
+  }
+
+#if defined(LLVM_ON_UNIX)
+  // We need to munge the paths so that they are relative to the repository
+  // srcroot. We first resolve the symlinktastic relative path and then
+  // remove our known srcroot from it if needed.
+  char resolvedPath[MAXPATHLEN];
+  if (realpath(filename.c_str(), resolvedPath)) {
+    filename = resolvedPath;
+  }
+#endif
+
+#if defined(LLVM_ON_WIN32)
+  std::replace(filename.begin(), filename.end(), '\\', '/');
+#endif
+
+  for (const std::string& banned_dir : banned_directories_) {
+    // If any of the banned directories occur as a component in filename,
+    // this file is rejected.
+    assert(banned_dir.front() == '/' && "Banned dir must start with '/'");
+    assert(banned_dir.back() == '/' && "Banned dir must end with '/'");
+
+    if (filename.find(banned_dir) != std::string::npos)
+      return true;
+  }
+
+  return false;
+}
+
 bool ChromeClassTester::InBannedNamespace(const Decl* record) {
   std::string n = GetNamespace(record);
   if (!n.empty()) {
@@ -239,47 +286,6 @@
   }
 }
 
-bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
-  std::string filename;
-  if (!GetFilename(loc, &filename)) {
-    // If the filename cannot be determined, simply treat this as a banned
-    // location, instead of going through the full lookup process.
-    return true;
-  }
-
-  // We need to special case scratch space; which is where clang does its
-  // macro expansion. We explicitly want to allow people to do otherwise bad
-  // things through macros that were defined due to third party libraries.
-  if (filename == "<scratch space>")
-    return true;
-
-  // Don't complain about autogenerated protobuf files.
-  if (ends_with(filename, ".pb.h")) {
-    return true;
-  }
-
-  // We need to munge the paths so that they are relative to the repository
-  // srcroot. We first resolve the symlinktastic relative path and then
-  // remove our known srcroot from it if needed.
-  char resolvedPath[MAXPATHLEN];
-  if (realpath(filename.c_str(), resolvedPath)) {
-    filename = resolvedPath;
-  }
-
-  for (size_t i = 0; i < banned_directories_.size(); ++i) {
-    // If any of the banned directories occur as a component in filename,
-    // this file is rejected.
-    const std::string& banned_dir = banned_directories_[i];
-    assert(banned_dir.front() == '/' && "Banned dir must start with '/'");
-    assert(banned_dir.back() == '/' && "Banned dir must end with '/'");
-
-    if (filename.find(banned_dir) != std::string::npos)
-      return true;
-  }
-
-  return false;
-}
-
 bool ChromeClassTester::IsIgnoredType(const std::string& base_name) {
   return ignored_record_names_.find(base_name) != ignored_record_names_.end();
 }
diff --git a/tools/clang/plugins/ChromeClassTester.h b/tools/clang/plugins/ChromeClassTester.h
index 963b90f..ed65050 100644
--- a/tools/clang/plugins/ChromeClassTester.h
+++ b/tools/clang/plugins/ChromeClassTester.h
@@ -37,6 +37,10 @@
   // namespace.
   bool InBannedNamespace(const clang::Decl* record);
 
+  // Utility method for subclasses to check if the source location is in a
+  // directory the plugin should ignore.
+  bool InBannedDirectory(clang::SourceLocation loc);
+
   // Utility method for subclasses to determine the namespace of the
   // specified record, if any. Unnamed namespaces will be identified as
   // "<anonymous namespace>".
@@ -64,7 +68,6 @@
   // deliberately ignore) in HandleTagDeclDefinition().
   std::string GetNamespaceImpl(const clang::DeclContext* context,
                                const std::string& candidate);
-  bool InBannedDirectory(clang::SourceLocation loc);
   bool IsIgnoredType(const std::string& base_name);
 
   // Attempts to determine the filename for the given SourceLocation.
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
index 770e255..20919a4 100644
--- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
+++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -70,14 +70,15 @@
   return decl->getQualifiedNameAsString() == "testing::Test";
 }
 
+// Generates a fixit hint to remove the 'virtual' keyword.
+// Unfortunately, there doesn't seem to be a good way to determine the source
+// location of the 'virtual' keyword. It's available in Declarator, but that
+// isn't accessible from the AST. So instead, make an educated guess that the
+// first token is probably the virtual keyword. Strictly speaking, this doesn't
+// have to be true, but it probably will be.
+// TODO(dcheng): Add a warning to force virtual to always appear first ;-)
 FixItHint FixItRemovalForVirtual(const SourceManager& manager,
                                  const CXXMethodDecl* method) {
-  // Unfortunately, there doesn't seem to be a good way to determine the
-  // location of the 'virtual' keyword. It's available in Declarator, but that
-  // isn't accessible from the AST. So instead, make an educated guess that the
-  // first token is probably the virtual keyword. Strictly speaking, this
-  // doesn't have to be true, but it probably will be.
-  // TODO(dcheng): Add a warning to force virtual to always appear first ;-)
   SourceRange range(method->getLocStart());
   // Get the spelling loc just in case it was expanded from a macro.
   SourceRange spelling_range(manager.getSpellingLoc(range.getBegin()));
@@ -413,32 +414,68 @@
 
   // Complain if a method is annotated virtual && (override || final).
   if (has_virtual && (override_attr || final_attr)) {
-    diagnostic().Report(method->getLocStart(),
-                        diag_redundant_virtual_specifier_)
-        << "'virtual'"
-        << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
-        << FixItRemovalForVirtual(manager, method);
+    // ... but only if virtual does not originate in a macro from a banned file.
+    // Note this is just an educated guess: the assumption here is that any
+    // macro for declaring methods will probably be at the start of the method's
+    // source range.
+    if (!InBannedDirectory(manager.getSpellingLoc(method->getLocStart()))) {
+      diagnostic().Report(method->getLocStart(),
+                          diag_redundant_virtual_specifier_)
+          << "'virtual'"
+          << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
+          << FixItRemovalForVirtual(manager, method);
+    }
   }
 
   // Complain if a method is an override and is not annotated with override or
   // final.
   if (is_override && !override_attr && !final_attr) {
-    SourceRange type_info_range =
-        method->getTypeSourceInfo()->getTypeLoc().getSourceRange();
-    FullSourceLoc loc(type_info_range.getBegin(), manager);
-
-    // Build the FixIt insertion point after the end of the method definition,
-    // including any const-qualifiers and attributes, and before the opening
-    // of the l-curly-brace (if inline) or the semi-color (if a declaration).
-    SourceLocation spelling_end =
-        manager.getSpellingLoc(type_info_range.getEnd());
-    if (spelling_end.isValid()) {
-      SourceLocation token_end =
-          Lexer::getLocForEndOfToken(spelling_end, 0, manager, LangOptions());
-      diagnostic().Report(token_end, diag_method_requires_override_)
-          << FixItHint::CreateInsertion(token_end, " override");
+    SourceRange range = method->getSourceRange();
+    SourceLocation loc;
+    if (method->hasInlineBody()) {
+      loc = method->getBody()->getSourceRange().getBegin();
     } else {
-      diagnostic().Report(loc, diag_method_requires_override_);
+      // TODO(dcheng): We should probably use ASTContext's LangOptions here.
+      LangOptions lang_options;
+      loc = Lexer::getLocForEndOfToken(
+          manager.getSpellingLoc(range.getEnd()), 0,
+          manager, lang_options);
+      // The original code used the ending source loc of TypeSourceInfo's
+      // TypeLoc. Unfortunately, this breaks down in the presence of attributes.
+      // Attributes often appear at the end of a TypeLoc, e.g.
+      //   virtual ULONG __stdcall AddRef()
+      // has a TypeSourceInfo that looks something like:
+      //   ULONG AddRef() __attribute(stdcall)
+      // so a fix-it insertion would be generated to insert 'override' after
+      // __stdcall in the code as written.
+      // While using the spelling loc of the CXXMethodDecl fixes attribute
+      // handling, it breaks handling of "= 0" and similar constructs.. To work
+      // around this, scan backwards in the source text for a '=' or ')' token
+      // and adjust the location as needed...
+      for (SourceLocation l = loc.getLocWithOffset(-1);
+           l != manager.getLocForStartOfFile(manager.getFileID(loc));
+           l = l.getLocWithOffset(-1)) {
+        l = Lexer::GetBeginningOfToken(l, manager, lang_options);
+        Token token;
+        // getRawToken() returns *true* on failure. In that case, just give up
+        // and don't bother generating a possibly incorrect fix-it.
+        if (Lexer::getRawToken(l, token, manager, lang_options, true)) {
+          loc = SourceLocation();
+          break;
+        }
+        if (token.is(tok::r_paren)) {
+          break;
+        } else if (token.is(tok::equal)) {
+          loc = l;
+          break;
+        }
+      }
+    }
+    if (loc.isValid()) {
+      diagnostic().Report(loc, diag_method_requires_override_)
+          << FixItHint::CreateInsertion(loc, " override");
+    } else {
+      diagnostic().Report(range.getBegin(), diag_method_requires_override_);
     }
   }
 
@@ -559,8 +596,14 @@
 // Adds either a warning or error, based on the current handling of
 // -Werror.
 DiagnosticsEngine::Level FindBadConstructsConsumer::getErrorLevel() {
+#if defined(LLVM_ON_WIN32)
+  // TODO(dcheng): Re-enable -Werror for these diagnostics on Windows once all
+  // the pre-existing warnings are cleaned up. https://crbug.com/467287
+  return DiagnosticsEngine::Warning;
+#else
   return diagnostic().getWarningsAsErrors() ? DiagnosticsEngine::Error
                                             : DiagnosticsEngine::Warning;
+#endif
 }
 
 // Returns true if |base| specifies one of the Chromium reference counted
diff --git a/tools/clang/plugins/tests/overridden_methods.txt b/tools/clang/plugins/tests/overridden_methods.txt
index 69ff2b1..bc2d1ac 100644
--- a/tools/clang/plugins/tests/overridden_methods.txt
+++ b/tools/clang/plugins/tests/overridden_methods.txt
@@ -1,82 +1,82 @@
 In file included from overridden_methods.cpp:5:
-./overridden_methods.h:25:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+./overridden_methods.h:25:29: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethod() = 0;
-                           ^
-                            override
-./overridden_methods.h:46:26: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                            ^
+                             override
+./overridden_methods.h:46:27: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual ~DerivedClass() {}
-                         ^
-                          override
+                          ^
+                           override
 ./overridden_methods.h:48:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethod();
                            ^
                             override
-./overridden_methods.h:52:34: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+./overridden_methods.h:52:35: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeInlineMethod() {}
-                                 ^
-                                  override
-./overridden_methods.h:56:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                  ^
+                                   override
+./overridden_methods.h:56:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeConstMethod() const {}
-                                      ^
-                                       override
-./overridden_methods.h:58:55: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                       ^
+                                        override
+./overridden_methods.h:58:54: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethodWithExceptionSpec() throw() {}
-                                                      ^
-                                                       override
-./overridden_methods.h:61:69: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                                     ^
+                                                      override
+./overridden_methods.h:61:68: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeConstMethodWithExceptionSpec() const throw(int) {}
-                                                                    ^
-                                                                     override
-./overridden_methods.h:63:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                                                   ^
+                                                                    override
+./overridden_methods.h:63:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeNonPureBaseMethod() {}
-                                      ^
-                                       override
+                                       ^
+                                        override
 ./overridden_methods.h:65:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethodWithComment();  // This is a comment.
                                       ^
                                        override
-./overridden_methods.h:67:46: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+./overridden_methods.h:67:47: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethodWithCommentAndBody() {}  // This is a comment.
-                                             ^
-                                              override
-overridden_methods.cpp:15:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                              ^
+                                               override
+overridden_methods.cpp:15:29: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethod() = 0;
-                           ^
-                            override
-overridden_methods.cpp:22:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                            ^
+                             override
+overridden_methods.cpp:22:41: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual ~ImplementationDerivedClass() {}
-                                       ^
-                                        override
+                                        ^
+                                         override
 overridden_methods.cpp:24:28: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethod();
                            ^
                             override
-overridden_methods.cpp:28:34: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+overridden_methods.cpp:28:35: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeInlineMethod() {}
-                                 ^
-                                  override
-overridden_methods.cpp:32:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                  ^
+                                   override
+overridden_methods.cpp:32:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeConstMethod() const {}
-                                      ^
-                                       override
-overridden_methods.cpp:34:55: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                       ^
+                                        override
+overridden_methods.cpp:34:54: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethodWithExceptionSpec() throw() {}
-                                                      ^
-                                                       override
-overridden_methods.cpp:37:69: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                                     ^
+                                                      override
+overridden_methods.cpp:37:68: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeConstMethodWithExceptionSpec() const throw(int) {}
-                                                                    ^
-                                                                     override
-overridden_methods.cpp:39:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                                                                   ^
+                                                                    override
+overridden_methods.cpp:39:40: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeNonPureBaseMethod() {}
-                                      ^
-                                       override
+                                       ^
+                                        override
 overridden_methods.cpp:41:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethodWithComment();  // This is a comment.
                                       ^
                                        override
-overridden_methods.cpp:43:46: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+overridden_methods.cpp:43:47: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void SomeMethodWithCommentAndBody() {}  // This is a comment.
-                                             ^
-                                              override
+                                              ^
+                                               override
 20 warnings generated.
diff --git a/tools/clang/plugins/tests/system/windows.h b/tools/clang/plugins/tests/system/windows.h
new file mode 100644
index 0000000..f93d5e2
--- /dev/null
+++ b/tools/clang/plugins/tests/system/windows.h
@@ -0,0 +1,10 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_CLANG_PLUGINS_TESTS_SYSTEM_WINDOWS_H_
+#define TOOLS_CLANG_PLUGINS_TESTS_SYSTEM_WINDOWS_H_
+
+#define STDMETHOD(x) virtual void x
+
+#endif  // TOOLS_CLANG_PLUGINS_TESTS_SYSTEM_WINDOWS_H_
diff --git a/tools/clang/plugins/tests/test.sh b/tools/clang/plugins/tests/test.sh
index ea21054..cf26252 100755
--- a/tools/clang/plugins/tests/test.sh
+++ b/tools/clang/plugins/tests/test.sh
@@ -12,6 +12,8 @@
 
 failed_any_test=
 
+THIS_DIR="$(dirname "${0}")"
+
 # Prints usage information.
 usage() {
   echo "Usage: $(basename "${0}")" \
@@ -38,6 +40,7 @@
 
   local output="$("${CLANG_PATH}" -fsyntax-only -Wno-c++11-extensions \
       -Wno-inconsistent-missing-override \
+      -isystem ${THIS_DIR}/system \
       -Xclang -load -Xclang "${PLUGIN_PATH}" \
       -Xclang -add-plugin -Xclang find-bad-constructs ${flags} ${1} 2>&1)"
   local diffout="$(echo "${output}" | diff - "${2}")"
@@ -81,7 +84,7 @@
 
   # The golden files assume that the cwd is this directory. To make the script
   # work no matter what the cwd is, explicitly cd to there.
-  cd "$(dirname "${0}")"
+  cd "${THIS_DIR}"
 fi
 
 for input in *.cpp; do
diff --git a/tools/clang/plugins/tests/virtual_specifiers.cpp b/tools/clang/plugins/tests/virtual_specifiers.cpp
index 28321e8..2103248 100644
--- a/tools/clang/plugins/tests/virtual_specifiers.cpp
+++ b/tools/clang/plugins/tests/virtual_specifiers.cpp
@@ -5,6 +5,8 @@
 // Tests for chromium style checks for virtual/override/final specifiers on
 // virtual methods.
 
+#include <windows.h>
+
 // Purposely use macros to test that the FixIt hints don't try to remove the
 // macro body.
 #define OVERRIDE override
@@ -79,7 +81,13 @@
   virtual void F() override = 0;
 };
 
-// Finally, some simple sanity tests that overrides in the testing namespace
+// Test that the redundant virtual warning is suppressed when the virtual
+// keyword comes from a macro in a system header.
+class COMIsAwesome : public Base {
+  STDMETHOD(F)() override = 0;
+};
+
+// Some tests that overrides in the testing namespace
 // don't trigger warnings, except for testing::Test.
 namespace testing {
 
diff --git a/tools/clang/plugins/tests/virtual_specifiers.txt b/tools/clang/plugins/tests/virtual_specifiers.txt
index a51236c..135ebdd 100644
--- a/tools/clang/plugins/tests/virtual_specifiers.txt
+++ b/tools/clang/plugins/tests/virtual_specifiers.txt
@@ -1,69 +1,69 @@
-virtual_specifiers.cpp:36:21: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+virtual_specifiers.cpp:38:22: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   ~MissingOverride() {}
-                    ^
-                     override
-virtual_specifiers.cpp:37:11: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                     ^
+                      override
+virtual_specifiers.cpp:39:12: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   void F() {}
-          ^
-           override
-virtual_specifiers.cpp:43:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+           ^
+            override
+virtual_specifiers.cpp:45:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
   virtual ~VirtualAndOverride() OVERRIDE {}
   ^~~~~~~~
-virtual_specifiers.cpp:44:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:46:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
   virtual void F() OVERRIDE {}
   ^~~~~~~~
-virtual_specifiers.cpp:49:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
+virtual_specifiers.cpp:51:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
   virtual ~VirtualAndFinal() FINAL {}
   ^~~~~~~~
-virtual_specifiers.cpp:50:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
+virtual_specifiers.cpp:52:3: warning: [chromium-style] 'virtual' is redundant; 'final' implies 'virtual'.
   virtual void F() FINAL {}
   ^~~~~~~~
-virtual_specifiers.cpp:55:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:57:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
   virtual ~VirtualAndOverrideFinal() OVERRIDE FINAL {}
   ^~~~~~~~
-virtual_specifiers.cpp:55:38: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:57:38: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
   virtual ~VirtualAndOverrideFinal() OVERRIDE FINAL {}
                                      ^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
 #define OVERRIDE override
                  ^
-virtual_specifiers.cpp:56:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:58:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
   virtual void F() OVERRIDE FINAL {}
   ^~~~~~~~
-virtual_specifiers.cpp:56:20: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:58:20: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
   virtual void F() OVERRIDE FINAL {}
                    ^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
 #define OVERRIDE override
                  ^
-virtual_specifiers.cpp:61:23: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:63:23: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
   ~OverrideAndFinal() OVERRIDE FINAL {}
                       ^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
 #define OVERRIDE override
                  ^
-virtual_specifiers.cpp:62:12: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
+virtual_specifiers.cpp:64:12: warning: [chromium-style] 'override' is redundant; 'final' implies 'override'.
   void F() OVERRIDE FINAL {}
            ^~~~~~~~~
-virtual_specifiers.cpp:10:18: note: expanded from macro 'OVERRIDE'
+virtual_specifiers.cpp:12:18: note: expanded from macro 'OVERRIDE'
 #define OVERRIDE override
                  ^
-virtual_specifiers.cpp:67:19: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+virtual_specifiers.cpp:69:20: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual void F() = 0;
-                  ^
-                   override
-virtual_specifiers.cpp:71:11: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+                   ^
+                    override
+virtual_specifiers.cpp:73:12: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   void F() = 0;
-          ^
-           override
-virtual_specifiers.cpp:79:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+           ^
+            override
+virtual_specifiers.cpp:81:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
   virtual void F() override = 0;
   ^~~~~~~~
-virtual_specifiers.cpp:102:20: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
+virtual_specifiers.cpp:110:20: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'.
   virtual ~MyTest();
                    ^
                     override
-virtual_specifiers.cpp:103:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
+virtual_specifiers.cpp:111:3: warning: [chromium-style] 'virtual' is redundant; 'override' implies 'virtual'.
   virtual void SetUp() override;
   ^~~~~~~~
 17 warnings generated.
diff --git a/tools/clang/scripts/blink_gc_plugin_flags.sh b/tools/clang/scripts/blink_gc_plugin_flags.sh
index 38ea72d..96dcade 100755
--- a/tools/clang/scripts/blink_gc_plugin_flags.sh
+++ b/tools/clang/scripts/blink_gc_plugin_flags.sh
@@ -25,8 +25,10 @@
     FLAGS="$FLAGS $PREFIX warn-raw-ptr"
   elif [[ "$arg" = "warn-unneeded-finalizer=1" ]]; then
     FLAGS="$FLAGS $PREFIX warn-unneeded-finalizer"
+  elif [[ "$arg" = custom_clang_lib_path=* ]]; then
+    CLANG_LIB_PATH="$(cd "${arg#*=}" && echo $PWD)"
   fi
 done
 
-echo -Xclang -load -Xclang $CLANG_LIB_PATH/libBlinkGCPlugin.$LIBSUFFIX \
+echo -Xclang -load -Xclang \"$CLANG_LIB_PATH/libBlinkGCPlugin.$LIBSUFFIX\" \
   -Xclang -add-plugin -Xclang blink-gc-plugin $FLAGS
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 7c4a214..30d9ce9 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -6,6 +6,7 @@
 """Windows can't run .sh files, so this is a Python implementation of
 update.sh. This script should replace update.sh on all platforms eventually."""
 
+import argparse
 import os
 import re
 import shutil
@@ -24,12 +25,13 @@
 # in bringup. Use a pinned revision to make it slightly more stable.
 if (re.search(r'\b(asan)=1', os.environ.get('GYP_DEFINES', '')) and
     not 'LLVM_FORCE_HEAD_REVISION' in os.environ):
-  LLVM_WIN_REVISION = '232554'
+  LLVM_WIN_REVISION = '235793'
 
 # Path constants. (All of these should be absolute paths.)
 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
 CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
 LLVM_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm')
+CHROME_TOOLS_SHIM_DIR = os.path.join(LLVM_DIR, 'tools', 'chrometools')
 LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build',
                               'Release+Asserts')
 COMPILER_RT_BUILD_DIR = os.path.join(LLVM_BUILD_DIR, '32bit-compiler-rt')
@@ -129,6 +131,32 @@
   RunCommand(command)
 
 
+def DeleteChromeToolsShim():
+  shutil.rmtree(CHROME_TOOLS_SHIM_DIR, ignore_errors=True)
+
+
+def CreateChromeToolsShim():
+  """Hooks the Chrome tools into the LLVM build.
+
+  Several Chrome tools have dependencies on LLVM/Clang libraries. The LLVM build
+  detects implicit tools in the tools subdirectory, so this helper install a
+  shim CMakeLists.txt that forwards to the real directory for the Chrome tools.
+
+  Note that the shim directory name intentionally has no - or _. The implicit
+  tool detection logic munges them in a weird way."""
+  assert not any(i in os.path.basename(CHROME_TOOLS_SHIM_DIR) for i in '-_')
+  os.mkdir(CHROME_TOOLS_SHIM_DIR)
+  with file(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f:
+    f.write('# Automatically generated by tools/clang/scripts/update.py. ' +
+            'Do not edit.\n')
+    f.write('# Since tools/clang is located in another directory, use the \n')
+    f.write('# two arg version to specify where build artifacts go. CMake\n')
+    f.write('# disallows reuse of the same binary dir for multiple source\n')
+    f.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
+    f.write('add_subdirectory(${CHROMIUM_TOOLS_SRC} ' +
+            '${CMAKE_CURRENT_BINARY_DIR}/a)\n')
+
+
 def AddCMakeToPath():
   """Look for CMake and add it to PATH if it's not there already."""
   try:
@@ -181,30 +209,38 @@
   return ''
 
 
-def UpdateClang():
+def UpdateClang(args):
   print 'Updating Clang to %s...' % (LLVM_WIN_REVISION)
   if LLVM_WIN_REVISION != 'HEAD' and ReadStampFile() == LLVM_WIN_REVISION:
     print 'Already up to date.'
     return 0
 
   AddCMakeToPath()
-  ClobberChromiumBuildFiles()
+  if args.clobber:
+    ClobberChromiumBuildFiles()
 
   # Reset the stamp file in case the build is unsuccessful.
   WriteStampFile('')
 
+  DeleteChromeToolsShim();
   Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR)
   Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR)
   Checkout('LLD', LLVM_REPO_URL + '/lld/trunk', LLD_DIR)
   Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR)
+  CreateChromeToolsShim();
 
   if not os.path.exists(LLVM_BUILD_DIR):
     os.makedirs(LLVM_BUILD_DIR)
   os.chdir(LLVM_BUILD_DIR)
 
+  cmake_args = ['-GNinja', '-DCMAKE_BUILD_TYPE=Release',
+                '-DLLVM_ENABLE_ASSERTIONS=ON', SubversionCmakeArg(),
+                '-DCHROMIUM_TOOLS_SRC=%s' % os.path.join(
+                    CHROMIUM_DIR, 'tools', 'clang'),
+                '-DCHROMIUM_TOOLS=%s' % ';'.join(args.tools)]
+
   RunCommand(GetVSVersion().SetupScript('x64') +
-             ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release',
-              '-DLLVM_ENABLE_ASSERTIONS=ON', SubversionCmakeArg(), LLVM_DIR])
+             ['&&', 'cmake'] + cmake_args + [LLVM_DIR])
   RunCommand(GetVSVersion().SetupScript('x64') + ['&&', 'ninja', 'all'])
 
   # Do an x86 build of compiler-rt to get the 32-bit ASan run-time.
@@ -213,8 +249,7 @@
     os.makedirs(COMPILER_RT_BUILD_DIR)
   os.chdir(COMPILER_RT_BUILD_DIR)
   RunCommand(GetVSVersion().SetupScript('x86') +
-             ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release',
-              '-DLLVM_ENABLE_ASSERTIONS=ON', LLVM_DIR])
+             ['&&', 'cmake'] + cmake_args + [LLVM_DIR])
   RunCommand(GetVSVersion().SetupScript('x86') + ['&&', 'ninja', 'compiler-rt'])
 
   # TODO(hans): Make this (and the .gypi and .isolate files) version number
@@ -276,7 +311,13 @@
     print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).'
     return 0
 
-  return UpdateClang()
+  parser = argparse.ArgumentParser(description='Build Clang.')
+  parser.add_argument('--no-clobber', dest='clobber', action='store_false')
+  parser.add_argument('--tools', nargs='*', default=['plugins'])
+  # For now, this flag is only used for the non-Windows flow, but argparser gets
+  # mad if it sees a flag it doesn't recognize.
+  parser.add_argument('--if-needed', action='store_true')
+  return UpdateClang(parser.parse_args())
 
 
 if __name__ == '__main__':
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index 10a4645..f0dbeb0 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -11,7 +11,7 @@
 CLANG_REVISION=233105
 
 # This is incremented when pushing a new build of Clang at the same revision.
-CLANG_SUB_REVISION=1
+CLANG_SUB_REVISION=2
 
 PACKAGE_VERSION="${CLANG_REVISION}-${CLANG_SUB_REVISION}"
 
@@ -63,13 +63,6 @@
   PACKAGE_VERSION="${CLANG_REVISION}-0"
 fi
 
-# Use both the clang revision and the plugin revisions to test for updates.
-BLINKGCPLUGIN_REVISION=\
-$(grep 'set(LIBRARYNAME' "$THIS_DIR"/../blink_gc_plugin/CMakeLists.txt \
-    | cut -d ' ' -f 2 | tr -cd '[0-9]')
-CLANG_AND_PLUGINS_REVISION="${CLANG_REVISION}-${BLINKGCPLUGIN_REVISION}"
-
-
 OS="$(uname -s)"
 
 # Parse command line options.
@@ -190,14 +183,13 @@
     fi
   fi
 
-  if [[ "${OS}" == "Linux" ]]; then
-    # TODO(hans): Might need to make this work on Mac eventually.
+  if [[ "${OS}" == "Linux" || "${OS}" == "Darwin" ]]; then
     if [[ $(cmake --version | grep -Eo '[0-9.]+') < "3.0" ]]; then
       # We need a newer CMake version.
       if [[ ! -e "${LLVM_BUILD_TOOLS_DIR}/cmake310" ]]; then
         echo "Downloading pre-built CMake 3.10..."
         mkdir -p "${LLVM_BUILD_TOOLS_DIR}"
-        curl --fail -L "${CDS_URL}/tools/cmake310.tgz" | \
+        curl --fail -L "${CDS_URL}/tools/cmake310_${OS}.tgz" | \
           tar zxf - -C "${LLVM_BUILD_TOOLS_DIR}"
         echo Done
       fi
@@ -322,6 +314,7 @@
       "${CLANG_DIR}/test/SemaCXX/typo-correction-delayed.cpp" \
       "${COMPILER_RT_DIR}/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc" \
       "${COMPILER_RT_DIR}/test/tsan/signal_segv_handler.cc" \
+      "${COMPILER_RT_DIR}/lib/sanitizer_common/sanitizer_coverage_libcdep.cc" \
       ; do
   if [[ -e "${i}" ]]; then
     rm -f "${i}"  # For unversioned files.
@@ -404,6 +397,27 @@
   patch -p0
   popd
 
+  # Cherry-pick r234010 [sancov] Shrink pc array on Android back to 2**24."
+  pushd "${COMPILER_RT_DIR}"
+  cat << 'EOF' |
+diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+index 4b976fc..cfd9e7e 100644
+--- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
++++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+@@ -109,7 +109,8 @@ class CoverageData {
+ 
+   // Maximal size pc array may ever grow.
+   // We MmapNoReserve this space to ensure that the array is contiguous.
+-  static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 27);
++  static const uptr kPcArrayMaxSize =
++      FIRST_32_SECOND_64(1 << (SANITIZER_ANDROID ? 24 : 26), 1 << 27);
+   // The amount file mapping for the pc array is grown by.
+   static const uptr kPcArrayMmapSize = 64 * 1024;
+
+EOF
+  patch -p1
+  popd
+
   # This Go bindings test doesn't work after the bootstrap build on Linux. (PR21552)
   pushd "${LLVM_DIR}"
   cat << 'EOF' |
@@ -551,6 +565,14 @@
   BINUTILS_INCDIR="${ABS_BINUTILS_DIR}/Linux_x64/Release/include"
 fi
 
+
+# If building at head, define a macro that plugins can use for #ifdefing
+# out code that builds at head, but not at CLANG_REVISION or vice versa.
+if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+  CFLAGS="${CFLAGS} -DLLVM_FORCE_HEAD_REVISION"
+  CXXFLAGS="${CXXFLAGS} -DLLVM_FORCE_HEAD_REVISION"
+fi
+
 # Hook the Chromium tools into the LLVM build. Several Chromium tools have
 # dependencies on LLVM/Clang libraries. The LLVM build detects implicit tools
 # in the tools subdirectory, so install a shim CMakeLists.txt that forwards to
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index a64ae83..d56ba05 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -45,6 +45,9 @@
   "content/app/resources/content_resources.grd": {
     "structures": [4700],
   },
+  "third_party/WebKit/public/blink_image_resources.grd": {
+    "structures": [4750],
+  },
   "ui/resources/ui_resources.grd": {
     "structures": [5500],
   },
@@ -166,8 +169,11 @@
   },
   # iOS resources overlap with ash, chromeos and extensions_api, as these are
   # not used on iOS.
+  "ios/chrome/app/strings/ios_strings_resources.grd": {
+    "messages": [26000],
+  },
   "ios/chrome/app/theme/ios_theme_resources.grd": {
-    "structures": [26000],
+    "structures": [27000],
   },
   "ash/ash_strings.grd": {
     "messages": [26000],
@@ -237,10 +243,11 @@
     "includes": [30250],
   },
   "components/resources/components_scaled_resources.grd": {
-    "structures": [30350],
+    "structures": [30280],
   },
   "third_party/WebKit/public/blink_resources.grd": {
-    "includes": [30500],
+    "includes": [30350],
+    "structures": [30650],
   },
   "chrome/browser/devtools/device/webrtc/resources.grd": {
     "includes": [30800],
diff --git a/tools/valgrind/.gitignore b/tools/valgrind/.gitignore
new file mode 100644
index 0000000..a77c220
--- /dev/null
+++ b/tools/valgrind/.gitignore
@@ -0,0 +1,2 @@
+buildlogs.tmp
+waterfall.tmp
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 554beb3..e8074f3 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -568,7 +568,7 @@
                   # http://crbug.com/176908: Don't launch a browser when done.
                   "--no-show-results",
                   "--nocheck-sys-deps",
-                  "--additional-drt-flag=--no-sandbox"]
+                  "--additional-driver-flag=--no-sandbox"]
     # Pass build mode to run-webkit-tests.  We aren't passed it directly,
     # so parse it out of build_dir.  run-webkit-tests can only handle
     # the two values "Release" and "Debug".
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt
index 4e084a7..e54404b 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -478,10 +478,8 @@
 name=http://crbug.com/371368
 system call NtCreateNamedPipeFile
 KERNELBASE.dll!CreateNamedPipeW
-ipc.dll!IPC::Channel::ChannelImpl::CreatePipe
-ipc.dll!IPC::Channel::ChannelImpl::ChannelImpl
-ipc.dll!IPC::Channel::Channel
-ipc.dll!IPC::ChannelProxy::Context::CreateChannel
+ipc.dll!IPC::ChannelWin::CreatePipe
+ipc.dll!IPC::ChannelWin::ChannelWin
 
 HANDLE LEAK
 name=http://crbug.com/371942
@@ -755,7 +753,24 @@
 name=http://crbug.com/463261
 ...
 blink_web.dll!blink::WebFrameWidgetImpl::selectionBounds
-content.dll!content::RenderWidget::GetSelectionBounds
+...
 content.dll!content::RenderWidget::UpdateSelectionBounds
 content.dll!content::RenderWidget::willBeginCompositorFrame
 cc.dll!base::internal::InvokeHelper<>::MakeItSo
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/476586
+*!blink::WebFrameWidgetImpl::beginFrame
+*!content::RenderWidgetCompositor::BeginMainFrame
+*!cc::LayerTreeHost::BeginMainFrame
+*!cc::ThreadProxy::BeginMainFrame
+*!base::internal::InvokeHelper<>::MakeItSo
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/476586b
+*!blink::PageWidgetDelegate::animate
+*!blink::WebFrameWidgetImpl::beginFrame
+*!content::RenderWidgetCompositor::BeginMainFrame
+*!cc::LayerTreeHost::BeginMainFrame
+*!cc::ThreadProxy::BeginMainFrame
+*!base::internal::InvokeHelper<>::MakeItSo
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index 81fcb31..b48c199 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1916,10 +1916,36 @@
 *!encode_nonrd_sb_row
 *!vp9_encode_tile
 
+UNADDRESSABLE ACCESS
+name=bug_470055
+blink_web.dll!blink::*::focused*Frame
+blink_web.dll!blink::WebFrameWidgetImpl::selectionBounds
+content.dll!content::RenderWidget::UpdateSelectionBounds
+content.dll!content::RenderWidget::willBeginCompositorFrame
+
 UNINITIALIZED READ
-name=bug_468638
-*!egl::ConfigSorter::operator()
-*!std::_Insertion_sort1<>
-*!std::_Sort<>
-*!egl::ConfigSet::filter
-*!ConfigSetTest_*_BitSizes_Test::TestBody
+name=bug_470848
+blink_platform.dll!blink::Heap::RegionTree::lookup
+*!testing::internal::HandleExceptionsInMethodIfSupported<>
+
+HANDLE LEAK
+name=https://crbug.com/480741
+system call NtDuplicateObject
+KERNELBASE.dll!DuplicateHandle
+KERNEL32.dll!DuplicateHandle
+base.dll!base::SharedMemory::ShareToProcessCommon
+gl_wrapper.dll!gfx::GLImageSharedMemory::Initialize
+content.dll!content::GpuChannel::CreateImageForGpuMemoryBuffer
+content.dll!content::GpuCommandBufferStub::OnCreateImage
+
+HANDLE LEAK
+name=https://crbug.com/481305
+system call NtCreateSection
+KERNELBASE.dll!CreateFileMappingW
+base.dll!base::SharedMemory::Create
+base.dll!base::SharedMemory::CreateAnonymous
+content.dll!content::ChildThreadImpl::AllocateSharedMemory
+content.dll!content::RenderThreadImpl::HostAllocateSharedMemoryBuffer
+content.dll!content::RenderThreadImpl::AllocateSharedMemory
+...
+content.dll!content::WebGraphicsContext3DCommandBufferImpl::CreateContext
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
index cc442bc..ec243c5 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
@@ -36,3 +36,5 @@
 # so we can avoid excluding this for light mode.
 MessageLoopTestTypeUI.RecursiveDenial3
 
+# https://crbug.com/481231
+WinHeapDumpProviderTest.DumpInto
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
index 937bf28..ee2d424 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
@@ -18,3 +18,6 @@
 MessageLoopTestTypeUI.RecursivePosts
 MessageLoopTestTypeIO.RecursivePosts
 MessageLoopTestTypeDefault.RecursivePosts
+
+# Check-fails on Valgrind/Mac, see https://crbug.com/481290
+MessagePumpLibeventTest.QuitWatcher
diff --git a/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt b/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt
new file mode 100644
index 0000000..c080b7a
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt
@@ -0,0 +1,3 @@
+# https://crbug.com/480650: fails
+HarfBuzzShaperTest.ResolveCandidateRunsLatin
+HarfBuzzShaperTest.ResolveCandidateRunsLeadingCommon
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
index 371b4bf..6823027 100644
--- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -30,3 +30,8 @@
 # http://crbug.com/459000
 ClipboardApiTest.HostedAppNoPermission
 
+# http://crbug.com/475172
+BasicExtensionSettingsWebUITest.testUninstall 
+
+# https://crbug.com/480721
+OutOfProcessProxyResolverBrowserTest.Verify
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
index f5dcbb0..b5e2b57 100644
--- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
@@ -137,6 +137,8 @@
 Pe*
 Plat*Bro*
 Policy*H*
+# PopupBlockerBrowserTest.TapGestureWithCtrlKey
+Pop*
 Port*
 Prefe*
 PrefsF*
@@ -177,7 +179,8 @@
 SRC*.Fr*
 SSL*ed
 Sup*Mo*
-Str*
+# StartupBrowserCreatorTest.ProfilesLaunchedAfterCrash
+St*orTest.*
 SyncF*
 SyncInt*
 Sys*Di*
diff --git a/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
index 5a76d89..7946e97 100644
--- a/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
@@ -10,6 +10,8 @@
 # http://crbug.com/416643
 LayerTreeHostCopyRequestTestMultipleRequests.GLRenderer_RunSingleThread
 LayerTreeHostCopyRequestTestMultipleRequests.SoftwareRenderer_RunSingleThread
+LayerTreeHostTestReadyToDrawNonEmpty.*
+LayerTreeHostTestMaxTransferBufferUsageBytes.*
 
 # http://crbug.com/430400
 PixelResourceTest*
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
index 2ec3183..55df649 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -28,6 +28,7 @@
 
 # http://crbug.com/456131
 BrowserSideNavigationBrowserTest.BrowserInitiatedNavigations
+BrowserSideNavigationBrowserTest.FailedNavigation
 
 # http://crbug.com/464029
 WebRtcBrowserTest.CallAndModifyStream
@@ -35,3 +36,6 @@
 # http://crbug.com/464033
 RenderFrameHostImplBrowserTest.IsFocused_AtLoad
 RenderFrameHostImplBrowserTest.IsFocused_Widget
+
+# http://crbug.com/470507
+SRC_ClearKey/EncryptedMediaTest.Playback_VideoClearAudio_WebM/0
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
index 664400d..0e91022 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
@@ -16,6 +16,7 @@
 Http/MediaTest.VideoTulipWebm/0
 IndexedDBBrowserTest.DeleteCompactsBackingStore
 MSE_ClearKey/EncryptedMediaTest.FrameSizeChangeVideo/0
+MSE_ClearKey/EncryptedMediaTest.Playback_VideoAudio_WebM/0
 OutOfProcessPPAPITest.MediaStreamAudioTrack
 OutOfProcessPPAPITest.NetworkProxy
 OutOfProcessPPAPITest.VideoDecoder
@@ -51,3 +52,6 @@
 WebRtcBrowserTest.CanSetupVideoCallWith4To3AspectRatio
 WebRtcBrowserTest.NegotiateOfferWithBLine
 WebRtcBrowserTest.CanMakeAudioCallAndThenRenegotiateToVideo
+
+# https://crbug.com/480750
+MSE_ClearKey/EncryptedMediaTest.Playback_AudioClearVideo_WebM/0
diff --git a/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory.txt
new file mode 100644
index 0000000..d73c572
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory.txt
@@ -0,0 +1,2 @@
+# http://crbug.com/470517
+VideoRendererImplTest.Underflow
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
index d804f42..6e8f352 100644
--- a/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
@@ -82,3 +82,6 @@
 
 # http://crbug.com/467004
 SigninErrorNotifierTest.NoErrorAuthStatusProviders
+
+# http://crbug.com/473689
+ManagePasswordsBubbleModelTest.CloseWithoutLogging
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
index fa0595b..bae79ce 100644
--- a/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
+++ b/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
@@ -13,3 +13,9 @@
 
 # Test fail: crbug.com/314216
 ExtensionIconManagerTest.LoadComponentExtensionResource
+
+# Test fail: crbug.com/473689
+ManagePasswordsBubbleModelTest.CloseWithoutLogging
+
+# Test fail: crbug.com/476731
+PluginInfoMessageFilterTest.FindEnabledPlugin
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 4374a72..56948ef 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -2961,9 +2961,8 @@
    fun:_Znw*
    fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
    fun:_ZN4base10WorkerPool16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_b
-   fun:_ZN3net16HostResolverImpl16LoopbackProbeJobC1ERKN4base7WeakPtrIS0_EE
-   fun:_ZN3net16HostResolverImplC1ERKNS_12HostResolver7OptionsEPNS_6NetLogE
-   fun:_ZN8chromeos24HostResolverImplChromeOSC1E13*
+   fun:_ZN3net16HostResolverImpl16LoopbackProbeJob*
+   fun:_ZN3net16HostResolverImplC*
 }
 {
    bug_387993
@@ -3012,7 +3011,7 @@
    bug_388668
    Memcheck:Leak
    fun:_Znw*
-   fun:_ZN20data_reduction_proxy69DataReductionProxyUsageStatsTest_isDataReductionProxyUnreachable_Test8TestBodyEv
+   fun:_ZN20data_reduction_proxy69DataReductionProxyBypassStatsTest_isDataReductionProxyUnreachable_Test8TestBodyEv
 }
 {
    bug_392912
@@ -3025,18 +3024,6 @@
    fun:_ZN14SkBitmapDevice8drawPathERK6SkDrawRK6SkPathRK7SkPaintPK8SkMatrixb
 }
 {
-   bug_392936
-   Memcheck:Leak
-   fun:_Znw*
-   fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
-   fun:_ZN4base10WorkerPool16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_b
-   fun:_ZN3net16HostResolverImpl16LoopbackProbeJobC2ERKN4base7WeakPtrIS0_EE
-   fun:_ZN3net16HostResolverImplC1ERKNS_12HostResolver7OptionsEPNS_6NetLogE
-   fun:_ZN8chromeos24HostResolverImplChromeOSC1E13scoped_refptrIN4base16MessageLoopProxyEEPNS_19NetworkStateHandlerERKN3net12HostResolver7OptionsEPNS7_6NetLogE
-   fun:_ZN8chromeos24HostResolverImplChromeOS25CreateHostResolverForTestE13scoped_refptrIN4base16MessageLoopProxyEEPNS_19NetworkStateHandlerE
-   fun:_ZN28HostResolverImplChromeOSTest22InitializeHostResolverEv
-}
-{
    bug_394558
    Memcheck:Leak
    fun:_Znw*
@@ -3629,9 +3616,6 @@
    Memcheck:Leak
    fun:_Znw*
    ...
-   fun:_ZN4mojo7BindingINS_15ServiceProviderEE4BindENS_16ScopedHandleBaseINS_17MessagePipeHandleEEEPK15MojoAsyncWaiter
-   fun:_ZN4mojo7BindingINS_15ServiceProviderEE4BindENS_16InterfaceRequestIS1_EEPK15MojoAsyncWaiter
-   fun:_ZN7content19ServiceRegistryImpl4BindEN4mojo16InterfaceRequestINS1_15ServiceProviderEEE
    fun:_ZN7content12_GLOBAL__N_120ApplicationSetupImpl24ExchangeServiceProvidersEN4mojo16InterfaceRequestINS2_15ServiceProviderEEENS2_12InterfacePtrIS4_EE
    fun:_ZN7content20ApplicationSetupStub6AcceptEPN4mojo7MessageE
    fun:_ZN4mojo8internal6Router21HandleIncomingMessageEPNS_7MessageE
@@ -3656,4 +3640,15 @@
    fun:_ZN4base12_GLOBAL__N_112WorkerThread10ThreadMainEv
    fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
 }
-
+{
+   bug_476940
+   Memcheck:Leak
+   fun:malloc
+   fun:_ZN3WTF9BitVector13OutOfLineBits6createEm
+   fun:_ZN3WTF9BitVector15resizeOutOfLineEm
+   fun:_ZN3WTF9BitVector10ensureSizeEm
+   fun:_ZN3WTF9BitVectorC2Em
+   fun:_ZN5blink10UseCounter9CountBitsC2Ev
+   fun:_ZN5blink10UseCounterC1Ev
+   fun:_ZN5blink4PageC1ERNS0_11PageClientsE
+}
diff --git a/tools/valgrind/memcheck/suppressions_mac.txt b/tools/valgrind/memcheck/suppressions_mac.txt
index c9ed9bf..ac9c687 100644
--- a/tools/valgrind/memcheck/suppressions_mac.txt
+++ b/tools/valgrind/memcheck/suppressions_mac.txt
@@ -94,6 +94,14 @@
    fun:__CFRunLoopRun
    ...
 }
+{
+   # See also http://openradar.appspot.com/20698633
+   bug_481286
+   Memcheck:Leak
+   ...
+   fun:_ZN8Security13PluginSession6mallocEm
+   fun:_Z20CL_extractCSSMKeyNSSRK33cssm_x509_subject_public_key_infoRN8Security9AllocatorEPK11DecodedCert
+}
 # Intentional leaks in AppKit, for an OS-level cache. Only appear on the first
 # run of each reboot.  See also issues 105525, 257276, 340847.
 {
diff --git a/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java b/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java
index c868f32..c40b0a9 100644
--- a/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java
+++ b/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java
@@ -13,8 +13,6 @@
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
 
-import org.chromium.base.ApiCompatibilityUtils;
-
 /**
  * Encapsulates a single gradient view of the HSV color display, including its label, gradient
  * view and seek bar.
@@ -90,6 +88,6 @@
         } else {
             mGradientDrawable.setColors(mGradientColors);
         }
-        ApiCompatibilityUtils.setBackgroundForView(mGradientView, mGradientDrawable);
+        mGradientView.setBackground(mGradientDrawable);
     }
 }
diff --git a/ui/android/java/src/org/chromium/ui/DropdownAdapter.java b/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
index 2b561d1..51bb6b6 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
@@ -15,8 +15,6 @@
 import android.widget.ArrayAdapter;
 import android.widget.TextView;
 
-import org.chromium.base.ApiCompatibilityUtils;
-
 import java.util.List;
 import java.util.Set;
 
@@ -59,7 +57,7 @@
             LayoutInflater inflater =
                     (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             layout = inflater.inflate(R.layout.dropdown_item, null);
-            ApiCompatibilityUtils.setBackgroundForView(layout, new DropdownDividerDrawable());
+            layout.setBackground(new DropdownDividerDrawable());
         }
 
         DropdownItem item = getItem(position);
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 33886ee..536a63c 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -63,13 +63,6 @@
 
     libs += [ "jnigraphics" ]
   }
-
-  if (is_android && is_android_webview_build) {
-    deps += [
-      #TODO(GYP): port this component to GN.
-      #"//ui/android:ui_java",
-    ]
-  }
 }
 
 if (is_android) {
diff --git a/ui/events/gesture_detection/scale_gesture_detector.cc b/ui/events/gesture_detection/scale_gesture_detector.cc
index 7afe91f..a8316c7 100644
--- a/ui/events/gesture_detection/scale_gesture_detector.cc
+++ b/ui/events/gesture_detection/scale_gesture_detector.cc
@@ -7,7 +7,6 @@
 #include <limits.h>
 #include <cmath>
 
-#include "base/float_util.h"
 #include "base/logging.h"
 #include "ui/events/gesture_detection/motion_event.h"
 #include "ui/events/gesture_detection/scale_gesture_listeners.h"
@@ -285,7 +284,7 @@
   float total = 0;
   int sample_count = 0;
   for (int i = 0; i < count; i++) {
-    const bool has_last_accepted = !base::IsNaN(touch_history_last_accepted_);
+    const bool has_last_accepted = !std::isnan(touch_history_last_accepted_);
     const int history_size = static_cast<int>(ev.GetHistorySize());
     const int pointersample_count = history_size + 1;
     for (int h = 0; h < pointersample_count; h++) {
@@ -301,10 +300,10 @@
         major = touch_max_major_;
       total += major;
 
-      if (base::IsNaN(touch_upper_) || major > touch_upper_) {
+      if (std::isnan(touch_upper_) || major > touch_upper_) {
         touch_upper_ = major;
       }
-      if (base::IsNaN(touch_lower_) || major < touch_lower_) {
+      if (std::isnan(touch_lower_) || major < touch_lower_) {
         touch_lower_ = major;
       }
 
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 9e66cc2..3ca2c09 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -111,11 +111,6 @@
       "display_observer.cc",
     ]
 
-    # TODO(GYP) re-enable when base_java exists.
-    #if (!is_android_webview_build) {
-    #  deps += [ "//base:base_java" ]
-    #}
-
     # TODO(jdduke): Revisit optimization after gauging benefit, crbug/419051.
     if (!is_debug) {
       configs -= [ "//build/config/compiler:optimize" ]
diff --git a/ui/gfx/display_change_notifier_unittest.cc b/ui/gfx/display_change_notifier_unittest.cc
index 47b5bd0..9c1dda2 100644
--- a/ui/gfx/display_change_notifier_unittest.cc
+++ b/ui/gfx/display_change_notifier_unittest.cc
@@ -70,13 +70,6 @@
   EXPECT_EQ(1, observer.display_added());
 }
 
-TEST(DisplayChangeNotifierTest, AddObserver_Null) {
-  DisplayChangeNotifier change_notifier;
-
-  change_notifier.AddObserver(NULL);
-  // Should not crash.
-}
-
 TEST(DisplayChangeNotifier, RemoveObserver_Smoke) {
   DisplayChangeNotifier change_notifier;
   MockDisplayObserver observer;
@@ -93,13 +86,6 @@
   EXPECT_EQ(0, observer.display_added());
 }
 
-TEST(DisplayChangeNotifierTest, RemoveObserver_Null) {
-  DisplayChangeNotifier change_notifier;
-
-  change_notifier.RemoveObserver(NULL);
-  // Should not crash.
-}
-
 TEST(DisplayChangeNotifierTest, RemoveObserver_Unknown) {
   DisplayChangeNotifier change_notifier;
   MockDisplayObserver observer;
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 29bed31..04dea9c 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -208,7 +208,7 @@
     ]
   }
 
-  if (is_android && !is_android_webview_build) {
+  if (is_android) {
     deps += [ "//ui/android:ui_java" ]
   }
 }