Update from https://crrev.com/315085

This includes the switch to libc++ on Android.

Other fixes:

*) Add (dumb) impl of OrderingBarrier() to command buffer
*) "base/debug/trace_event.h" -> "base/trace_event/trace_event.h"
*) Added a few <cmath> includes to sky

Review URL: https://codereview.chromium.org/903273002
diff --git a/DEPS b/DEPS
index 97a3afe..2ac908e 100644
--- a/DEPS
+++ b/DEPS
@@ -21,19 +21,19 @@
   'chromium_git': 'https://chromium.googlesource.com',
   'dart_svn': 'https://dart.googlecode.com',
   'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
-  'skia_revision': 'fef4c32bdf02f1bf3cde722cd48c4ac4cd137ab6',
+  'skia_revision': '02c8fd0ad5e5279004dd49ec49fbae00f8522ec0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and V8 without interference from each other.
-  'v8_revision': '224d14897d9b7df09e08a94e4cbc13feb339346d',
+  'v8_revision': '0aa5f75929fa3b383ec749555e045e47199ba6d5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'bc393df9cd8ae893da686533644da29a8c4911ae',
+  'angle_revision': '592ab9dd91e653f5c2d4f7395267046d229e20c1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': '451dcd05a5b34936f5be67b2472cd63aaa508401',
+  'buildtools_revision': 'da0df3fdac6036e862addb1155a2d6c11b6c18d5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Dart
   # and whatever else without interference from each other.
@@ -41,11 +41,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'b3a788e5e37955620b26be5b6e3048d37b605e00',
+  'pdfium_revision': '7061d1af45752617fafa85e2242dc5b2844650b5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': 'be629e0e920ae32cca691f5e45410ff00db1a849',
+  'boringssl_revision': '8f5e2ebcee628ef02add9b21955402b0c6256624',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lss
   # and whatever else without interference from each other.
@@ -159,7 +159,7 @@
         Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
 
     'src/third_party/android_tools':
-     Var('chromium_git') + '/android_tools.git' + '@' + 'aaeda3d69df4b4352e3cac7c16bea7f16bd1ec12',
+     Var('chromium_git') + '/android_tools.git' + '@' + 'f6e2370dff438125897bb3b3800de1ad7aa62c27',
 
     'src/third_party/appurify-python/src':
      Var('chromium_git') + '/external/github.com/appurify/appurify-python.git' + '@' + 'ee7abd5c5ae3106f72b2a0b9d2cb55094688e867',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index c1df2ec..44e656c 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -171,11 +171,6 @@
     "debug/stack_trace_win.cc",
     "debug/task_annotator.cc",
     "debug/task_annotator.h",
-    "debug/trace_event.h",
-    "debug/trace_event_argument.h",
-    "debug/trace_event_impl.h",
-    "debug/trace_event_synthetic_delay.h",
-    "debug/trace_event_win.h",
     "deferred_sequenced_task_runner.cc",
     "deferred_sequenced_task_runner.h",
     "environment.cc",
@@ -347,7 +342,6 @@
     "memory/ref_counted_delete_on_message_loop.h",
     "memory/ref_counted_memory.cc",
     "memory/ref_counted_memory.h",
-    "memory/scoped_open_process.h",
     "memory/scoped_policy.h",
     "memory/scoped_ptr.h",
     "memory/scoped_vector.h",
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 602358b..2168c21 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
@@ -175,18 +175,12 @@
                     String apkFilePath = null;
                     boolean useMapExecSupportFallback = false;
 
-                    // If the Android build version pre-dates KitKat and the device
-                    // manufacturer is Samsung, skip the check for mmap exec support and
-                    // return false. This avoids triggering a warning on these devices.
-                    // The version check is included because these devices do not show
-                    // the warning on later OS builds.
+                    // If manufacturer is Samsung then skip the mmap exec check.
                     //
                     // For more, see:
                     //   https://code.google.com/p/chromium/issues/detail?id=448084
                     final String manufacturer = android.os.Build.MANUFACTURER;
-                    final int version = android.os.Build.VERSION.SDK_INT;
                     if (manufacturer != null
-                            && version < android.os.Build.VERSION_CODES.KITKAT
                             && manufacturer.toLowerCase(Locale.ENGLISH).contains("samsung")) {
                         Log.w(TAG, "Suppressed load from APK support check on this device");
                         sProbeMapApkWithExecPermission = false;
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc
index a157354..4bebec7 100644
--- a/base/android/jni_array.cc
+++ b/base/android/jni_array.cc
@@ -7,6 +7,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/logging.h"
+#include "base/stl_util.h"
 
 namespace base {
 namespace android {
@@ -53,7 +54,7 @@
 
 ScopedJavaLocalRef<jintArray> ToJavaIntArray(
     JNIEnv* env, const std::vector<int>& ints) {
-  return ToJavaIntArray(env, ints.begin(), ints.size());
+  return ToJavaIntArray(env, vector_as_array(&ints), ints.size());
 }
 
 ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
@@ -72,7 +73,7 @@
 // Returns a new Java long array converted from the given int64 array.
 BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
     JNIEnv* env, const std::vector<int64>& longs) {
-  return ToJavaLongArray(env, longs.begin(), longs.size());
+  return ToJavaLongArray(env, vector_as_array(&longs), longs.size());
 }
 
 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
diff --git a/base/android/scoped_java_ref_unittest.cc b/base/android/scoped_java_ref_unittest.cc
index 36f253c..3f4419a 100644
--- a/base/android/scoped_java_ref_unittest.cc
+++ b/base/android/scoped_java_ref_unittest.cc
@@ -40,7 +40,7 @@
 
 class ScopedJavaRefTest : public testing::Test {
  protected:
-  virtual void SetUp() {
+  void SetUp() override {
     g_local_refs = 0;
     g_global_refs = 0;
     JNIEnv* env = AttachCurrentThread();
@@ -55,7 +55,7 @@
     hooked_functions.DeleteLocalRef = &DeleteLocalRef;
   }
 
-  virtual void TearDown() {
+  void TearDown() override {
     JNIEnv* env = AttachCurrentThread();
     env->functions = g_previous_functions;
   }
diff --git a/base/android/trace_event_binding.cc b/base/android/trace_event_binding.cc
index 94eb214..b8ce6d9 100644
--- a/base/android/trace_event_binding.cc
+++ b/base/android/trace_event_binding.cc
@@ -57,11 +57,11 @@
 
 class TraceEnabledObserver : public debug::TraceLog::EnabledStateObserver {
   public:
-    virtual void OnTraceLogEnabled() override {
+   void OnTraceLogEnabled() override {
       JNIEnv* env = base::android::AttachCurrentThread();
       base::android::Java_TraceEvent_setEnabled(env, true);
     }
-    virtual void OnTraceLogDisabled() override {
+    void OnTraceLogDisabled() override {
       JNIEnv* env = base::android::AttachCurrentThread();
       base::android::Java_TraceEvent_setEnabled(env, false);
     }
diff --git a/base/base.gypi b/base/base.gypi
index d4dd4dc..6dd6fcf 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -173,11 +173,6 @@
           'debug/stack_trace_win.cc',
           'debug/task_annotator.cc',
           'debug/task_annotator.h',
-          'debug/trace_event.h',
-          'debug/trace_event_argument.h',
-          'debug/trace_event_impl.h',
-          'debug/trace_event_synthetic_delay.h',
-          'debug/trace_event_win.h',
           'deferred_sequenced_task_runner.cc',
           'deferred_sequenced_task_runner.h',
           'environment.cc',
@@ -353,7 +348,6 @@
           'memory/ref_counted_delete_on_message_loop.h',
           'memory/ref_counted_memory.cc',
           'memory/ref_counted_memory.h',
-          'memory/scoped_open_process.h',
           'memory/scoped_policy.h',
           'memory/scoped_ptr.h',
           'memory/scoped_vector.h',
diff --git a/base/base.isolate b/base/base.isolate
index 021c01c..cb85965 100644
--- a/base/base.isolate
+++ b/base/base.isolate
@@ -9,13 +9,20 @@
     '../third_party/icu/icu.isolate',
   ],
   'conditions': [
-    ['OS=="linux" and asan==1 and chromeos==0', {
+    ['use_custom_libcxx==1', {
       'variables': {
         'files': [
           '<(PRODUCT_DIR)/lib/libc++.so',
         ],
       },
     }],
+    ['use_instrumented_libraries==1', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/instrumented_libraries/',
+        ],
+      },
+    }],
     ['OS=="mac" and asan==1', {
       'variables': {
         'files': [
@@ -30,7 +37,7 @@
         ],
       },
     }],
-    ['OS=="linux" and asan==1', {
+    ['OS=="linux" and (asan==1 or lsan==1 or msan==1 or tsan==1)', {
       'variables': {
         'files': [
           # For llvm-symbolizer.
@@ -38,7 +45,7 @@
         ],
       },
     }],
-    ['asan==1', {
+    ['asan==1 or lsan==1 or msan==1 or tsan==1', {
       'variables': {
         'files': [
           '../tools/valgrind/asan/',
@@ -53,27 +60,43 @@
         ],
       },
     }],
+    # Copy the VS runtime DLLs into the isolate so that they
+    # don't have to be preinstalled on the target machine.
+    ['OS=="win" and component=="shared_library" and CONFIGURATION_NAME=="Debug"', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/x64/msvcp120d.dll',
+          '<(PRODUCT_DIR)/x64/msvcr120d.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and component=="shared_library" and CONFIGURATION_NAME=="Release"', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/x64/msvcp120.dll',
+          '<(PRODUCT_DIR)/x64/msvcr120.dll',
+        ],
+      },
+    }],
     ['OS=="win" and component=="shared_library" and (CONFIGURATION_NAME=="Debug" or CONFIGURATION_NAME=="Debug_x64")', {
       'variables': {
         'files': [
-          # Copy the VS runtime DLLs into the isolate so that they
-          # don't have to be preinstalled on the target machine.
           '<(PRODUCT_DIR)/msvcp120d.dll',
           '<(PRODUCT_DIR)/msvcr120d.dll',
-          '<(PRODUCT_DIR)/x64/msvcp120d.dll',
-          '<(PRODUCT_DIR)/x64/msvcr120d.dll',
         ],
       },
     }],
     ['OS=="win" and component=="shared_library" and (CONFIGURATION_NAME=="Release" or CONFIGURATION_NAME=="Release_x64")', {
       'variables': {
         'files': [
-          # Copy the VS runtime DLLs into the isolate so that they
-          # don't have to be preinstalled on the target machine.
           '<(PRODUCT_DIR)/msvcp120.dll',
           '<(PRODUCT_DIR)/msvcr120.dll',
         ],
       },
     }],
+    # Workaround for https://code.google.com/p/swarming/issues/detail?id=211
+    ['asan==0 or lsan==0 or msan==0 or tsan==0', {
+      'variables': {},
+    }],
   ],
 }
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate
index f561d20..0822b24 100644
--- a/base/base_unittests.isolate
+++ b/base/base_unittests.isolate
@@ -20,6 +20,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
         'files': [
           '../testing/xvfb.py',
@@ -51,6 +53,15 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
+        ],
+      },
+    }],
+    ['OS=="mac" and asan==1', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/base_unittests.dSYM/',
         ],
       },
     }],
diff --git a/base/bind.h b/base/bind.h
index 7874656..51be10d 100644
--- a/base/bind.h
+++ b/base/bind.h
@@ -52,13 +52,14 @@
     typename internal::BindState<
         typename internal::FunctorTraits<Functor>::RunnableType,
         typename internal::FunctorTraits<Functor>::RunType,
-        void()>::UnboundRunType>
+        internal::TypeList<>>::UnboundRunType>
 Bind(Functor functor) {
   // Typedefs for how to store and run the functor.
   typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
   typedef typename internal::FunctorTraits<Functor>::RunType RunType;
 
-  typedef internal::BindState<RunnableType, RunType, void()> BindState;
+  typedef internal::BindState<RunnableType, RunType,
+                              internal::TypeList<>> BindState;
 
   return Callback<typename BindState::UnboundRunType>(
       new BindState(internal::MakeRunnable(functor)));
@@ -69,7 +70,8 @@
     typename internal::BindState<
         typename internal::FunctorTraits<Functor>::RunnableType,
         typename internal::FunctorTraits<Functor>::RunType,
-        void(typename internal::CallbackParamTraits<Args>::StorageType...)>
+        internal::TypeList<
+            typename internal::CallbackParamTraits<Args>::StorageType...>>
             ::UnboundRunType>
 Bind(Functor functor, const Args&... args) {
   // Typedefs for how to store and run the functor.
@@ -101,8 +103,10 @@
       !internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value,
       "a_parameter_is_refcounted_type_and_needs_scoped_refptr");
 
-  typedef internal::BindState<RunnableType, RunType,
-      void(typename internal::CallbackParamTraits<Args>::StorageType...)>
+  typedef internal::BindState<
+      RunnableType, RunType,
+      internal::TypeList<
+          typename internal::CallbackParamTraits<Args>::StorageType...>>
       BindState;
 
   return Callback<typename BindState::UnboundRunType>(
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index f3efc31..f8e89bd 100644
--- a/base/bind_helpers.h
+++ b/base/bind_helpers.h
@@ -435,45 +435,46 @@
 
 // Utility for handling different refcounting semantics in the Bind()
 // function.
-template <bool is_method, typename T>
-struct MaybeRefcount;
+template <bool is_method, typename... T>
+struct MaybeScopedRefPtr;
 
-template <typename T>
-struct MaybeRefcount<false, T> {
-  static void AddRef(const T&) {}
-  static void Release(const T&) {}
+template <bool is_method>
+struct MaybeScopedRefPtr<is_method> {
+  MaybeScopedRefPtr() {}
 };
 
-template <typename T, size_t n>
-struct MaybeRefcount<false, T[n]> {
-  static void AddRef(const T*) {}
-  static void Release(const T*) {}
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<false, T, Rest...> {
+  MaybeScopedRefPtr(const T&, const Rest&...) {}
 };
 
-template <typename T>
-struct MaybeRefcount<true, T> {
-  static void AddRef(const T&) {}
-  static void Release(const T&) {}
+template <typename T, size_t n, typename... Rest>
+struct MaybeScopedRefPtr<false, T[n], Rest...> {
+  MaybeScopedRefPtr(const T*, const Rest&...) {}
 };
 
-template <typename T>
-struct MaybeRefcount<true, T*> {
-  static void AddRef(T* o) { o->AddRef(); }
-  static void Release(T* o) { o->Release(); }
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, T, Rest...> {
+  MaybeScopedRefPtr(const T& o, const Rest&...) {}
+};
+
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, T*, Rest...> {
+  MaybeScopedRefPtr(T* o, const Rest&...) : ref_(o) {}
+  scoped_refptr<T> ref_;
 };
 
 // No need to additionally AddRef() and Release() since we are storing a
 // scoped_refptr<> inside the storage object already.
-template <typename T>
-struct MaybeRefcount<true, scoped_refptr<T> > {
-  static void AddRef(const scoped_refptr<T>& o) {}
-  static void Release(const scoped_refptr<T>& o) {}
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, scoped_refptr<T>, Rest...> {
+  MaybeScopedRefPtr(const scoped_refptr<T>&, const Rest&...) {}
 };
 
-template <typename T>
-struct MaybeRefcount<true, const T*> {
-  static void AddRef(const T* o) { o->AddRef(); }
-  static void Release(const T* o) { o->Release(); }
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, const T*, Rest...> {
+  MaybeScopedRefPtr(const T* o, const Rest&...) : ref_(o) {}
+  scoped_refptr<const T> ref_;
 };
 
 // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
@@ -481,15 +482,89 @@
 // InvokeHelper that will no-op itself in the event the WeakPtr<> for
 // the target object is invalidated.
 //
-// P1 should be the type of the object that will be received of the method.
-template <bool IsMethod, typename P1>
+// The first argument should be the type of the object that will be received by
+// the method.
+template <bool IsMethod, typename... Args>
 struct IsWeakMethod : public false_type {};
 
-template <typename T>
-struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
+template <typename T, typename... Args>
+struct IsWeakMethod<true, WeakPtr<T>, Args...> : public true_type {};
 
-template <typename T>
-struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
+template <typename T, typename... Args>
+struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T>>, Args...>
+    : public true_type {};
+
+
+// Packs a list of types to hold them in a single type.
+template <typename... Types>
+struct TypeList {};
+
+// Used for DropTypeListItem implementation.
+template <size_t n, typename List>
+struct DropTypeListItemImpl;
+
+// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
+template <size_t n, typename T, typename... List>
+struct DropTypeListItemImpl<n, TypeList<T, List...>>
+    : DropTypeListItemImpl<n - 1, TypeList<List...>> {};
+
+template <typename T, typename... List>
+struct DropTypeListItemImpl<0, TypeList<T, List...>> {
+  typedef TypeList<T, List...> Type;
+};
+
+template <>
+struct DropTypeListItemImpl<0, TypeList<>> {
+  typedef TypeList<> Type;
+};
+
+// A type-level function that drops |n| list item from given TypeList.
+template <size_t n, typename List>
+using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
+
+// Used for ConcatTypeLists implementation.
+template <typename List1, typename List2>
+struct ConcatTypeListsImpl;
+
+template <typename... Types1, typename... Types2>
+struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
+  typedef TypeList<Types1..., Types2...> Type;
+};
+
+// A type-level function that concats two TypeLists.
+template <typename List1, typename List2>
+using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
+
+template <size_t n, typename List>
+struct NthTypeImpl;
+
+template <size_t n, typename T, typename... Types>
+struct NthTypeImpl<n, TypeList<T, Types...>>
+    : NthTypeImpl<n - 1, TypeList<Types...>> {
+};
+
+template <typename T, typename... Types>
+struct NthTypeImpl<0, TypeList<T, Types...>> {
+  typedef T Type;
+};
+
+// A type-level function that extracts |n|th type from a TypeList.
+template <size_t n, typename List>
+using NthType = typename NthTypeImpl<n, List>::Type;
+
+// Used for MakeFunctionType implementation.
+template <typename R, typename ArgList>
+struct MakeFunctionTypeImpl;
+
+template <typename R, typename... Args>
+struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
+  typedef R(Type)(Args...);
+};
+
+// A type-level function that constructs a function type that has |R| as its
+// return type and has TypeLists items as its arguments.
+template <typename R, typename ArgList>
+using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
 
 }  // namespace internal
 
diff --git a/base/bind_internal.h b/base/bind_internal.h
index b568c16..5fc1459 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -1,8 +1,3 @@
-// This file was GENERATED by command:
-//     pump.py bind_internal.h.pump
-// DO NOT EDIT BY HAND!!!
-
-
 // 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.
@@ -15,6 +10,7 @@
 #include "base/memory/raw_scoped_refptr_mismatch_checker.h"
 #include "base/memory/weak_ptr.h"
 #include "base/template_util.h"
+#include "base/tuple.h"
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
@@ -51,10 +47,6 @@
 // Types:
 //  RunnableAdapter<> -- Wraps the various "function" pointer types into an
 //                       object that adheres to the Runnable interface.
-//  FunctionTraits<> -- Type traits that unwrap a function signature into a
-//                      a set of easier to use typedefs.  Used mainly for
-//                      compile time asserts.
-//                      There are |ARITY| FunctionTraits types.
 //  ForceVoidReturn<> -- Helper class for translating function signatures to
 //                       equivalent forms with a "void" return type.
 //  FunctorTraits<> -- Type traits used determine the correct RunType and
@@ -64,12 +56,11 @@
 //                    type class that represents the underlying Functor.
 //                    There are |O(1)| MakeRunnable types.
 //  InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
-// Handle the differing syntaxes needed for WeakPtr<> support,
-//                    and for ignoring return values.  This is separate from
-//                    Invoker to avoid creating multiple version of Invoker<>
-//                    which grows at O(n^2) with the arity.
+//                    Handle the differing syntaxes needed for WeakPtr<>
+//                    support, and for ignoring return values.  This is separate
+//                    from Invoker to avoid creating multiple version of
+//                    Invoker<>.
 //  Invoker<> -- Unwraps the curried parameters and executes the Runnable.
-//               There are |(ARITY^2 + ARITY)/2| Invoketypes.
 //  BindState<> -- Stores the curried parameters, and is the main entry point
 //                 into the Bind() system, doing most of the type resolution.
 //                 There are ARITY BindState types.
@@ -209,84 +200,6 @@
   R (T::*method_)(Args...) const;
 };
 
-// TODO(tzik): Remove FunctionTraits after we finish removing bind.pump.
-// FunctionTraits<>
-//
-// Breaks a function signature apart into typedefs for easier introspection.
-template <typename Sig>
-struct FunctionTraits;
-
-template <typename R>
-struct FunctionTraits<R()> {
-  typedef R ReturnType;
-};
-
-template <typename R, typename A1>
-struct FunctionTraits<R(A1)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-};
-
-template <typename R, typename A1, typename A2>
-struct FunctionTraits<R(A1, A2)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-struct FunctionTraits<R(A1, A2, A3)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-struct FunctionTraits<R(A1, A2, A3, A4)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-struct FunctionTraits<R(A1, A2, A3, A4, A5)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-  typedef A5 A5Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-struct FunctionTraits<R(A1, A2, A3, A4, A5, A6)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-  typedef A5 A5Type;
-  typedef A6 A6Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-struct FunctionTraits<R(A1, A2, A3, A4, A5, A6, A7)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-  typedef A5 A5Type;
-  typedef A6 A6Type;
-  typedef A7 A7Type;
-};
-
 
 // ForceVoidReturn<>
 //
@@ -310,14 +223,14 @@
 };
 
 template <typename T>
-struct FunctorTraits<IgnoreResultHelper<T> > {
+struct FunctorTraits<IgnoreResultHelper<T>> {
   typedef typename FunctorTraits<T>::RunnableType RunnableType;
   typedef typename ForceVoidReturn<
       typename RunnableType::RunType>::RunType RunType;
 };
 
 template <typename T>
-struct FunctorTraits<Callback<T> > {
+struct FunctorTraits<Callback<T>> {
   typedef Callback<T> RunnableType;
   typedef typename Callback<T>::RunType RunType;
 };
@@ -339,7 +252,7 @@
 }
 
 template <typename T>
-const typename FunctorTraits<Callback<T> >::RunnableType&
+const typename FunctorTraits<Callback<T>>::RunnableType&
 MakeRunnable(const Callback<T>& t) {
   DCHECK(!t.is_null());
   return t;
@@ -368,22 +281,21 @@
 struct InvokeHelper;
 
 template <typename ReturnType, typename Runnable, typename... Args>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(Args...)>  {
+struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> {
   static ReturnType MakeItSo(Runnable runnable, Args... args) {
     return runnable.Run(CallbackForward(args)...);
   }
 };
 
 template <typename Runnable, typename... Args>
-struct InvokeHelper<false, void, Runnable, void(Args...)>  {
+struct InvokeHelper<false, void, Runnable, TypeList<Args...>> {
   static void MakeItSo(Runnable runnable, Args... args) {
     runnable.Run(CallbackForward(args)...);
   }
 };
 
 template <typename Runnable, typename BoundWeakPtr, typename... Args>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, Args...)>  {
+struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> {
   static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
     if (!weak_ptr.get()) {
       return;
@@ -408,1419 +320,30 @@
 // Invoker<>
 //
 // See description at the top of the file.
-template <int NumBound, typename Storage, typename RunType>
+template <typename BoundIndices,
+          typename StorageType, typename Unwrappers,
+          typename InvokeHelperType, typename UnboundForwardRunType>
 struct Invoker;
 
-// Arity 0 -> 0.
-template <typename StorageType, typename R>
-struct Invoker<0, StorageType, R()> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void()>
-               ::MakeItSo(storage->runnable_);
-  }
-};
-
-// Arity 1 -> 1.
-template <typename StorageType, typename R,typename X1>
-struct Invoker<0, StorageType, R(X1)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X1>::ForwardType);
-
-  typedef R(UnboundRunType)(X1);
-
+template <size_t... bound_indices,
+          typename StorageType,
+          typename... Unwrappers,
+          typename InvokeHelperType,
+          typename R,
+          typename... UnboundForwardArgs>
+struct Invoker<IndexSequence<bound_indices...>,
+               StorageType, TypeList<Unwrappers...>,
+               InvokeHelperType, R(UnboundForwardArgs...)> {
   static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X1>::ForwardType x1) {
+               UnboundForwardArgs... unbound_args) {
     StorageType* storage = static_cast<StorageType*>(base);
-
     // Local references to make debugger stepping easier. If in a debugger,
     // you really want to warp ahead and step through the
     // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename CallbackParamTraits<X1>::ForwardType x1)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1));
-  }
-};
-
-// Arity 1 -> 0.
-template <typename StorageType, typename R,typename X1>
-struct Invoker<1, StorageType, R(X1)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1));
-  }
-};
-
-// Arity 2 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker<0, StorageType, R(X1, X2)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X1>::ForwardType,
-      typename CallbackParamTraits<X2>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X1>::ForwardType x1,
-      typename CallbackParamTraits<X2>::ForwardType x2) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2));
-  }
-};
-
-// Arity 2 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker<1, StorageType, R(X1, X2)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X2>::ForwardType);
-
-  typedef R(UnboundRunType)(X2);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X2>::ForwardType x2) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X2>::ForwardType x2)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2));
-  }
-};
-
-// Arity 2 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker<2, StorageType, R(X1, X2)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2));
-  }
-};
-
-// Arity 3 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3>
-struct Invoker<0, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X1>::ForwardType,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X1>::ForwardType x1,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3));
-  }
-};
-
-// Arity 3 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3>
-struct Invoker<1, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3));
-  }
-};
-
-// Arity 3 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3>
-struct Invoker<2, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X3>::ForwardType);
-
-  typedef R(UnboundRunType)(X3);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X3>::ForwardType x3) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X3>::ForwardType x3)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3));
-  }
-};
-
-// Arity 3 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3>
-struct Invoker<3, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3));
-  }
-};
-
-// Arity 4 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X1>::ForwardType,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X1>::ForwardType x1,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X4);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X4>::ForwardType x4)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4));
-  }
-};
-
-// Arity 5 -> 5.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X1>::ForwardType,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4, X5);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X1>::ForwardType x1,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4, X5);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4, X5);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X4, X5);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X5);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X5>::ForwardType x5)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename Bound5UnwrapTraits::ForwardType)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 6 -> 6.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X1>::ForwardType,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X1>::ForwardType x1,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 5.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X5, X6);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X6);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename Bound5UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X6>::ForwardType x6)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6>
-struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-    typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    typename Bound6UnwrapTraits::ForwardType x6 =
-        Bound6UnwrapTraits::Unwrap(storage->p6_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename Bound5UnwrapTraits::ForwardType,
-               typename Bound6UnwrapTraits::ForwardType)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6));
-  }
-};
-
-// Arity 7 -> 7.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X1>::ForwardType,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType,
-      typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X1>::ForwardType x1,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6,
-      typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 6.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X2>::ForwardType,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType,
-      typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X2>::ForwardType x2,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6,
-      typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 5.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X3>::ForwardType,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType,
-      typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X3>::ForwardType x3,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6,
-      typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X4>::ForwardType,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType,
-      typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X4>::ForwardType x4,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6,
-      typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X5>::ForwardType,
-      typename CallbackParamTraits<X6>::ForwardType,
-      typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X5>::ForwardType x5,
-      typename CallbackParamTraits<X6>::ForwardType x6,
-      typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X6>::ForwardType,
-      typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X6, X7);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X6>::ForwardType x6,
-      typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename Bound5UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-      typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X7);
-
-  static R Run(BindStateBase* base,
-      typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-    typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    typename Bound6UnwrapTraits::ForwardType x6 =
-        Bound6UnwrapTraits::Unwrap(storage->p6_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename Bound5UnwrapTraits::ForwardType,
-               typename Bound6UnwrapTraits::ForwardType,
-               typename CallbackParamTraits<X7>::ForwardType x7)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
-    typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<7, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-    typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-    typedef typename StorageType::Bound7UnwrapTraits Bound7UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    typename Bound6UnwrapTraits::ForwardType x6 =
-        Bound6UnwrapTraits::Unwrap(storage->p6_);
-    typename Bound7UnwrapTraits::ForwardType x7 =
-        Bound7UnwrapTraits::Unwrap(storage->p7_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(typename Bound1UnwrapTraits::ForwardType,
-               typename Bound2UnwrapTraits::ForwardType,
-               typename Bound3UnwrapTraits::ForwardType,
-               typename Bound4UnwrapTraits::ForwardType,
-               typename Bound5UnwrapTraits::ForwardType,
-               typename Bound6UnwrapTraits::ForwardType,
-               typename Bound7UnwrapTraits::ForwardType)>
-               ::MakeItSo(storage->runnable_, CallbackForward(x1),
-                   CallbackForward(x2), CallbackForward(x3),
-                   CallbackForward(x4), CallbackForward(x5),
-                   CallbackForward(x6), CallbackForward(x7));
+    return InvokeHelperType::MakeItSo(
+        storage->runnable_,
+        Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))...,
+        CallbackForward(unbound_args)...);
   }
 };
 
@@ -1837,275 +360,52 @@
 //
 // BoundArgsType contains the storage type for all the bound arguments by
 // (ab)using a function type.
-template <typename Runnable, typename RunType, typename BoundArgsType>
+template <typename Runnable, typename RunType, typename BoundArgList>
 struct BindState;
 
-template <typename Runnable, typename RunType>
-struct BindState<Runnable, RunType, void()> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef false_type IsWeakCall;
-  typedef Invoker<0, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-  explicit BindState(const Runnable& runnable)
-      : runnable_(runnable) {
-  }
+template <typename Runnable,
+          typename R, typename... Args,
+          typename... BoundArgs>
+struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>>
+    : public BindStateBase {
+ private:
+  using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>;
+  using RunnableType = Runnable;
+
+  // true_type if Runnable is a method invocation and the first bound argument
+  // is a WeakPtr.
+  using IsWeakCall =
+      IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>;
+
+  using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
+  using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>;
+  using UnboundForwardArgs = DropTypeListItem<
+      sizeof...(BoundArgs),
+      TypeList<typename CallbackParamTraits<Args>::ForwardType...>>;
+  using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>;
+
+  using InvokeHelperArgs = ConcatTypeLists<
+      TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>,
+      UnboundForwardArgs>;
+  using InvokeHelperType =
+      InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>;
+
+  using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
+
+ public:
+  using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers,
+                              InvokeHelperType, UnboundForwardRunType>;
+  using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
+
+  BindState(const Runnable& runnable, const BoundArgs&... bound_args)
+      : runnable_(runnable), ref_(bound_args...), bound_args_(bound_args...) {}
 
   RunnableType runnable_;
+  MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_;
+  Tuple<BoundArgs...> bound_args_;
 
  private:
-  ~BindState() override {  }
-
-};
-
-template <typename Runnable, typename RunType, typename P1>
-struct BindState<Runnable, RunType, void(P1)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<1, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1)
-      : runnable_(runnable),
-        p1_(p1) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-
- private:
-  ~BindState() override {    MaybeRefcount<HasIsMethodTag<Runnable>::value,
-      P1>::Release(p1_);  }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2>
-struct BindState<Runnable, RunType, void(P1, P2)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<2, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2)
-      : runnable_(runnable),
-        p1_(p1),
-        p2_(p2) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-
- private:
-  ~BindState() override {    MaybeRefcount<HasIsMethodTag<Runnable>::value,
-      P1>::Release(p1_);  }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
-    typename P3>
-struct BindState<Runnable, RunType, void(P1, P2, P3)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<3, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3)
-      : runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-
- private:
-  ~BindState() override {    MaybeRefcount<HasIsMethodTag<Runnable>::value,
-      P1>::Release(p1_);  }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
-    typename P3, typename P4>
-struct BindState<Runnable, RunType, void(P1, P2, P3,
-    P4)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<4, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
-      const P4& p4)
-      : runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
-
- private:
-  ~BindState() override {    MaybeRefcount<HasIsMethodTag<Runnable>::value,
-      P1>::Release(p1_);  }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
-    typename P3, typename P4, typename P5>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4,
-    P5)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<5, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-  typedef UnwrapTraits<P5> Bound5UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
-      const P4& p4, const P5& p5)
-      : runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4),
-        p5_(p5) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
-  P5 p5_;
-
- private:
-  ~BindState() override {    MaybeRefcount<HasIsMethodTag<Runnable>::value,
-      P1>::Release(p1_);  }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
-    typename P3, typename P4, typename P5, typename P6>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5,
-    P6)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<6, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-  typedef UnwrapTraits<P5> Bound5UnwrapTraits;
-  typedef UnwrapTraits<P6> Bound6UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
-      const P4& p4, const P5& p5, const P6& p6)
-      : runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4),
-        p5_(p5),
-        p6_(p6) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
-  P5 p5_;
-  P6 p6_;
-
- private:
-  ~BindState() override {    MaybeRefcount<HasIsMethodTag<Runnable>::value,
-      P1>::Release(p1_);  }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
-    typename P3, typename P4, typename P5, typename P6, typename P7>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5, P6,
-    P7)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<7, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-  typedef UnwrapTraits<P5> Bound5UnwrapTraits;
-  typedef UnwrapTraits<P6> Bound6UnwrapTraits;
-  typedef UnwrapTraits<P7> Bound7UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
-      const P4& p4, const P5& p5, const P6& p6, const P7& p7)
-      : runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4),
-        p5_(p5),
-        p6_(p6),
-        p7_(p7) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
-  P5 p5_;
-  P6 p6_;
-  P7 p7_;
-
- private:
-  ~BindState() override {    MaybeRefcount<HasIsMethodTag<Runnable>::value,
-      P1>::Release(p1_);  }
-
+  ~BindState() override {}
 };
 
 }  // namespace internal
diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump
deleted file mode 100644
index 0ed3ca2..0000000
--- a/base/bind_internal.h.pump
+++ /dev/null
@@ -1,516 +0,0 @@
-$$ This is a pump file for generating file templates.  Pump is a python
-$$ script that is part of the Google Test suite of utilities.  Description
-$$ can be found here:
-$$
-$$ http://code.google.com/p/googletest/wiki/PumpManual
-$$
-
-$$ See comment for MAX_ARITY in base/bind.h.pump.
-$var MAX_ARITY = 7
-$range ARITY 0..MAX_ARITY
-
-// 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.
-
-#ifndef BASE_BIND_INTERNAL_H_
-#define BASE_BIND_INTERNAL_H_
-
-#include "base/bind_helpers.h"
-#include "base/callback_internal.h"
-#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
-#include "base/memory/weak_ptr.h"
-#include "base/template_util.h"
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include "base/bind_internal_win.h"
-#endif
-
-namespace base {
-namespace internal {
-
-// See base/callback.h for user documentation.
-//
-//
-// CONCEPTS:
-//  Runnable -- A type (really a type class) that has a single Run() method
-//              and a RunType typedef that corresponds to the type of Run().
-//              A Runnable can declare that it should treated like a method
-//              call by including a typedef named IsMethod.  The value of
-//              this typedef is NOT inspected, only the existence.  When a
-//              Runnable declares itself a method, Bind() will enforce special
-//              refcounting + WeakPtr handling semantics for the first
-//              parameter which is expected to be an object.
-//  Functor -- A copyable type representing something that should be called.
-//             All function pointers, Callback<>, and Runnables are functors
-//             even if the invocation syntax differs.
-//  RunType -- A function type (as opposed to function _pointer_ type) for
-//             a Run() function.  Usually just a convenience typedef.
-//  (Bound)ArgsType -- A function type that is being (ab)used to store the
-//                     types of set of arguments.  The "return" type is always
-//                     void here.  We use this hack so that we do not need
-//                     a new type name for each arity of type. (eg.,
-//                     BindState1, BindState2).  This makes forward
-//                     declarations and friending much much easier.
-//
-// Types:
-//  RunnableAdapter<> -- Wraps the various "function" pointer types into an
-//                       object that adheres to the Runnable interface.
-//  FunctionTraits<> -- Type traits that unwrap a function signature into a
-//                      a set of easier to use typedefs.  Used mainly for
-//                      compile time asserts.
-//                      There are |ARITY| FunctionTraits types.
-//  ForceVoidReturn<> -- Helper class for translating function signatures to
-//                       equivalent forms with a "void" return type.
-//  FunctorTraits<> -- Type traits used determine the correct RunType and
-//                     RunnableType for a Functor.  This is where function
-//                     signature adapters are applied.
-//  MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
-//                    type class that represents the underlying Functor.
-//                    There are |O(1)| MakeRunnable types.
-//  InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
-//                    Handle the differing syntaxes needed for WeakPtr<> support,
-//                    and for ignoring return values.  This is separate from
-//                    Invoker to avoid creating multiple version of Invoker<>
-//                    which grows at O(n^2) with the arity.
-//  Invoker<> -- Unwraps the curried parameters and executes the Runnable.
-//               There are |(ARITY^2 + ARITY)/2| Invoketypes.
-//  BindState<> -- Stores the curried parameters, and is the main entry point
-//                 into the Bind() system, doing most of the type resolution.
-//                 There are ARITY BindState types.
-
-// HasNonConstReferenceParam selects true_type when any of the parameters in
-// |Sig| is a non-const reference.
-// Implementation note: This non-specialized case handles zero-arity case only.
-// Non-zero-arity cases should be handled by the specialization below.
-template <typename Sig>
-struct HasNonConstReferenceParam : false_type {};
-
-// Implementation note: Select true_type if the first parameter is a non-const
-// reference.  Otherwise, skip the first parameter and check rest of parameters
-// recursively.
-template <typename R, typename T, typename... Args>
-struct HasNonConstReferenceParam<R(T, Args...)>
-    : SelectType<is_non_const_reference<T>::value,
-                 true_type,
-                 HasNonConstReferenceParam<R(Args...)>>::Type {};
-
-// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
-// pointer to a RefCounted type.
-// Implementation note: This non-specialized case handles zero-arity case only.
-// Non-zero-arity cases should be handled by the specialization below.
-template <typename... Args>
-struct HasRefCountedTypeAsRawPtr : false_type {};
-
-// Implementation note: Select true_type if the first parameter is a raw pointer
-// to a RefCounted type. Otherwise, skip the first parameter and check rest of
-// parameters recursively.
-template <typename T, typename... Args>
-struct HasRefCountedTypeAsRawPtr<T, Args...>
-    : SelectType<NeedsScopedRefptrButGetsRawPtr<T>::value,
-                 true_type,
-                 HasRefCountedTypeAsRawPtr<Args...>>::Type {};
-
-// BindsArrayToFirstArg selects true_type when |is_method| is true and the first
-// item of |Args| is an array type.
-// Implementation note: This non-specialized case handles !is_method case and
-// zero-arity case only.  Other cases should be handled by the specialization
-// below.
-template <bool is_method, typename... Args>
-struct BindsArrayToFirstArg : false_type {};
-
-template <typename T, typename... Args>
-struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {};
-
-// HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except
-// when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument.
-// Implementation note: This non-specialized case handles !is_method case and
-// zero-arity case only.  Other cases should be handled by the specialization
-// below.
-template <bool is_method, typename... Args>
-struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {};
-
-template <typename T, typename... Args>
-struct HasRefCountedParamAsRawPtr<true, T, Args...>
-    : HasRefCountedTypeAsRawPtr<Args...> {};
-
-// RunnableAdapter<>
-//
-// The RunnableAdapter<> templates provide a uniform interface for invoking
-// a function pointer, method pointer, or const method pointer. The adapter
-// exposes a Run() method with an appropriate signature. Using this wrapper
-// allows for writing code that supports all three pointer types without
-// undue repetition.  Without it, a lot of code would need to be repeated 3
-// times.
-//
-// For method pointers and const method pointers the first argument to Run()
-// is considered to be the received of the method.  This is similar to STL's
-// mem_fun().
-//
-// This class also exposes a RunType typedef that is the function type of the
-// Run() function.
-//
-// If and only if the wrapper contains a method or const method pointer, an
-// IsMethod typedef is exposed.  The existence of this typedef (NOT the value)
-// marks that the wrapper should be considered a method wrapper.
-
-template <typename Functor>
-class RunnableAdapter;
-
-// Function.
-template <typename R, typename... Args>
-class RunnableAdapter<R(*)(Args...)> {
- public:
-  typedef R (RunType)(Args...);
-
-  explicit RunnableAdapter(R(*function)(Args...))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
-    return function_(CallbackForward(args)...);
-  }
-
- private:
-  R (*function_)(Args...);
-};
-
-// Method.
-template <typename R, typename T, typename... Args>
-class RunnableAdapter<R(T::*)(Args...)> {
- public:
-  typedef R (RunType)(T*, Args...);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(Args...))
-      : method_(method) {
-  }
-
-  R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
-    return (object->*method_)(CallbackForward(args)...);
-  }
-
- private:
-  R (T::*method_)(Args...);
-};
-
-// Const Method.
-template <typename R, typename T, typename... Args>
-class RunnableAdapter<R(T::*)(Args...) const> {
- public:
-  typedef R (RunType)(const T*, Args...);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R(T::*method)(Args...) const)
-      : method_(method) {
-  }
-
-  R Run(const T* object,
-        typename CallbackParamTraits<Args>::ForwardType... args) {
-    return (object->*method_)(CallbackForward(args)...);
-  }
-
- private:
-  R (T::*method_)(Args...) const;
-};
-
-// TODO(tzik): Remove FunctionTraits after we finish removing bind.pump.
-// FunctionTraits<>
-//
-// Breaks a function signature apart into typedefs for easier introspection.
-template <typename Sig>
-struct FunctionTraits;
-
-$for ARITY [[
-$range ARG 1..ARITY
-
-template <typename R[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
-struct FunctionTraits<R($for ARG , [[A$(ARG)]])> {
-  typedef R ReturnType;
-$for ARG [[
-
-  typedef A$(ARG) A$(ARG)Type;
-]]
-
-};
-
-]]
-
-
-// ForceVoidReturn<>
-//
-// Set of templates that support forcing the function return type to void.
-template <typename Sig>
-struct ForceVoidReturn;
-
-template <typename R, typename... Args>
-struct ForceVoidReturn<R(Args...)> {
-  typedef void(RunType)(Args...);
-};
-
-
-// FunctorTraits<>
-//
-// See description at top of file.
-template <typename T>
-struct FunctorTraits {
-  typedef RunnableAdapter<T> RunnableType;
-  typedef typename RunnableType::RunType RunType;
-};
-
-template <typename T>
-struct FunctorTraits<IgnoreResultHelper<T> > {
-  typedef typename FunctorTraits<T>::RunnableType RunnableType;
-  typedef typename ForceVoidReturn<
-      typename RunnableType::RunType>::RunType RunType;
-};
-
-template <typename T>
-struct FunctorTraits<Callback<T> > {
-  typedef Callback<T> RunnableType;
-  typedef typename Callback<T>::RunType RunType;
-};
-
-
-// MakeRunnable<>
-//
-// Converts a passed in functor to a RunnableType using type inference.
-
-template <typename T>
-typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
-  return RunnableAdapter<T>(t);
-}
-
-template <typename T>
-typename FunctorTraits<T>::RunnableType
-MakeRunnable(const IgnoreResultHelper<T>& t) {
-  return MakeRunnable(t.functor_);
-}
-
-template <typename T>
-const typename FunctorTraits<Callback<T> >::RunnableType&
-MakeRunnable(const Callback<T>& t) {
-  DCHECK(!t.is_null());
-  return t;
-}
-
-
-// InvokeHelper<>
-//
-// There are 3 logical InvokeHelper<> specializations: normal, void-return,
-// WeakCalls.
-//
-// The normal type just calls the underlying runnable.
-//
-// We need a InvokeHelper to handle void return types in order to support
-// IgnoreResult().  Normally, if the Runnable's RunType had a void return,
-// the template system would just accept "return functor.Run()" ignoring
-// the fact that a void function is being used with return. This piece of
-// sugar breaks though when the Runnable's RunType is not void.  Thus, we
-// need a partial specialization to change the syntax to drop the "return"
-// from the invocation call.
-//
-// WeakCalls similarly need special syntax that is applied to the first
-// argument to check if they should no-op themselves.
-template <bool IsWeakCall, typename ReturnType, typename Runnable,
-          typename ArgsType>
-struct InvokeHelper;
-
-template <typename ReturnType, typename Runnable, typename... Args>
-struct InvokeHelper<false, ReturnType, Runnable,
-    void(Args...)>  {
-  static ReturnType MakeItSo(Runnable runnable, Args... args) {
-    return runnable.Run(CallbackForward(args)...);
-  }
-};
-
-template <typename Runnable, typename... Args>
-struct InvokeHelper<false, void, Runnable, void(Args...)>  {
-  static void MakeItSo(Runnable runnable, Args... args) {
-    runnable.Run(CallbackForward(args)...);
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename... Args>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, Args...)>  {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(args)...);
-  }
-};
-
-#if !defined(_MSC_VER)
-
-template <typename ReturnType, typename Runnable, typename ArgsType>
-struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
-  // WeakCalls are only supported for functions with a void return type.
-  // Otherwise, the function result would be undefined if the the WeakPtr<>
-  // is invalidated.
-  COMPILE_ASSERT(is_void<ReturnType>::value,
-                 weak_ptrs_can_only_bind_to_methods_without_return_values);
-};
-
-#endif
-
-// Invoker<>
-//
-// See description at the top of the file.
-template <int NumBound, typename Storage, typename RunType>
-struct Invoker;
-
-$for ARITY [[
-
-$$ Number of bound arguments.
-$range BOUND 0..ARITY
-$for BOUND [[
-
-$var UNBOUND = ARITY - BOUND
-$range ARG 1..ARITY
-$range BOUND_ARG 1..BOUND
-$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY
-
-// Arity $(ARITY) -> $(UNBOUND).
-template <typename StorageType, typename R[[]]
-$if ARITY > 0 [[,]][[]]
-$for ARG , [[typename X$(ARG)]]>
-struct Invoker<$(BOUND), StorageType, R($for ARG , [[X$(ARG)]])> {
-  typedef R(RunType)(BindStateBase*[[]]
-$if UNBOUND != 0 [[, ]]
-$for UNBOUND_ARG , [[typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType]]);
-
-  typedef R(UnboundRunType)($for UNBOUND_ARG , [[X$(UNBOUND_ARG)]]);
-
-  static R Run(BindStateBase* base[[]]
-$if UNBOUND != 0 [[, ]][[]]
-$for UNBOUND_ARG , [[
-typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
-]][[]]
-) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-$for BOUND_ARG
-[[
-
-    typedef typename StorageType::Bound$(BOUND_ARG)UnwrapTraits Bound$(BOUND_ARG)UnwrapTraits;
-]]
-
-
-$for BOUND_ARG
-[[
-
-    typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType x$(BOUND_ARG) =
-        Bound$(BOUND_ARG)UnwrapTraits::Unwrap(storage->p$(BOUND_ARG)_);
-]]
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-           typename StorageType::RunnableType,
-           void(
-$for BOUND_ARG , [[
-typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType
-]]
-
-$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]
-
-$for UNBOUND_ARG , [[
-typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
-]]
-)>
-               ::MakeItSo(storage->runnable_
-$if ARITY > 0[[, ]] $for ARG , [[CallbackForward(x$(ARG))]]);
-  }
-};
-
-]] $$ for BOUND
-]] $$ for ARITY
-
-
-// BindState<>
-//
-// This stores all the state passed into Bind() and is also where most
-// of the template resolution magic occurs.
-//
-// Runnable is the functor we are binding arguments to.
-// RunType is type of the Run() function that the Invoker<> should use.
-// Normally, this is the same as the RunType of the Runnable, but it can
-// be different if an adapter like IgnoreResult() has been used.
-//
-// BoundArgsType contains the storage type for all the bound arguments by
-// (ab)using a function type.
-template <typename Runnable, typename RunType, typename BoundArgsType>
-struct BindState;
-
-$for ARITY [[
-$range ARG 1..ARITY
-
-template <typename Runnable, typename RunType[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename P$(ARG)]]>
-struct BindState<Runnable, RunType, void($for ARG , [[P$(ARG)]])> : public BindStateBase {
-  typedef Runnable RunnableType;
-
-$if ARITY > 0 [[
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-]] $else [[
-  typedef false_type IsWeakCall;
-]]
-
-  typedef Invoker<$(ARITY), BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-$if ARITY > 0 [[
-
-  // Convenience typedefs for bound argument types.
-
-$for ARG [[
-  typedef UnwrapTraits<P$(ARG)> Bound$(ARG)UnwrapTraits;
-
-]]  $$ for ARG
-
-
-]]  $$ if ARITY > 0
-
-$$ The extra [[ ]] is needed to massage spacing. Silly pump.py.
-[[  ]]$if ARITY == 0 [[explicit ]]BindState(const Runnable& runnable
-$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]])
-      : runnable_(runnable)[[]]
-$if ARITY == 0 [[
- {
-
-]] $else [[
-, $for ARG , [[
-
-        p$(ARG)_(p$(ARG))
-]] {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-
-]]
-  }
-
-  RunnableType runnable_;
-
-$for ARG [[
-  P$(ARG) p$(ARG)_;
-
-]]
-
- private:
-  ~BindState() override {
-$if ARITY > 0 [[
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-]]
-  }
-
-};
-
-]] $$ for ARITY
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_BIND_INTERNAL_H_
diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc
index 33b5f5c..2596386 100644
--- a/base/bind_unittest.nc
+++ b/base/bind_unittest.nc
@@ -190,7 +190,7 @@
   weak_ptr_with_non_void_return_type.Run();
 }
 
-#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES)  // [r"fatal error: no viable conversion from 'Callback<typename internal::BindState<typename internal::FunctorTraits<void \(\*\)\(int\)>::RunnableType, typename internal::FunctorTraits<void \(\*\)\(int\)>::RunType, void \(\)>::UnboundRunType>' to 'Callback<void \(\)>'"]
+#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES)  // [r"fatal error: no viable conversion from 'Callback<typename internal::BindState<typename internal::FunctorTraits<void \(\*\)\(int\)>::RunnableType, typename internal::FunctorTraits<void \(\*\)\(int\)>::RunType, internal::TypeList<> >::UnboundRunType>' to 'Callback<void \(\)>'"]
 
 // Bind result cannot be assigned to Callbacks with a mismatching type.
 void WontCompile() {
diff --git a/base/chromeos/memory_pressure_observer_chromeos.cc b/base/chromeos/memory_pressure_observer_chromeos.cc
index 8112c76..5691eb8 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.cc
+++ b/base/chromeos/memory_pressure_observer_chromeos.cc
@@ -5,6 +5,7 @@
 #include "base/chromeos/memory_pressure_observer_chromeos.h"
 
 #include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/process/process_metrics.h"
 #include "base/time/time.h"
 
@@ -29,6 +30,16 @@
 const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
 const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
 
+// The possible state for memory pressure level. The values should be in line
+// with values in MemoryPressureListener::MemoryPressureLevel and should be
+// updated if more memory pressure levels are introduced.
+enum MemoryPressureLevelUMA {
+  MEMORY_PRESSURE_LEVEL_NONE = 0,
+  MEMORY_PRESSURE_LEVEL_MODERATE,
+  MEMORY_PRESSURE_LEVEL_CRITICAL,
+  NUM_MEMORY_PRESSURE_LEVELS
+};
+
 // Converts a |MemoryPressureThreshold| value into a used memory percentage for
 // the moderate pressure event.
 int GetModerateMemoryThresholdInPercent(
@@ -92,7 +103,8 @@
 void MemoryPressureObserverChromeOS::StartObserving() {
   timer_.Start(FROM_HERE,
                TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
-               Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
+               Bind(&MemoryPressureObserverChromeOS::
+                        CheckMemoryPressureAndRecordStatistics,
                     weak_ptr_factory_.GetWeakPtr()));
 }
 
@@ -101,6 +113,28 @@
   timer_.Stop();
 }
 
+void MemoryPressureObserverChromeOS::CheckMemoryPressureAndRecordStatistics() {
+  CheckMemoryPressure();
+
+  // Record UMA histogram statistics for the current memory pressure level.
+  MemoryPressureLevelUMA memory_pressure_level_uma(MEMORY_PRESSURE_LEVEL_NONE);
+  switch (current_memory_pressure_level_) {
+    case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+      memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_NONE;
+      break;
+    case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+      memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_MODERATE;
+      break;
+    case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+      memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_CRITICAL;
+      break;
+  }
+
+  UMA_HISTOGRAM_ENUMERATION("ChromeOS.MemoryPressureLevel",
+                            memory_pressure_level_uma,
+                            NUM_MEMORY_PRESSURE_LEVELS);
+}
+
 void MemoryPressureObserverChromeOS::CheckMemoryPressure() {
   MemoryPressureListener::MemoryPressureLevel old_pressure =
       current_memory_pressure_level_;
diff --git a/base/chromeos/memory_pressure_observer_chromeos.h b/base/chromeos/memory_pressure_observer_chromeos.h
index 739b795..9af07d4 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.h
+++ b/base/chromeos/memory_pressure_observer_chromeos.h
@@ -76,6 +76,10 @@
   // critical pressure levels.
   void CheckMemoryPressure();
 
+  // The function periodically checks the memory pressure changes and records
+  // the UMA histogram statistics for the current memory pressure level.
+  void CheckMemoryPressureAndRecordStatistics();
+
   // Get the memory pressure in percent (virtual for testing).
   virtual int GetUsedMemoryInPercent();
 
diff --git a/base/containers/hash_tables.h b/base/containers/hash_tables.h
index 6bf029e..736e892 100644
--- a/base/containers/hash_tables.h
+++ b/base/containers/hash_tables.h
@@ -45,7 +45,7 @@
 #undef __DEPRECATED
 #endif
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && defined(USE_STLPORT)
 #include <hash_map>
 #include <hash_set>
 #define BASE_HASH_IMPL_NAMESPACE std
@@ -84,7 +84,7 @@
   }
 };
 
-#if !defined(OS_ANDROID)
+#if !defined(USE_STLPORT)
 // The GNU C++ library provides identity hash functions for many integral types,
 // but not for |long long|.  This hash function will truncate if |size_t| is
 // narrower than |long long|.  This is probably good enough for what we will
@@ -102,7 +102,7 @@
 DEFINE_TRIVIAL_HASH(unsigned long long);
 
 #undef DEFINE_TRIVIAL_HASH
-#endif  // !defined(OS_ANDROID)
+#endif  // !defined(USE_STLPORT)
 
 // Implement string hash functions so that strings of various flavors can
 // be used as keys in STL maps and sets.  The hash algorithm comes from the
diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h
index 572f285..fb271b6 100644
--- a/base/debug/stack_trace.h
+++ b/base/debug/stack_trace.h
@@ -17,6 +17,7 @@
 
 #if defined(OS_WIN)
 struct _EXCEPTION_POINTERS;
+struct _CONTEXT;
 #endif
 
 namespace base {
@@ -54,6 +55,7 @@
   // Note: this function will throw an import not found (StackWalk64) exception
   // on system without dbghelp 5.1.
   StackTrace(const _EXCEPTION_POINTERS* exception_pointers);
+  StackTrace(const _CONTEXT* context);
 #endif
 
   // Copying and assignment are allowed with the default functions.
@@ -76,6 +78,10 @@
   std::string ToString() const;
 
  private:
+#if defined(OS_WIN)
+  void InitTrace(_CONTEXT* context_record);
+#endif
+
   // From http://msdn.microsoft.com/en-us/library/bb204633.aspx,
   // the sum of FramesToSkip and FramesToCapture must be less than 63,
   // so set it to 62. Even if on POSIX it could be a larger value, it usually
diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc
index 8df6fc6..27661ed 100644
--- a/base/debug/stack_trace_win.cc
+++ b/base/debug/stack_trace_win.cc
@@ -214,24 +214,35 @@
 #endif
 
 StackTrace::StackTrace(const EXCEPTION_POINTERS* exception_pointers) {
-  // When walking an exception stack, we need to use StackWalk64().
-  count_ = 0;
   // StackWalk64() may modify context record passed to it, so we will
   // use a copy.
   CONTEXT context_record = *exception_pointers->ContextRecord;
+  InitTrace(&context_record);
+}
+
+StackTrace::StackTrace(const CONTEXT* context) {
+  // StackWalk64() may modify context record passed to it, so we will
+  // use a copy.
+  CONTEXT context_record = *context;
+  InitTrace(&context_record);
+}
+
+void StackTrace::InitTrace(CONTEXT* context_record) {
+  // When walking an exception stack, we need to use StackWalk64().
+  count_ = 0;
   // Initialize stack walking.
   STACKFRAME64 stack_frame;
   memset(&stack_frame, 0, sizeof(stack_frame));
 #if defined(_WIN64)
   int machine_type = IMAGE_FILE_MACHINE_AMD64;
-  stack_frame.AddrPC.Offset = context_record.Rip;
-  stack_frame.AddrFrame.Offset = context_record.Rbp;
-  stack_frame.AddrStack.Offset = context_record.Rsp;
+  stack_frame.AddrPC.Offset = context_record->Rip;
+  stack_frame.AddrFrame.Offset = context_record->Rbp;
+  stack_frame.AddrStack.Offset = context_record->Rsp;
 #else
   int machine_type = IMAGE_FILE_MACHINE_I386;
-  stack_frame.AddrPC.Offset = context_record.Eip;
-  stack_frame.AddrFrame.Offset = context_record.Ebp;
-  stack_frame.AddrStack.Offset = context_record.Esp;
+  stack_frame.AddrPC.Offset = context_record->Eip;
+  stack_frame.AddrFrame.Offset = context_record->Ebp;
+  stack_frame.AddrStack.Offset = context_record->Esp;
 #endif
   stack_frame.AddrPC.Mode = AddrModeFlat;
   stack_frame.AddrFrame.Mode = AddrModeFlat;
@@ -240,7 +251,7 @@
                      GetCurrentProcess(),
                      GetCurrentThread(),
                      &stack_frame,
-                     &context_record,
+                     context_record,
                      NULL,
                      &SymFunctionTableAccess64,
                      &SymGetModuleBase64,
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
deleted file mode 100644
index 7d97e16..0000000
--- a/base/debug/trace_event.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_H_
-#define BASE_DEBUG_TRACE_EVENT_H_
-
-#include "base/trace_event/trace_event.h"
-
-#endif  // BASE_DEBUG_TRACE_EVENT_H_
diff --git a/base/debug/trace_event_argument.h b/base/debug/trace_event_argument.h
deleted file mode 100644
index 167b46c..0000000
--- a/base/debug/trace_event_argument.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
-#define BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
-
-#include "base/trace_event/trace_event_argument.h"
-
-#endif // BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h
deleted file mode 100644
index a619d29..0000000
--- a/base/debug/trace_event_impl.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_
-#define BASE_DEBUG_TRACE_EVENT_IMPL_H_
-
-#include "base/trace_event/trace_event_impl.h"
-
-#endif  // BASE_DEBUG_TRACE_EVENT_IMPL_H_
diff --git a/base/debug/trace_event_synthetic_delay.h b/base/debug/trace_event_synthetic_delay.h
deleted file mode 100644
index 1f1eafb..0000000
--- a/base/debug/trace_event_synthetic_delay.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
-#define BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
-
-#include "base/trace_event/trace_event_synthetic_delay.h"
-
-#endif  // BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
diff --git a/base/debug/trace_event_win.h b/base/debug/trace_event_win.h
deleted file mode 100644
index 473e174..0000000
--- a/base/debug/trace_event_win.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_WIN_H_
-#define BASE_DEBUG_TRACE_EVENT_WIN_H_
-
-#include "base/trace_event/trace_event_win.h"
-
-#endif  // BASE_DEBUG_TRACE_EVENT_WIN_H_
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
index 73f9cfb..63e5480 100644
--- a/base/files/file_path_watcher_win.cc
+++ b/base/files/file_path_watcher_win.cc
@@ -149,7 +149,8 @@
 void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) {
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("FilePathWatcherImpl_OnObjectSignaled"));
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 FilePathWatcherImpl::OnObjectSignaled"));
 
   DCHECK(object == handle_);
   // Make sure we stay alive through the body of this function.
diff --git a/base/json/json_string_value_serializer.cc b/base/json/json_string_value_serializer.cc
index 59f030d..b626640 100644
--- a/base/json/json_string_value_serializer.cc
+++ b/base/json/json_string_value_serializer.cc
@@ -10,6 +10,21 @@
 
 using base::Value;
 
+JSONStringValueSerializer::JSONStringValueSerializer(std::string* json_string)
+    : json_string_(json_string),
+      json_string_readonly_(*json_string),
+      pretty_print_(false),
+      allow_trailing_comma_(false) {
+}
+
+JSONStringValueSerializer::JSONStringValueSerializer(
+    const base::StringPiece& json_string)
+    : json_string_(nullptr),
+      json_string_readonly_(json_string),
+      pretty_print_(false),
+      allow_trailing_comma_(false) {
+}
+
 JSONStringValueSerializer::~JSONStringValueSerializer() {}
 
 bool JSONStringValueSerializer::Serialize(const Value& root) {
@@ -23,7 +38,7 @@
 
 bool JSONStringValueSerializer::SerializeInternal(const Value& root,
                                                   bool omit_binary_values) {
-  if (!json_string_ || initialized_with_const_string_)
+  if (!json_string_)
     return false;
 
   int options = 0;
@@ -37,10 +52,7 @@
 
 Value* JSONStringValueSerializer::Deserialize(int* error_code,
                                               std::string* error_str) {
-  if (!json_string_)
-    return NULL;
-
-  return base::JSONReader::ReadAndReturnError(*json_string_,
+  return base::JSONReader::ReadAndReturnError(json_string_readonly_,
       allow_trailing_comma_ ? base::JSON_ALLOW_TRAILING_COMMAS :
           base::JSON_PARSE_RFC,
       error_code, error_str);
diff --git a/base/json/json_string_value_serializer.h b/base/json/json_string_value_serializer.h
index 6435051..7f99bc9 100644
--- a/base/json/json_string_value_serializer.h
+++ b/base/json/json_string_value_serializer.h
@@ -10,28 +10,20 @@
 #include "base/base_export.h"
 #include "base/basictypes.h"
 #include "base/files/file_path.h"
+#include "base/strings/string_piece.h"
 #include "base/values.h"
 
 class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer {
  public:
-  // json_string is the string that will be source of the deserialization
+  // |json_string| is the string that will be source of the deserialization
   // or the destination of the serialization.  The caller of the constructor
-  // retains ownership of the string.
-  explicit JSONStringValueSerializer(std::string* json_string)
-      : json_string_(json_string),
-        initialized_with_const_string_(false),
-        pretty_print_(false),
-        allow_trailing_comma_(false) {
-  }
+  // retains ownership of the string. |json_string| must not be null.
+  explicit JSONStringValueSerializer(std::string* json_string);
 
-  // This version allows initialization with a const string reference for
-  // deserialization only.
-  explicit JSONStringValueSerializer(const std::string& json_string)
-      : json_string_(&const_cast<std::string&>(json_string)),
-        initialized_with_const_string_(true),
-        pretty_print_(false),
-        allow_trailing_comma_(false) {
-  }
+  // This version allows initialization with a StringPiece for deserialization
+  // only. Retains a reference to the contents of |json_string|, so the data
+  // must outlive the JSONStringValueSerializer.
+  explicit JSONStringValueSerializer(const base::StringPiece& json_string);
 
   ~JSONStringValueSerializer() override;
 
@@ -46,7 +38,7 @@
 
   // Attempt to deserialize the data structure encoded in the string passed
   // in to the constructor into a structure of Value objects.  If the return
-  // value is NULL, and if |error_code| is non-null, |error_code| will
+  // value is null, and if |error_code| is non-null, |error_code| will
   // contain an integer error code (a JsonParseError in this case).
   // If |error_message| is non-null, it will be filled in with a formatted
   // error message including the location of the error if appropriate.
@@ -64,8 +56,12 @@
  private:
   bool SerializeInternal(const base::Value& root, bool omit_binary_values);
 
+  // String for writing. Owned by the caller of the constructor. Will be null if
+  // the serializer was initialized with a const string.
   std::string* json_string_;
-  bool initialized_with_const_string_;
+  // String for reading. Data is owned by the caller of the constructor. If
+  // |json_string_| is non-null, this is a view onto |json_string_|.
+  base::StringPiece json_string_readonly_;
   bool pretty_print_;  // If true, serialization will span multiple lines.
   // If true, deserialization will allow trailing commas.
   bool allow_trailing_comma_;
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc
index e3c349c..d2a84de 100644
--- a/base/json/json_value_serializer_unittest.cc
+++ b/base/json/json_value_serializer_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/json/json_writer.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/path_service.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -42,6 +43,20 @@
     "\t\"compound\": { \"a\": 1, \"b\": 2, },\n"
     "}\n";
 
+// kProperJSON with a few misc characters at the begin and end.
+const char kProperJSONPadded[] =
+    ")]}'\n"
+    "{\n"
+    "   \"compound\": {\n"
+    "      \"a\": 1,\n"
+    "      \"b\": 2\n"
+    "   },\n"
+    "   \"some_String\": \"1337\",\n"
+    "   \"some_int\": 42,\n"
+    "   \"the_list\": [ \"val1\", \"val2\" ]\n"
+    "}\n"
+    "?!ab\n";
+
 const char kWinLineEnds[] = "\r\n";
 const char kLinuxLineEnds[] = "\n";
 
@@ -74,7 +89,43 @@
 // Test proper JSON [de]serialization from string is working.
 TEST(JSONValueSerializerTest, ReadProperJSONFromString) {
   // Try to deserialize it through the serializer.
+  JSONStringValueSerializer str_deserializer(kProperJSON);
+
+  int error_code = 0;
+  std::string error_message;
+  scoped_ptr<Value> value(
+      str_deserializer.Deserialize(&error_code, &error_message));
+  ASSERT_TRUE(value.get());
+  ASSERT_EQ(0, error_code);
+  ASSERT_TRUE(error_message.empty());
+  // Verify if the same JSON is still there.
+  CheckJSONIsStillTheSame(*value);
+}
+
+// Test proper JSON deserialization from a string pointer is working.
+TEST(JSONValueSerializerTest, ReadProperJSONFromStringPointer) {
+  // Try to deserialize a string pointer through the serializer. (This exercises
+  // a separate code path to passing a StringPiece.)
   std::string proper_json(kProperJSON);
+  JSONStringValueSerializer str_deserializer(&proper_json);
+
+  int error_code = 0;
+  std::string error_message;
+  scoped_ptr<Value> value(
+      str_deserializer.Deserialize(&error_code, &error_message));
+  ASSERT_TRUE(value.get());
+  ASSERT_EQ(0, error_code);
+  ASSERT_TRUE(error_message.empty());
+  // Verify if the same JSON is still there.
+  CheckJSONIsStillTheSame(*value);
+}
+
+// Test proper JSON deserialization from a StringPiece substring.
+TEST(JSONValueSerializerTest, ReadProperJSONFromStringPiece) {
+  // Create a StringPiece for the substring of kProperJSONPadded that matches
+  // kProperJSON.
+  base::StringPiece proper_json(kProperJSONPadded);
+  proper_json = proper_json.substr(5, proper_json.length() - 10);
   JSONStringValueSerializer str_deserializer(proper_json);
 
   int error_code = 0;
@@ -92,8 +143,7 @@
 // the proper flag for that is set.
 TEST(JSONValueSerializerTest, ReadJSONWithTrailingCommasFromString) {
   // Try to deserialize it through the serializer.
-  std::string proper_json(kProperJSONWithCommas);
-  JSONStringValueSerializer str_deserializer(proper_json);
+  JSONStringValueSerializer str_deserializer(kProperJSONWithCommas);
 
   int error_code = 0;
   std::string error_message;
@@ -165,9 +215,9 @@
 }
 
 TEST(JSONValueSerializerTest, Roundtrip) {
-  const std::string original_serialization =
+  static const char kOriginalSerialization[] =
     "{\"bool\":true,\"double\":3.14,\"int\":42,\"list\":[1,2],\"null\":null}";
-  JSONStringValueSerializer serializer(original_serialization);
+  JSONStringValueSerializer serializer(kOriginalSerialization);
   scoped_ptr<Value> root(serializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(root.get());
   ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
@@ -198,7 +248,7 @@
   std::string test_serialization;
   JSONStringValueSerializer mutable_serializer(&test_serialization);
   ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
-  ASSERT_EQ(original_serialization, test_serialization);
+  ASSERT_EQ(kOriginalSerialization, test_serialization);
 
   mutable_serializer.set_pretty_print(true);
   ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
@@ -273,15 +323,15 @@
   string16 test(WideToUTF16(L"\x7F51\x9875"));
   root.SetString("web", test);
 
-  std::string expected = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}";
+  static const char kExpected[] = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}";
 
   std::string actual;
   JSONStringValueSerializer serializer(&actual);
   ASSERT_TRUE(serializer.Serialize(root));
-  ASSERT_EQ(expected, actual);
+  ASSERT_EQ(kExpected, actual);
 
   // escaped ascii text -> json
-  JSONStringValueSerializer deserializer(expected);
+  JSONStringValueSerializer deserializer(kExpected);
   scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(deserial_root.get());
   DictionaryValue* dict_root =
@@ -297,15 +347,15 @@
   string16 test(WideToUTF16(L"\x01\x02"));
   root.SetString("test", test);
 
-  std::string expected = "{\"test\":\"\\u0001\\u0002\"}";
+  static const char kExpected[] = "{\"test\":\"\\u0001\\u0002\"}";
 
   std::string actual;
   JSONStringValueSerializer serializer(&actual);
   ASSERT_TRUE(serializer.Serialize(root));
-  ASSERT_EQ(expected, actual);
+  ASSERT_EQ(kExpected, actual);
 
   // escaped ascii text -> json
-  JSONStringValueSerializer deserializer(expected);
+  JSONStringValueSerializer deserializer(kExpected);
   scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(deserial_root.get());
   DictionaryValue* dict_root =
@@ -315,8 +365,8 @@
   ASSERT_EQ(test, test_value);
 
   // Test converting escaped regular chars
-  std::string escaped_chars = "{\"test\":\"\\u0067\\u006f\"}";
-  JSONStringValueSerializer deserializer2(escaped_chars);
+  static const char kEscapedChars[] = "{\"test\":\"\\u0067\\u006f\"}";
+  JSONStringValueSerializer deserializer2(kEscapedChars);
   deserial_root.reset(deserializer2.Deserialize(NULL, NULL));
   ASSERT_TRUE(deserial_root.get());
   dict_root = static_cast<DictionaryValue*>(deserial_root.get());
@@ -327,12 +377,12 @@
 TEST(JSONValueSerializerTest, AllowTrailingComma) {
   scoped_ptr<Value> root;
   scoped_ptr<Value> root_expected;
-  std::string test_with_commas("{\"key\": [true,],}");
-  std::string test_no_commas("{\"key\": [true]}");
+  static const char kTestWithCommas[] = "{\"key\": [true,],}";
+  static const char kTestNoCommas[] = "{\"key\": [true]}";
 
-  JSONStringValueSerializer serializer(test_with_commas);
+  JSONStringValueSerializer serializer(kTestWithCommas);
   serializer.set_allow_trailing_comma(true);
-  JSONStringValueSerializer serializer_expected(test_no_commas);
+  JSONStringValueSerializer serializer_expected(kTestNoCommas);
   root.reset(serializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(root.get());
   root_expected.reset(serializer_expected.Deserialize(NULL, NULL));
diff --git a/base/memory/discardable_memory_ashmem.h b/base/memory/discardable_memory_ashmem.h
index c1cc077..100655b 100644
--- a/base/memory/discardable_memory_ashmem.h
+++ b/base/memory/discardable_memory_ashmem.h
@@ -25,20 +25,20 @@
                                    DiscardableMemoryAshmemAllocator* allocator,
                                    DiscardableMemoryManager* manager);
 
-  virtual ~DiscardableMemoryAshmem();
+  ~DiscardableMemoryAshmem() override;
 
   bool Initialize();
 
   // Overridden from DiscardableMemory:
-  virtual DiscardableMemoryLockStatus Lock() override;
-  virtual void Unlock() override;
-  virtual void* Memory() const override;
+  DiscardableMemoryLockStatus Lock() override;
+  void Unlock() override;
+  void* Memory() const override;
 
   // Overridden from internal::DiscardableMemoryManagerAllocation:
-  virtual bool AllocateAndAcquireLock() override;
-  virtual void ReleaseLock() override;
-  virtual void Purge() override;
-  virtual bool IsMemoryResident() const override;
+  bool AllocateAndAcquireLock() override;
+  void ReleaseLock() override;
+  void Purge() override;
+  bool IsMemoryResident() const override;
 
  private:
   const size_t bytes_;
diff --git a/base/memory/scoped_open_process.h b/base/memory/scoped_open_process.h
deleted file mode 100644
index 8bb19e2..0000000
--- a/base/memory/scoped_open_process.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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.
-
-#ifndef BASE_MEMORY_SCOPED_OPEN_PROCESS_H_
-#define BASE_MEMORY_SCOPED_OPEN_PROCESS_H_
-
-#include "base/process/process_handle.h"
-
-namespace base {
-
-// A class that opens a process from its process id and closes it when the
-// instance goes out of scope.
-class ScopedOpenProcess {
- public:
-  ScopedOpenProcess() : handle_(kNullProcessHandle) {
-  }
-
-  // Automatically close the process.
-  ~ScopedOpenProcess() {
-    Close();
-  }
-
-  // Open a new process by pid. Closes any previously opened process (even if
-  // opening the new one fails).
-  bool Open(ProcessId pid) {
-    Close();
-    return OpenProcessHandle(pid, &handle_);
-  }
-
-  // Close the previously opened process.
-  void Close() {
-    if (handle_ == kNullProcessHandle)
-      return;
-
-    CloseProcessHandle(handle_);
-    handle_ = kNullProcessHandle;
-  }
-
-  ProcessHandle handle() const { return handle_; }
-
- private:
-  ProcessHandle handle_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedOpenProcess);
-};
-}  // namespace base
-
-#endif  // BASE_MEMORY_SCOPED_OPEN_PROCESS_H_
diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc
index 9e5b013..c1ce939 100644
--- a/base/message_loop/incoming_task_queue.cc
+++ b/base/message_loop/incoming_task_queue.cc
@@ -4,6 +4,8 @@
 
 #include "base/message_loop/incoming_task_queue.h"
 
+#include <limits>
+
 #include "base/location.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
@@ -15,6 +17,13 @@
 
 namespace {
 
+#ifndef NDEBUG
+// Delays larger than this are often bogus, and a warning should be emitted in
+// debug builds to warn developers.  http://crbug.com/450045
+const int kTaskDelayWarningThresholdInSeconds =
+    14 * 24 * 60 * 60;  // 14 days.
+#endif
+
 // Returns true if MessagePump::ScheduleWork() must be called one
 // time for every task that is added to the MessageLoop incoming queue.
 bool AlwaysNotifyPump(MessageLoop::Type type) {
@@ -43,6 +52,11 @@
     const Closure& task,
     TimeDelta delay,
     bool nestable) {
+  DLOG_IF(WARNING,
+          delay.InSeconds() > kTaskDelayWarningThresholdInSeconds)
+      << "Requesting super-long task delay period of " << delay.InSeconds()
+      << " seconds from here: " << from_here.ToString();
+
   AutoLock locked(incoming_queue_lock_);
   PendingTask pending_task(
       from_here, task, CalculateDelayedRuntime(delay), nestable);
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 24db543..86771e4 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -5,7 +5,6 @@
 #include "base/message_loop/message_loop.h"
 
 #include <algorithm>
-#include <limits>
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
@@ -44,12 +43,6 @@
 LazyInstance<base::ThreadLocalPointer<MessageLoop> >::Leaky lazy_tls_ptr =
     LAZY_INSTANCE_INITIALIZER;
 
-// Delays larger than this many microseconds are likely bogus, and a warning
-// should be emitted in debug builds to warn developers.
-// http://crbug.com/450045
-const int kTaskDelayWarningThresholdInMicroseconds =
-    std::numeric_limits<int>::max() / 2;
-
 // Logical events for Histogram profiling. Run with -message-loop-histogrammer
 // to get an accounting of messages and actions taken on each thread.
 const int kTaskRunEvent = 0x1;
@@ -286,10 +279,6 @@
     const Closure& task,
     TimeDelta delay) {
   DCHECK(!task.is_null()) << from_here.ToString();
-  DLOG_IF(WARNING,
-          delay.InMicroseconds() > kTaskDelayWarningThresholdInMicroseconds)
-      << "Requesting super-long task delay period of " << delay.InMicroseconds()
-      << " usec from " << from_here.ToString();
   incoming_task_queue_->AddToIncomingQueue(from_here, task, delay, true);
 }
 
@@ -305,10 +294,6 @@
     const Closure& task,
     TimeDelta delay) {
   DCHECK(!task.is_null()) << from_here.ToString();
-  DLOG_IF(WARNING,
-          delay.InMicroseconds() > kTaskDelayWarningThresholdInMicroseconds)
-      << "Requesting super-long task delay period of " << delay.InMicroseconds()
-      << " usec from " << from_here.ToString();
   incoming_task_queue_->AddToIncomingQueue(from_here, task, delay, false);
 }
 
diff --git a/base/message_loop/message_pump_android.h b/base/message_loop/message_pump_android.h
index 9b4540f..d48050d 100644
--- a/base/message_loop/message_pump_android.h
+++ b/base/message_loop/message_pump_android.h
@@ -22,12 +22,12 @@
 class BASE_EXPORT MessagePumpForUI : public MessagePump {
  public:
   MessagePumpForUI();
-  virtual ~MessagePumpForUI();
+  ~MessagePumpForUI() override;
 
-  virtual void Run(Delegate* delegate) override;
-  virtual void Quit() override;
-  virtual void ScheduleWork() override;
-  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
+  void Run(Delegate* delegate) override;
+  void Quit() override;
+  void ScheduleWork() override;
+  void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
 
   virtual void Start(Delegate* delegate);
 
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index 0a0c99c..4d7225f 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -73,7 +73,8 @@
 void TimerExpiredTask::OnObjectSignaled(HANDLE object) {
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("TimerExpiredTask_OnObjectSignaled"));
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 TimerExpiredTask::OnObjectSignaled"));
 
   process_.Close();
 }
diff --git a/base/process/process.h b/base/process/process.h
index 70aca6d..77d2bce 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -49,6 +49,9 @@
   // Returns an object for the current process.
   static Process Current();
 
+  // Returns a Process for the given |pid|.
+  static Process Open(ProcessId pid);
+
   // Returns a Process for the given |pid|. On Windows the handle is opened
   // with more access rights and must only be used by trusted code (can read the
   // address space and duplicate handles).
diff --git a/base/process/process_handle.h b/base/process/process_handle.h
index 976552c..c99ea15 100644
--- a/base/process/process_handle.h
+++ b/base/process/process_handle.h
@@ -40,9 +40,7 @@
 // Returns the ProcessHandle of the current process.
 BASE_EXPORT ProcessHandle GetCurrentProcessHandle();
 
-// Converts a PID to a process handle. This handle must be closed by
-// CloseProcessHandle when you are done with it. Returns true on success.
-BASE_EXPORT bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle);
+
 
 // Closes the process handle opened by OpenProcessHandle.
 BASE_EXPORT void CloseProcessHandle(ProcessHandle process);
diff --git a/base/process/process_handle_posix.cc b/base/process/process_handle_posix.cc
index 3d92300..a661ecd 100644
--- a/base/process/process_handle_posix.cc
+++ b/base/process/process_handle_posix.cc
@@ -16,13 +16,6 @@
   return GetCurrentProcId();
 }
 
-bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
-  // On Posix platforms, process handles are the same as PIDs, so we
-  // don't need to do anything.
-  *handle = pid;
-  return true;
-}
-
 void CloseProcessHandle(ProcessHandle process) {
   // See OpenProcessHandle, nothing to do.
   return;
diff --git a/base/process/process_handle_win.cc b/base/process/process_handle_win.cc
index 4683311..30b2066 100644
--- a/base/process/process_handle_win.cc
+++ b/base/process/process_handle_win.cc
@@ -20,22 +20,6 @@
   return ::GetCurrentProcess();
 }
 
-bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
-  // We try to limit privileges granted to the handle. If you need this
-  // for test code, consider using OpenPrivilegedProcessHandle instead of
-  // adding more privileges here.
-  ProcessHandle result = OpenProcess(PROCESS_TERMINATE |
-                                     PROCESS_QUERY_INFORMATION |
-                                     SYNCHRONIZE,
-                                     FALSE, pid);
-
-  if (result == NULL)
-    return false;
-
-  *handle = result;
-  return true;
-}
-
 void CloseProcessHandle(ProcessHandle process) {
   CloseHandle(process);
 }
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index e8db571..dd37236 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -399,17 +399,36 @@
   return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached;
 }
 
-// Exposed for testing.
 int ParseProcStatCPU(const std::string& input) {
-  std::vector<std::string> proc_stats;
-  if (!internal::ParseProcStats(input, &proc_stats))
+  // |input| may be empty if the process disappeared somehow.
+  // e.g. http://crbug.com/145811.
+  if (input.empty())
     return -1;
 
-  if (proc_stats.size() <= internal::VM_STIME)
+  size_t start = input.find_last_of(')');
+  if (start == input.npos)
     return -1;
-  int utime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME);
-  int stime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME);
-  return utime + stime;
+
+  // Number of spaces remaining until reaching utime's index starting after the
+  // last ')'.
+  int num_spaces_remaining = internal::VM_UTIME - 1;
+
+  size_t i = start;
+  while ((i = input.find(' ', i + 1)) != input.npos) {
+    // Validate the assumption that there aren't any contiguous spaces
+    // in |input| before utime.
+    DCHECK_NE(input[i - 1], ' ');
+    if (--num_spaces_remaining == 0) {
+      int utime = 0;
+      int stime = 0;
+      if (sscanf(&input.data()[i], "%d %d", &utime, &stime) != 2)
+        return -1;
+
+      return utime + stime;
+    }
+  }
+
+  return -1;
 }
 
 const char kProcSelfExe[] = "/proc/self/exe";
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
index 69f5e83..dbfaa1a 100644
--- a/base/process/process_metrics_unittest.cc
+++ b/base/process/process_metrics_unittest.cc
@@ -323,6 +323,17 @@
       "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0";
 
   EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat));
+
+  // Some weird long-running process with a weird name that I created for the
+  // purposes of this test.
+  const char kWeirdNameStat[] = "26115 (Hello) You ()))  ) R 24614 26115 24614"
+      " 34839 26115 4218880 227 0 0 0 "
+      "5186 11 0 0 "
+      "20 0 1 0 36933953 4296704 90 18446744073709551615 4194304 4196116 "
+      "140735857761568 140735857761160 4195644 0 0 0 0 0 0 0 17 14 0 0 0 0 0 "
+      "6295056 6295616 16519168 140735857770710 140735857770737 "
+      "140735857770737 140735857774557 0";
+  EXPECT_EQ(5186 + 11, base::ParseProcStatCPU(kWeirdNameStat));
 }
 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
 
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index 5d7007c..bc2f3f8 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -14,7 +14,6 @@
 namespace base {
 
 Process::Process(ProcessHandle handle) : process_(handle) {
-  CHECK_NE(handle, GetCurrentProcessHandle());
 }
 
 Process::Process(RValue other)
@@ -32,19 +31,22 @@
 
 // static
 Process Process::Current() {
-  Process process;
-  process.process_ = GetCurrentProcessHandle();
-  return process.Pass();
+  return Process(GetCurrentProcessHandle());
+}
+
+// static
+Process Process::Open(ProcessId pid) {
+  if (pid == GetCurrentProcId())
+    return Current();
+
+  // On POSIX process handles are the same as PIDs.
+  return Process(pid);
 }
 
 // static
 Process Process::OpenWithExtraPriviles(ProcessId pid) {
-  if (pid == GetCurrentProcId())
-    return Current();
-
-  // On POSIX process handles are the same as PIDs, and there are no privileges
-  // to set.
-  return Process(pid);
+  // On POSIX there are no privileges to set.
+  return Open(pid);
 }
 
 // static
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index 0107015..4e600f9 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -47,10 +47,14 @@
 }
 
 // static
+Process Process::Open(ProcessId pid) {
+  return Process(::OpenProcess(kBasicProcessAccess, FALSE, pid));
+}
+
+// static
 Process Process::OpenWithExtraPriviles(ProcessId pid) {
   DWORD access = kBasicProcessAccess | PROCESS_DUP_HANDLE | PROCESS_VM_READ;
-  ProcessHandle handle = ::OpenProcess(access, FALSE, pid);
-  return Process(handle);
+  return Process(::OpenProcess(access, FALSE, pid));
 }
 
 // static
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index f77034b..8f334da 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -454,8 +454,8 @@
   return DoLowerCaseEqualsASCII(a_begin, a_end, b);
 }
 
-// TODO(port): Resolve wchar_t/iterator issues that require OS_ANDROID here.
-#if !defined(OS_ANDROID)
+// TODO(jdduke): Remove guards after complete adoption of libc++ on Android.
+#if !defined(OS_ANDROID) || !defined(USE_STLPORT)
 bool LowerCaseEqualsASCII(const char* a_begin,
                           const char* a_end,
                           const char* b) {
@@ -467,8 +467,7 @@
                           const char* b) {
   return DoLowerCaseEqualsASCII(a_begin, a_end, b);
 }
-
-#endif  // !defined(OS_ANDROID)
+#endif  // !defined(OS_ANDROID) || !defined(USE_STLPORT)
 
 bool EqualsASCII(const string16& a, const base::StringPiece& b) {
   if (a.length() != b.length())
diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h
index 602ba27..61eda20 100644
--- a/base/strings/string_util_win.h
+++ b/base/strings/string_util_win.h
@@ -34,12 +34,9 @@
 
 inline int vsnprintf(char* buffer, size_t size,
                      const char* format, va_list arguments) {
-  int length = _vsprintf_p(buffer, size, format, arguments);
-  if (length < 0) {
-    if (size > 0)
-      buffer[0] = 0;
-    return _vscprintf_p(format, arguments);
-  }
+  int length = vsnprintf_s(buffer, size, size - 1, format, arguments);
+  if (length < 0)
+    return _vscprintf(format, arguments);
   return length;
 }
 
@@ -47,12 +44,9 @@
                      const wchar_t* format, va_list arguments) {
   DCHECK(IsWprintfFormatPortable(format));
 
-  int length = _vswprintf_p(buffer, size, format, arguments);
-  if (length < 0) {
-    if (size > 0)
-      buffer[0] = 0;
-    return _vscwprintf_p(format, arguments);
-  }
+  int length = _vsnwprintf_s(buffer, size, size - 1, format, arguments);
+  if (length < 0)
+    return _vscwprintf(format, arguments);
   return length;
 }
 
diff --git a/base/strings/stringprintf_unittest.cc b/base/strings/stringprintf_unittest.cc
index 3217478..c49637c 100644
--- a/base/strings/stringprintf_unittest.cc
+++ b/base/strings/stringprintf_unittest.cc
@@ -163,19 +163,6 @@
 }
 #endif
 
-// Test that the positional parameters work.
-TEST(StringPrintfTest, PositionalParameters) {
-  std::string out;
-  SStringPrintf(&out, "%1$s %1$s", "test");
-  EXPECT_STREQ("test test", out.c_str());
-
-#if defined(OS_WIN)
-  std::wstring wout;
-  SStringPrintf(&wout, L"%1$ls %1$ls", L"test");
-  EXPECT_STREQ(L"test test", wout.c_str());
-#endif
-}
-
 // Test that StringPrintf and StringAppendV do not change errno.
 TEST(StringPrintfTest, StringPrintfErrno) {
   errno = 1;
diff --git a/base/synchronization/waitable_event_watcher_win.cc b/base/synchronization/waitable_event_watcher_win.cc
index f5218f1..a04a435 100644
--- a/base/synchronization/waitable_event_watcher_win.cc
+++ b/base/synchronization/waitable_event_watcher_win.cc
@@ -39,7 +39,8 @@
 void WaitableEventWatcher::OnObjectSignaled(HANDLE h) {
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("WaitableEventWatche_OnObjectSignaled"));
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 WaitableEventWatcher::OnObjectSignaled"));
 
   WaitableEvent* event = event_;
   EventCallback callback = callback_;
diff --git a/base/test/test_support_android.cc b/base/test/test_support_android.cc
index eeab9ee..11a0871 100644
--- a/base/test/test_support_android.cc
+++ b/base/test/test_support_android.cc
@@ -72,14 +72,14 @@
 
 // The MessagePumpForUI implementation for test purpose.
 class MessagePumpForUIStub : public base::MessagePumpForUI {
-  virtual ~MessagePumpForUIStub() {}
+  ~MessagePumpForUIStub() override {}
 
-  virtual void Start(base::MessagePump::Delegate* delegate) override {
+  void Start(base::MessagePump::Delegate* delegate) override {
     NOTREACHED() << "The Start() method shouldn't be called in test, using"
         " Run() method should be used.";
   }
 
-  virtual void Run(base::MessagePump::Delegate* delegate) override {
+  void Run(base::MessagePump::Delegate* delegate) override {
     // The following was based on message_pump_glib.cc, except we're using a
     // WaitableEvent since there are no native message loop to use.
     RunState state(delegate, g_state ? g_state->run_depth + 1 : 1);
@@ -119,16 +119,11 @@
     g_state = previous_state;
   }
 
-  virtual void Quit() override {
-    Waitable::GetInstance()->Quit();
-  }
+  void Quit() override { Waitable::GetInstance()->Quit(); }
 
-  virtual void ScheduleWork() override {
-    Waitable::GetInstance()->Signal();
-  }
+  void ScheduleWork() override { Waitable::GetInstance()->Signal(); }
 
-  virtual void ScheduleDelayedWork(
-      const base::TimeTicks& delayed_work_time) override {
+  void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override {
     Waitable::GetInstance()->Signal();
   }
 };
diff --git a/base/test/test_support_ios.mm b/base/test/test_support_ios.mm
index 67fae06..3b31da6 100644
--- a/base/test/test_support_ios.mm
+++ b/base/test/test_support_ios.mm
@@ -11,6 +11,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_pump_default.h"
 #include "base/test/test_suite.h"
+#include "testing/coverage_util_ios.h"
 
 // Springboard will kill any iOS app that fails to check in after launch within
 // a given time. Starting a UIApplication before invoking TestSuite::Run
@@ -165,6 +166,8 @@
   UIApplication* application = [UIApplication sharedApplication];
   [application _terminateWithStatus:exitStatus];
 
+  coverage_util::FlushCoverageDataIfNecessary();
+
   exit(exitStatus);
 }
 
diff --git a/base/threading/thread_checker.h b/base/threading/thread_checker.h
index 4d71f79..449247a 100644
--- a/base/threading/thread_checker.h
+++ b/base/threading/thread_checker.h
@@ -30,7 +30,7 @@
 // right version for your build configuration.
 class ThreadCheckerDoNothing {
  public:
-  bool CalledOnValidThread() const {
+  bool CalledOnValidThread() const WARN_UNUSED_RESULT {
     return true;
   }
 
diff --git a/base/threading/thread_checker_impl.h b/base/threading/thread_checker_impl.h
index 879ac3a..c92e143 100644
--- a/base/threading/thread_checker_impl.h
+++ b/base/threading/thread_checker_impl.h
@@ -6,6 +6,7 @@
 #define BASE_THREADING_THREAD_CHECKER_IMPL_H_
 
 #include "base/base_export.h"
+#include "base/compiler_specific.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 
@@ -22,7 +23,7 @@
   ThreadCheckerImpl();
   ~ThreadCheckerImpl();
 
-  bool CalledOnValidThread() const;
+  bool CalledOnValidThread() const WARN_UNUSED_RESULT;
 
   // Changes the thread that is checked for in CalledOnValidThread.  This may
   // be useful when an object may be created on one thread and then used
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index 7f73071..c8583d7 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -141,7 +141,7 @@
 // means, if the category for the event is disabled, the conversion will not
 // happen.
 //
-//   class MyData : public base::debug::ConvertableToTraceFormat {
+//   class MyData : public base::trace_event::ConvertableToTraceFormat {
 //    public:
 //     MyData() {}
 //     virtual void AppendAsTraceFormat(std::string* out) const override {
@@ -596,6 +596,15 @@
         category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
         arg1_name, arg1_val)
 
+// Similar to TRACE_EVENT_ASYNC_STEP_INTOx but with a custom |at| timestamp
+// provided.
+#define TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category_group, name, \
+        id, step, timestamp) \
+    INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+        TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \
+        static_cast<int>(base::PlatformThread::CurrentId()), \
+        timestamp, TRACE_EVENT_FLAG_NONE, "step", step)
+
 // Records a single ASYNC_STEP_PAST event for |step| immediately. If the
 // category is not enabled, then this does nothing. The |name| and |id| must
 // match the ASYNC_BEGIN event above. The |step| param identifies this step
@@ -795,8 +804,8 @@
 
 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
     UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
-        (base::debug::TraceLog::ENABLED_FOR_RECORDING | \
-         base::debug::TraceLog::ENABLED_FOR_EVENT_CALLBACK))
+        (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \
+         base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK))
 
 // Macro to efficiently determine if a given category group is enabled.
 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
@@ -839,16 +848,16 @@
 // const unsigned char*
 //     TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
-    base::debug::TraceLog::GetCategoryGroupEnabled
+    base::trace_event::TraceLog::GetCategoryGroupEnabled
 
 // Get the number of times traces have been recorded. This is used to implement
 // the TRACE_EVENT_IS_NEW_TRACE facility.
 // unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
 #define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \
-    base::debug::TraceLog::GetInstance()->GetNumTracesRecorded
+    base::trace_event::TraceLog::GetInstance()->GetNumTracesRecorded
 
 // Add a trace event to the platform tracing system.
-// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
+// base::trace_event::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
 //                    char phase,
 //                    const unsigned char* category_group_enabled,
 //                    const char* name,
@@ -859,10 +868,11 @@
 //                    const unsigned long long* arg_values,
 //                    unsigned char flags)
 #define TRACE_EVENT_API_ADD_TRACE_EVENT \
-    base::debug::TraceLog::GetInstance()->AddTraceEvent
+    base::trace_event::TraceLog::GetInstance()->AddTraceEvent
 
 // Add a trace event to the platform tracing system.
-// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
+// base::trace_event::TraceEventHandle
+// TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
 //                    char phase,
 //                    const unsigned char* category_group_enabled,
 //                    const char* name,
@@ -875,15 +885,16 @@
 //                    const unsigned long long* arg_values,
 //                    unsigned char flags)
 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \
-    base::debug::TraceLog::GetInstance()->AddTraceEventWithThreadIdAndTimestamp
+    base::trace_event::TraceLog::GetInstance() \
+      ->AddTraceEventWithThreadIdAndTimestamp
 
 // Set the duration field of a COMPLETE trace event.
 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
 //     const unsigned char* category_group_enabled,
 //     const char* name,
-//     base::debug::TraceEventHandle id)
+//     base::trace_event::TraceEventHandle id)
 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
-    base::debug::TraceLog::GetInstance()->UpdateTraceEventDuration
+    base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDuration
 
 // Defines atomic operations used internally by the tracing system.
 #define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord
@@ -956,11 +967,12 @@
     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
     trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
-      base::debug::TraceEventHandle h = trace_event_internal::AddTraceEvent( \
-          TRACE_EVENT_PHASE_COMPLETE, \
-          INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
-          name, trace_event_internal::kNoEventId, \
-          TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
+      base::trace_event::TraceEventHandle h = \
+          trace_event_internal::AddTraceEvent( \
+              TRACE_EVENT_PHASE_COMPLETE, \
+              INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
+              trace_event_internal::kNoEventId, TRACE_EVENT_FLAG_NONE, \
+              ##__VA_ARGS__); \
       INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
           INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
     }
@@ -1253,7 +1265,7 @@
 // pointers to the internal c_str and pass through to the tracing API,
 // the arg_values must live throughout these procedures.
 
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
@@ -1263,7 +1275,8 @@
     const base::TimeTicks& timestamp,
     unsigned char flags,
     const char* arg1_name,
-    const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val) {
+    const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
+        arg1_val) {
   const int num_args = 1;
   unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE };
   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
@@ -1272,7 +1285,7 @@
 }
 
 template<class ARG1_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
@@ -1284,7 +1297,8 @@
     const char* arg1_name,
     const ARG1_TYPE& arg1_val,
     const char* arg2_name,
-    const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) {
+    const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
+        arg2_val) {
   const int num_args = 2;
   const char* arg_names[2] = { arg1_name, arg2_name };
 
@@ -1293,7 +1307,8 @@
   SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
   arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE;
 
-  scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2];
+  scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[2];
   convertable_values[1] = arg2_val;
 
   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
@@ -1302,7 +1317,7 @@
 }
 
 template<class ARG2_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
@@ -1312,7 +1327,7 @@
     const base::TimeTicks& timestamp,
     unsigned char flags,
     const char* arg1_name,
-    const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val,
+    const scoped_refptr<base::trace_event::ConvertableToTraceFormat>& arg1_val,
     const char* arg2_name,
     const ARG2_TYPE& arg2_val) {
   const int num_args = 2;
@@ -1324,7 +1339,8 @@
   arg_values[0] = 0;
   SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
 
-  scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2];
+  scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[2];
   convertable_values[0] = arg1_val;
 
   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
@@ -1332,7 +1348,7 @@
       num_args, arg_names, arg_types, arg_values, convertable_values, flags);
 }
 
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
@@ -1342,22 +1358,23 @@
     const base::TimeTicks& timestamp,
     unsigned char flags,
     const char* arg1_name,
-    const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val,
+    const scoped_refptr<base::trace_event::ConvertableToTraceFormat>& arg1_val,
     const char* arg2_name,
-    const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) {
+    const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
+        arg2_val) {
   const int num_args = 2;
   const char* arg_names[2] = { arg1_name, arg2_name };
   unsigned char arg_types[2] =
       { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE };
-  scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2] =
-      { arg1_val, arg2_val };
+  scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[2] = {arg1_val, arg2_val};
 
   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
       phase, category_group_enabled, name, id, thread_id, timestamp,
       num_args, arg_names, arg_types, NULL, convertable_values, flags);
 }
 
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
@@ -1371,7 +1388,7 @@
       kZeroNumArgs, NULL, NULL, NULL, NULL, flags);
 }
 
-static inline base::debug::TraceEventHandle AddTraceEvent(
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
     char phase,
     const unsigned char* category_group_enabled,
     const char* name,
@@ -1384,7 +1401,7 @@
 }
 
 template<class ARG1_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
@@ -1405,7 +1422,7 @@
 }
 
 template<class ARG1_TYPE>
-static inline base::debug::TraceEventHandle AddTraceEvent(
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
     char phase,
     const unsigned char* category_group_enabled,
     const char* name,
@@ -1421,7 +1438,7 @@
 }
 
 template<class ARG1_TYPE, class ARG2_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
@@ -1446,7 +1463,7 @@
 }
 
 template<class ARG1_TYPE, class ARG2_TYPE>
-static inline base::debug::TraceEventHandle AddTraceEvent(
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
     char phase,
     const unsigned char* category_group_enabled,
     const char* name,
@@ -1478,7 +1495,7 @@
 
   void Initialize(const unsigned char* category_group_enabled,
                   const char* name,
-                  base::debug::TraceEventHandle event_handle) {
+                  base::trace_event::TraceEventHandle event_handle) {
     data_.category_group_enabled = category_group_enabled;
     data_.name = name;
     data_.event_handle = event_handle;
@@ -1494,7 +1511,7 @@
   struct Data {
     const unsigned char* category_group_enabled;
     const char* name;
-    base::debug::TraceEventHandle event_handle;
+    base::trace_event::TraceEventHandle event_handle;
   };
   Data* p_data_;
   Data data_;
@@ -1509,7 +1526,7 @@
  private:
   const unsigned char* category_group_enabled_;
   const char* name_;
-  base::debug::TraceEventHandle event_handle_;
+  base::trace_event::TraceEventHandle event_handle_;
 };
 
 // This macro generates less code then TRACE_EVENT0 but is also
@@ -1555,7 +1572,7 @@
 }  // namespace trace_event_internal
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 template<typename IDType> class TraceScopedTrackableObject {
  public:
@@ -1583,7 +1600,15 @@
   DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject);
 };
 
-} // namespace debug
-} // namespace base
+}  // namespace trace_event
+}  // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::TraceScopedTrackableObject;
+}  // namespace debug
+}  // namespace base
 
 #endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */
diff --git a/base/trace_event/trace_event_android.cc b/base/trace_event/trace_event_android.cc
index 31da26d..bcba436 100644
--- a/base/trace_event/trace_event_android.cc
+++ b/base/trace_event/trace_event_android.cc
@@ -24,8 +24,8 @@
     unsigned long long id,
     const char** arg_names,
     const unsigned char* arg_types,
-    const base::debug::TraceEvent::TraceValue* arg_values,
-    const scoped_refptr<base::debug::ConvertableToTraceFormat>*
+    const base::trace_event::TraceEvent::TraceValue* arg_values,
+    const scoped_refptr<base::trace_event::ConvertableToTraceFormat>*
         convertable_values,
     unsigned char flags) {
   std::string out = base::StringPrintf("%c|%d|%s", phase, getpid(), name);
@@ -33,7 +33,8 @@
     base::StringAppendF(&out, "-%" PRIx64, static_cast<uint64>(id));
   out += '|';
 
-  for (int i = 0; i < base::debug::kTraceMaxNumArgs && arg_names[i]; ++i) {
+  for (int i = 0; i < base::trace_event::kTraceMaxNumArgs && arg_names[i];
+       ++i) {
     if (i)
       out += ';';
     out += arg_names[i];
@@ -42,8 +43,8 @@
     if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
       convertable_values[i]->AppendAsTraceFormat(&out);
     } else {
-      base::debug::TraceEvent::AppendValueAsJSON(
-          arg_types[i], arg_values[i], &out);
+      base::trace_event::TraceEvent::AppendValueAsJSON(arg_types[i],
+                                                       arg_values[i], &out);
     }
     // Remove the quotes which may confuse the atrace script.
     ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'");
@@ -65,7 +66,7 @@
     complete_event->Signal();
 }
 
-void EndChromeTracing(base::debug::TraceLog* trace_log,
+void EndChromeTracing(base::trace_event::TraceLog* trace_log,
                       base::WaitableEvent* complete_event) {
   trace_log->SetDisabled();
   // Delete the buffered trace events as they have been sent to atrace.
@@ -75,7 +76,7 @@
 }  // namespace
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 // These functions support Android systrace.py when 'webview' category is
 // traced. With the new adb_profile_chrome, we may have two phases:
@@ -195,5 +196,5 @@
   close(atrace_fd);
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_argument.cc b/base/trace_event/trace_event_argument.cc
index 00fcde1..91ed9e8 100644
--- a/base/trace_event/trace_event_argument.cc
+++ b/base/trace_event/trace_event_argument.cc
@@ -8,7 +8,7 @@
 #include "base/values.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 TracedValue::TracedValue() : root_(new DictionaryValue()) {
   stack_.push_back(root_.get());
@@ -113,5 +113,5 @@
   DCHECK_EQ(1u, stack_.size()) << tmp;
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h
index 08a5b50..43a0f38 100644
--- a/base/trace_event/trace_event_argument.h
+++ b/base/trace_event/trace_event_argument.h
@@ -16,7 +16,7 @@
 class ListValue;
 class Value;
 
-namespace debug {
+namespace trace_event {
 
 class BASE_EXPORT TracedValue : public ConvertableToTraceFormat {
  public:
@@ -53,6 +53,14 @@
   DISALLOW_COPY_AND_ASSIGN(TracedValue);
 };
 
+}  // namespace trace_event
+}  // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::TracedValue;
 }  // namespace debug
 }  // namespace base
 
diff --git a/base/trace_event/trace_event_argument_unittest.cc b/base/trace_event/trace_event_argument_unittest.cc
index 39cafef..c59910e 100644
--- a/base/trace_event/trace_event_argument_unittest.cc
+++ b/base/trace_event/trace_event_argument_unittest.cc
@@ -6,7 +6,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 TEST(TraceEventArgumentTest, FlatDictionary) {
   scoped_refptr<TracedValue> value = new TracedValue();
@@ -49,5 +49,5 @@
       json);
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index a8a0cc1..95cf06d 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -41,8 +41,8 @@
 class DeleteTraceLogForTesting {
  public:
   static void Delete() {
-    Singleton<base::debug::TraceLog,
-              LeakySingletonTraits<base::debug::TraceLog> >::OnExit(0);
+    Singleton<base::trace_event::TraceLog,
+              LeakySingletonTraits<base::trace_event::TraceLog>>::OnExit(0);
   }
 };
 
@@ -50,7 +50,7 @@
 BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3];
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 namespace {
 
@@ -2560,7 +2560,7 @@
   return delays_;
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
 
 namespace trace_event_internal {
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 6d04c76..742f6b6 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -27,17 +27,17 @@
 // Older style trace macros with explicit id and extra data
 // Only these macros result in publishing data to ETW as currently implemented.
 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
-    base::debug::TraceLog::AddTraceEventEtw( \
+    base::trace_event::TraceLog::AddTraceEventEtw( \
         TRACE_EVENT_PHASE_BEGIN, \
         name, reinterpret_cast<const void*>(id), extra)
 
 #define TRACE_EVENT_END_ETW(name, id, extra) \
-    base::debug::TraceLog::AddTraceEventEtw( \
+    base::trace_event::TraceLog::AddTraceEventEtw( \
         TRACE_EVENT_PHASE_END, \
         name, reinterpret_cast<const void*>(id), extra)
 
 #define TRACE_EVENT_INSTANT_ETW(name, id, extra) \
-    base::debug::TraceLog::AddTraceEventEtw( \
+    base::trace_event::TraceLog::AddTraceEventEtw( \
         TRACE_EVENT_PHASE_INSTANT, \
         name, reinterpret_cast<const void*>(id), extra)
 
@@ -49,7 +49,7 @@
 class WaitableEvent;
 class MessageLoop;
 
-namespace debug {
+namespace trace_event {
 
 // For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
 // class must implement this interface.
@@ -807,6 +807,23 @@
   DISALLOW_COPY_AND_ASSIGN(TraceLog);
 };
 
+}  // namespace trace_event
+}  // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::CategoryFilter;
+using base::trace_event::ConvertableToTraceFormat;
+using base::trace_event::RECORD_UNTIL_FULL;
+using base::trace_event::RECORD_CONTINUOUSLY;
+using base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE;
+using base::trace_event::TraceEventHandle;
+using base::trace_event::TraceLog;
+using base::trace_event::TraceLogStatus;
+using base::trace_event::TraceOptions;
+using base::trace_event::TraceResultBuffer;
 }  // namespace debug
 }  // namespace base
 
diff --git a/base/trace_event/trace_event_impl_constants.cc b/base/trace_event/trace_event_impl_constants.cc
index c46cf49..ffeacff 100644
--- a/base/trace_event/trace_event_impl_constants.cc
+++ b/base/trace_event/trace_event_impl_constants.cc
@@ -5,7 +5,7 @@
 #include "base/trace_event/trace_event_impl.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 // Enable everything but debug and test categories by default.
 const char CategoryFilter::kDefaultCategoryFilterString[] = "-*Debug,-*Test";
@@ -24,5 +24,5 @@
 const TraceLog::InternalTraceOptions
     TraceLog::kInternalRecordAsMuchAsPossible = 1 << 4;
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_memory.cc b/base/trace_event/trace_event_memory.cc
index 96b28e4..2bf6d38 100644
--- a/base/trace_event/trace_event_memory.cc
+++ b/base/trace_event/trace_event_memory.cc
@@ -15,7 +15,7 @@
 #include "base/trace_event/trace_event.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 namespace {
 
@@ -26,13 +26,13 @@
 
 /////////////////////////////////////////////////////////////////////////////
 // Holds a memory dump until the tracing system needs to serialize it.
-class MemoryDumpHolder : public base::debug::ConvertableToTraceFormat {
+class MemoryDumpHolder : public base::trace_event::ConvertableToTraceFormat {
  public:
   // Takes ownership of dump, which must be a JSON string, allocated with
   // malloc() and NULL terminated.
   explicit MemoryDumpHolder(char* dump) : dump_(dump) {}
 
-  // base::debug::ConvertableToTraceFormat overrides:
+  // base::trace_event::ConvertableToTraceFormat overrides:
   void AppendAsTraceFormat(std::string* out) const override {
     AppendHeapProfileAsTraceFormat(dump_, out);
   }
@@ -165,7 +165,7 @@
   TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
 }
 
-  // base::debug::TraceLog::EnabledStateChangedObserver overrides:
+// base::trace_event::TraceLog::EnabledStateChangedObserver overrides:
 void TraceMemoryController::OnTraceLogEnabled() {
   // Check to see if tracing is enabled for the memory category.
   bool enabled;
@@ -436,5 +436,5 @@
   return reinterpret_cast<const char*>(address);
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_memory.h b/base/trace_event/trace_event_memory.h
index f16467f..8e70020 100644
--- a/base/trace_event/trace_event_memory.h
+++ b/base/trace_event/trace_event_memory.h
@@ -22,7 +22,7 @@
 
 class MessageLoopProxy;
 
-namespace debug {
+namespace trace_event {
 
 // Watches for chrome://tracing to be enabled or disabled. When tracing is
 // enabled, also enables tcmalloc heap profiling. This class is the preferred
@@ -46,7 +46,7 @@
       GetHeapProfileFunction get_heap_profile_function);
   virtual ~TraceMemoryController();
 
-  // base::debug::TraceLog::EnabledStateChangedObserver overrides:
+  // base::trace_event::TraceLog::EnabledStateChangedObserver overrides:
   void OnTraceLogEnabled() override;
   void OnTraceLogDisabled() override;
 
@@ -146,7 +146,7 @@
 // and "error" if |address| could not be parsed. Visible for testing.
 BASE_EXPORT const char* StringFromHexAddress(const std::string& hex_address);
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
 
 // Make local variables with unique names based on the line number. Note that
@@ -159,7 +159,7 @@
 // It generates a unique local variable name using the macros above.
 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
 #define INTERNAL_TRACE_MEMORY(category, name) \
-  base::debug::ScopedTraceMemory INTERNAL_TRACE_MEMORY_ID(category, name);
+  base::trace_event::ScopedTraceMemory INTERNAL_TRACE_MEMORY_ID(category, name);
 #else
 #define INTERNAL_TRACE_MEMORY(category, name)
 #endif  // defined(TRACE_MEMORY_SUPPORTED)
diff --git a/base/trace_event/trace_event_memory_unittest.cc b/base/trace_event/trace_event_memory_unittest.cc
index 220c0e6..4732733 100644
--- a/base/trace_event/trace_event_memory_unittest.cc
+++ b/base/trace_event/trace_event_memory_unittest.cc
@@ -16,7 +16,7 @@
 #endif
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 // Tests for the trace event memory tracking system. Exists as a class so it
 // can be a friend of TraceMemoryController.
@@ -236,5 +236,5 @@
   EXPECT_STREQ(kHello, StringFromHexAddress(hex_address.str()));
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_synthetic_delay.cc b/base/trace_event/trace_event_synthetic_delay.cc
index 3651611..4b957c3 100644
--- a/base/trace_event/trace_event_synthetic_delay.cc
+++ b/base/trace_event/trace_event_synthetic_delay.cc
@@ -10,7 +10,7 @@
 }  // namespace
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 TraceEventSyntheticDelayClock::TraceEventSyntheticDelayClock() {}
 TraceEventSyntheticDelayClock::~TraceEventSyntheticDelayClock() {}
@@ -200,7 +200,7 @@
   TraceEventSyntheticDelayRegistry::GetInstance()->ResetAllDelays();
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
 
 namespace trace_event_internal {
@@ -215,15 +215,16 @@
   delay_impl_->EndParallel(end_time_);
 }
 
-base::debug::TraceEventSyntheticDelay* GetOrCreateDelay(
+base::trace_event::TraceEventSyntheticDelay* GetOrCreateDelay(
     const char* name,
     base::subtle::AtomicWord* impl_ptr) {
-  base::debug::TraceEventSyntheticDelay* delay_impl =
-      reinterpret_cast<base::debug::TraceEventSyntheticDelay*>(
+  base::trace_event::TraceEventSyntheticDelay* delay_impl =
+      reinterpret_cast<base::trace_event::TraceEventSyntheticDelay*>(
           base::subtle::Acquire_Load(impl_ptr));
   if (!delay_impl) {
-    delay_impl = base::debug::TraceEventSyntheticDelayRegistry::GetInstance()
-                     ->GetOrCreateDelay(name);
+    delay_impl =
+        base::trace_event::TraceEventSyntheticDelayRegistry::GetInstance()
+            ->GetOrCreateDelay(name);
     base::subtle::Release_Store(
         impl_ptr, reinterpret_cast<base::subtle::AtomicWord>(delay_impl));
   }
diff --git a/base/trace_event/trace_event_synthetic_delay.h b/base/trace_event/trace_event_synthetic_delay.h
index b52f3b0..14801be 100644
--- a/base/trace_event/trace_event_synthetic_delay.h
+++ b/base/trace_event/trace_event_synthetic_delay.h
@@ -65,7 +65,7 @@
 struct DefaultSingletonTraits;
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 // Time source for computing delay durations. Used for testing.
 class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelayClock {
@@ -138,7 +138,7 @@
 // Set the target durations of all registered synthetic delay points to zero.
 TRACE_EVENT_API_CLASS_EXPORT void ResetTraceEventSyntheticDelays();
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
 
 namespace trace_event_internal {
@@ -151,14 +151,14 @@
   ~ScopedSyntheticDelay();
 
  private:
-  base::debug::TraceEventSyntheticDelay* delay_impl_;
+  base::trace_event::TraceEventSyntheticDelay* delay_impl_;
   base::TimeTicks end_time_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay);
 };
 
 // Helper for registering delays. Do not use directly.
-TRACE_EVENT_API_CLASS_EXPORT base::debug::TraceEventSyntheticDelay*
+TRACE_EVENT_API_CLASS_EXPORT base::trace_event::TraceEventSyntheticDelay*
     GetOrCreateDelay(const char* name, base::subtle::AtomicWord* impl_ptr);
 
 }  // namespace trace_event_internal
diff --git a/base/trace_event/trace_event_synthetic_delay_unittest.cc b/base/trace_event/trace_event_synthetic_delay_unittest.cc
index 84ac75c..1dc0fc2 100644
--- a/base/trace_event/trace_event_synthetic_delay_unittest.cc
+++ b/base/trace_event/trace_event_synthetic_delay_unittest.cc
@@ -7,7 +7,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 namespace {
 
 const int kTargetDurationMs = 100;
@@ -150,5 +150,5 @@
   EXPECT_LT((Now() - start_time).InMilliseconds(), kShortDurationMs);
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_system_stats_monitor.cc b/base/trace_event/trace_event_system_stats_monitor.cc
index 6fa0174..98f361a 100644
--- a/base/trace_event/trace_event_system_stats_monitor.cc
+++ b/base/trace_event/trace_event_system_stats_monitor.cc
@@ -16,13 +16,13 @@
 #include "base/trace_event/trace_event.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 namespace {
 
 /////////////////////////////////////////////////////////////////////////////
 // Holds profiled system stats until the tracing system needs to serialize it.
-class SystemStatsHolder : public base::debug::ConvertableToTraceFormat {
+class SystemStatsHolder : public base::trace_event::ConvertableToTraceFormat {
  public:
   SystemStatsHolder() { }
 
@@ -30,7 +30,7 @@
   // Uses the previous stats to compute rates if this is not the first profile.
   void GetSystemProfilingStats();
 
-  // base::debug::ConvertableToTraceFormat overrides:
+  // base::trace_event::ConvertableToTraceFormat overrides:
   void AppendAsTraceFormat(std::string* out) const override {
     AppendSystemProfileAsTraceFormat(system_stats_, out);
   }
@@ -129,5 +129,5 @@
   *output += tmp;
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_system_stats_monitor.h b/base/trace_event/trace_event_system_stats_monitor.h
index 08fbfea..051669a 100644
--- a/base/trace_event/trace_event_system_stats_monitor.h
+++ b/base/trace_event/trace_event_system_stats_monitor.h
@@ -17,7 +17,7 @@
 
 class SingleThreadTaskRunner;
 
-namespace debug {
+namespace trace_event {
 
 // Watches for chrome://tracing to be enabled or disabled. When tracing is
 // enabled, also enables system events profiling. This class is the preferred
@@ -35,7 +35,7 @@
 
   virtual ~TraceEventSystemStatsMonitor();
 
-  // base::debug::TraceLog::EnabledStateChangedObserver overrides:
+  // base::trace_event::TraceLog::EnabledStateChangedObserver overrides:
   void OnTraceLogEnabled() override;
   void OnTraceLogDisabled() override;
 
@@ -69,7 +69,7 @@
                                                   system_stats,
                                                   std::string* output);
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
 
 #endif  // BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_
diff --git a/base/trace_event/trace_event_system_stats_monitor_unittest.cc b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
index 143ac4a..995f53b 100644
--- a/base/trace_event/trace_event_system_stats_monitor_unittest.cc
+++ b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
@@ -12,7 +12,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 #if !defined(OS_IOS)
 // Tests for the system stats monitor.
@@ -62,5 +62,5 @@
 }
 #endif  // !defined(OS_IOS)
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc
index 47b5ab6..a6bc0d4 100644
--- a/base/trace_event/trace_event_unittest.cc
+++ b/base/trace_event/trace_event_unittest.cc
@@ -25,7 +25,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 namespace {
 
@@ -3079,6 +3079,5 @@
   }
 }
 
-
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_win.cc b/base/trace_event/trace_event_win.cc
index d2c3dc8..ebb55c8 100644
--- a/base/trace_event/trace_event_win.cc
+++ b/base/trace_event/trace_event_win.cc
@@ -9,7 +9,7 @@
 #include <initguid.h>  // NOLINT
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 using base::win::EtwEventType;
 using base::win::EtwMofEvent;
@@ -120,5 +120,5 @@
   StaticMemorySingletonTraits<TraceEventETWProvider>::Resurrect();
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_win.h b/base/trace_event/trace_event_win.h
index e447c35..dcb5aac 100644
--- a/base/trace_event/trace_event_win.h
+++ b/base/trace_event/trace_event_win.h
@@ -17,7 +17,7 @@
 struct StaticMemorySingletonTraits;
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 // This EtwTraceProvider subclass implements ETW logging
 // for the macros above on Windows.
@@ -119,6 +119,20 @@
 // Optionally the stack trace, consisting of a DWORD "depth", followed
 //    by an array of void* (machine bitness) of length "depth".
 
+}  // namespace trace_event
+}  // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::kChromeTraceProviderName;
+using base::trace_event::kTraceEventClass32;
+using base::trace_event::kTraceEventClass64;
+using base::trace_event::kTraceEventTypeBegin;
+using base::trace_event::kTraceEventTypeEnd;
+using base::trace_event::kTraceEventTypeInstant;
+using base::trace_event::TraceEventETWProvider;
 }  // namespace debug
 }  // namespace base
 
diff --git a/base/trace_event/trace_event_win_unittest.cc b/base/trace_event/trace_event_win_unittest.cc
index a411301..7f1004e 100644
--- a/base/trace_event/trace_event_win_unittest.cc
+++ b/base/trace_event/trace_event_win_unittest.cc
@@ -20,7 +20,7 @@
 #include <initguid.h>  // NOLINT - must be last include.
 
 namespace base {
-namespace debug {
+namespace trace_event {
 
 namespace {
 
@@ -315,5 +315,5 @@
   PlayLog();
 }
 
-}  // namespace debug
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/win/object_watcher.cc b/base/win/object_watcher.cc
index fe209f5..35609fc 100644
--- a/base/win/object_watcher.cc
+++ b/base/win/object_watcher.cc
@@ -77,7 +77,11 @@
   return true;
 }
 
-HANDLE ObjectWatcher::GetWatchedObject() {
+bool ObjectWatcher::IsWatching() const {
+  return object_ != NULL;
+}
+
+HANDLE ObjectWatcher::GetWatchedObject() const {
   return object_;
 }
 
diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h
index bf7f8b3..ecd0415 100644
--- a/base/win/object_watcher.h
+++ b/base/win/object_watcher.h
@@ -74,9 +74,11 @@
   //
   bool StopWatching();
 
-  // Returns the handle of the object being watched, or NULL if the object
-  // watcher is stopped.
-  HANDLE GetWatchedObject();
+  // Returns true if currently watching an object.
+  bool IsWatching() const;
+
+  // Returns the handle of the object being watched.
+  HANDLE GetWatchedObject() const;
 
  private:
   // Called on a background thread when done waiting.
diff --git a/base/win/object_watcher_unittest.cc b/base/win/object_watcher_unittest.cc
index 46b98de..1a5e9e2 100644
--- a/base/win/object_watcher_unittest.cc
+++ b/base/win/object_watcher_unittest.cc
@@ -37,7 +37,7 @@
   MessageLoop message_loop(message_loop_type);
 
   ObjectWatcher watcher;
-  EXPECT_EQ(NULL, watcher.GetWatchedObject());
+  EXPECT_FALSE(watcher.IsWatching());
 
   // A manual-reset event that is not yet signaled.
   HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -45,13 +45,14 @@
   QuitDelegate delegate;
   bool ok = watcher.StartWatching(event, &delegate);
   EXPECT_TRUE(ok);
+  EXPECT_TRUE(watcher.IsWatching());
   EXPECT_EQ(event, watcher.GetWatchedObject());
 
   SetEvent(event);
 
   MessageLoop::current()->Run();
 
-  EXPECT_EQ(NULL, watcher.GetWatchedObject());
+  EXPECT_FALSE(watcher.IsWatching());
   CloseHandle(event);
 }
 
@@ -115,7 +116,7 @@
 
   MessageLoop::current()->Run();
 
-  EXPECT_EQ(NULL, watcher.GetWatchedObject());
+  EXPECT_FALSE(watcher.IsWatching());
   CloseHandle(event);
 }
 
diff --git a/build/PRESUBMIT.py b/build/PRESUBMIT.py
new file mode 100644
index 0000000..3c70193
--- /dev/null
+++ b/build/PRESUBMIT.py
@@ -0,0 +1,18 @@
+# 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.
+
+WHITELIST = [ r'.+_test.py$' ]
+
+
+def _RunTests(input_api, output_api):
+  return (input_api.canned_checks.RunUnitTestsInDirectory(
+          input_api, output_api, '.', whitelist=[r'.+_test.py$']))
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return _RunTests(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return _RunTests(input_api, output_api)
diff --git a/build/all.gyp b/build/all.gyp
index 90c0120..8556aa7 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -750,7 +750,6 @@
               'dependencies': [
                 '../chrome/chrome_syzygy.gyp:chrome_dll_syzygy',
                 '../content/content_shell_and_tests.gyp:content_shell_syzyasan',
-                '../pdf/pdf.gyp:pdf_syzyasan',
               ],
               'conditions': [
                 ['chrome_multiple_dll==1', {
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index 7f3a868..d1daaf2 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -62,6 +62,7 @@
       output_api,
       unit_tests=[
           J('pylib', 'device', 'device_utils_test.py'),
+          J('pylib', 'device', 'logcat_monitor_test.py'),
           J('pylib', 'gtest', 'gtest_test_instance_test.py'),
           J('pylib', 'instrumentation',
             'instrumentation_test_instance_test.py'),
diff --git a/build/android/adb_gdb b/build/android/adb_gdb
index 97d37db..c71b816 100755
--- a/build/android/adb_gdb
+++ b/build/android/adb_gdb
@@ -26,6 +26,7 @@
 TMPDIR=
 GDBSERVER_PIDFILE=
 TARGET_GDBSERVER=
+COMMAND_PREFIX=
 
 clean_exit () {
   if [ "$TMPDIR" ]; then
@@ -36,7 +37,7 @@
     fi
     if [ "$TARGET_GDBSERVER" ]; then
       log "Removing target gdbserver binary: $TARGET_GDBSERVER."
-      "$ADB" shell run-as "$PACKAGE_NAME" rm "$TARGET_GDBSERVER" >/dev/null 2>&1
+      "$ADB" shell "$COMMAND_PREFIX" rm "$TARGET_GDBSERVER" >/dev/null 2>&1
     fi
     log "Cleaning up: $TMPDIR"
     rm -rf "$TMPDIR"
@@ -908,7 +909,7 @@
 # Push gdbserver to the device
 log "Pushing gdbserver $GDBSERVER to $TARGET_GDBSERVER"
 adb push $GDBSERVER $TMP_TARGET_GDBSERVER &>/dev/null
-adb shell run-as $PACKAGE_NAME cp $TMP_TARGET_GDBSERVER .
+adb shell $COMMAND_PREFIX cp $TMP_TARGET_GDBSERVER $TARGET_GDBSERVER
 adb shell rm $TMP_TARGET_GDBSERVER
 fail_panic "Could not copy gdbserver to the device!"
 
diff --git a/build/android/finalize_apk_action.gypi b/build/android/finalize_apk_action.gypi
index 5ffbffa..9934c1a 100644
--- a/build/android/finalize_apk_action.gypi
+++ b/build/android/finalize_apk_action.gypi
@@ -12,7 +12,7 @@
 #      'input_apk_path': 'relative/path/to/input.apk',
 #      'output_apk_path': 'relative/path/to/output.apk',
 #    },
-#    'includes': [ '../../build/android/finalize_apk.gypi' ],
+#    'includes': [ '../../build/android/finalize_apk_action.gypi' ],
 #  },
 #
 
@@ -34,8 +34,8 @@
     ],
   },
   'inputs': [
-    '<(DEPTH)/build/android/gyp/util/build_utils.py',
     '<(DEPTH)/build/android/gyp/finalize_apk.py',
+    '<(DEPTH)/build/android/gyp/util/build_utils.py',
     '<(keystore_path)',
     '<(input_apk_path)',
   ],
diff --git a/build/android/findbugs_filter/findbugs_known_bugs.txt b/build/android/findbugs_filter/findbugs_known_bugs.txt
index 5ec1107..09c12b2 100644
--- a/build/android/findbugs_filter/findbugs_known_bugs.txt
+++ b/build/android/findbugs_filter/findbugs_known_bugs.txt
@@ -5,4 +5,3 @@
 M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.webContents  In PendingDocumentData.java
 M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.originalIntent  In PendingDocumentData.java
 M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.url  In PendingDocumentData.java
-M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.userGesture  In PendingDocumentData.java
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index 1dbb1d8..7d11671 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -285,7 +285,8 @@
           cmd, 'path does not specify an accessible directory in the device',
           device_serial=self._device_serial)
 
-  def Logcat(self, filter_spec=None, timeout=None):
+  def Logcat(self, clear=False, dump=False, filter_spec=None,
+             logcat_format=None, timeout=None):
     """Get an iterator over the logcat output.
 
     Args:
@@ -296,6 +297,12 @@
       logcat output line by line.
     """
     cmd = ['logcat']
+    if clear:
+      cmd.append('-c')
+    if dump:
+      cmd.append('-d')
+    if logcat_format:
+      cmd.extend(['-v', logcat_format])
     if filter_spec is not None:
       cmd.append(filter_spec)
     return self._IterRunDeviceAdbCmd(cmd, timeout)
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 805df65..6b1a91c 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -6,7 +6,7 @@
 
 Eventually, this will be based on adb_wrapper.
 """
-# pylint: disable=W0613
+# pylint: disable=unused-argument
 
 import logging
 import multiprocessing
@@ -24,6 +24,7 @@
 from pylib.device import decorators
 from pylib.device import device_errors
 from pylib.device import intent
+from pylib.device import logcat_monitor
 from pylib.device.commands import install_commands
 from pylib.utils import apk_helper
 from pylib.utils import device_temp_file
@@ -103,6 +104,9 @@
   _MAX_ADB_COMMAND_LENGTH = 512
   _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
 
+  # Property in /data/local.prop that controls Java assertions.
+  JAVA_ASSERT_PROPERTY = 'dalvik.vm.enableassertions'
+
   def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
                default_retries=_DEFAULT_RETRIES):
     """DeviceUtils constructor.
@@ -350,11 +354,13 @@
   @decorators.WithTimeoutAndRetriesDefaults(
       REBOOT_DEFAULT_TIMEOUT,
       REBOOT_DEFAULT_RETRIES)
-  def Reboot(self, block=True, timeout=None, retries=None):
+  def Reboot(self, block=True, wifi=False, timeout=None, retries=None):
     """Reboot the device.
 
     Args:
       block: A boolean indicating if we should wait for the reboot to complete.
+      wifi: A boolean indicating if we should wait for wifi to be enabled after
+        the reboot. The option has no effect unless |block| is also True.
       timeout: timeout in seconds
       retries: number of retries
 
@@ -369,7 +375,7 @@
     self._cache = {}
     timeout_retry.WaitFor(device_offline, wait_period=1)
     if block:
-      self.WaitUntilFullyBooted()
+      self.WaitUntilFullyBooted(wifi=wifi)
 
   INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT
   INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES
@@ -1038,7 +1044,43 @@
     Raises:
       CommandTimeoutError on timeout.
     """
-    return self.old_interface.SetJavaAssertsEnabled(enabled)
+    def find_property(lines, property_name):
+      for index, line in enumerate(lines):
+        key, value = (s.strip() for s in line.split('=', 1))
+        if key == property_name:
+          return index, value
+      return None, ''
+
+    new_value = 'all' if enabled else ''
+
+    # First ensure the desired property is persisted.
+    try:
+      properties = self.ReadFile(
+          constants.DEVICE_LOCAL_PROPERTIES_PATH).splitlines()
+    except device_errors.CommandFailedError:
+      properties = []
+    index, value = find_property(properties, self.JAVA_ASSERT_PROPERTY)
+    if new_value != value:
+      if new_value:
+        new_line = '%s=%s' % (self.JAVA_ASSERT_PROPERTY, new_value)
+        if index is None:
+          properties.append(new_line)
+        else:
+          properties[index] = new_line
+      else:
+        assert index is not None # since new_value == '' and new_value != value
+        properties.pop(index)
+      self.WriteFile(constants.DEVICE_LOCAL_PROPERTIES_PATH,
+                     _JoinLines(properties))
+
+    # Next, check the current runtime value is what we need, and
+    # if not, set it and report that a reboot is required.
+    value = self.GetProp(self.JAVA_ASSERT_PROPERTY)
+    if new_value != value:
+      self.SetProp(self.JAVA_ASSERT_PROPERTY, new_value)
+      return True
+    else:
+      return False
 
 
   @property
@@ -1288,6 +1330,19 @@
     """
     return self.old_interface.GetMemoryUsageForPid(pid)
 
+  @decorators.WithTimeoutAndRetriesFromInstance()
+  def GetLogcatMonitor(self, timeout=None, retries=None, *args, **kwargs):
+    """Returns a new LogcatMonitor associated with this device.
+
+    Parameters passed to this function are passed directly to
+    |logcat_monitor.LogcatMonitor| and are documented there.
+
+    Args:
+      timeout: timeout in seconds
+      retries: number of retries
+    """
+    return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs)
+
   def __str__(self):
     """Returns the device serial."""
     return self.adb.GetDeviceSerial()
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 68c8b71..6071fd5 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -457,9 +457,17 @@
         self.call.adb.Reboot(),
         (self.call.device.IsOnline(), True),
         (self.call.device.IsOnline(), False),
-        self.call.device.WaitUntilFullyBooted()):
+        self.call.device.WaitUntilFullyBooted(wifi=False)):
       self.device.Reboot(block=True)
 
+  def testReboot_blockUntilWifi(self):
+    with self.assertCalls(
+        self.call.adb.Reboot(),
+        (self.call.device.IsOnline(), True),
+        (self.call.device.IsOnline(), False),
+        self.call.device.WaitUntilFullyBooted(wifi=True)):
+      self.device.Reboot(block=True, wifi=True)
+
 
 class DeviceUtilsInstallTest(DeviceUtilsNewImplTest):
 
@@ -1230,81 +1238,44 @@
         self.device.Stat('/data/local/tmp/does.not.exist.txt')
 
 
-class DeviceUtilsSetJavaAssertsTest(DeviceUtilsOldImplTest):
-
-  @staticmethod
-  def mockNamedTemporary(name='/tmp/file/property.file',
-                         read_contents=''):
-    mock_file = mock.MagicMock(spec=file)
-    mock_file.name = name
-    mock_file.__enter__.return_value = mock_file
-    mock_file.read.return_value = read_contents
-    return mock_file
+class DeviceUtilsSetJavaAssertsTest(DeviceUtilsNewImplTest):
 
   def testSetJavaAsserts_enable(self):
-    mock_file = self.mockNamedTemporary()
-    with mock.patch('tempfile.NamedTemporaryFile',
-                    return_value=mock_file), (
-         mock.patch('__builtin__.open', return_value=mock_file)):
-      with self.assertCallsSequence(
-          [('adb -s 0123456789abcdef shell ls %s' %
-                constants.DEVICE_LOCAL_PROPERTIES_PATH,
-            '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH),
-           ('adb -s 0123456789abcdef pull %s %s' %
-                (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name),
-            '100 B/s (100 bytes in 1.000s)\r\n'),
-           ('adb -s 0123456789abcdef push %s %s' %
-                (mock_file.name, constants.DEVICE_LOCAL_PROPERTIES_PATH),
-            '100 B/s (100 bytes in 1.000s)\r\n'),
-           ('adb -s 0123456789abcdef shell '
-                'getprop dalvik.vm.enableassertions',
-            '\r\n'),
-           ('adb -s 0123456789abcdef shell '
-                'setprop dalvik.vm.enableassertions "all"',
-            '')]):
-        self.assertTrue(self.device.SetJavaAsserts(True))
+    with self.assertCalls(
+        (self.call.device.ReadFile(constants.DEVICE_LOCAL_PROPERTIES_PATH),
+         'some.example.prop=with an example value\n'
+         'some.other.prop=value_ok\n'),
+        self.call.device.WriteFile(
+            constants.DEVICE_LOCAL_PROPERTIES_PATH,
+            'some.example.prop=with an example value\n'
+            'some.other.prop=value_ok\n'
+            'dalvik.vm.enableassertions=all\n'),
+        (self.call.device.GetProp('dalvik.vm.enableassertions'), ''),
+        self.call.device.SetProp('dalvik.vm.enableassertions', 'all')):
+      self.assertTrue(self.device.SetJavaAsserts(True))
 
   def testSetJavaAsserts_disable(self):
-    mock_file = self.mockNamedTemporary(
-        read_contents='dalvik.vm.enableassertions=all\n')
-    with mock.patch('tempfile.NamedTemporaryFile',
-                    return_value=mock_file), (
-         mock.patch('__builtin__.open', return_value=mock_file)):
-      with self.assertCallsSequence(
-          [('adb -s 0123456789abcdef shell ls %s' %
-                constants.DEVICE_LOCAL_PROPERTIES_PATH,
-            '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH),
-           ('adb -s 0123456789abcdef pull %s %s' %
-                (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name),
-            '100 B/s (100 bytes in 1.000s)\r\n'),
-           ('adb -s 0123456789abcdef push %s %s' %
-                (mock_file.name, constants.DEVICE_LOCAL_PROPERTIES_PATH),
-            '100 B/s (100 bytes in 1.000s)\r\n'),
-           ('adb -s 0123456789abcdef shell '
-                'getprop dalvik.vm.enableassertions',
-            'all\r\n'),
-           ('adb -s 0123456789abcdef shell '
-                'setprop dalvik.vm.enableassertions ""',
-            '')]):
-        self.assertTrue(self.device.SetJavaAsserts(False))
+    with self.assertCalls(
+        (self.call.device.ReadFile(constants.DEVICE_LOCAL_PROPERTIES_PATH),
+         'some.example.prop=with an example value\n'
+         'dalvik.vm.enableassertions=all\n'
+         'some.other.prop=value_ok\n'),
+        self.call.device.WriteFile(
+            constants.DEVICE_LOCAL_PROPERTIES_PATH,
+            'some.example.prop=with an example value\n'
+            'some.other.prop=value_ok\n'),
+        (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all'),
+        self.call.device.SetProp('dalvik.vm.enableassertions', '')):
+      self.assertTrue(self.device.SetJavaAsserts(False))
 
   def testSetJavaAsserts_alreadyEnabled(self):
-    mock_file = self.mockNamedTemporary(
-        read_contents='dalvik.vm.enableassertions=all\n')
-    with mock.patch('tempfile.NamedTemporaryFile',
-                    return_value=mock_file), (
-         mock.patch('__builtin__.open', return_value=mock_file)):
-      with self.assertCallsSequence(
-          [('adb -s 0123456789abcdef shell ls %s' %
-                constants.DEVICE_LOCAL_PROPERTIES_PATH,
-            '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH),
-           ('adb -s 0123456789abcdef pull %s %s' %
-                (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name),
-            '100 B/s (100 bytes in 1.000s)\r\n'),
-           ('adb -s 0123456789abcdef shell '
-                'getprop dalvik.vm.enableassertions',
-            'all\r\n')]):
-        self.assertFalse(self.device.SetJavaAsserts(True))
+    with self.assertCalls(
+        (self.call.device.ReadFile(constants.DEVICE_LOCAL_PROPERTIES_PATH),
+         'some.example.prop=with an example value\n'
+         'dalvik.vm.enableassertions=all\n'
+         'some.other.prop=value_ok\n'),
+        (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all')):
+      self.assertFalse(self.device.SetJavaAsserts(True))
 
 
 class DeviceUtilsGetPropTest(DeviceUtilsNewImplTest):
diff --git a/build/android/pylib/device/logcat_monitor.py b/build/android/pylib/device/logcat_monitor.py
new file mode 100644
index 0000000..7ede49c
--- /dev/null
+++ b/build/android/pylib/device/logcat_monitor.py
@@ -0,0 +1,143 @@
+# 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.
+
+# pylint: disable=unused-argument
+
+import collections
+import itertools
+import logging
+import subprocess
+import tempfile
+import time
+import re
+
+from pylib.device import adb_wrapper
+from pylib.device import decorators
+from pylib.device import device_errors
+
+
+class LogcatMonitor(object):
+
+  # Format: <DATE> <TIME> <PID> <TID> <LEVEL> <COMPONENT>: <MESSAGE>
+  _THREADTIME_RE_FORMAT = r'\S* +\S* +(%s) +(%s) +(%s) +(%s): +(%s)$'
+
+  def __init__(self, adb, clear=True):
+    """Create a LogcatMonitor instance.
+
+    Args:
+      adb: An instance of adb_wrapper.AdbWrapper.
+      clear: If True, clear the logcat when monitoring starts.
+    """
+    if isinstance(adb, adb_wrapper.AdbWrapper):
+      self._adb = adb
+    else:
+      raise ValueError('Unsupported type passed for argument "device"')
+    self._clear = clear
+    self._logcat_out = None
+    self._logcat_out_file = None
+    self._logcat_proc = None
+
+  @decorators.WithTimeoutAndRetriesDefaults(10, 0)
+  def WaitFor(self, success_regex, failure_regex=None, timeout=None,
+              retries=None):
+    """Wait for a matching logcat line or until a timeout occurs.
+
+    This will attempt to match lines in the logcat against both |success_regex|
+    and |failure_regex| (if provided). Note that this calls re.search on each
+    logcat line, not re.match, so the provided regular expressions don't have
+    to match an entire line.
+
+    Args:
+      success_regex: The regular expression to search for.
+      failure_regex: An optional regular expression that, if hit, causes this
+        to stop looking for a match. Can be None.
+      timeout: timeout in seconds
+      retries: number of retries
+
+    Returns:
+      A match object if |success_regex| matches a part of a logcat line, or
+      None if |failure_regex| matches a part of a logcat line.
+    Raises:
+      CommandFailedError on logcat failure (NOT on a |failure_regex| match).
+      CommandTimeoutError if no logcat line matching either |success_regex| or
+        |failure_regex| is found in |timeout| seconds.
+      DeviceUnreachableError if the device becomes unreachable.
+    """
+    if isinstance(success_regex, basestring):
+      success_regex = re.compile(success_regex)
+    if isinstance(failure_regex, basestring):
+      failure_regex = re.compile(failure_regex)
+
+    logging.debug('Waiting %d seconds for "%s"', timeout, success_regex.pattern)
+
+    # NOTE This will continue looping until:
+    #  - success_regex matches a line, in which case the match object is
+    #    returned.
+    #  - failure_regex matches a line, in which case None is returned
+    #  - the timeout is hit, in which case a CommandTimeoutError is raised.
+    for l in self._adb.Logcat():
+      m = success_regex.search(l)
+      if m:
+        return m
+      if failure_regex and failure_regex.search(l):
+        return None
+
+  def FindAll(self, message_regex, proc_id=None, thread_id=None, log_level=None,
+              component=None):
+    """Finds all lines in the logcat that match the provided constraints.
+
+    Args:
+      message_regex: The regular expression that the <message> section must
+        match.
+      proc_id: The process ID to match. If None, matches any process ID.
+      thread_id: The thread ID to match. If None, matches any thread ID.
+      log_level: The log level to match. If None, matches any log level.
+      component: The component to match. If None, matches any component.
+
+    Returns:
+      An iterable containing objects with five attributes:
+        |proc_id|: the process ID
+        |thread_id|: the thread ID
+        |log_level|: the log level
+        |component|: the component
+        |message|: the logcat message
+    """
+    LogcatLine = collections.namedtuple(
+        'LogcatLine',
+        ['proc_id', 'thread_id', 'log_level', 'component', 'message'])
+
+    if proc_id is None:
+      proc_id = r'\d+'
+    if thread_id is None:
+      thread_id = r'\d+'
+    if log_level is None:
+      log_level = r'[VDIWEF]'
+    if component is None:
+      component = r'[^\s:]+'
+    threadtime_re = re.compile(
+        type(self)._THREADTIME_RE_FORMAT % (
+            proc_id, thread_id, log_level, component, message_regex))
+
+    regexed_lines = (
+        re.match(threadtime_re, l)
+        for l in self._adb.Logcat(dump=True, logcat_format='threadtime'))
+    only_matches = (m for m in regexed_lines if m)
+    return (LogcatLine(*m.group(1, 2, 3, 4, 5)) for m in only_matches)
+
+  def Start(self):
+    """Starts the logcat monitor.
+
+    Clears the logcat if |clear| was set in |__init__|.
+    """
+    if self._clear:
+      self._adb.Logcat(clear=True)
+
+  def __enter__(self):
+    """Starts the logcat monitor."""
+    self.Start()
+    return self
+
+  def __exit__(self, exc_type, exc_val, exc_tb):
+    """Stops the logcat monitor."""
+    pass
diff --git a/build/android/pylib/device/logcat_monitor_test.py b/build/android/pylib/device/logcat_monitor_test.py
new file mode 100755
index 0000000..7a6bf56
--- /dev/null
+++ b/build/android/pylib/device/logcat_monitor_test.py
@@ -0,0 +1,164 @@
+#!/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.
+
+import itertools
+import os
+import sys
+import unittest
+
+from pylib import constants
+from pylib.device import adb_wrapper
+from pylib.device import decorators
+from pylib.device import logcat_monitor
+
+sys.path.append(os.path.join(
+    constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
+import mock # pylint: disable=F0401
+
+
+class LogcatMonitorTest(unittest.TestCase):
+
+  _TEST_THREADTIME_LOGCAT_DATA = [
+        '01-01 01:02:03.456  7890  0987 V LogcatMonitorTest: '
+            'verbose logcat monitor test message 1',
+        '01-01 01:02:03.457  8901  1098 D LogcatMonitorTest: '
+            'debug logcat monitor test message 2',
+        '01-01 01:02:03.458  9012  2109 I LogcatMonitorTest: '
+            'info logcat monitor test message 3',
+        '01-01 01:02:03.459  0123  3210 W LogcatMonitorTest: '
+            'warning logcat monitor test message 4',
+        '01-01 01:02:03.460  1234  4321 E LogcatMonitorTest: '
+            'error logcat monitor test message 5',
+        '01-01 01:02:03.461  2345  5432 F LogcatMonitorTest: '
+            'fatal logcat monitor test message 6',
+        '01-01 01:02:03.462  3456  6543 D LogcatMonitorTest: '
+            'ignore me',]
+
+  def _createTestLog(self, raw_logcat=None):
+    test_adb = adb_wrapper.AdbWrapper('0123456789abcdef')
+    test_adb.Logcat = mock.Mock(return_value=(l for l in raw_logcat))
+    test_log = logcat_monitor.LogcatMonitor(test_adb, clear=False)
+    return test_log
+
+  def assertIterEqual(self, expected_iter, actual_iter):
+    for expected, actual in itertools.izip_longest(expected_iter, actual_iter):
+      self.assertIsNotNone(
+          expected,
+          msg='actual has unexpected elements starting with %s' % str(actual))
+      self.assertIsNotNone(
+          actual,
+          msg='actual is missing elements starting with %s' % str(expected))
+      self.assertEqual(actual.proc_id, expected[0])
+      self.assertEqual(actual.thread_id, expected[1])
+      self.assertEqual(actual.log_level, expected[2])
+      self.assertEqual(actual.component, expected[3])
+      self.assertEqual(actual.message, expected[4])
+
+    with self.assertRaises(StopIteration):
+      next(actual_iter)
+    with self.assertRaises(StopIteration):
+      next(expected_iter)
+
+  def testWaitFor_success(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    actual_match = test_log.WaitFor(r'.*(fatal|error) logcat monitor.*', None)
+    self.assertTrue(actual_match)
+    self.assertEqual(
+        '01-01 01:02:03.460  1234  4321 E LogcatMonitorTest: '
+            'error logcat monitor test message 5',
+        actual_match.group(0))
+    self.assertEqual('error', actual_match.group(1))
+
+  def testWaitFor_failure(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    actual_match = test_log.WaitFor(
+        r'.*My Success Regex.*', r'.*(fatal|error) logcat monitor.*')
+    self.assertIsNone(actual_match)
+
+  def testFindAll_defaults(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    expected_results = [
+        ('7890', '0987', 'V', 'LogcatMonitorTest',
+         'verbose logcat monitor test message 1'),
+        ('8901', '1098', 'D', 'LogcatMonitorTest',
+         'debug logcat monitor test message 2'),
+        ('9012', '2109', 'I', 'LogcatMonitorTest',
+         'info logcat monitor test message 3'),
+        ('0123', '3210', 'W', 'LogcatMonitorTest',
+         'warning logcat monitor test message 4'),
+        ('1234', '4321', 'E', 'LogcatMonitorTest',
+         'error logcat monitor test message 5'),
+        ('2345', '5432', 'F', 'LogcatMonitorTest',
+         'fatal logcat monitor test message 6')]
+    actual_results = test_log.FindAll(r'\S* logcat monitor test message \d')
+    self.assertIterEqual(iter(expected_results), actual_results)
+
+  def testFindAll_defaults_miss(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    expected_results = []
+    actual_results = test_log.FindAll(r'\S* nothing should match this \d')
+    self.assertIterEqual(iter(expected_results), actual_results)
+
+  def testFindAll_filterProcId(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    actual_results = test_log.FindAll(
+        r'\S* logcat monitor test message \d', proc_id=1234)
+    expected_results = [
+        ('1234', '4321', 'E', 'LogcatMonitorTest',
+         'error logcat monitor test message 5')]
+    self.assertIterEqual(iter(expected_results), actual_results)
+
+  def testFindAll_filterThreadId(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    actual_results = test_log.FindAll(
+        r'\S* logcat monitor test message \d', thread_id=2109)
+    expected_results = [
+        ('9012', '2109', 'I', 'LogcatMonitorTest',
+         'info logcat monitor test message 3')]
+    self.assertIterEqual(iter(expected_results), actual_results)
+
+  def testFindAll_filterLogLevel(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    actual_results = test_log.FindAll(
+        r'\S* logcat monitor test message \d', log_level=r'[DW]')
+    expected_results = [
+        ('8901', '1098', 'D', 'LogcatMonitorTest',
+         'debug logcat monitor test message 2'),
+        ('0123', '3210', 'W', 'LogcatMonitorTest',
+         'warning logcat monitor test message 4'),]
+    self.assertIterEqual(iter(expected_results), actual_results)
+
+  def testFindAll_filterComponent(self):
+    test_log = self._createTestLog(
+        raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+    actual_results = test_log.FindAll(r'.*', component='LogcatMonitorTest')
+    expected_results = [
+        ('7890', '0987', 'V', 'LogcatMonitorTest',
+         'verbose logcat monitor test message 1'),
+        ('8901', '1098', 'D', 'LogcatMonitorTest',
+         'debug logcat monitor test message 2'),
+        ('9012', '2109', 'I', 'LogcatMonitorTest',
+         'info logcat monitor test message 3'),
+        ('0123', '3210', 'W', 'LogcatMonitorTest',
+         'warning logcat monitor test message 4'),
+        ('1234', '4321', 'E', 'LogcatMonitorTest',
+         'error logcat monitor test message 5'),
+        ('2345', '5432', 'F', 'LogcatMonitorTest',
+         'fatal logcat monitor test message 6'),
+        ('3456', '6543', 'D', 'LogcatMonitorTest',
+         'ignore me'),]
+    self.assertIterEqual(iter(expected_results), actual_results)
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
+
diff --git a/build/android/pylib/gtest/filter/unit_tests_disabled b/build/android/pylib/gtest/filter/unit_tests_disabled
index 93defbe..c7851fd 100644
--- a/build/android/pylib/gtest/filter/unit_tests_disabled
+++ b/build/android/pylib/gtest/filter/unit_tests_disabled
@@ -1,10 +1,5 @@
 # List of suppressions
 
-# crbug.com/139429
-BrowserMainTest.WarmConnectionFieldTrial_Invalid
-BrowserMainTest.WarmConnectionFieldTrial_Random
-BrowserMainTest.WarmConnectionFieldTrial_WarmestSocket
-
 # The UDP related tests currently do not work on Android because
 # we lack a UDP forwarder tool.
 NetworkStatsTestUDP.*
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index 424dcb3..fb9557e 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -51,6 +51,7 @@
     super(TestRunner, self).__init__(device, test_options.tool,
                                      test_options.cleanup_test_files)
     self._lighttp_port = constants.LIGHTTPD_RANDOM_PORT_FIRST + shard_index
+    self._logcat_monitor = None
 
     self.coverage_device_file = None
     self.coverage_dir = test_options.coverage_dir
@@ -174,9 +175,10 @@
     """
     if not self._IsPerfTest(test):
       return
-    self.device.old_interface.Adb().SendCommand(
-        'shell rm ' + TestRunner._DEVICE_PERF_OUTPUT_SEARCH_PREFIX)
-    self.device.old_interface.StartMonitoringLogcat()
+    self.device.RunShellCommand(
+        ['rm', TestRunner._DEVICE_PERF_OUTPUT_SEARCH_PREFIX])
+    self._logcat_monitor = self.device.GetLogcatMonitor()
+    self._logcat_monitor.Start()
 
   def TestTeardown(self, test, result):
     """Cleans up the test harness after running a particular test.
@@ -219,9 +221,8 @@
     raw_test_name = test.split('#')[1]
 
     # Wait and grab annotation data so we can figure out which traces to parse
-    regex = self.device.old_interface.WaitForLogMatch(
-        re.compile(r'\*\*PERFANNOTATION\(' + raw_test_name + r'\)\:(.*)'),
-        None)
+    regex = self._logcat_monitor.WaitFor(
+        re.compile(r'\*\*PERFANNOTATION\(' + raw_test_name + r'\)\:(.*)'))
 
     # If the test is set to run on a specific device type only (IE: only
     # tablet or phone) and it is being run on the wrong device, the test
diff --git a/build/android/pylib/linker/test_case.py b/build/android/pylib/linker/test_case.py
index 13f68cb..8ebf803 100644
--- a/build/android/pylib/linker/test_case.py
+++ b/build/android/pylib/linker/test_case.py
@@ -42,6 +42,7 @@
 
 from pylib import constants
 from pylib.base import base_test_result
+from pylib.device import device_errors
 from pylib.device import intent
 
 
@@ -70,10 +71,11 @@
 #_LOGCAT_FILTERS = ['*:v']  ## DEBUG
 
 # Regular expression used to match status lines in logcat.
-re_status_line = re.compile(r'(BROWSER|RENDERER)_LINKER_TEST: (FAIL|SUCCESS)')
+_RE_BROWSER_STATUS_LINE = re.compile(r' BROWSER_LINKER_TEST: (FAIL|SUCCESS)$')
+_RE_RENDERER_STATUS_LINE = re.compile(r' RENDERER_LINKER_TEST: (FAIL|SUCCESS)$')
 
 # Regular expression used to mach library load addresses in logcat.
-re_library_address = re.compile(
+_RE_LIBRARY_ADDRESS = re.compile(
     r'(BROWSER|RENDERER)_LIBRARY_ADDRESS: (\S+) ([0-9A-Fa-f]+)')
 
 
@@ -109,46 +111,6 @@
     return configs[0]
 
 
-def _WriteCommandLineFile(device, command_line, command_line_file):
-  """Create a command-line file on the device. This does not use FlagChanger
-     because its implementation assumes the device has 'su', and thus does
-     not work at all with production devices."""
-  device.RunShellCommand(
-      'echo "%s" > %s' % (command_line, command_line_file))
-
-
-def _CheckLinkerTestStatus(logcat):
-  """Parse the content of |logcat| and checks for both a browser and
-     renderer status line.
-
-  Args:
-    logcat: A string to parse. Can include line separators.
-
-  Returns:
-    A tuple, result[0] is True if there is a complete match, then
-    result[1] and result[2] will be True or False to reflect the
-    test status for the browser and renderer processes, respectively.
-  """
-  browser_found = False
-  renderer_found = False
-  for m in re_status_line.finditer(logcat):
-    process_type, status = m.groups()
-    if process_type == 'BROWSER':
-      browser_found = True
-      browser_success = (status == 'SUCCESS')
-    elif process_type == 'RENDERER':
-      renderer_found = True
-      renderer_success = (status == 'SUCCESS')
-    else:
-      assert False, 'Invalid process type ' + process_type
-
-  if browser_found and renderer_found:
-    return (True, browser_success, renderer_success)
-
-  # Didn't find anything.
-  return (False, None, None)
-
-
 def _StartActivityAndWaitForLinkerTestStatus(device, timeout):
   """Force-start an activity and wait up to |timeout| seconds until the full
      linker test status lines appear in the logcat, recorded through |device|.
@@ -159,38 +121,30 @@
     A (status, logs) tuple, where status is a ResultType constant, and logs
     if the final logcat output as a string.
   """
-  # 1. Start recording logcat with appropriate filters.
-  device.old_interface.StartRecordingLogcat(
-      clear=True, filters=_LOGCAT_FILTERS)
 
-  try:
+  # 1. Start recording logcat with appropriate filters.
+  with device.GetLogcatMonitor(filters=_LOGCAT_FILTERS) as logmon:
+
     # 2. Force-start activity.
     device.StartActivity(
         intent.Intent(package=_PACKAGE_NAME, activity=_ACTIVITY_NAME),
         force_stop=True)
 
     # 3. Wait up to |timeout| seconds until the test status is in the logcat.
-    num_tries = 0
-    max_tries = timeout
-    found = False
-    while num_tries < max_tries:
-      time.sleep(1)
-      num_tries += 1
-      found, browser_ok, renderer_ok = _CheckLinkerTestStatus(
-          device.old_interface.GetCurrentRecordedLogcat())
-      if found:
-        break
+    result = ResultType.PASS
+    try:
+      browser_match = logmon.WaitFor(_RE_BROWSER_STATUS_LINE, timeout=timeout)
+      logging.debug('Found browser match: %s', browser_match.group(0))
+      renderer_match = logmon.WaitFor(_RE_RENDERER_STATUS_LINE,
+                                      timeout=timeout)
+      logging.debug('Found renderer match: %s', renderer_match.group(0))
+      if (browser_match.group(1) != 'SUCCESS'
+          or renderer_match.group(1) != 'SUCCESS'):
+        result = ResultType.FAIL
+    except device_errors.CommandTimeoutError:
+      result = ResultType.TIMEOUT
 
-  finally:
-    logs = device.old_interface.StopRecordingLogcat()
-
-  if num_tries >= max_tries:
-    return ResultType.TIMEOUT, logs
-
-  if browser_ok and renderer_ok:
-    return ResultType.PASS, logs
-
-  return ResultType.FAIL, logs
+    return result, '\n'.join(device.adb.Logcat(dump=True))
 
 
 class LibraryLoadMap(dict):
@@ -226,7 +180,7 @@
   """
   browser_libs = LibraryLoadMap()
   renderer_libs = LibraryLoadMap()
-  for m in re_library_address.finditer(logs):
+  for m in _RE_LIBRARY_ADDRESS.finditer(logs):
     process_type, lib_name, lib_address = m.groups()
     lib_address = int(lib_address, 16)
     if process_type == 'BROWSER':
@@ -323,7 +277,7 @@
     command_line_flags = ''
     if self.is_low_memory:
       command_line_flags = '--low-memory-device'
-    _WriteCommandLineFile(device, command_line_flags, _COMMAND_LINE_FILE)
+    device.WriteFile(_COMMAND_LINE_FILE, command_line_flags)
 
     # Run the test.
     status, logs = self._RunTest(device)
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index a701d95..cc39112 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -4,6 +4,8 @@
 
 """Environment setup and teardown for remote devices."""
 
+import distutils.version
+import json
 import logging
 import os
 import random
@@ -28,50 +30,138 @@
       error_func: error to show when using bad command line arguments.
     """
     super(RemoteDeviceEnvironment, self).__init__()
-
-    if args.api_key_file:
-      with open(args.api_key_file) as api_key_file:
-        self._api_key = api_key_file.read().strip()
-    elif args.api_key:
-      self._api_key = args.api_key
-    else:
-      error_func('Must set api key with --api-key or --api-key-file')
-
-    if args.api_secret_file:
-      with open(args.api_secret_file) as api_secret_file:
-        self._api_secret = api_secret_file.read().strip()
-    elif args.api_secret:
-      self._api_secret = args.api_secret
-    else:
-      error_func('Must set api secret with --api-secret or --api-secret-file')
-
-    if not args.api_protocol:
-      error_func('Must set api protocol with --api-protocol. Example: http')
-    self._api_protocol = args.api_protocol
-
-    if not args.api_address:
-      error_func('Must set api address with --api-address')
-    self._api_address = args.api_address
-
-    if not args.api_port:
-      error_func('Must set api port with --api-port.')
-    self._api_port = args.api_port
-
-    self._access_token = ''
-    self._results_path = args.results_path
-    self._remote_device = args.remote_device
-    self._remote_device_os = args.remote_device_os
-    self._runner_package = args.runner_package
-    self._runner_type = args.runner_type
-    self._device = ''
-    self._verbose_count = args.verbose_count
+    self._access_token = None
+    self._device = None
     self._device_type = args.device_type
+    self._verbose_count = args.verbose_count
     self._timeouts = {
         'queueing': 60 * 10,
         'installing': 60 * 10,
         'in-progress': 60 * 30,
         'unknown': 60 * 5
     }
+    # Example config file:
+    # {
+    #   "remote_device": ["Galaxy S4", "Galaxy S3"],
+    #   "remote_device_os": ["4.4.2", "4.4.4"],
+    #   "remote_device_minimum_os": "4.4.2",
+    #   "api_address": "www.example.com",
+    #   "api_port": "80",
+    #   "api_protocol": "http",
+    #   "api_secret": "apisecret",
+    #   "api_key": "apikey",
+    #   "timeouts": {
+    #     "queueing": 600,
+    #     "installing": 600,
+    #     "in-progress": 1800,
+    #     "unknown": 300
+    #   }
+    # }
+    if args.remote_device_file:
+      with open(args.remote_device_file) as device_file:
+        device_json = json.load(device_file)
+    else:
+      device_json = {}
+
+    self._api_address = device_json.get('api_address', None)
+    self._api_key = device_json.get('api_key', None)
+    self._api_port = device_json.get('api_port', None)
+    self._api_protocol = device_json.get('api_protocol', None)
+    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._remote_device = device_json.get('remote_device', None)
+    self._remote_device_minimum_os = device_json.get(
+        'remote_device_minimum_os', None)
+    self._remote_device_os = device_json.get('remote_device_os', None)
+    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]
+
+    def command_line_override(
+        file_value, cmd_line_value, desc, print_value=True):
+      if cmd_line_value:
+        if file_value and file_value != cmd_line_value:
+          if print_value:
+            logging.info('Overriding %s from %s to %s',
+                         desc, file_value, cmd_line_value)
+          else:
+            logging.info('overriding %s', desc)
+        return cmd_line_value
+      return file_value
+
+    self._api_address = command_line_override(
+        self._api_address, args.api_address, 'api_address')
+    self._api_port = command_line_override(
+        self._api_port, args.api_port, 'api_port')
+    self._api_protocol = command_line_override(
+        self._api_protocol, args.api_protocol, 'api_protocol')
+    self._device_oem = command_line_override(
+        self._device_oem, args.device_oem, 'device_oem')
+    self._device_type = command_line_override(
+        self._device_type, args.device_type, 'device_type')
+    self._remote_device = command_line_override(
+        self._remote_device, args.remote_device, 'remote_device')
+    self._remote_device_minimum_os = command_line_override(
+        self._remote_device_minimum_os, args.remote_device_minimum_os,
+        'remote_device_minimum_os')
+    self._remote_device_os = command_line_override(
+        self._remote_device_os, args.remote_device_os, 'remote_device_os')
+    self._results_path = command_line_override(
+        self._results_path, args.results_path, 'results_path')
+    self._runner_package = command_line_override(
+        self._runner_package, args.runner_package, 'runner_package')
+    self._runner_type = command_line_override(
+        self._runner_type, args.runner_type, 'runner_type')
+
+    if args.api_key_file:
+      with open(args.api_key_file) as api_key_file:
+        temp_key = api_key_file.read().strip()
+        self._api_key = command_line_override(
+            self._api_key, temp_key, 'api_key', print_value=False)
+    self._api_key = command_line_override(
+        self._api_key, args.api_key, 'api_key', print_value=False)
+
+    if args.api_secret_file:
+      with open(args.api_secret_file) as api_secret_file:
+        temp_secret = api_secret_file.read().strip()
+        self._api_secret = command_line_override(
+            self._api_secret, temp_secret, 'api_secret', print_value=False)
+    self._api_secret = command_line_override(
+        self._api_secret, args.api_secret, 'api_secret', print_value=False)
+
+    if not self._api_address:
+      error_func('Must set api address with --api-address'
+                 ' or in --remote-device-file.')
+    if not self._api_key:
+      error_func('Must set api key with --api-key, --api-key-file'
+                 ' or in --remote-device-file')
+    if not self._api_port:
+      error_func('Must set api port with --api-port'
+                 ' or in --remote-device-file')
+    if not self._api_protocol:
+      error_func('Must set api protocol with --api-protocol'
+                 ' or in --remote-device-file. Example: http')
+    if not self._api_secret:
+      error_func('Must set api secret with --api-secret, --api-secret-file'
+                 ' or in --remote-device-file')
+
+    logging.info('Api address: %s', self._api_address)
+    logging.info('Api port: %s', self._api_port)
+    logging.info('Api protocol: %s', self._api_protocol)
+    logging.info('Remote device: %s', self._remote_device)
+    logging.info('Remote device minimum OS: %s',
+                 self._remote_device_minimum_os)
+    logging.info('Remote device OS: %s', self._remote_device_os)
+    logging.info('Remote device OEM: %s', self._device_oem)
+    logging.info('Remote device type: %s', self._device_type)
+    logging.info('Results Path: %s', self._results_path)
+    logging.info('Runner package: %s', self._runner_package)
+    logging.info('Runner type: %s', self._runner_type)
+    logging.info('Timeouts: %s', self._timeouts)
 
     if not args.trigger and not args.collect:
       self._trigger = True
@@ -150,10 +240,16 @@
     for device in device_list:
       if device['os_name'] != self._device_type:
         continue
-      if self._remote_device and device['name'] != self._remote_device:
+      if self._remote_device and device['name'] not in self._remote_device:
         continue
       if (self._remote_device_os
-          and device['os_version'] != self._remote_device_os):
+          and device['os_version'] not in self._remote_device_os):
+        continue
+      if self._device_oem and device['brand'] not in self._device_oem:
+        continue
+      if (self._remote_device_minimum_os
+          and distutils.version.LooseVersion(device['os_version'])
+          < distutils.version.LooseVersion(self._remote_device_minimum_os)):
         continue
       if ((self._remote_device and self._remote_device_os)
           or device['available_devices_count']):
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 0b2deae..91701b0 100644
--- a/build/android/pylib/remote/device/remote_device_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -49,7 +49,7 @@
     if self._env.trigger:
       self._TriggerSetUp()
     elif self._env.collect:
-      assert isinstance(self._env.trigger, basestring), (
+      assert isinstance(self._env.collect, basestring), (
                         'File for storing test_run_id must be a string.')
       with open(self._env.collect, 'r') as persisted_data_file:
         persisted_data = json.loads(persisted_data_file.read())
diff --git a/build/android/pylib/uirobot/uirobot_test_instance.py b/build/android/pylib/uirobot/uirobot_test_instance.py
index f73c569..e3f6eb7 100644
--- a/build/android/pylib/uirobot/uirobot_test_instance.py
+++ b/build/android/pylib/uirobot/uirobot_test_instance.py
@@ -3,6 +3,8 @@
 # found in the LICENSE file.
 
 import os
+import json
+import logging
 
 from pylib import constants
 from pylib.base import test_instance
@@ -20,16 +22,27 @@
     if not args.app_under_test:
       error_func('Must set --app-under-test.')
     self._app_under_test = args.app_under_test
+    self._minutes = args.minutes
 
-    if args.device_type == 'Android':
+    if args.remote_device_file:
+      with open(args.remote_device_file) as remote_device_file:
+        device_json = json.load(remote_device_file)
+    else:
+      device_json = {}
+    device_type = device_json.get('device_type', 'Android')
+    if args.device_type:
+      if device_type and device_type != args.device_type:
+        logging.info('Overriding device_type from %s to %s',
+                     device_type, args.device_type)
+      device_type = args.device_type
+
+    if device_type == 'Android':
       self._suite = 'Android Uirobot'
       self._package_name = apk_helper.GetPackageName(self._app_under_test)
-
-    elif args.device_type == 'iOS':
+    elif device_type == 'iOS':
       self._suite = 'iOS Uirobot'
       self._package_name = self._app_under_test
 
-    self._minutes = args.minutes
 
   #override
   def TestType(self):
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py
index afbee2a..845d093 100644
--- a/build/android/pylib/utils/isolator.py
+++ b/build/android/pylib/utils/isolator.py
@@ -33,8 +33,12 @@
     'fastbuild': '0',
     'icu_use_data_file_flag': '1',
     'lsan': '0',
+    'msan': '0',
     # TODO(maruel): This may not always be true.
     'target_arch': 'arm',
+    'tsan': '0',
+    'use_custom_libcxx': '0',
+    'use_instrumented_libraries': '0',
     'use_openssl': '0',
     'use_ozone': '0',
     'v8_use_external_startup_data': '0',
diff --git a/build/android/setup.gyp b/build/android/setup.gyp
index 7dce19d..b3c3422 100644
--- a/build/android/setup.gyp
+++ b/build/android/setup.gyp
@@ -16,7 +16,7 @@
             {
               'destination': '<(SHARED_LIB_DIR)/',
               'files': [
-                '<(android_stlport_libs_dir)/libstlport_shared.so',
+                '<(android_libcpp_libs_dir)/libc++_shared.so',
               ],
             },
           ],
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index bc0980e..cc7bbee 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -121,28 +121,40 @@
 def AddRemoteDeviceOptions(parser):
   group = parser.add_argument_group('Remote Device Options')
 
-  group.add_argument('--trigger', default='',
+  group.add_argument('--trigger',
                      help=('Only triggers the test if set. Stores test_run_id '
                            'in given file path. '))
-  group.add_argument('--collect', default='',
+  group.add_argument('--collect',
                      help=('Only collects the test results if set. '
                            'Gets test_run_id from given file path.'))
-  group.add_argument('--remote-device', default='',
+  group.add_argument('--remote-device', action='append',
                      help='Device type to run test on.')
-  group.add_argument('--remote-device-os', default='',
-                     help='OS to have on the device.')
-  group.add_argument('--results-path', default='',
+  group.add_argument('--results-path',
                      help='File path to download results to.')
   group.add_argument('--api-protocol',
                      help='HTTP protocol to use. (http or https)')
-  group.add_argument('--api-address', help='Address to send HTTP requests.')
-  group.add_argument('--api-port', help='Port to send HTTP requests to.')
-  group.add_argument('--runner-type', default='',
+  group.add_argument('--api-address',
+                     help='Address to send HTTP requests.')
+  group.add_argument('--api-port',
+                     help='Port to send HTTP requests to.')
+  group.add_argument('--runner-type',
                      help='Type of test to run as.')
-  group.add_argument('--runner-package', help='Package name of test.')
-  group.add_argument('--device-type', default='Android',
+  group.add_argument('--runner-package',
+                     help='Package name of test.')
+  group.add_argument('--device-type',
                      choices=constants.VALID_DEVICE_TYPES,
                      help=('Type of device to run on. iOS or android'))
+  group.add_argument('--device-oem', action='append',
+                     help='Device OEM to run on.')
+  group.add_argument('--remote-device-file',
+                     help=('File with JSON to select remote device. '
+                           'Overrides all other flags.'))
+
+  device_os_group = group.add_mutually_exclusive_group()
+  device_os_group.add_argument('--remote-device-minimum-os',
+                               help='Minimum OS on device.')
+  device_os_group.add_argument('--remote-device-os', action='append',
+                               help='OS to have on the device.')
 
   api_secret_group = group.add_mutually_exclusive_group()
   api_secret_group.add_argument('--api-secret', default='',
@@ -513,7 +525,8 @@
   """Adds uirobot test options to |option_parser|."""
   group = parser.add_argument_group('Uirobot Test Options')
 
-  group.add_argument('--app-under-test', help='APK to run tests on.')
+  group.add_argument('--app-under-test', required=True,
+                     help='APK to run tests on.')
   group.add_argument(
       '--minutes', default=5, type=int,
       help='Number of minutes to run uirobot test [default: %default].')
diff --git a/build/common.gypi b/build/common.gypi
index 948dcec..153a500 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -318,7 +318,7 @@
       # Only used on Windows.
       'win_z7%' : 0,
 
-      # Set to 1 to enable dcheck in release.
+      # Set to 1 to enable dcheck in Release build.
       'dcheck_always_on%': 0,
 
       # Set to 1 to make a build that disables unshipped tracing events.
@@ -1588,6 +1588,18 @@
             'sysroot%': '<(sysroot)',
             'CXX%': '<(CXX)',
           }],
+          # Use a 64-bit linker to avoid running out of address space. The
+          # buildbots should have a 64-bit kernel and a 64-bit libc installed.
+          ['host_arch=="ia32" and target_arch=="ia32"', {
+            # TODO(thestig) This is a horrible way to force the desired
+            # configuration. Our gyp variable scoping is likely wrong and
+            # needs to be cleaned up. The GN configuration should be changed
+            # to match.
+            'binutils_version%': 224,
+            'linux_use_bundled_binutils%': '1',
+            'linux_use_bundled_gold%': '1',
+            'binutils_dir%': 'third_party/binutils/Linux_x64/Release/bin',
+          }],
           # All Chrome builds have breakpad symbols, but only process the
           # symbols from official builds.
           ['(branding=="Chrome" and buildtype=="Official")', {
@@ -1596,16 +1608,6 @@
             # Omit unwind support in official release builds to save space. We
             # can use breakpad for these builds.
             'release_unwind_tables%': 0,
-
-            'conditions': [
-              # For official builds, use a 64-bit linker to avoid running out
-              # of address space. The buildbots should have a 64-bit kernel
-              # and a 64-bit libc installed.
-              ['host_arch=="ia32" and target_arch=="ia32"', {
-                'linux_use_bundled_gold%': '1',
-                'binutils_dir%': 'third_party/binutils/Linux_x64/Release/bin',
-              }],
-            ],
           }],
         ],
       }],  # os_posix==1 and OS!="mac" and OS!="ios"
@@ -1666,7 +1668,7 @@
           'android_ndk_root%': '<(android_ndk_root)',
           'android_sdk_root%': '<(android_sdk_root)',
           'android_sdk_version%': '<(android_sdk_version)',
-          'android_stlport_root': '<(android_ndk_root)/sources/cxx-stl/stlport',
+          'android_libcpp_root': '<(android_ndk_root)/sources/cxx-stl/llvm-libc++',
           'host_os%': '<(host_os)',
 
           'android_sdk%': '<(android_sdk_root)/platforms/android-<(android_sdk_version)',
@@ -1743,9 +1745,10 @@
         'android_sdk%': '<(android_sdk)',
         'android_sdk_jar%': '<(android_sdk)/android.jar',
 
-        'android_stlport_root': '<(android_stlport_root)',
-        'android_stlport_include': '<(android_stlport_root)/stlport',
-        'android_stlport_libs_dir': '<(android_stlport_root)/libs/<(android_app_abi)',
+        'android_libcpp_root': '<(android_libcpp_root)',
+        'android_libcpp_include': '<(android_libcpp_root)/libcxx/include',
+        'android_libcpp_libs_dir': '<(android_libcpp_root)/libs/<(android_app_abi)',
+
         'host_os%': '<(host_os)',
 
         # Location of the "objcopy" binary, used by both gyp and scripts.
@@ -2143,7 +2146,7 @@
         'conditions': [
           # TODO(dcheng): https://crbug.com/417463 -- work to enable this flag
           # on all platforms is currently underway.
-          ['OS=="linux" or OS=="mac" or OS=="ios"', {
+          ['OS=="android" or OS=="linux" or OS=="mac" or OS=="ios"', {
             'clang_chrome_plugins_flags': [
               '-Xclang',
               '-plugin-arg-find-bad-constructs',
@@ -4403,10 +4406,8 @@
                   # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
                   # Only apply this to the target linker, since the host
                   # linker might not be gold, but isn't used much anyway.
-                  # TODO(raymes): Disable threading because gold is frequently
-                  # crashing on the bots: crbug.com/161942.
-                  # '-Wl,--threads',
-                  # '-Wl,--thread-count=4',
+                  '-Wl,--threads',
+                  '-Wl,--thread-count=4',
                 ],
               }],
             ],
@@ -4498,9 +4499,9 @@
           # Figure this out early since it needs symbols from libgcc.a, so it
           # has to be before that in the set of libraries.
           ['component=="shared_library"', {
-              'android_stlport_library': 'stlport_shared',
+              'android_libcpp_library': 'c++_shared',
           }, {
-              'android_stlport_library': 'stlport_static',
+              'android_libcpp_library': 'c++_static',
           }],
         ],
 
@@ -4584,8 +4585,6 @@
             'defines': [
               'ANDROID',
               '__GNU_SOURCE=1',  # Necessary for clone()
-              'USE_STLPORT=1',
-              '_STLP_USE_PTR_SPECIALIZATIONS=1',
               'CHROME_BUILD_ID="<(chrome_build_id)"',
             ],
             'ldflags!': [
@@ -4659,12 +4658,13 @@
                   '-nostdlib',
                 ],
                 'libraries': [
-                  '-l<(android_stlport_library)',
+                  '-l<(android_libcpp_library)',
+                  '-latomic',
                   # Manually link the libgcc.a that the cross compiler uses.
                   '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
+                  '-lm',
                   '-lc',
                   '-ldl',
-                  '-lm',
                 ],
               }],
               ['android_webview_build==1', {
@@ -4716,20 +4716,20 @@
                   '-Wl,--icf=safe',
                 ],
               }],
-              # 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)',
+                  '-isystem<(android_libcpp_include)',
+                  '-isystem<(android_ndk_root)/sources/cxx-stl/llvm-libc++abi/libcxxabi/include',
+                  '-isystem<(android_ndk_root)/sources/android/support/include',
                 ],
                 'ldflags': [
-                  '-L<(android_stlport_libs_dir)',
+                  '-L<(android_libcpp_libs_dir)',
                 ],
               }, { # else: android_webview_build!=0
+                'defines': [
+                  'USE_STLPORT=1',
+                  '_STLP_USE_PTR_SPECIALIZATIONS=1',
+                ],
                 'aosp_build_settings': {
                   # Specify that we want to statically link stlport from the
                   # NDK. This will provide all the include and library paths
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index c57ba3f..5f93dd9 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -19,6 +19,9 @@
   # TODO(sebmarchand): Update this comment once this flag guarantee that
   #     there's no build metadata in the build artifacts.
   dont_embed_build_metadata = false
+
+  # Set to true to enable dcheck in Release builds.
+  dcheck_always_on = false
 }
 
 # TODO(brettw) Most of these should be removed. Instead of global feature
@@ -74,6 +77,9 @@
   if (dont_embed_build_metadata) {
     defines += [ "DONT_EMBED_BUILD_METADATA" ]
   }
+  if (dcheck_always_on) {
+    defines += [ "DCHECK_ALWAYS_ON=1" ]
+  }
   if (use_udev) {
     # TODO(brettw) should probably be "=1".
     defines += [ "USE_UDEV" ]
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 60934c2..c6202d4 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -129,14 +129,6 @@
   android_gdbserver =
       "$android_ndk_root/prebuilt/$android_prebuilt_arch/gdbserver/gdbserver"
 
-  # stlport stuff --------------------------------------------------------------
-
-  if (component_mode == "shared_library") {
-    android_stlport_library = "stlport_shared"
-  } else {
-    android_stlport_library = "stlport_static"
-  }
-
   # ABI ------------------------------------------------------------------------
 
   if (cpu_arch == "x86") {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 164b97d..b50a64c 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -380,10 +380,8 @@
       # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
       # Only apply this to the target linker, since the host
       # linker might not be gold, but isn't used much anyway.
-      # TODO(raymes): Disable threading because gold is frequently
-      # crashing on the bots: crbug.com/161942.
-      #"-Wl,--threads",
-      #"-Wl,--thread-count=4",
+      "-Wl,--threads",
+      "-Wl,--thread-count=4",
     ]
   }
 
@@ -531,7 +529,7 @@
     ]
   }
 
-  # Stlport setup. Android uses a different (smaller) version of the STL.
+  # Android standard library setup.
   if (is_android) {
     if (is_clang) {
       # Work around incompatibilities between bionic and clang headers.
@@ -541,55 +539,44 @@
       ]
     }
 
-    defines += [
-      "USE_STLPORT=1",
-      "_STLP_USE_PTR_SPECIALIZATIONS=1",
-      "__GNU_SOURCE=1",  # Necessary for clone().
-    ]
+    defines += [ "__GNU_SOURCE=1" ]  # Necessary for clone().
 
     ldflags += [
       "-Wl,--warn-shared-textrel",
       "-nostdlib",
     ]
 
-    # 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_stlport_root = "$android_ndk_root/sources/cxx-stl/stlport"
+    android_libcpp_root = "$android_ndk_root/sources/cxx-stl/llvm-libc++"
 
-    cflags += [ "-isystem" +
-                rebase_path("$android_stlport_root/stlport", root_build_dir) ]
-    lib_dirs += [ "$android_stlport_root/libs/$android_app_abi" ]
+    cflags += [
+      "-isystem" +
+          rebase_path("$android_libcpp_root/libcxx/include", root_build_dir),
+      "-isystem" + rebase_path(
+              "$android_ndk_root/sources/cxx-stl/llvm-libc++abi/libcxxabi/include",
+              root_build_dir),
+      "-isystem" +
+          rebase_path("$android_ndk_root/sources/android/support/include",
+                      root_build_dir),
+    ]
+
+    lib_dirs += [ "$android_libcpp_root/libs/$android_app_abi" ]
 
     if (component_mode == "shared_library") {
-      libs += [ "stlport_shared" ]
+      android_libcpp_library = "c++_shared"
     } else {
-      libs += [ "stlport_static" ]
-    }
-
-    if (cpu_arch == "mipsel") {
-      libs += [
-        # ld linker is used for mips Android, and ld does not accept library
-        # absolute path prefixed by "-l"; Since libgcc does not exist in mips
-        # sysroot the proper library will be linked.
-        # TODO(gordanac): Remove once gold linker is used for mips Android.
-        "gcc",
-      ]
-    } else {
-      libs += [
-        # Manually link the libgcc.a that the cross compiler uses. This is
-        # absolute because the linker will look inside the sysroot if it's not.
-        rebase_path(android_libgcc_file),
-      ]
+      android_libcpp_library = "c++_static"
     }
 
     libs += [
+      "$android_libcpp_library",
+      "atomic",
+
+      # Manually link the libgcc.a that the cross compiler uses. This is
+      # absolute because the linker will look inside the sysroot if it's not.
+      rebase_path(android_libgcc_file),
+      "m",
       "c",
       "dl",
-      "m",
     ]
   }
 }
diff --git a/build/gyp_chromium b/build/gyp_chromium
index 1112575..45f3206 100755
--- a/build/gyp_chromium
+++ b/build/gyp_chromium
@@ -7,6 +7,7 @@
 # This script is wrapper for Chromium that adds some support for how GYP
 # is invoked by Chromium beyond what can be done in the gclient hooks.
 
+import argparse
 import glob
 import gyp_environment
 import os
@@ -27,6 +28,7 @@
 SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 # 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'))
@@ -124,15 +126,10 @@
   env_items = ProcessGypDefinesItems(
       shlex.split(os.environ.get('GYP_DEFINES', '')))
 
-  # GYP defines from the command line. We can't use optparse since we want
-  # to ignore all arguments other than "-D".
-  cmdline_input_items = []
-  for i in range(len(sys.argv))[1:]:
-    if sys.argv[i].startswith('-D'):
-      if sys.argv[i] == '-D' and i + 1 < len(sys.argv):
-        cmdline_input_items += [sys.argv[i + 1]]
-      elif len(sys.argv[i]) > 2:
-        cmdline_input_items += [sys.argv[i][2:]]
+  # GYP defines from the command line.
+  parser = argparse.ArgumentParser()
+  parser.add_argument('-D', dest='defines', action='append', default=[])
+  cmdline_input_items = parser.parse_known_args()[0].defines
   cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
 
   vars_dict = dict(supp_items + env_items + cmdline_items)
@@ -141,21 +138,21 @@
 
 def GetOutputDirectory():
   """Returns the output directory that GYP will use."""
-  # GYP generator flags from the command line. We can't use optparse since we
-  # want to ignore all arguments other than "-G".
-  needle = '-Goutput_dir='
-  cmdline_input_items = []
-  for item in sys.argv[1:]:
-    if item.startswith(needle):
-      return item[len(needle):]
 
-  env_items = shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
+  # Handle command line generator flags.
+  parser = argparse.ArgumentParser()
+  parser.add_argument('-G', dest='genflags', default=[], action='append')
+  genflags = parser.parse_known_args()[0].genflags
+
+  # Handle generator flags from the environment.
+  genflags += shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
+
   needle = 'output_dir='
-  for item in env_items:
+  for item in genflags:
     if item.startswith(needle):
       return item[len(needle):]
 
-  return "out"
+  return 'out'
 
 
 def additional_include_files(supplemental_files, args=[]):
diff --git a/build/gyp_chromium_test.py b/build/gyp_chromium_test.py
new file mode 100755
index 0000000..0c0e479
--- /dev/null
+++ b/build/gyp_chromium_test.py
@@ -0,0 +1,66 @@
+#!/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.
+
+import os
+import sys
+import unittest
+
+SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
+SRC_DIR = os.path.dirname(SCRIPT_DIR)
+
+sys.path.append(os.path.join(SRC_DIR, 'third_party', 'pymock'))
+
+import mock
+
+# TODO(sbc): Make gyp_chromium more testable by putting the code in
+# a .py file.
+gyp_chromium = __import__('gyp_chromium')
+
+
+class TestGetOutputDirectory(unittest.TestCase):
+  @mock.patch('os.environ', {})
+  @mock.patch('sys.argv', [__file__])
+  def testDefaultValue(self):
+    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'out')
+
+  @mock.patch('os.environ', {'GYP_GENERATOR_FLAGS': 'output_dir=envfoo'})
+  @mock.patch('sys.argv', [__file__])
+  def testEnvironment(self):
+    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'envfoo')
+
+  @mock.patch('os.environ', {'GYP_GENERATOR_FLAGS': 'output_dir=envfoo'})
+  @mock.patch('sys.argv', [__file__, '-Goutput_dir=cmdfoo'])
+  def testGFlagOverridesEnv(self):
+    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'cmdfoo')
+
+  @mock.patch('os.environ', {})
+  @mock.patch('sys.argv', [__file__, '-G', 'output_dir=foo'])
+  def testGFlagWithSpace(self):
+    self.assertEqual(gyp_chromium.GetOutputDirectory(), 'foo')
+
+
+class TestGetGypVars(unittest.TestCase):
+  @mock.patch('os.environ', {})
+  def testDefault(self):
+    self.assertEqual(gyp_chromium.GetGypVars([]), {})
+
+  @mock.patch('os.environ', {})
+  @mock.patch('sys.argv', [__file__, '-D', 'foo=bar'])
+  def testDFlags(self):
+    self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': 'bar'})
+
+  @mock.patch('os.environ', {})
+  @mock.patch('sys.argv', [__file__, '-D', 'foo'])
+  def testDFlagsNoValue(self):
+    self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': '1'})
+
+  @mock.patch('os.environ', {})
+  @mock.patch('sys.argv', [__file__, '-D', 'foo=bar', '-Dbaz'])
+  def testDFlagMulti(self):
+    self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': 'bar', 'baz': '1'})
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/build/isolate.gypi b/build/isolate.gypi
index e6d2f98..d7070fe 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -74,24 +74,28 @@
         # the .isolate file but are not considered relative paths.
         '--extra-variable', 'version_full=<(version_full)',
 
-        '--config-variable', 'OS=<(OS)',
         '--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)',
+        '--config-variable', 'OS=<(OS)',
         '--config-variable', 'asan=<(asan)',
         '--config-variable', 'chromeos=<(chromeos)',
         '--config-variable', 'component=<(component)',
+        '--config-variable', 'disable_nacl=<(disable_nacl)',
         '--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
         # once support for user-defined config variables is added.
         '--config-variable',
           'internal_gles2_conform_tests=<(internal_gles2_conform_tests)',
-        '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
-        '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
-        '--config-variable', 'lsan=<(lsan)',
         '--config-variable', 'libpeer_target_type=<(libpeer_target_type)',
-        '--config-variable', 'use_openssl=<(use_openssl)',
+        '--config-variable', 'lsan=<(lsan)',
+        '--config-variable', 'msan=<(msan)',
         '--config-variable', 'target_arch=<(target_arch)',
+        '--config-variable', 'tsan=<(tsan)',
+        '--config-variable', 'use_custom_libcxx=<(use_custom_libcxx)',
+        '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
+        '--config-variable', 'use_openssl=<(use_openssl)',
         '--config-variable', 'use_ozone=<(use_ozone)',
-        '--config-variable', 'disable_nacl=<(disable_nacl)',
+        '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
       ],
       'conditions': [
         # Note: When gyp merges lists, it appends them to the old value.
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index ae69583..a15cba1 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -111,7 +111,8 @@
 "race:content::GpuWatchdogThread::CheckArmed\n"
 
 // http://crbug.com/257396
-"race:base::debug::TraceEventTestFixture_TraceSamplingScope_Test::TestBody\n"
+"race:base::trace_event::"
+    "TraceEventTestFixture_TraceSamplingScope_Test::TestBody\n"
 
 // http://crbug.com/258479
 "race:SamplingStateScope\n"
@@ -291,10 +292,10 @@
 
 // http://crbug.com/397022
 "deadlock:"
-"base::debug::TraceEventTestFixture_ThreadOnceBlocking_Test::TestBody\n"
+"base::trace_event::TraceEventTestFixture_ThreadOnceBlocking_Test::TestBody\n"
 
 // http://crbug.com/415472
-"deadlock:base::debug::TraceLog::GetCategoryGroupEnabled\n"
+"deadlock:base::trace_event::TraceLog::GetCategoryGroupEnabled\n"
 
 // http://crbug.com/425057
 "deadlock:webrtc::ViEChannelManagerScoped::ViEChannelManagerScoped\n"
@@ -315,6 +316,15 @@
 // https://crbug.com/448203
 "race:blink::RemoteFrame::detach\n"
 
+// https://crbug.com/455638
+"deadlock:dbus::Bus::ShutdownAndBlock\n"
+
+// https://crbug.com/455665
+"race:mojo::common::*::tick_clock\n"
+
+// https://crbug.com/456095
+"race:blink::Scheduler\n"
+
 // End of suppressions.
 ;  // Please keep this semicolon.
 
diff --git a/build/secondary/third_party/libjpeg_turbo/BUILD.gn b/build/secondary/third_party/libjpeg_turbo/BUILD.gn
index 82472e7..be16302 100644
--- a/build/secondary/third_party/libjpeg_turbo/BUILD.gn
+++ b/build/secondary/third_party/libjpeg_turbo/BUILD.gn
@@ -84,7 +84,7 @@
     } else if (is_mac) {
       defines += [ "MACHO" ]
       include_dirs = [ "mac" ]
-    } else if (is_linux) {
+    } else if (is_linux || is_android) {
       defines += [ "ELF" ]
       include_dirs = [ "linux" ]
     }
diff --git a/build/whitespace_file.txt b/build/whitespace_file.txt
index ee4f527..7191150 100644
--- a/build/whitespace_file.txt
+++ b/build/whitespace_file.txt
@@ -152,4 +152,3 @@
 
 In the BUILD we trust.
 ^_^
-
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index d9cc43b..ddc8955 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -21,10 +21,16 @@
 
 namespace base {
 class Value;
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace gfx {
 class QuadF;
diff --git a/cc/base/region.h b/cc/base/region.h
index 294ea63..b84dbd5 100644
--- a/cc/base/region.h
+++ b/cc/base/region.h
@@ -15,10 +15,16 @@
 
 namespace base {
 class Value;
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 class SimpleEnclosedRegion;
diff --git a/cc/base/synced_property.h b/cc/base/synced_property.h
index 8b554c6..6b02e7a 100644
--- a/cc/base/synced_property.h
+++ b/cc/base/synced_property.h
@@ -24,7 +24,7 @@
 template <typename T>
 class SyncedProperty : public base::RefCounted<SyncedProperty<T>> {
  public:
-  SyncedProperty() {}
+  SyncedProperty() : clobber_active_value_(false) {}
 
   // Returns the canonical value for the specified tree, including the sum of
   // all deltas.  The pending tree should use this for activation purposes and
@@ -84,6 +84,7 @@
     active_base_ = pending_base_;
     active_delta_ = PendingDelta();
     sent_delta_ = T::Identity();
+    clobber_active_value_ = false;
 
     return true;
   }
@@ -105,7 +106,13 @@
   // The new delta we would use if we decide to activate now.  This delta
   // excludes the amount that we expect the main thread to reflect back at the
   // impl thread during the commit.
-  T PendingDelta() const { return active_delta_.InverseCombine(sent_delta_); }
+  T PendingDelta() const {
+    if (clobber_active_value_)
+      return T::Identity();
+    return active_delta_.InverseCombine(sent_delta_);
+  }
+
+  void set_clobber_active_value() { clobber_active_value_ = true; }
 
  private:
   // Value last committed to the pending tree.
@@ -117,6 +124,9 @@
   // The value sent to the main thread (on the last BeginFrame); this is always
   // identity outside of the BeginFrame-to-activation interval.
   T sent_delta_;
+  // When true the pending delta is always identity so that it does not change
+  // and will clobber the active value on push.
+  bool clobber_active_value_;
 
   friend class base::RefCounted<SyncedProperty<T>>;
   ~SyncedProperty() {}
diff --git a/cc/blink/context_provider_web_context.h b/cc/blink/context_provider_web_context.h
new file mode 100644
index 0000000..21d1df3
--- /dev/null
+++ b/cc/blink/context_provider_web_context.h
@@ -0,0 +1,24 @@
+// 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 CC_BLINK_CONTEXT_PROVIDER_WEB_CONTEXT_H_
+#define CC_BLINK_CONTEXT_PROVIDER_WEB_CONTEXT_H_
+
+#include "cc/output/context_provider.h"
+
+namespace blink { class WebGraphicsContext3D; }
+
+namespace cc_blink {
+
+class ContextProviderWebContext : public cc::ContextProvider {
+ public:
+  virtual blink::WebGraphicsContext3D* WebContext3D() = 0;
+
+ protected:
+  ~ContextProviderWebContext() override {}
+};
+
+}  // namespace cc_blink
+
+#endif  // CC_BLINK_CONTEXT_PROVIDER_WEB_CONTEXT_H_
diff --git a/cc/blink/web_content_layer_impl.cc b/cc/blink/web_content_layer_impl.cc
index abe3eb3..9224223 100644
--- a/cc/blink/web_content_layer_impl.cc
+++ b/cc/blink/web_content_layer_impl.cc
@@ -19,6 +19,21 @@
 
 namespace cc_blink {
 
+static blink::WebContentLayerClient::PaintingControlSetting
+PaintingControlToWeb(
+    cc::ContentLayerClient::PaintingControlSetting painting_control) {
+  switch (painting_control) {
+    case cc::ContentLayerClient::PAINTING_BEHAVIOR_NORMAL:
+      return blink::WebContentLayerClient::PaintDefaultBehavior;
+    case cc::ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED:
+      return blink::WebContentLayerClient::DisplayListConstructionDisabled;
+    case cc::ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED:
+      return blink::WebContentLayerClient::DisplayListCachingDisabled;
+  }
+  NOTREACHED();
+  return blink::WebContentLayerClient::PaintDefaultBehavior;
+}
+
 WebContentLayerImpl::WebContentLayerImpl(blink::WebContentLayerClient* client)
     : client_(client) {
   if (WebLayerImpl::UsingPictureLayer())
@@ -50,30 +65,22 @@
 void WebContentLayerImpl::PaintContents(
     SkCanvas* canvas,
     const gfx::Rect& clip,
-    ContentLayerClient::GraphicsContextStatus graphics_context_status) {
+    cc::ContentLayerClient::PaintingControlSetting painting_control) {
   if (!client_)
     return;
 
-  client_->paintContents(
-      canvas, clip,
-      graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED
-          ? blink::WebContentLayerClient::GraphicsContextEnabled
-          : blink::WebContentLayerClient::GraphicsContextDisabled);
+  client_->paintContents(canvas, clip, PaintingControlToWeb(painting_control));
 }
 
 scoped_refptr<cc::DisplayItemList>
 WebContentLayerImpl::PaintContentsToDisplayList(
     const gfx::Rect& clip,
-    ContentLayerClient::GraphicsContextStatus graphics_context_status) {
+    cc::ContentLayerClient::PaintingControlSetting painting_control) {
   if (!client_)
     return cc::DisplayItemList::Create();
 
   WebDisplayItemListImpl list;
-  client_->paintContents(
-      &list, clip,
-      graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED
-          ? blink::WebContentLayerClient::GraphicsContextEnabled
-          : blink::WebContentLayerClient::GraphicsContextDisabled);
+  client_->paintContents(&list, clip, PaintingControlToWeb(painting_control));
   return list.ToDisplayItemList();
 }
 
diff --git a/cc/blink/web_content_layer_impl.h b/cc/blink/web_content_layer_impl.h
index 148f4fc..3e7b55c 100644
--- a/cc/blink/web_content_layer_impl.h
+++ b/cc/blink/web_content_layer_impl.h
@@ -38,11 +38,10 @@
   // ContentLayerClient implementation.
   void PaintContents(SkCanvas* canvas,
                      const gfx::Rect& clip,
-                     ContentLayerClient::GraphicsContextStatus
-                         graphics_context_status) override;
+                     PaintingControlSetting painting_control) override;
   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus graphics_context_status) override;
+      PaintingControlSetting painting_control) override;
   bool FillsBoundsCompletely() const override;
 
   scoped_ptr<WebLayerImpl> layer_;
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc
index 6ce8ac5..bcebfec 100644
--- a/cc/blink/web_layer_impl.cc
+++ b/cc/blink/web_layer_impl.cc
@@ -383,6 +383,28 @@
   return result;
 }
 
+static_assert(static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnNone) ==
+                  ScrollBlocksOnNone,
+              "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+static_assert(static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnStartTouch) ==
+                  ScrollBlocksOnStartTouch,
+              "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+static_assert(static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnWheelEvent) ==
+                  ScrollBlocksOnWheelEvent,
+              "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+static_assert(
+    static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnScrollEvent) ==
+        ScrollBlocksOnScrollEvent,
+    "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+
+void WebLayerImpl::setScrollBlocksOn(blink::WebScrollBlocksOn blocks) {
+  layer_->SetScrollBlocksOn(static_cast<ScrollBlocksOn>(blocks));
+}
+
+blink::WebScrollBlocksOn WebLayerImpl::scrollBlocksOn() const {
+  return static_cast<blink::WebScrollBlocksOn>(layer_->scroll_blocks_on());
+}
+
 void WebLayerImpl::setIsContainerForFixedPositionLayers(bool enable) {
   layer_->SetIsContainerForFixedPositionLayers(enable);
 }
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h
index 111c6cf..787f632 100644
--- a/cc/blink/web_layer_impl.h
+++ b/cc/blink/web_layer_impl.h
@@ -31,10 +31,16 @@
 }
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
 }
+}  // namespace base
 
 namespace cc {
 class Layer;
@@ -123,6 +129,8 @@
   virtual void setTouchEventHandlerRegion(
       const blink::WebVector<blink::WebRect>& region);
   virtual blink::WebVector<blink::WebRect> touchEventHandlerRegion() const;
+  virtual void setScrollBlocksOn(blink::WebScrollBlocksOn);
+  virtual blink::WebScrollBlocksOn scrollBlocksOn() const;
   virtual void setIsContainerForFixedPositionLayers(bool is_container);
   virtual bool isContainerForFixedPositionLayers() const;
   virtual void setPositionConstraint(
diff --git a/cc/cc_unittests.isolate b/cc/cc_unittests.isolate
index 4e5ac92..5d652d9 100644
--- a/cc/cc_unittests.isolate
+++ b/cc/cc_unittests.isolate
@@ -22,6 +22,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
         'files': [
           '../testing/xvfb.py',
@@ -46,6 +48,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
         'files': [
           '<(PRODUCT_DIR)/ffmpegsumo.so',
@@ -62,6 +66,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
         'files': [
           '<(PRODUCT_DIR)/ffmpegsumo.dll',
diff --git a/cc/debug/devtools_instrumentation.h b/cc/debug/devtools_instrumentation.h
index cfe3e5a..73788a5 100644
--- a/cc/debug/devtools_instrumentation.h
+++ b/cc/debug/devtools_instrumentation.h
@@ -6,6 +6,7 @@
 #define CC_DEBUG_DEVTOOLS_INSTRUMENTATION_H_
 
 #include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
 
 namespace cc {
 namespace devtools_instrumentation {
@@ -14,6 +15,7 @@
 const char kCategory[] = TRACE_DISABLED_BY_DEFAULT("devtools.timeline");
 const char kCategoryFrame[] =
     TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame");
+const char kData[] = "data";
 const char kFrameId[] = "frameId";
 const char kLayerId[] = "layerId";
 const char kLayerTreeId[] = "layerTreeId";
@@ -23,7 +25,9 @@
 const char kBeginFrame[] = "BeginFrame";
 const char kActivateLayerTree[] = "ActivateLayerTree";
 const char kRequestMainThreadFrame[] = "RequestMainThreadFrame";
+const char kBeginMainThreadFrame[] = "BeginMainThreadFrame";
 const char kDrawFrame[] = "DrawFrame";
+const char kCompositeLayers[] = "CompositeLayers";
 }  // namespace internal
 
 const char kPaintSetup[] = "PaintSetup";
@@ -77,6 +81,20 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedLayerTreeTask);
 };
 
+struct ScopedCommitTrace {
+ public:
+  explicit ScopedCommitTrace(int layer_tree_host_id) {
+    TRACE_EVENT_BEGIN1(internal::kCategory, internal::kCompositeLayers,
+                       internal::kLayerTreeId, layer_tree_host_id);
+  }
+  ~ScopedCommitTrace() {
+    TRACE_EVENT_END0(internal::kCategory, internal::kCompositeLayers);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedCommitTrace);
+};
+
 struct ScopedLayerObjectTracker
     : public base::debug::TraceScopedTrackableObject<int> {
   explicit ScopedLayerObjectTracker(int layer_id)
@@ -124,6 +142,21 @@
                        layer_tree_host_id);
 }
 
+inline scoped_refptr<base::debug::ConvertableToTraceFormat>
+BeginMainThreadFrameData(int frame_id) {
+  scoped_refptr<base::debug::TracedValue> value =
+      new base::debug::TracedValue();
+  value->SetInteger("frameId", frame_id);
+  return value;
+}
+
+inline void WillBeginMainThreadFrame(int layer_tree_host_id, int frame_id) {
+  TRACE_EVENT_INSTANT2(
+      internal::kCategoryFrame, internal::kBeginMainThreadFrame,
+      TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, layer_tree_host_id,
+      internal::kData, BeginMainThreadFrameData(frame_id));
+}
+
 }  // namespace devtools_instrumentation
 }  // namespace cc
 
diff --git a/cc/debug/frame_timing_request.h b/cc/debug/frame_timing_request.h
index 7ab97de..0937998 100644
--- a/cc/debug/frame_timing_request.h
+++ b/cc/debug/frame_timing_request.h
@@ -5,6 +5,7 @@
 #ifndef CC_DEBUG_FRAME_TIMING_REQUEST_H_
 #define CC_DEBUG_FRAME_TIMING_REQUEST_H_
 
+#include "cc/base/cc_export.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace cc {
@@ -13,12 +14,15 @@
 // given rect (in layer space) and an associated request id. When this request
 // is propagated to the active LayerImpl, it will cause events to be saved in
 // FrameTimingTracker, which in turn can be consumed by the requester.
-class FrameTimingRequest {
+class CC_EXPORT FrameTimingRequest {
  public:
   FrameTimingRequest();
   FrameTimingRequest(int64_t request_id, const gfx::Rect& rect);
 
+  // Return the ID for the request.
   int64_t id() const { return id_; }
+
+  // Return the layer space rect for this request.
   const gfx::Rect& rect() const { return rect_; }
 
  private:
diff --git a/cc/debug/picture_record_benchmark.cc b/cc/debug/picture_record_benchmark.cc
index d0d031d..b1b8188 100644
--- a/cc/debug/picture_record_benchmark.cc
+++ b/cc/debug/picture_record_benchmark.cc
@@ -106,8 +106,9 @@
 
         base::TimeTicks start = base::TimeTicks::Now();
 
-        scoped_refptr<Picture> picture = Picture::Create(
-            rect, painter, tile_grid_size, false, Picture::RECORD_NORMALLY);
+        scoped_refptr<Picture> picture =
+            Picture::Create(rect, painter, tile_grid_size, false,
+                            RecordingSource::RECORD_NORMALLY);
 
         base::TimeTicks end = base::TimeTicks::Now();
         base::TimeDelta duration = end - start;
diff --git a/cc/debug/rasterize_and_record_benchmark.cc b/cc/debug/rasterize_and_record_benchmark.cc
index 3a0c98b..e56a1e1 100644
--- a/cc/debug/rasterize_and_record_benchmark.cc
+++ b/cc/debug/rasterize_and_record_benchmark.cc
@@ -34,10 +34,8 @@
 const int kWarmupRuns = 0;
 const int kTimeCheckInterval = 1;
 
-const char* kModeSuffixes[Picture::RECORDING_MODE_COUNT] = {
-    "",
-    "_sk_null_canvas",
-    "_painting_disabled"};
+const char* kModeSuffixes[RecordingSource::RECORDING_MODE_COUNT] =
+    {"", "_sk_null_canvas", "_painting_disabled", "_caching_disabled"};
 
 }  // namespace
 
@@ -74,7 +72,7 @@
   results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
   results_->SetInteger("picture_memory_usage", record_results_.bytes_used);
 
-  for (int i = 0; i < Picture::RECORDING_MODE_COUNT; i++) {
+  for (int i = 0; i < RecordingSource::RECORDING_MODE_COUNT; i++) {
     std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]);
     results_->SetDouble(name,
                         record_results_.total_best_time[i].InMillisecondsF());
@@ -132,10 +130,10 @@
 
   gfx::Size tile_grid_size = host_->settings().default_tile_size;
 
-  for (int mode_index = 0; mode_index < Picture::RECORDING_MODE_COUNT;
+  for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
        mode_index++) {
-    Picture::RecordingMode mode =
-        static_cast<Picture::RecordingMode>(mode_index);
+    RecordingSource::RecordingMode mode =
+        static_cast<RecordingSource::RecordingMode>(mode_index);
     base::TimeDelta min_time = base::TimeDelta::Max();
     size_t memory_used = 0;
 
@@ -164,7 +162,7 @@
         min_time = duration;
     }
 
-    if (mode == Picture::RECORD_NORMALLY) {
+    if (mode == RecordingSource::RECORD_NORMALLY) {
       record_results_.bytes_used += memory_used;
       record_results_.pixels_recorded +=
           visible_content_rect.width() * visible_content_rect.height();
@@ -180,49 +178,62 @@
 
   DCHECK(host_ && host_->settings().use_display_lists);
 
-  base::TimeDelta min_time = base::TimeDelta::Max();
-  size_t memory_used = 0;
+  for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
+       mode_index++) {
+    ContentLayerClient::PaintingControlSetting painting_control =
+        ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
+    switch (static_cast<RecordingSource::RecordingMode>(mode_index)) {
+      case RecordingSource::RECORD_NORMALLY:
+        // Already setup for normal recording.
+        break;
+      case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
+      // TODO(schenney): Remove this when DisplayList recording is the only
+      // option. For now, fall through and disable construction.
+      case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
+        painting_control =
+            ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
+        break;
+      case RecordingSource::RECORD_WITH_CACHING_DISABLED:
+        painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
+        break;
+      default:
+        NOTREACHED();
+    }
+    base::TimeDelta min_time = base::TimeDelta::Max();
+    size_t memory_used = 0;
 
-  // TODO(schenney): What are the corresponding Picture::RecordingMode modes
-  // for Slimming Paint. We could disable SkPicture creation in
-  // DrawingDisplayItems, or we could only generate the display list and not
-  // do any work on it in the compositor, or something else, or all of the
-  // above.
-  scoped_refptr<DisplayItemList> display_list;
-  for (int i = 0; i < record_repeat_count_; ++i) {
-    // Run for a minimum amount of time to avoid problems with timer
-    // quantization when the layer is very small.
-    LapTimer timer(kWarmupRuns,
-                   base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
-                   kTimeCheckInterval);
+    scoped_refptr<DisplayItemList> display_list;
+    for (int i = 0; i < record_repeat_count_; ++i) {
+      // Run for a minimum amount of time to avoid problems with timer
+      // quantization when the layer is very small.
+      LapTimer timer(kWarmupRuns,
+                     base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
+                     kTimeCheckInterval);
 
-    do {
-      // TODO(schenney): Cached content will not be regenerated, which skews
-      // the results significantly in favor of Slimming Paint (or should).
-      // Add a flag or API call to disable caching, and maybe run the test
-      // twice, without and with caching.
-      display_list = painter->PaintContentsToDisplayList(
-          visible_content_rect, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+      do {
+        display_list = painter->PaintContentsToDisplayList(visible_content_rect,
+                                                           painting_control);
 
-      if (memory_used) {
-        // Verify we are recording the same thing each time.
-        DCHECK(memory_used == display_list->PictureMemoryUsage());
-      } else {
-        memory_used = display_list->PictureMemoryUsage();
-      }
+        if (memory_used) {
+          // Verify we are recording the same thing each time.
+          DCHECK(memory_used == display_list->PictureMemoryUsage());
+        } else {
+          memory_used = display_list->PictureMemoryUsage();
+        }
 
-      timer.NextLap();
-    } while (!timer.HasTimeLimitExpired());
-    base::TimeDelta duration =
-        base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
-    if (duration < min_time)
-      min_time = duration;
+        timer.NextLap();
+      } while (!timer.HasTimeLimitExpired());
+      base::TimeDelta duration =
+          base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
+      if (duration < min_time)
+        min_time = duration;
+    }
+
+    record_results_.bytes_used += memory_used;
+    record_results_.pixels_recorded +=
+        visible_content_rect.width() * visible_content_rect.height();
+    record_results_.total_best_time[mode_index] += min_time;
   }
-
-  record_results_.bytes_used += memory_used;
-  record_results_.pixels_recorded +=
-      visible_content_rect.width() * visible_content_rect.height();
-  record_results_.total_best_time[Picture::RECORD_NORMALLY] += min_time;
 }
 
 RasterizeAndRecordBenchmark::RecordResults::RecordResults()
diff --git a/cc/debug/rasterize_and_record_benchmark.h b/cc/debug/rasterize_and_record_benchmark.h
index 5ae45fa..30dcde0 100644
--- a/cc/debug/rasterize_and_record_benchmark.h
+++ b/cc/debug/rasterize_and_record_benchmark.h
@@ -51,7 +51,7 @@
 
     int pixels_recorded;
     size_t bytes_used;
-    base::TimeDelta total_best_time[Picture::RECORDING_MODE_COUNT];
+    base::TimeDelta total_best_time[RecordingSource::RECORDING_MODE_COUNT];
   };
 
   RecordResults record_results_;
diff --git a/cc/debug/rendering_stats.cc b/cc/debug/rendering_stats.cc
index 9c62a3c..2247b3a 100644
--- a/cc/debug/rendering_stats.cc
+++ b/cc/debug/rendering_stats.cc
@@ -17,10 +17,13 @@
 }
 
 void RenderingStats::TimeDeltaList::AddToTracedValue(
+    const char* name,
     base::debug::TracedValue* list_value) const {
+  list_value->BeginArray(name);
   for (const auto& value : values) {
     list_value->AppendDouble(value.InMillisecondsF());
   }
+  list_value->EndArray();
 }
 
 void RenderingStats::TimeDeltaList::Add(const TimeDeltaList& other) {
@@ -48,30 +51,22 @@
   record_data->SetInteger("visible_content_area", visible_content_area);
   record_data->SetInteger("approximated_visible_content_area",
                           approximated_visible_content_area);
-  record_data->BeginArray("draw_duration_ms");
-  draw_duration.AddToTracedValue(record_data.get());
-  record_data->EndArray();
+  draw_duration.AddToTracedValue("draw_duration_ms", record_data.get());
 
-  record_data->BeginArray("draw_duration_estimate_ms");
-  draw_duration_estimate.AddToTracedValue(record_data.get());
-  record_data->EndArray();
+  draw_duration_estimate.AddToTracedValue("draw_duration_estimate_ms",
+                                          record_data.get());
 
-  record_data->BeginArray("begin_main_frame_to_commit_duration_ms");
-  begin_main_frame_to_commit_duration.AddToTracedValue(record_data.get());
-  record_data->EndArray();
+  begin_main_frame_to_commit_duration.AddToTracedValue(
+      "begin_main_frame_to_commit_duration_ms", record_data.get());
 
-  record_data->BeginArray("begin_main_frame_to_commit_duration_estimate_ms");
   begin_main_frame_to_commit_duration_estimate.AddToTracedValue(
-      record_data.get());
-  record_data->EndArray();
+      "begin_main_frame_to_commit_duration_estimate_ms", record_data.get());
 
-  record_data->BeginArray("commit_to_activate_duration_ms");
-  commit_to_activate_duration.AddToTracedValue(record_data.get());
-  record_data->EndArray();
+  commit_to_activate_duration.AddToTracedValue("commit_to_activate_duration_ms",
+                                               record_data.get());
 
-  record_data->BeginArray("commit_to_activate_duration_estimate_ms");
-  commit_to_activate_duration_estimate.AddToTracedValue(record_data.get());
-  record_data->EndArray();
+  commit_to_activate_duration_estimate.AddToTracedValue(
+      "commit_to_activate_duration_estimate_ms", record_data.get());
   return record_data;
 }
 
diff --git a/cc/debug/rendering_stats.h b/cc/debug/rendering_stats.h
index 24acb93..3a72371 100644
--- a/cc/debug/rendering_stats.h
+++ b/cc/debug/rendering_stats.h
@@ -24,7 +24,8 @@
     ~TimeDeltaList();
 
     void Append(base::TimeDelta value);
-    void AddToTracedValue(base::debug::TracedValue* list_value) const;
+    void AddToTracedValue(const char* name,
+                          base::debug::TracedValue* list_value) const;
 
     void Add(const TimeDeltaList& other);
 
diff --git a/cc/debug/rendering_stats_unittest.cc b/cc/debug/rendering_stats_unittest.cc
index a634093..c1e189a 100644
--- a/cc/debug/rendering_stats_unittest.cc
+++ b/cc/debug/rendering_stats_unittest.cc
@@ -15,9 +15,7 @@
 static std::string ToString(const RenderingStats::TimeDeltaList& list) {
   scoped_refptr<base::debug::TracedValue> value =
       new base::debug::TracedValue();
-  value->BeginArray("list_value");
-  list.AddToTracedValue(value.get());
-  value->EndArray();
+  list.AddToTracedValue("list_value", value.get());
   return value->ToString();
 }
 
diff --git a/cc/debug/traced_value.h b/cc/debug/traced_value.h
index c5ea30a..db0a08a 100644
--- a/cc/debug/traced_value.h
+++ b/cc/debug/traced_value.h
@@ -6,10 +6,16 @@
 #define CC_DEBUG_TRACED_VALUE_H_
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h
index 0208627..d899a85 100644
--- a/cc/input/input_handler.h
+++ b/cc/input/input_handler.h
@@ -143,7 +143,10 @@
                                            ScrollInputType type) = 0;
 
   virtual bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) = 0;
-  virtual bool HaveTouchEventHandlersAt(const gfx::Point& viewport_point) = 0;
+
+  // Whether the page should be given the opportunity to suppress scrolling by
+  // consuming touch events that started at |viewport_point|.
+  virtual bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_point) = 0;
 
   // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped
   // LatencyInfoSwapPromiseMonitor. During the life time of the
diff --git a/cc/layers/content_layer.cc b/cc/layers/content_layer.cc
index 53c7120..6af92ec 100644
--- a/cc/layers/content_layer.cc
+++ b/cc/layers/content_layer.cc
@@ -26,9 +26,8 @@
 
 void ContentLayerPainter::Paint(SkCanvas* canvas,
                                 const gfx::Rect& content_rect) {
-  client_->PaintContents(canvas,
-                         content_rect,
-                         ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+  client_->PaintContents(canvas, content_rect,
+                         ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
 }
 
 scoped_refptr<ContentLayer> ContentLayer::Create(ContentLayerClient* client) {
@@ -128,9 +127,8 @@
 
   SkPictureRecorder recorder;
   SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0);
-  client_->PaintContents(canvas,
-                         gfx::Rect(width, height),
-                         ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+  client_->PaintContents(canvas, gfx::Rect(width, height),
+                         ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
   skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
   return picture;
 }
diff --git a/cc/layers/content_layer_client.h b/cc/layers/content_layer_client.h
index c8d3a7e..4f9c754 100644
--- a/cc/layers/content_layer_client.h
+++ b/cc/layers/content_layer_client.h
@@ -19,18 +19,19 @@
 
 class CC_EXPORT ContentLayerClient {
  public:
-  enum GraphicsContextStatus {
-    GRAPHICS_CONTEXT_DISABLED,
-    GRAPHICS_CONTEXT_ENABLED
+  enum PaintingControlSetting {
+    PAINTING_BEHAVIOR_NORMAL,
+    DISPLAY_LIST_CONSTRUCTION_DISABLED,
+    DISPLAY_LIST_CACHING_DISABLED
   };
 
   virtual void PaintContents(SkCanvas* canvas,
                              const gfx::Rect& clip,
-                             GraphicsContextStatus gc_status) = 0;
+                             PaintingControlSetting painting_status) = 0;
 
   virtual scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) = 0;
+      PaintingControlSetting painting_status) = 0;
 
   // If true the layer may skip clearing the background before rasterizing,
   // because it will cover any uncleared data with content.
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index cdb000f..60d984b 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -69,11 +69,10 @@
 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
                                                  int id)
     : LayerImpl(tree_impl, id),
-      typeface_(skia::AdoptRef(
-          SkTypeface::CreateFromName("monospace", SkTypeface::kBold))),
       fps_graph_(60.0, 80.0),
       paint_time_graph_(16.0, 48.0),
-      fade_step_(0) {}
+      fade_step_(0) {
+}
 
 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {}
 
@@ -173,36 +172,36 @@
     return;
 
   SkISize canvas_size;
-  if (hud_canvas_)
-    canvas_size = hud_canvas_->getDeviceSize();
+  if (hud_surface_)
+    canvas_size = hud_surface_->getCanvas()->getDeviceSize();
   else
     canvas_size.set(0, 0);
 
   if (canvas_size.width() != content_bounds().width() ||
-      canvas_size.height() != content_bounds().height() || !hud_canvas_) {
+      canvas_size.height() != content_bounds().height() || !hud_surface_) {
     TRACE_EVENT0("cc", "ResizeHudCanvas");
-    bool opaque = false;
-    hud_canvas_ = make_scoped_ptr(skia::CreateBitmapCanvas(
-        content_bounds().width(), content_bounds().height(), opaque));
+
+    hud_surface_ = skia::AdoptRef(SkSurface::NewRasterN32Premul(
+        content_bounds().width(), content_bounds().height()));
   }
 
   UpdateHudContents();
 
   {
     TRACE_EVENT0("cc", "DrawHudContents");
-    hud_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
-    hud_canvas_->save();
-    hud_canvas_->scale(contents_scale_x(), contents_scale_y());
+    hud_surface_->getCanvas()->clear(SkColorSetARGB(0, 0, 0, 0));
+    hud_surface_->getCanvas()->save();
+    hud_surface_->getCanvas()->scale(contents_scale_x(), contents_scale_y());
 
-    DrawHudContents(hud_canvas_.get());
+    DrawHudContents(hud_surface_->getCanvas());
 
-    hud_canvas_->restore();
+    hud_surface_->getCanvas()->restore();
   }
 
   TRACE_EVENT0("cc", "UploadHudTexture");
   SkImageInfo info;
   size_t row_bytes = 0;
-  const void* pixels = hud_canvas_->peekPixels(&info, &row_bytes);
+  const void* pixels = hud_surface_->getCanvas()->peekPixels(&info, &row_bytes);
   DCHECK(pixels);
   gfx::Rect content_rect(content_bounds());
   DCHECK(info.colorType() == kN32_SkColorType);
@@ -300,7 +299,7 @@
 
   paint->setTextSize(size);
   paint->setTextAlign(align);
-  paint->setTypeface(typeface_.get());
+  paint->setTypeface(layer_tree_impl()->settings().hud_typeface.get());
   canvas->drawText(text.c_str(), text.length(), x, y, *paint);
 
   paint->setAntiAlias(anti_alias);
@@ -706,7 +705,7 @@
 
     SkPaint label_paint = CreatePaint();
     label_paint.setTextSize(kFontHeight);
-    label_paint.setTypeface(typeface_.get());
+    label_paint.setTypeface(layer_tree_impl()->settings().hud_typeface.get());
     label_paint.setColor(stroke_color);
 
     const SkScalar label_text_width =
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h
index 3e9436b..abba5dc 100644
--- a/cc/layers/heads_up_display_layer_impl.h
+++ b/cc/layers/heads_up_display_layer_impl.h
@@ -126,9 +126,7 @@
   void ReleaseUnmatchedSizeResources(ResourceProvider* resource_provider);
 
   ScopedPtrVector<ScopedResource> resources_;
-  scoped_ptr<SkCanvas> hud_canvas_;
-
-  skia::RefPtr<SkTypeface> typeface_;
+  skia::RefPtr<SkSurface> hud_surface_;
 
   Graph fps_graph_;
   Graph paint_time_graph_;
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index face433..01e67c5 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -71,6 +71,7 @@
       force_render_surface_(false),
       transform_is_invertible_(true),
       has_render_surface_(false),
+      scroll_blocks_on_(ScrollBlocksOnNone),
       background_color_(0),
       opacity_(1.f),
       blend_mode_(SkXfermode::kSrcOver_Mode),
@@ -758,6 +759,14 @@
   SetNeedsCommit();
 }
 
+void Layer::SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on) {
+  DCHECK(IsPropertyChangeAllowed());
+  if (scroll_blocks_on_ == scroll_blocks_on)
+    return;
+  scroll_blocks_on_ = scroll_blocks_on;
+  SetNeedsCommit();
+}
+
 void Layer::SetDrawCheckerboardForMissingTiles(bool checkerboard) {
   DCHECK(IsPropertyChangeAllowed());
   if (draw_checkerboard_for_missing_tiles_ == checkerboard)
@@ -911,6 +920,7 @@
   layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
   layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
   layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
+  layer->SetScrollBlocksOn(scroll_blocks_on_);
   layer->SetContentsOpaque(contents_opaque_);
   if (!layer->OpacityIsAnimatingOnImplOnly() && !OpacityIsAnimating())
     layer->SetOpacity(opacity_);
@@ -978,10 +988,14 @@
     layer->SetClipChildren(nullptr);
   }
 
-  layer->PushScrollOffsetFromMainThread(scroll_offset_);
-  if (layer_animation_controller_->scroll_offset_animation_was_interrupted() &&
-      layer->IsActive())
-    layer->SetScrollDelta(gfx::Vector2dF());
+  // When a scroll offset animation is interrupted the new scroll position on
+  // the pending tree will clobber any impl-side scrolling occuring on the
+  // active tree. To do so, avoid scrolling the pending tree along with it
+  // instead of trying to undo that scrolling later.
+  if (layer_animation_controller_->scroll_offset_animation_was_interrupted())
+    layer->PushScrollOffsetFromMainThreadAndClobberActiveValue(scroll_offset_);
+  else
+    layer->PushScrollOffsetFromMainThread(scroll_offset_);
   layer->SetScrollCompensationAdjustment(ScrollCompensationAdjustment());
 
   // Wrap the copy_requests_ in a PostTask to the main thread.
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index db472c6..cf1356c 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -25,6 +25,7 @@
 #include "cc/layers/layer_position_constraint.h"
 #include "cc/layers/paint_properties.h"
 #include "cc/layers/render_surface.h"
+#include "cc/layers/scroll_blocks_on.h"
 #include "cc/output/filter_operations.h"
 #include "cc/trees/property_tree.h"
 #include "skia/ext/refptr.h"
@@ -43,10 +44,16 @@
 }
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
 }
+}  // namespace base
 
 namespace cc {
 
@@ -305,6 +312,9 @@
     return touch_event_handler_region_;
   }
 
+  void SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on);
+  ScrollBlocksOn scroll_blocks_on() const { return scroll_blocks_on_; }
+
   void set_did_scroll_callback(const base::Closure& callback) {
     did_scroll_callback_ = callback;
   }
@@ -667,6 +677,7 @@
   bool force_render_surface_ : 1;
   bool transform_is_invertible_ : 1;
   bool has_render_surface_ : 1;
+  ScrollBlocksOn scroll_blocks_on_ : 3;
   Region non_fast_scrollable_region_;
   Region touch_event_handler_region_;
   gfx::PointF position_;
diff --git a/cc/layers/layer_client.h b/cc/layers/layer_client.h
index 4b98a95..efdbe51 100644
--- a/cc/layers/layer_client.h
+++ b/cc/layers/layer_client.h
@@ -11,10 +11,16 @@
 #include "cc/base/cc_export.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
 }
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 55ffa7f..eae3685 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -54,6 +54,7 @@
       should_scroll_on_main_thread_(false),
       have_wheel_event_handlers_(false),
       have_scroll_event_handlers_(false),
+      scroll_blocks_on_(ScrollBlocksOnNone),
       user_scrollable_horizontal_(true),
       user_scrollable_vertical_(true),
       stacking_order_changed_(false),
@@ -392,7 +393,8 @@
 
 InputHandler::ScrollStatus LayerImpl::TryScroll(
     const gfx::PointF& screen_space_point,
-    InputHandler::ScrollInputType type) const {
+    InputHandler::ScrollInputType type,
+    ScrollBlocksOn effective_block_mode) const {
   if (should_scroll_on_main_thread()) {
     TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
     return InputHandler::ScrollOnMainThread;
@@ -430,7 +432,14 @@
     }
   }
 
-  if (type == InputHandler::Wheel && have_wheel_event_handlers()) {
+  if (have_scroll_event_handlers() &&
+      effective_block_mode & ScrollBlocksOnScrollEvent) {
+    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed ScrollEventHandlers");
+    return InputHandler::ScrollOnMainThread;
+  }
+
+  if (type == InputHandler::Wheel && have_wheel_event_handlers() &&
+      effective_block_mode & ScrollBlocksOnWheelEvent) {
     TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
     return InputHandler::ScrollOnMainThread;
   }
@@ -487,6 +496,7 @@
   layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
   layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
   layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
+  layer->SetScrollBlocksOn(scroll_blocks_on_);
   layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
   layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
   layer->SetContentsOpaque(contents_opaque_);
@@ -649,6 +659,17 @@
     result->Set("TouchRegion", region.release());
   }
 
+  if (scroll_blocks_on_) {
+    list = new base::ListValue;
+    if (scroll_blocks_on_ & ScrollBlocksOnStartTouch)
+      list->AppendString("StartTouch");
+    if (scroll_blocks_on_ & ScrollBlocksOnWheelEvent)
+      list->AppendString("WheelEvent");
+    if (scroll_blocks_on_ & ScrollBlocksOnScrollEvent)
+      list->AppendString("ScrollEvent");
+    result->Set("ScrollBlocksOn", list);
+  }
+
   list = new base::ListValue;
   for (size_t i = 0; i < children_.size(); ++i)
     list->Append(children_[i]->LayerTreeAsJson());
@@ -1080,22 +1101,15 @@
   PushScrollOffset(&scroll_offset);
 }
 
+void LayerImpl::PushScrollOffsetFromMainThreadAndClobberActiveValue(
+    const gfx::ScrollOffset& scroll_offset) {
+  scroll_offset_->set_clobber_active_value();
+  PushScrollOffset(&scroll_offset);
+}
+
 gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() {
   RefreshFromScrollDelegate();
-
-  // TODO(aelias, miletus): Remove all this temporary flooring machinery when
-  // Blink fully supports fractional scrolls.
-  gfx::ScrollOffset current_offset = CurrentScrollOffset();
-  gfx::Vector2dF current_delta = ScrollDelta();
-  gfx::Vector2dF floored_delta(floor(current_delta.x()),
-                               floor(current_delta.y()));
-  gfx::Vector2dF diff_delta = floored_delta - current_delta;
-  gfx::ScrollOffset tmp_offset = ScrollOffsetWithDelta(current_offset,
-                                                       diff_delta);
-  scroll_offset_->SetCurrent(tmp_offset);
-  gfx::ScrollOffset delta = scroll_offset_->PullDeltaForMainThread();
-  scroll_offset_->SetCurrent(current_offset);
-  return delta;
+  return scroll_offset_->PullDeltaForMainThread();
 }
 
 void LayerImpl::RefreshFromScrollDelegate() {
@@ -1140,8 +1154,6 @@
   }
   if (IsActive()) {
     changed |= scroll_offset_->PushPendingToActive();
-    if (layer_animation_controller_->scroll_offset_animation_was_interrupted())
-      SetScrollDelta(gfx::Vector2dF());
   }
 
   if (changed)
@@ -1177,6 +1189,9 @@
 
 void LayerImpl::ReleaseResources() {}
 
+void LayerImpl::RecreateResources() {
+}
+
 gfx::ScrollOffset LayerImpl::MaxScrollOffset() const {
   if (!scroll_clip_layer_ || bounds().IsEmpty())
     return gfx::ScrollOffset();
@@ -1440,6 +1455,9 @@
     non_fast_scrollable_region_.AsValueInto(state);
     state->EndArray();
   }
+  if (scroll_blocks_on_) {
+    state->SetInteger("scroll_blocks_on", scroll_blocks_on_);
+  }
 
   state->BeginArray("children");
   for (size_t i = 0; i < children_.size(); ++i) {
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index f46c16e..96f915f 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -27,6 +27,7 @@
 #include "cc/layers/layer_lists.h"
 #include "cc/layers/layer_position_constraint.h"
 #include "cc/layers/render_surface_impl.h"
+#include "cc/layers/scroll_blocks_on.h"
 #include "cc/output/filter_operations.h"
 #include "cc/quads/shared_quad_state.h"
 #include "cc/resources/resource_provider.h"
@@ -41,13 +42,19 @@
 #include "ui/gfx/transform.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 class TracedValue;
 }
 
-class DictionaryValue;
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
 }
+class DictionaryValue;
+}  // namespace base
 
 namespace cc {
 
@@ -399,6 +406,11 @@
 
   void SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset);
   void PushScrollOffsetFromMainThread(const gfx::ScrollOffset& scroll_offset);
+  // This method is similar to PushScrollOffsetFromMainThread but will cause the
+  // scroll offset given to clobber any scroll changes on the active tree in the
+  // time until this value is pushed to the active tree.
+  void PushScrollOffsetFromMainThreadAndClobberActiveValue(
+      const gfx::ScrollOffset& scroll_offset);
   gfx::ScrollOffset PullDeltaForMainThread();
   gfx::ScrollOffset CurrentScrollOffset() const;
   gfx::ScrollOffset BaseScrollOffset() const;
@@ -474,6 +486,10 @@
     return touch_event_handler_region_;
   }
 
+  void SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on) {
+    scroll_blocks_on_ = scroll_blocks_on;
+  }
+  ScrollBlocksOn scroll_blocks_on() const { return scroll_blocks_on_; }
   void SetDrawCheckerboardForMissingTiles(bool checkerboard) {
     draw_checkerboard_for_missing_tiles_ = checkerboard;
   }
@@ -483,7 +499,8 @@
 
   InputHandler::ScrollStatus TryScroll(
       const gfx::PointF& screen_space_point,
-      InputHandler::ScrollInputType type) const;
+      InputHandler::ScrollInputType type,
+      ScrollBlocksOn effective_block_mode) const;
 
   void SetDoubleSided(bool double_sided);
   bool double_sided() const { return double_sided_; }
@@ -530,6 +547,10 @@
   // that rendered this layer was lost or a rendering mode switch has occured.
   virtual void ReleaseResources();
 
+  // Recreate resources that are required after they were released by a
+  // ReleaseResources call.
+  virtual void RecreateResources();
+
   ScrollbarAnimationController* scrollbar_animation_controller() const {
     return scrollbar_animation_controller_.get();
   }
@@ -657,6 +678,10 @@
   bool should_scroll_on_main_thread_ : 1;
   bool have_wheel_event_handlers_ : 1;
   bool have_scroll_event_handlers_ : 1;
+
+  static_assert(ScrollBlocksOnMax < (1 << 3), "ScrollBlocksOn too big");
+  ScrollBlocksOn scroll_blocks_on_ : 3;
+
   bool user_scrollable_horizontal_ : 1;
   bool user_scrollable_vertical_ : 1;
   bool stacking_order_changed_ : 1;
diff --git a/cc/layers/picture_image_layer.cc b/cc/layers/picture_image_layer.cc
index 85bc582..9f35d6e 100644
--- a/cc/layers/picture_image_layer.cc
+++ b/cc/layers/picture_image_layer.cc
@@ -47,7 +47,7 @@
 void PictureImageLayer::PaintContents(
     SkCanvas* canvas,
     const gfx::Rect& clip,
-    ContentLayerClient::GraphicsContextStatus gc_status) {
+    ContentLayerClient::PaintingControlSetting painting_control) {
   if (!bitmap_.width() || !bitmap_.height())
     return;
 
@@ -65,12 +65,12 @@
 
 scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList(
     const gfx::Rect& clip,
-    GraphicsContextStatus gc_status) {
+    ContentLayerClient::PaintingControlSetting painting_control) {
   scoped_refptr<DisplayItemList> display_item_list = DisplayItemList::Create();
 
   SkPictureRecorder recorder;
   SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(clip));
-  PaintContents(canvas, clip, gc_status);
+  PaintContents(canvas, clip, painting_control);
 
   skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
   display_item_list->AppendItem(
diff --git a/cc/layers/picture_image_layer.h b/cc/layers/picture_image_layer.h
index 57c7de2..8d40550 100644
--- a/cc/layers/picture_image_layer.h
+++ b/cc/layers/picture_image_layer.h
@@ -26,10 +26,10 @@
   void PaintContents(
       SkCanvas* canvas,
       const gfx::Rect& clip,
-      ContentLayerClient::GraphicsContextStatus gc_status) override;
+      ContentLayerClient::PaintingControlSetting painting_control) override;
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override;
+      ContentLayerClient::PaintingControlSetting painting_control) override;
   bool FillsBoundsCompletely() const override;
 
  protected:
diff --git a/cc/layers/picture_image_layer_unittest.cc b/cc/layers/picture_image_layer_unittest.cc
index acf691d..5b9375d 100644
--- a/cc/layers/picture_image_layer_unittest.cc
+++ b/cc/layers/picture_image_layer_unittest.cc
@@ -35,7 +35,7 @@
 
   scoped_refptr<DisplayItemList> display_list =
       layer->PaintContentsToDisplayList(
-          layer_rect, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+          layer_rect, ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
   unsigned char actual_pixels[4 * 200 * 200] = {0};
   DrawDisplayList(actual_pixels, layer_rect, display_list);
 
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 0b7d699..52288e9 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -148,7 +148,7 @@
   updated |= recording_source_->UpdateAndExpandInvalidation(
       client_, &recording_invalidation_, can_use_lcd_text_for_update_,
       layer_size, visible_layer_rect, update_source_frame_number_,
-      Picture::RECORD_NORMALLY);
+      RecordingSource::RECORD_NORMALLY);
   last_updated_visible_content_rect_ = visible_content_rect();
 
   if (updated) {
@@ -192,9 +192,8 @@
 
   SkPictureRecorder recorder;
   SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0);
-  client_->PaintContents(canvas,
-                         gfx::Rect(width, height),
-                         ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+  client_->PaintContents(canvas, gfx::Rect(width, height),
+                         ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
   skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
   return picture;
 }
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 15059ba..3a0753f 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -602,8 +602,12 @@
 void PictureLayerImpl::ReleaseResources() {
   // Recreate tilings with new settings, since some of those might change when
   // we release resources.
-  tilings_ = CreatePictureLayerTilingSet();
+  tilings_ = nullptr;
   ResetRasterScale();
+}
+
+void PictureLayerImpl::RecreateResources() {
+  tilings_ = CreatePictureLayerTilingSet();
 
   // To avoid an edge case after lost context where the tree is up to date but
   // the tilings have not been managed, request an update draw properties
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index fa40683..e7f4fba 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -62,6 +62,7 @@
   void NotifyTileStateChanged(const Tile* tile) override;
   void DidBeginTracing() override;
   void ReleaseResources() override;
+  void RecreateResources() override;
   skia::RefPtr<SkPicture> GetPicture() override;
 
   // PictureLayerTilingClient overrides.
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 0a95f31..600f3e2 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -278,11 +278,14 @@
 
   void ResetTilingsAndRasterScales() {
     pending_layer_->ReleaseResources();
+    EXPECT_FALSE(pending_layer_->tilings());
+    pending_layer_->RecreateResources();
+    EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
     active_layer_->ReleaseResources();
-    if (pending_layer_)
-      EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
-    if (active_layer_)
-      EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+    EXPECT_FALSE(active_layer_->tilings());
+    active_layer_->RecreateResources();
+    EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
   }
 
   void AssertAllTilesRequired(PictureLayerTiling* tiling) {
@@ -711,7 +714,7 @@
     VerifyAllTilesExistAndHavePile(tilings->tiling_at(i), pending_pile.get());
 }
 
-TEST_F(PictureLayerImplTest, ManageTilingsCreatesTilings) {
+TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) {
   gfx::Size tile_size(400, 400);
   gfx::Size layer_bounds(1300, 1900);
 
@@ -726,6 +729,8 @@
   EXPECT_LT(low_res_factor, 1.f);
 
   active_layer_->ReleaseResources();
+  EXPECT_FALSE(active_layer_->tilings());
+  active_layer_->RecreateResources();
   EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
 
   SetupDrawPropertiesAndUpdateTiles(active_layer_,
@@ -796,6 +801,8 @@
   EXPECT_LT(low_res_factor, 1.f);
 
   pending_layer_->ReleaseResources();
+  EXPECT_FALSE(pending_layer_->tilings());
+  pending_layer_->RecreateResources();
   EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
 
   SetupDrawPropertiesAndUpdateTiles(pending_layer_,
@@ -1326,6 +1333,8 @@
   // Drop resources and recreate them, still the same.
   pending_mask->ReleaseResources();
   active_mask->ReleaseResources();
+  pending_mask->RecreateResources();
+  active_mask->RecreateResources();
   SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, false);
   active_mask->HighResTiling()->CreateAllTilesForTesting();
   EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
@@ -1369,6 +1378,8 @@
   // Drop resources and recreate them, still the same.
   pending_mask->ReleaseResources();
   active_mask->ReleaseResources();
+  pending_mask->RecreateResources();
+  active_mask->RecreateResources();
   SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, false);
   active_mask->HighResTiling()->CreateAllTilesForTesting();
   EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
@@ -1475,8 +1486,12 @@
 
   // All tilings should be removed when losing output surface.
   active_layer_->ReleaseResources();
+  EXPECT_FALSE(active_layer_->tilings());
+  active_layer_->RecreateResources();
   EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
   pending_layer_->ReleaseResources();
+  EXPECT_FALSE(pending_layer_->tilings());
+  pending_layer_->RecreateResources();
   EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
 
   // This should create new tilings.
@@ -3744,8 +3759,12 @@
 
   // All tilings should be removed when losing output surface.
   active_layer_->ReleaseResources();
+  EXPECT_FALSE(active_layer_->tilings());
+  active_layer_->RecreateResources();
   EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
   pending_layer_->ReleaseResources();
+  EXPECT_FALSE(pending_layer_->tilings());
+  pending_layer_->RecreateResources();
   EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
 
   // This should create new tilings.
@@ -4644,7 +4663,7 @@
   Region invalidation(layer_rect);
   recording_source->UpdateAndExpandInvalidation(
       &client, &invalidation, false, layer_bounds, layer_rect, frame_number++,
-      Picture::RECORD_NORMALLY);
+      RecordingSource::RECORD_NORMALLY);
 
   scoped_refptr<RasterSource> pending_raster_source =
       recording_source->CreateRasterSource();
@@ -4707,7 +4726,7 @@
   Region invalidation1(layer_rect);
   recording_source->UpdateAndExpandInvalidation(
       &client, &invalidation1, false, layer_bounds, layer_rect, frame_number++,
-      Picture::RECORD_NORMALLY);
+      RecordingSource::RECORD_NORMALLY);
 
   scoped_refptr<RasterSource> raster_source1 =
       recording_source->CreateRasterSource();
@@ -4725,7 +4744,7 @@
   Region invalidation2(layer_rect);
   recording_source->UpdateAndExpandInvalidation(
       &client, &invalidation2, false, layer_bounds, layer_rect, frame_number++,
-      Picture::RECORD_NORMALLY);
+      RecordingSource::RECORD_NORMALLY);
 
   scoped_refptr<RasterSource> raster_source2 =
       recording_source->CreateRasterSource();
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 9327e13..afb6096 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -20,13 +20,12 @@
 
 class MockContentLayerClient : public ContentLayerClient {
  public:
-  void PaintContents(
-      SkCanvas* canvas,
-      const gfx::Rect& clip,
-      ContentLayerClient::GraphicsContextStatus gc_status) override {}
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& clip,
+                     PaintingControlSetting picture_control) override {}
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override {
+      PaintingControlSetting picture_control) override {
     NOTIMPLEMENTED();
     return DisplayItemList::Create();
   }
diff --git a/cc/layers/scroll_blocks_on.h b/cc/layers/scroll_blocks_on.h
new file mode 100644
index 0000000..2447298
--- /dev/null
+++ b/cc/layers/scroll_blocks_on.h
@@ -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.
+
+#ifndef CC_LAYERS_SCROLL_BLOCKS_ON_H_
+#define CC_LAYERS_SCROLL_BLOCKS_ON_H_
+
+enum ScrollBlocksOn {
+  ScrollBlocksOnNone = 0x0,
+  ScrollBlocksOnStartTouch = 0x1,
+  ScrollBlocksOnWheelEvent = 0x2,
+  ScrollBlocksOnScrollEvent = 0x4,
+  ScrollBlocksOnMax = ScrollBlocksOnStartTouch | ScrollBlocksOnWheelEvent |
+                      ScrollBlocksOnScrollEvent
+};
+
+inline ScrollBlocksOn operator|(ScrollBlocksOn a, ScrollBlocksOn b) {
+  return ScrollBlocksOn(static_cast<int>(a) | static_cast<int>(b));
+}
+
+inline ScrollBlocksOn& operator|=(ScrollBlocksOn& a, ScrollBlocksOn b) {
+  return a = a | b;
+}
+
+#endif  // CC_LAYERS_SCROLL_BLOCKS_ON_H_
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 09de7d0..b24dcb1 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -107,8 +107,8 @@
   // responded to on the main thread as the compositor does not yet implement
   // scrollbar scrolling.
   EXPECT_EQ(InputHandler::ScrollOnMainThread,
-            scrollbar_layer_impl->TryScroll(gfx::Point(0, 0),
-                                            InputHandler::Gesture));
+            scrollbar_layer_impl->TryScroll(
+                gfx::Point(0, 0), InputHandler::Gesture, ScrollBlocksOnNone));
 
   // Create and attach an overlay scrollbar.
   scrollbar.reset(new FakeScrollbar(false, false, true));
@@ -121,8 +121,8 @@
   // The user shouldn't be able to drag an overlay scrollbar and the scroll
   // may be handled in the compositor.
   EXPECT_EQ(InputHandler::ScrollIgnored,
-            scrollbar_layer_impl->TryScroll(gfx::Point(0, 0),
-                                            InputHandler::Gesture));
+            scrollbar_layer_impl->TryScroll(
+                gfx::Point(0, 0), InputHandler::Gesture, ScrollBlocksOnNone));
 }
 
 TEST(PaintedScrollbarLayerTest, ScrollOffsetSynchronization) {
diff --git a/cc/output/begin_frame_args.h b/cc/output/begin_frame_args.h
index 53745f9..47430ca 100644
--- a/cc/output/begin_frame_args.h
+++ b/cc/output/begin_frame_args.h
@@ -12,11 +12,18 @@
 #include "cc/base/cc_export.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 /**
  * In debug builds we trace the creation origin of BeginFrameArgs objects. We
diff --git a/cc/output/filter_operation.h b/cc/output/filter_operation.h
index fc14cb1..157db99 100644
--- a/cc/output/filter_operation.h
+++ b/cc/output/filter_operation.h
@@ -16,11 +16,17 @@
 #include "ui/gfx/geometry/point.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
-class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+class Value;
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/output/filter_operations.h b/cc/output/filter_operations.h
index a8c206e..8e37933 100644
--- a/cc/output/filter_operations.h
+++ b/cc/output/filter_operations.h
@@ -12,11 +12,17 @@
 #include "cc/output/filter_operation.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
-class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+class Value;
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/output/overlay_candidate.cc b/cc/output/overlay_candidate.cc
index 4168253..46c3a7d 100644
--- a/cc/output/overlay_candidate.cc
+++ b/cc/output/overlay_candidate.cc
@@ -24,7 +24,7 @@
 gfx::OverlayTransform OverlayCandidate::GetOverlayTransform(
     const gfx::Transform& quad_transform,
     bool flipped) {
-  if (!quad_transform.IsIdentityOrTranslation())
+  if (!quad_transform.IsPositiveScaleOrTranslation())
     return gfx::OVERLAY_TRANSFORM_INVALID;
 
   return flipped ? gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
@@ -32,9 +32,105 @@
 }
 
 // static
+gfx::OverlayTransform OverlayCandidate::ModifyTransform(
+    gfx::OverlayTransform in,
+    gfx::OverlayTransform delta) {
+  // There are 8 different possible transforms. We can characterize these
+  // by looking at where the origin moves and the direction the horizontal goes.
+  // (TL=top-left, BR=bottom-right, H=horizontal, V=vertical).
+  // NONE: TL, H
+  // FLIP_VERTICAL: BL, H
+  // FLIP_HORIZONTAL: TR, H
+  // ROTATE_90: TR, V
+  // ROTATE_180: BR, H
+  // ROTATE_270: BL, V
+  // Missing transforms: TL, V & BR, V
+  // Basic combinations:
+  // Flip X & Y -> Rotate 180 (TL,H -> TR,H -> BR,H or TL,H -> BL,H -> BR,H)
+  // Flip X or Y + Rotate 180 -> other flip (eg, TL,H -> TR,H -> BL,H)
+  // Rotate + Rotate simply adds values.
+  // Rotate 90/270 + flip is invalid because we can only have verticals with
+  // the origin in TR or BL.
+  if (delta == gfx::OVERLAY_TRANSFORM_NONE)
+    return in;
+  switch (in) {
+    case gfx::OVERLAY_TRANSFORM_NONE:
+      return delta;
+    case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+      switch (delta) {
+        case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+          return gfx::OVERLAY_TRANSFORM_NONE;
+        case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+          return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+        default:
+          return gfx::OVERLAY_TRANSFORM_INVALID;
+      }
+      break;
+    case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+      switch (delta) {
+        case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+          return gfx::OVERLAY_TRANSFORM_NONE;
+        case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+        case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+          return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+        default:
+          return gfx::OVERLAY_TRANSFORM_INVALID;
+      }
+      break;
+    case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+      switch (delta) {
+        case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+          return gfx::OVERLAY_TRANSFORM_NONE;
+        default:
+          return gfx::OVERLAY_TRANSFORM_INVALID;
+      }
+      break;
+    case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+      switch (delta) {
+        case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+          return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+        case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+          return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+          return gfx::OVERLAY_TRANSFORM_NONE;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+        default:
+          return gfx::OVERLAY_TRANSFORM_INVALID;
+      }
+      break;
+    case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+      switch (delta) {
+        case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+          return gfx::OVERLAY_TRANSFORM_NONE;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+        case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+          return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+        default:
+          return gfx::OVERLAY_TRANSFORM_INVALID;
+      }
+      break;
+    default:
+      return gfx::OVERLAY_TRANSFORM_INVALID;
+  }
+}
+
+// static
 gfx::Rect OverlayCandidate::GetOverlayRect(const gfx::Transform& quad_transform,
                                            const gfx::Rect& rect) {
-  DCHECK(quad_transform.IsIdentityOrTranslation());
+  DCHECK(quad_transform.IsPositiveScaleOrTranslation());
 
   gfx::RectF float_rect(rect);
   quad_transform.TransformRect(&float_rect);
diff --git a/cc/output/overlay_candidate.h b/cc/output/overlay_candidate.h
index 9a1e534..28ae8cb 100644
--- a/cc/output/overlay_candidate.h
+++ b/cc/output/overlay_candidate.h
@@ -20,6 +20,10 @@
   static gfx::OverlayTransform GetOverlayTransform(
       const gfx::Transform& quad_transform,
       bool flipped);
+  // Apply transform |delta| to |in| and return the resulting transform,
+  // or OVERLAY_TRANSFORM_INVALID.
+  static gfx::OverlayTransform ModifyTransform(gfx::OverlayTransform in,
+                                               gfx::OverlayTransform delta);
   static gfx::Rect GetOverlayRect(const gfx::Transform& quad_transform,
                                   const gfx::Rect& rect);
 
diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc
index 98d77ad..9a95206 100644
--- a/cc/output/overlay_strategy_single_on_top.cc
+++ b/cc/output/overlay_strategy_single_on_top.cc
@@ -4,8 +4,13 @@
 
 #include "cc/output/overlay_strategy_single_on_top.h"
 
+#include <limits>
+
 #include "cc/quads/draw_quad.h"
+#include "cc/quads/solid_color_draw_quad.h"
+#include "cc/quads/stream_video_draw_quad.h"
 #include "cc/quads/texture_draw_quad.h"
+#include "ui/gfx/geometry/point3_f.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/transform.h"
 
@@ -17,6 +22,103 @@
     : capability_checker_(capability_checker),
       resource_provider_(resource_provider) {}
 
+bool OverlayStrategySingleOnTop::IsOverlayQuad(const DrawQuad* draw_quad) {
+  unsigned int resource_id;
+  switch (draw_quad->material) {
+    case DrawQuad::TEXTURE_CONTENT:
+      resource_id = TextureDrawQuad::MaterialCast(draw_quad)->resource_id;
+      break;
+    case DrawQuad::STREAM_VIDEO_CONTENT:
+      resource_id = StreamVideoDrawQuad::MaterialCast(draw_quad)->resource_id;
+      break;
+    default:
+      return false;
+  }
+  return resource_provider_->AllowOverlay(resource_id);
+}
+
+bool OverlayStrategySingleOnTop::GetTextureQuadInfo(
+    const TextureDrawQuad& quad,
+    OverlayCandidate* quad_info) {
+  gfx::OverlayTransform overlay_transform =
+      OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped);
+  if (quad.background_color != SK_ColorTRANSPARENT ||
+      quad.premultiplied_alpha ||
+      overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
+    return false;
+  quad_info->resource_id = quad.resource_id;
+  quad_info->transform = overlay_transform;
+  quad_info->uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
+  return true;
+}
+
+bool OverlayStrategySingleOnTop::GetVideoQuadInfo(
+    const StreamVideoDrawQuad& quad,
+    OverlayCandidate* quad_info) {
+  gfx::OverlayTransform overlay_transform =
+      OverlayCandidate::GetOverlayTransform(quad.quadTransform(), false);
+  if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
+    return false;
+  if (!quad.matrix.IsScaleOrTranslation()) {
+    // We cannot handle anything other than scaling & translation for texture
+    // coordinates yet.
+    return false;
+  }
+  quad_info->resource_id = quad.resource_id;
+  quad_info->transform = overlay_transform;
+
+  gfx::Point3F uv0 = gfx::Point3F(0, 0, 0);
+  gfx::Point3F uv1 = gfx::Point3F(1, 1, 0);
+  quad.matrix.TransformPoint(&uv0);
+  quad.matrix.TransformPoint(&uv1);
+  gfx::Vector3dF delta = uv1 - uv0;
+  if (delta.x() < 0) {
+    quad_info->transform = OverlayCandidate::ModifyTransform(
+        quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL);
+    float x0 = uv0.x();
+    uv0.set_x(uv1.x());
+    uv1.set_x(x0);
+    delta.set_x(-delta.x());
+  }
+
+  if (delta.y() < 0) {
+    // In this situation, uv0y < uv1y. Since we overlay inverted, a request
+    // to invert the source texture means we can just output the texture
+    // normally and it will be correct.
+    quad_info->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y());
+  } else {
+    quad_info->transform = OverlayCandidate::ModifyTransform(
+        quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL);
+    quad_info->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y());
+  }
+  return true;
+}
+
+bool OverlayStrategySingleOnTop::GetCandidateQuadInfo(
+    const DrawQuad& draw_quad,
+    OverlayCandidate* quad_info) {
+  // All quad checks.
+  if (draw_quad.needs_blending || draw_quad.shared_quad_state->opacity != 1.f ||
+      draw_quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode)
+    return false;
+
+  if (draw_quad.material == DrawQuad::TEXTURE_CONTENT) {
+    const TextureDrawQuad& quad = *TextureDrawQuad::MaterialCast(&draw_quad);
+    if (!GetTextureQuadInfo(quad, quad_info))
+      return false;
+  } else if (draw_quad.material == DrawQuad::STREAM_VIDEO_CONTENT) {
+    const StreamVideoDrawQuad& quad =
+        *StreamVideoDrawQuad::MaterialCast(&draw_quad);
+    if (!GetVideoQuadInfo(quad, quad_info))
+      return false;
+  }
+
+  quad_info->format = RGBA_8888;
+  quad_info->display_rect = OverlayCandidate::GetOverlayRect(
+      draw_quad.quadTransform(), draw_quad.rect);
+  return true;
+}
+
 bool OverlayStrategySingleOnTop::Attempt(
     RenderPassList* render_passes_in_draw_order,
     OverlayCandidateList* candidate_list) {
@@ -27,15 +129,12 @@
   RenderPass* root_render_pass = render_passes_in_draw_order->back();
   DCHECK(root_render_pass);
 
+  OverlayCandidate candidate;
   QuadList& quad_list = root_render_pass->quad_list;
   auto candidate_iterator = quad_list.end();
   for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
     const DrawQuad* draw_quad = *it;
-    if (draw_quad->material == DrawQuad::TEXTURE_CONTENT) {
-      const TextureDrawQuad& quad = *TextureDrawQuad::MaterialCast(draw_quad);
-      if (!resource_provider_->AllowOverlay(quad.resource_id)) {
-        continue;
-      }
+    if (IsOverlayQuad(draw_quad)) {
       // Check that no prior quads overlap it.
       bool intersects = false;
       gfx::RectF rect = draw_quad->rect;
@@ -49,7 +148,7 @@
           break;
         }
       }
-      if (intersects)
+      if (intersects || !GetCandidateQuadInfo(*draw_quad, &candidate))
         continue;
       candidate_iterator = it;
       break;
@@ -57,34 +156,14 @@
   }
   if (candidate_iterator == quad_list.end())
     return false;
-  const TextureDrawQuad& quad =
-      *TextureDrawQuad::MaterialCast(*candidate_iterator);
-
-  // Simple quads only.
-  gfx::OverlayTransform overlay_transform =
-      OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped);
-  if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID ||
-      !quad.quadTransform().IsIdentityOrTranslation() || quad.needs_blending ||
-      quad.shared_quad_state->opacity != 1.f ||
-      quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode ||
-      quad.premultiplied_alpha || quad.background_color != SK_ColorTRANSPARENT)
-    return false;
 
   // Add our primary surface.
   OverlayCandidateList candidates;
   OverlayCandidate main_image;
   main_image.display_rect = root_render_pass->output_rect;
-  main_image.format = RGBA_8888;
   candidates.push_back(main_image);
 
   // Add the overlay.
-  OverlayCandidate candidate;
-  candidate.transform = overlay_transform;
-  candidate.display_rect =
-      OverlayCandidate::GetOverlayRect(quad.quadTransform(), quad.rect);
-  candidate.uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
-  candidate.format = RGBA_8888;
-  candidate.resource_id = quad.resource_id;
   candidate.plane_z_order = 1;
   candidates.push_back(candidate);
 
diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h
index e5518cc..f92e104 100644
--- a/cc/output/overlay_strategy_single_on_top.h
+++ b/cc/output/overlay_strategy_single_on_top.h
@@ -14,6 +14,8 @@
 
 namespace cc {
 class OverlayCandidateValidator;
+class StreamVideoDrawQuad;
+class TextureDrawQuad;
 
 class CC_EXPORT OverlayStrategySingleOnTop : public OverlayProcessor::Strategy {
  public:
@@ -23,6 +25,15 @@
                OverlayCandidateList* candidate_list) override;
 
  private:
+  bool IsOverlayQuad(const DrawQuad* draw_quad);
+  bool GetCandidateQuadInfo(const DrawQuad& draw_quad,
+                            OverlayCandidate* quad_info);
+
+  bool GetTextureQuadInfo(const TextureDrawQuad& quad,
+                          OverlayCandidate* quad_info);
+  bool GetVideoQuadInfo(const StreamVideoDrawQuad& quad,
+                        OverlayCandidate* quad_info);
+
   OverlayCandidateValidator* capability_checker_;
   ResourceProvider* resource_provider_;
   DISALLOW_COPY_AND_ASSIGN(OverlayStrategySingleOnTop);
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 8fa35cb..4682679 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -11,6 +11,7 @@
 #include "cc/output/overlay_strategy_single_on_top.h"
 #include "cc/quads/checkerboard_draw_quad.h"
 #include "cc/quads/render_pass.h"
+#include "cc/quads/stream_video_draw_quad.h"
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/texture_mailbox.h"
@@ -32,6 +33,16 @@
 const gfx::Rect kOverlayBottomRightRect(64, 64, 64, 64);
 const gfx::PointF kUVTopLeft(0.1f, 0.2f);
 const gfx::PointF kUVBottomRight(1.0f, 1.0f);
+const gfx::Transform kNormalTransform =
+    gfx::Transform(0.9f, 0, 0, 0.8f, 0.1f, 0.2f);  // x,y -> x,y.
+const gfx::Transform kXMirrorTransform =
+    gfx::Transform(-0.9f, 0, 0, 0.8f, 1.0f, 0.2f);  // x,y -> 1-x,y.
+const gfx::Transform kYMirrorTransform =
+    gfx::Transform(0.9f, 0, 0, -0.8f, 0.1f, 1.0f);  // x,y -> x,1-y.
+const gfx::Transform kBothMirrorTransform =
+    gfx::Transform(-0.9f, 0, 0, -0.8f, 1.0f, 1.0f);  // x,y -> 1-x,1-y.
+const gfx::Transform kSwapTransform =
+    gfx::Transform(0, 1, 1, 0, 0, 0);  // x,y -> y,x.
 
 void MailboxReleased(unsigned sync_point,
                      bool lost_resource,
@@ -173,6 +184,22 @@
   return overlay_quad;
 }
 
+StreamVideoDrawQuad* CreateCandidateVideoQuadAt(
+    ResourceProvider* resource_provider,
+    const SharedQuadState* shared_quad_state,
+    RenderPass* render_pass,
+    const gfx::Rect& rect,
+    const gfx::Transform& transform) {
+  ResourceProvider::ResourceId resource_id = CreateResource(resource_provider);
+
+  StreamVideoDrawQuad* overlay_quad =
+      render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
+  overlay_quad->SetNew(shared_quad_state, rect, rect, rect, resource_id,
+                       transform);
+
+  return overlay_quad;
+}
+
 TextureDrawQuad* CreateFullscreenCandidateQuad(
     ResourceProvider* resource_provider,
     const SharedQuadState* shared_quad_state,
@@ -181,6 +208,15 @@
       resource_provider, shared_quad_state, render_pass, kOverlayRect);
 }
 
+StreamVideoDrawQuad* CreateFullscreenCandidateVideoQuad(
+    ResourceProvider* resource_provider,
+    const SharedQuadState* shared_quad_state,
+    RenderPass* render_pass,
+    const gfx::Transform& transform) {
+  return CreateCandidateVideoQuadAt(resource_provider, shared_quad_state,
+                                    render_pass, kOverlayRect, transform);
+}
+
 void CreateCheckeredQuadAt(ResourceProvider* resource_provider,
                            const SharedQuadState* shared_quad_state,
                            RenderPass* render_pass,
@@ -484,13 +520,13 @@
   EXPECT_EQ(0U, candidate_list.size());
 }
 
-TEST_F(SingleOverlayOnTopTest, RejectTransform) {
+TEST_F(SingleOverlayOnTopTest, RejectNonScaleTransform) {
   scoped_ptr<RenderPass> pass = CreateRenderPass();
   CreateFullscreenCandidateQuad(resource_provider_.get(),
                                 pass->shared_quad_state_list.back(),
                                 pass.get());
-  pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.f,
-                                                                         2.f);
+  pass->shared_quad_state_list.back()
+      ->content_to_target_transform.RotateAboutXAxis(45.f);
 
   RenderPassList pass_list;
   pass_list.push_back(pass.Pass());
@@ -500,6 +536,39 @@
   EXPECT_EQ(0U, candidate_list.size());
 }
 
+TEST_F(SingleOverlayOnTopTest, RejectNegativeScaleTransform) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateQuad(resource_provider_.get(),
+                                pass->shared_quad_state_list.back(),
+                                pass.get());
+  pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f,
+                                                                         -1.0f);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  ASSERT_EQ(1U, pass_list.size());
+  EXPECT_EQ(0U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) {
+  gfx::Rect rect = kOverlayRect;
+  rect.set_width(rect.width() / 2);
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateCandidateQuadAt(resource_provider_.get(),
+                        pass->shared_quad_state_list.back(), pass.get(), rect);
+  pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f,
+                                                                         1.0f);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  ASSERT_EQ(1U, pass_list.size());
+  EXPECT_EQ(2U, candidate_list.size());
+}
+
 TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
   scoped_ptr<RenderPass> pass = CreateRenderPass();
   CreateCheckeredQuadAt(resource_provider_.get(),
@@ -523,6 +592,76 @@
   EXPECT_EQ(2U, candidate_list.size());
 }
 
+TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+                                     pass->shared_quad_state_list.back(),
+                                     pass.get(), kSwapTransform);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  ASSERT_EQ(1U, pass_list.size());
+  EXPECT_EQ(0U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoXMirrorTransform) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+                                     pass->shared_quad_state_list.back(),
+                                     pass.get(), kXMirrorTransform);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  ASSERT_EQ(1U, pass_list.size());
+  EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoBothMirrorTransform) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+                                     pass->shared_quad_state_list.back(),
+                                     pass.get(), kBothMirrorTransform);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  ASSERT_EQ(1U, pass_list.size());
+  EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoNormalTransform) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+                                     pass->shared_quad_state_list.back(),
+                                     pass.get(), kNormalTransform);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  ASSERT_EQ(1U, pass_list.size());
+  EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+                                     pass->shared_quad_state_list.back(),
+                                     pass.get(), kYMirrorTransform);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  ASSERT_EQ(1U, pass_list.size());
+  EXPECT_EQ(2U, candidate_list.size());
+}
+
 class OverlayInfoRendererGL : public GLRenderer {
  public:
   OverlayInfoRendererGL(RendererClient* client,
diff --git a/cc/quads/draw_quad.h b/cc/quads/draw_quad.h
index 61ca358..d9395cd 100644
--- a/cc/quads/draw_quad.h
+++ b/cc/quads/draw_quad.h
@@ -11,12 +11,18 @@
 #include "cc/resources/resource_provider.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
+}
 class Value;
 class DictionaryValue;
-}
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 2877588..8a40f17 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -20,11 +20,17 @@
 #include "ui/gfx/transform.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
 class Value;
-};
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
+}
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/quads/shared_quad_state.h b/cc/quads/shared_quad_state.h
index ebf7d11..0db23e1 100644
--- a/cc/quads/shared_quad_state.h
+++ b/cc/quads/shared_quad_state.h
@@ -12,11 +12,17 @@
 #include "ui/gfx/transform.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
 class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/resources/bitmap_tile_task_worker_pool.h b/cc/resources/bitmap_tile_task_worker_pool.h
index 404a3a5..20d57d2 100644
--- a/cc/resources/bitmap_tile_task_worker_pool.h
+++ b/cc/resources/bitmap_tile_task_worker_pool.h
@@ -11,10 +11,16 @@
 #include "cc/resources/tile_task_worker_pool.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
 }
+}  // namespace base
 
 namespace cc {
 class ResourceProvider;
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc
index 7b98e50..e60e4c1 100644
--- a/cc/resources/display_list_recording_source.cc
+++ b/cc/resources/display_list_recording_source.cc
@@ -45,7 +45,7 @@
     const gfx::Size& layer_size,
     const gfx::Rect& visible_layer_rect,
     int frame_number,
-    Picture::RecordingMode recording_mode) {
+    RecordingMode recording_mode) {
   bool updated = false;
 
   if (size_ != layer_size) {
@@ -81,12 +81,37 @@
   if (!updated && !invalidation->Intersects(recorded_viewport_))
     return false;
 
-  // TODO(ajuma): Does repeating this way really makes sense with display lists?
-  // With Blink caching recordings, repeated calls will not cause re-recording.
-  int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
+  ContentLayerClient::PaintingControlSetting painting_control =
+      ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
+
+  switch (recording_mode) {
+    case RECORD_NORMALLY:
+      // Already setup for normal recording.
+      break;
+    case RECORD_WITH_SK_NULL_CANVAS:
+    // TODO(schenney): Remove this when DisplayList recording is the only
+    // option. For now, fall through and disable construction.
+    case RECORD_WITH_PAINTING_DISABLED:
+      painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
+      break;
+    case RECORD_WITH_CACHING_DISABLED:
+      painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  int repeat_count = 1;
+  if (slow_down_raster_scale_factor_for_debug_ > 1) {
+    repeat_count = slow_down_raster_scale_factor_for_debug_;
+    if (painting_control !=
+        ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED) {
+      painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
+    }
+  }
   for (int i = 0; i < repeat_count; ++i) {
-    display_list_ = painter->PaintContentsToDisplayList(
-        recorded_viewport_, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+    display_list_ = painter->PaintContentsToDisplayList(recorded_viewport_,
+                                                        painting_control);
   }
   display_list_->set_layer_rect(recorded_viewport_);
   is_suitable_for_gpu_rasterization_ =
diff --git a/cc/resources/display_list_recording_source.h b/cc/resources/display_list_recording_source.h
index a2c8ea6..05e2ed7 100644
--- a/cc/resources/display_list_recording_source.h
+++ b/cc/resources/display_list_recording_source.h
@@ -18,14 +18,13 @@
   ~DisplayListRecordingSource() override;
 
   // RecordingSource overrides.
-  bool UpdateAndExpandInvalidation(
-      ContentLayerClient* painter,
-      Region* invalidation,
-      bool can_use_lcd_text,
-      const gfx::Size& layer_size,
-      const gfx::Rect& visible_layer_rect,
-      int frame_number,
-      Picture::RecordingMode recording_mode) override;
+  bool UpdateAndExpandInvalidation(ContentLayerClient* painter,
+                                   Region* invalidation,
+                                   bool can_use_lcd_text,
+                                   const gfx::Size& layer_size,
+                                   const gfx::Rect& visible_layer_rect,
+                                   int frame_number,
+                                   RecordingMode recording_mode) override;
   scoped_refptr<RasterSource> CreateRasterSource() const override;
   gfx::Size GetSize() const final;
   void SetEmptyBounds() override;
diff --git a/cc/resources/gpu_rasterizer.cc b/cc/resources/gpu_rasterizer.cc
index 3fdc8bb..369f12c 100644
--- a/cc/resources/gpu_rasterizer.cc
+++ b/cc/resources/gpu_rasterizer.cc
@@ -31,22 +31,22 @@
     ContextProvider* context_provider,
     ResourceProvider* resource_provider,
     bool use_distance_field_text,
-    bool tile_prepare_enabled,
+    bool threaded_gpu_rasterization_enabled,
     int msaa_sample_count) {
   return make_scoped_ptr<GpuRasterizer>(new GpuRasterizer(
       context_provider, resource_provider, use_distance_field_text,
-      tile_prepare_enabled, msaa_sample_count));
+      threaded_gpu_rasterization_enabled, msaa_sample_count));
 }
 
 GpuRasterizer::GpuRasterizer(ContextProvider* context_provider,
                              ResourceProvider* resource_provider,
                              bool use_distance_field_text,
-                             bool tile_prepare_enabled,
+                             bool threaded_gpu_rasterization_enabled,
                              int msaa_sample_count)
     : context_provider_(context_provider),
       resource_provider_(resource_provider),
       use_distance_field_text_(use_distance_field_text),
-      tile_prepare_enabled_(tile_prepare_enabled),
+      threaded_gpu_rasterization_enabled_(threaded_gpu_rasterization_enabled),
       msaa_sample_count_(msaa_sample_count) {
   DCHECK(context_provider_);
 }
@@ -55,8 +55,7 @@
 }
 
 PrepareTilesMode GpuRasterizer::GetPrepareTilesMode() {
-  return tile_prepare_enabled_ ? PrepareTilesMode::PREPARE_PRIORITIZED_TILES
-                               : PrepareTilesMode::PREPARE_NONE;
+  return PrepareTilesMode::PREPARE_NONE;
 }
 
 void GpuRasterizer::RasterizeTiles(
diff --git a/cc/resources/gpu_rasterizer.h b/cc/resources/gpu_rasterizer.h
index 206b051..79a0596 100644
--- a/cc/resources/gpu_rasterizer.h
+++ b/cc/resources/gpu_rasterizer.h
@@ -22,11 +22,12 @@
  public:
   ~GpuRasterizer() override;
 
-  static scoped_ptr<GpuRasterizer> Create(ContextProvider* context_provider,
-                                          ResourceProvider* resource_provider,
-                                          bool use_distance_field_text,
-                                          bool tile_prepare_enabled,
-                                          int msaa_sample_count);
+  static scoped_ptr<GpuRasterizer> Create(
+      ContextProvider* context_provider,
+      ResourceProvider* resource_provider,
+      bool use_distance_field_text,
+      bool threaded_gpu_rasterization_enabled,
+      int msaa_sample_count);
   PrepareTilesMode GetPrepareTilesMode() override;
   void RasterizeTiles(
       const TileVector& tiles,
@@ -38,7 +39,7 @@
   GpuRasterizer(ContextProvider* context_provider,
                 ResourceProvider* resource_provider,
                 bool use_distance_filed_text,
-                bool tile_prepare_enabled,
+                bool threaded_gpu_rasterization_enabled,
                 int msaa_sample_count);
 
   using ScopedResourceWriteLocks =
@@ -55,7 +56,7 @@
   SkMultiPictureDraw multi_picture_draw_;
 
   bool use_distance_field_text_;
-  bool tile_prepare_enabled_;
+  bool threaded_gpu_rasterization_enabled_;
   int msaa_sample_count_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuRasterizer);
diff --git a/cc/resources/one_copy_tile_task_worker_pool.h b/cc/resources/one_copy_tile_task_worker_pool.h
index 4568d35..85b3f32 100644
--- a/cc/resources/one_copy_tile_task_worker_pool.h
+++ b/cc/resources/one_copy_tile_task_worker_pool.h
@@ -15,11 +15,18 @@
 #include "cc/resources/tile_task_worker_pool.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 class ResourcePool;
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index 003a8f1..6bbeeaa 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -53,11 +53,12 @@
 
 }  // namespace
 
-scoped_refptr<Picture> Picture::Create(const gfx::Rect& layer_rect,
-                                       ContentLayerClient* client,
-                                       const gfx::Size& tile_grid_size,
-                                       bool gather_pixel_refs,
-                                       RecordingMode recording_mode) {
+scoped_refptr<Picture> Picture::Create(
+    const gfx::Rect& layer_rect,
+    ContentLayerClient* client,
+    const gfx::Size& tile_grid_size,
+    bool gather_pixel_refs,
+    RecordingSource::RecordingMode recording_mode) {
   scoped_refptr<Picture> picture = make_scoped_refptr(new Picture(layer_rect));
 
   picture->Record(client, tile_grid_size, recording_mode);
@@ -169,7 +170,7 @@
 
 void Picture::Record(ContentLayerClient* painter,
                      const gfx::Size& tile_grid_size,
-                     RecordingMode recording_mode) {
+                     RecordingSource::RecordingMode recording_mode) {
   TRACE_EVENT2("cc",
                "Picture::Record",
                "data",
@@ -189,23 +190,27 @@
       layer_rect_.width(), layer_rect_.height(), &factory,
       SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag));
 
-  ContentLayerClient::GraphicsContextStatus graphics_context_status =
-      ContentLayerClient::GRAPHICS_CONTEXT_ENABLED;
+  ContentLayerClient::PaintingControlSetting painting_control =
+      ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
 
   switch (recording_mode) {
-    case RECORD_NORMALLY:
+    case RecordingSource::RECORD_NORMALLY:
       // Already setup for normal recording.
       break;
-    case RECORD_WITH_SK_NULL_CANVAS:
+    case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
       canvas = skia::AdoptRef(SkCreateNullCanvas());
       break;
-    case RECORD_WITH_PAINTING_DISABLED:
+    case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
       // We pass a disable flag through the paint calls when perfromance
       // testing (the only time this case should ever arise) when we want to
       // prevent the Blink GraphicsContext object from consuming any compute
       // time.
       canvas = skia::AdoptRef(SkCreateNullCanvas());
-      graphics_context_status = ContentLayerClient::GRAPHICS_CONTEXT_DISABLED;
+      painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
+      break;
+    case RecordingSource::RECORD_WITH_CACHING_DISABLED:
+      // This mode should give the same results as RECORD_NORMALLY.
+      painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
       break;
     default:
       NOTREACHED();
@@ -221,7 +226,7 @@
                                          layer_rect_.height());
   canvas->clipRect(layer_skrect);
 
-  painter->PaintContents(canvas.get(), layer_rect_, graphics_context_status);
+  painter->PaintContents(canvas.get(), layer_rect_, painting_control);
 
   canvas->restore();
   picture_ = skia::AdoptRef(recorder.endRecording());
diff --git a/cc/resources/picture.h b/cc/resources/picture.h
index ec76f45..a2a4ec2 100644
--- a/cc/resources/picture.h
+++ b/cc/resources/picture.h
@@ -18,6 +18,7 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/base/cc_export.h"
 #include "cc/base/region.h"
+#include "cc/resources/recording_source.h"
 #include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkPicture.h"
 #include "ui/gfx/geometry/rect.h"
@@ -44,18 +45,12 @@
   typedef std::vector<SkPixelRef*> PixelRefs;
   typedef base::hash_map<PixelRefMapKey, PixelRefs> PixelRefMap;
 
-  enum RecordingMode {
-    RECORD_NORMALLY,
-    RECORD_WITH_SK_NULL_CANVAS,
-    RECORD_WITH_PAINTING_DISABLED,
-    RECORDING_MODE_COUNT,  // Must be the last entry.
-  };
-
-  static scoped_refptr<Picture> Create(const gfx::Rect& layer_rect,
-                                       ContentLayerClient* client,
-                                       const gfx::Size& tile_grid_size,
-                                       bool gather_pixels_refs,
-                                       RecordingMode recording_mode);
+  static scoped_refptr<Picture> Create(
+      const gfx::Rect& layer_rect,
+      ContentLayerClient* client,
+      const gfx::Size& tile_grid_size,
+      bool gather_pixels_refs,
+      RecordingSource::RecordingMode recording_mode);
   static scoped_refptr<Picture> CreateFromValue(const base::Value* value);
   static scoped_refptr<Picture> CreateFromSkpValue(const base::Value* value);
 
@@ -141,7 +136,7 @@
   // playback on a different thread this can only be called once.
   void Record(ContentLayerClient* client,
               const gfx::Size& tile_grid_size,
-              RecordingMode recording_mode);
+              RecordingSource::RecordingMode recording_mode);
 
   // Gather pixel refs from recording.
   void GatherPixelRefs(const gfx::Size& tile_grid_info);
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index 15fdb43..c9672c9 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -21,10 +21,16 @@
 #include "ui/gfx/geometry/rect.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index 779e2c0..7c36a3f 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -116,15 +116,16 @@
   }
 
   if (!tilings_.empty()) {
-    size_t num_high_res = std::count_if(tilings_.begin(), tilings_.end(),
-                                        [](PictureLayerTiling* tiling) {
-      return tiling->resolution() == HIGH_RESOLUTION;
-    });
-    DCHECK_LE(num_high_res, 1u);
+    DCHECK_LE(NumHighResTilings(), 1);
     // When commiting from the main thread the high res tiling may get dropped,
     // but when cloning to the active tree, there should always be one.
-    if (twin_set)
-      DCHECK_EQ(1u, num_high_res);
+    if (twin_set) {
+      DCHECK_EQ(1, NumHighResTilings())
+          << " num tilings on active: " << tilings_.size()
+          << " num tilings on pending: " << twin_set->tilings_.size()
+          << " num high res on pending: " << twin_set->NumHighResTilings()
+          << " are on active tree: " << (client_->GetTree() == ACTIVE_TREE);
+    }
   }
 #endif
 }
@@ -214,12 +215,10 @@
 }
 
 int PictureLayerTilingSet::NumHighResTilings() const {
-  int num_high_res = 0;
-  for (size_t i = 0; i < tilings_.size(); ++i) {
-    if (tilings_[i]->resolution() == HIGH_RESOLUTION)
-      num_high_res++;
-  }
-  return num_high_res;
+  return std::count_if(tilings_.begin(), tilings_.end(),
+                       [](PictureLayerTiling* tiling) {
+    return tiling->resolution() == HIGH_RESOLUTION;
+  });
 }
 
 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScale(
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index 9f6eba9..3e31ed9 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -14,10 +14,16 @@
 #include "ui/gfx/geometry/size.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index f42244c..dcfe49e 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -181,7 +181,7 @@
     const gfx::Size& layer_size,
     const gfx::Rect& visible_layer_rect,
     int frame_number,
-    Picture::RecordingMode recording_mode) {
+    RecordingSource::RecordingMode recording_mode) {
   bool can_use_lcd_text_changed = can_use_lcd_text_ != can_use_lcd_text;
   can_use_lcd_text_ = can_use_lcd_text;
 
@@ -532,7 +532,7 @@
 }
 
 void PicturePile::CreatePictures(ContentLayerClient* painter,
-                                 Picture::RecordingMode recording_mode,
+                                 RecordingSource::RecordingMode recording_mode,
                                  const std::vector<gfx::Rect>& record_rects) {
   for (const auto& record_rect : record_rects) {
     gfx::Rect padded_record_rect = PadRect(record_rect);
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index 1e3368c..8000c42 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -12,7 +12,7 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/ref_counted.h"
 #include "cc/base/tiling_data.h"
-#include "cc/resources/recording_source.h"
+#include "cc/resources/picture.h"
 
 namespace cc {
 class PicturePileImpl;
@@ -23,14 +23,13 @@
   ~PicturePile() override;
 
   // RecordingSource overrides.
-  bool UpdateAndExpandInvalidation(
-      ContentLayerClient* painter,
-      Region* invalidation,
-      bool can_use_lcd_text,
-      const gfx::Size& layer_size,
-      const gfx::Rect& visible_layer_rect,
-      int frame_number,
-      Picture::RecordingMode recording_mode) override;
+  bool UpdateAndExpandInvalidation(ContentLayerClient* painter,
+                                   Region* invalidation,
+                                   bool can_use_lcd_text,
+                                   const gfx::Size& layer_size,
+                                   const gfx::Rect& visible_layer_rect,
+                                   int frame_number,
+                                   RecordingMode recording_mode) override;
   scoped_refptr<RasterSource> CreateRasterSource() const override;
   gfx::Size GetSize() const final;
   void SetEmptyBounds() override;
@@ -106,7 +105,7 @@
   friend class PicturePileImpl;
 
   void CreatePictures(ContentLayerClient* painter,
-                      Picture::RecordingMode recording_mode,
+                      RecordingMode recording_mode,
                       const std::vector<gfx::Rect>& record_rects);
   void GetInvalidTileRects(const gfx::Rect& interest_rect,
                            Region* invalidation,
diff --git a/cc/resources/picture_pile_unittest.cc b/cc/resources/picture_pile_unittest.cc
index 4e3fe15..b834979 100644
--- a/cc/resources/picture_pile_unittest.cc
+++ b/cc/resources/picture_pile_unittest.cc
@@ -44,7 +44,7 @@
     frame_number_++;
     return pile_.UpdateAndExpandInvalidation(
         &client_, invalidation, false, layer_size, visible_layer_rect,
-        frame_number_, Picture::RECORD_NORMALLY);
+        frame_number_, RecordingSource::RECORD_NORMALLY);
   }
 
   bool UpdateWholePile() {
diff --git a/cc/resources/picture_unittest.cc b/cc/resources/picture_unittest.cc
index 0c41215..1e2ba44 100644
--- a/cc/resources/picture_unittest.cc
+++ b/cc/resources/picture_unittest.cc
@@ -44,7 +44,7 @@
 
   scoped_refptr<Picture> one_rect_picture =
       Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
-                      Picture::RECORD_NORMALLY);
+                      RecordingSource::RECORD_NORMALLY);
   scoped_ptr<base::Value> serialized_one_rect(one_rect_picture->AsValue());
 
   // Reconstruct the picture.
@@ -66,7 +66,7 @@
 
   scoped_refptr<Picture> two_rect_picture =
       Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
-                      Picture::RECORD_NORMALLY);
+                      RecordingSource::RECORD_NORMALLY);
 
   scoped_ptr<base::Value> serialized_two_rect(two_rect_picture->AsValue());
 
@@ -118,7 +118,7 @@
 
   scoped_refptr<Picture> picture =
       Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
-                      Picture::RECORD_NORMALLY);
+                      RecordingSource::RECORD_NORMALLY);
 
   // Default iterator does not have any pixel refs
   {
@@ -213,7 +213,7 @@
 
   scoped_refptr<Picture> picture =
       Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
-                      Picture::RECORD_NORMALLY);
+                      RecordingSource::RECORD_NORMALLY);
 
   // Default iterator does not have any pixel refs
   {
@@ -331,7 +331,7 @@
 
   scoped_refptr<Picture> picture =
       Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
-                      Picture::RECORD_NORMALLY);
+                      RecordingSource::RECORD_NORMALLY);
 
   for (int y = 0; y < 4; ++y) {
     for (int x = 0; x < 4; ++x) {
@@ -374,7 +374,7 @@
   content_layer_client.add_draw_rect(layer_rect, red_paint);
   scoped_refptr<Picture> one_rect_picture =
       Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
-                      Picture::RECORD_NORMALLY);
+                      RecordingSource::RECORD_NORMALLY);
   scoped_ptr<base::Value> serialized_one_rect(
       one_rect_picture->AsValue());
 
@@ -406,27 +406,36 @@
 
   scoped_refptr<Picture> picture =
       Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
-                      Picture::RECORD_NORMALLY);
+                      RecordingSource::RECORD_NORMALLY);
   EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
-  EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_ENABLED,
-            content_layer_client.last_context_status());
+  EXPECT_EQ(ContentLayerClient::PAINTING_BEHAVIOR_NORMAL,
+            content_layer_client.last_painting_control());
   EXPECT_TRUE(picture.get());
 
   picture = Picture::Create(layer_rect, &content_layer_client, tile_grid_size,
-                            false, Picture::RECORD_WITH_SK_NULL_CANVAS);
+                            false, RecordingSource::RECORD_WITH_SK_NULL_CANVAS);
   EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
-  EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_ENABLED,
-            content_layer_client.last_context_status());
+  EXPECT_EQ(ContentLayerClient::PAINTING_BEHAVIOR_NORMAL,
+            content_layer_client.last_painting_control());
   EXPECT_TRUE(picture.get());
 
-  picture = Picture::Create(layer_rect, &content_layer_client, tile_grid_size,
-                            false, Picture::RECORD_WITH_PAINTING_DISABLED);
+  picture =
+      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
+                      RecordingSource::RECORD_WITH_PAINTING_DISABLED);
   EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
-  EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_DISABLED,
-            content_layer_client.last_context_status());
+  EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED,
+            content_layer_client.last_painting_control());
   EXPECT_TRUE(picture.get());
 
-  EXPECT_EQ(3, Picture::RECORDING_MODE_COUNT);
+  picture =
+      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
+                      RecordingSource::RECORD_WITH_CACHING_DISABLED);
+  EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
+  EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED,
+            content_layer_client.last_painting_control());
+  EXPECT_TRUE(picture.get());
+
+  EXPECT_EQ(4, RecordingSource::RECORDING_MODE_COUNT);
 }
 
 }  // namespace
diff --git a/cc/resources/pixel_buffer_tile_task_worker_pool.h b/cc/resources/pixel_buffer_tile_task_worker_pool.h
index 8ee4b9c..edff89a 100644
--- a/cc/resources/pixel_buffer_tile_task_worker_pool.h
+++ b/cc/resources/pixel_buffer_tile_task_worker_pool.h
@@ -16,11 +16,18 @@
 #include "cc/resources/tile_task_worker_pool.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 class ResourceProvider;
diff --git a/cc/resources/rasterizer.h b/cc/resources/rasterizer.h
index 95b9ce2..43df0b0 100644
--- a/cc/resources/rasterizer.h
+++ b/cc/resources/rasterizer.h
@@ -16,7 +16,6 @@
 
 enum class PrepareTilesMode {
   RASTERIZE_PRIORITIZED_TILES,
-  PREPARE_PRIORITIZED_TILES,
   PREPARE_NONE
 };
 
diff --git a/cc/resources/recording_source.h b/cc/resources/recording_source.h
index 1e45047..d96c0fa 100644
--- a/cc/resources/recording_source.h
+++ b/cc/resources/recording_source.h
@@ -5,8 +5,8 @@
 #ifndef CC_RESOURCES_RECORDING_SOURCE_H_
 #define CC_RESOURCES_RECORDING_SOURCE_H_
 
+#include "base/memory/ref_counted.h"
 #include "cc/base/cc_export.h"
-#include "cc/resources/picture.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -18,20 +18,27 @@
 
 class CC_EXPORT RecordingSource {
  public:
+  enum RecordingMode {
+    RECORD_NORMALLY,
+    RECORD_WITH_SK_NULL_CANVAS,
+    RECORD_WITH_PAINTING_DISABLED,
+    RECORD_WITH_CACHING_DISABLED,
+    RECORDING_MODE_COUNT,  // Must be the last entry.
+  };
+
   virtual ~RecordingSource() {}
   // Re-record parts of the picture that are invalid.
   // Invalidations are in layer space, and will be expanded to cover everything
   // that was either recorded/changed or that has no recording, leaving out only
   // pieces that we had a recording for and it was not changed.
   // Return true iff the pile was modified.
-  virtual bool UpdateAndExpandInvalidation(
-      ContentLayerClient* painter,
-      Region* invalidation,
-      bool can_use_lcd_text,
-      const gfx::Size& layer_size,
-      const gfx::Rect& visible_layer_rect,
-      int frame_number,
-      Picture::RecordingMode recording_mode) = 0;
+  virtual bool UpdateAndExpandInvalidation(ContentLayerClient* painter,
+                                           Region* invalidation,
+                                           bool can_use_lcd_text,
+                                           const gfx::Size& layer_size,
+                                           const gfx::Rect& visible_layer_rect,
+                                           int frame_number,
+                                           RecordingMode recording_mode) = 0;
 
   virtual scoped_refptr<RasterSource> CreateRasterSource() const = 0;
 
diff --git a/cc/resources/tile_manager.h b/cc/resources/tile_manager.h
index 37ab765..0af823e 100644
--- a/cc/resources/tile_manager.h
+++ b/cc/resources/tile_manager.h
@@ -26,11 +26,18 @@
 #include "cc/resources/tile_task_runner.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 class PictureLayerImpl;
diff --git a/cc/resources/zero_copy_tile_task_worker_pool.h b/cc/resources/zero_copy_tile_task_worker_pool.h
index 8d3c0cf..4f3085c 100644
--- a/cc/resources/zero_copy_tile_task_worker_pool.h
+++ b/cc/resources/zero_copy_tile_task_worker_pool.h
@@ -11,10 +11,16 @@
 #include "cc/resources/tile_task_worker_pool.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
 }
+}  // namespace base
 
 namespace cc {
 class ResourceProvider;
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc
index c245bd6..9b200e9 100644
--- a/cc/scheduler/begin_frame_source.cc
+++ b/cc/scheduler/begin_frame_source.cc
@@ -414,11 +414,10 @@
   }
 }
 
-void BeginFrameSourceMultiplexer::SetNeedsBeginFrames(bool needs_begin_frames) {
-  DEBUG_FRAMES("BeginFrameSourceMultiplexer::SetNeedsBeginFrames",
-               "active_source",
-               active_source_,
-               "needs_begin_frames",
+void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange(
+    bool needs_begin_frames) {
+  DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange",
+               "active_source", active_source_, "needs_begin_frames",
                needs_begin_frames);
   if (active_source_) {
     active_source_->SetNeedsBeginFrames(needs_begin_frames);
diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h
index 299db8e..1612a28 100644
--- a/cc/scheduler/begin_frame_source.h
+++ b/cc/scheduler/begin_frame_source.h
@@ -138,7 +138,7 @@
 
   // BeginFrameSource
   bool NeedsBeginFrames() const override;
-  void SetNeedsBeginFrames(bool needs_begin_frames) override;
+  void SetNeedsBeginFrames(bool needs_begin_frames) final;
   void DidFinishFrame(size_t remaining_frames) override {}
   void AddObserver(BeginFrameObserver* obs) final;
   void RemoveObserver(BeginFrameObserver* obs) final;
@@ -261,9 +261,11 @@
 
   // BeginFrameSource
   bool NeedsBeginFrames() const override;
-  void SetNeedsBeginFrames(bool needs_begin_frames) override;
   void DidFinishFrame(size_t remaining_frames) override;
 
+  // BeginFrameSourceMixIn
+  void OnNeedsBeginFramesChange(bool needs_begin_frames) override;
+
   // Tracing
   void AsValueInto(base::debug::TracedValue* dict) const override;
 
diff --git a/cc/scheduler/delay_based_time_source.h b/cc/scheduler/delay_based_time_source.h
index ea03f9d..da968a6 100644
--- a/cc/scheduler/delay_based_time_source.h
+++ b/cc/scheduler/delay_based_time_source.h
@@ -12,11 +12,17 @@
 #include "cc/base/cc_export.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
-class SingleThreadTaskRunner;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+class SingleThreadTaskRunner;
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index e06a133..ddc3f2f 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -24,11 +24,17 @@
 #include "cc/scheduler/scheduler_state_machine.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 }
-class SingleThreadTaskRunner;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
 }
+class SingleThreadTaskRunner;
+}  // namespace base
 
 namespace cc {
 
diff --git a/cc/scheduler/scheduler_settings.h b/cc/scheduler/scheduler_settings.h
index 4ff3c7e..90c1a9c 100644
--- a/cc/scheduler/scheduler_settings.h
+++ b/cc/scheduler/scheduler_settings.h
@@ -11,10 +11,16 @@
 #include "cc/base/cc_export.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
 }
+}  // namespace base
 
 namespace cc {
 class LayerTreeSettings;
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index aa153c6..fb87c84 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -17,12 +17,19 @@
 #include "cc/scheduler/scheduler_settings.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class ConvertableToTraceFormat;
 class TracedValue;
 }
-class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
 }
+class Value;
+}  // namespace base
 
 namespace cc {
 
@@ -282,7 +289,6 @@
 
   bool ShouldAnimate() const;
   bool ShouldBeginOutputSurfaceCreation() const;
-  bool ShouldDrawForced() const;
   bool ShouldDraw() const;
   bool ShouldActivatePendingTree() const;
   bool ShouldSendBeginMainFrame() const;
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index 25f3114..065aa38 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -46,7 +46,11 @@
   current_frame_ = frame.Pass();
   factory_->ReceiveFromChild(
       current_frame_->delegated_frame_data->resource_list);
-  ++frame_index_;
+  // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't
+  // increment frame index for them.
+  if (!current_frame_ ||
+      !current_frame_->delegated_frame_data->render_pass_list.empty())
+    ++frame_index_;
 
   if (previous_frame) {
     ReturnedResourceArray previous_resources;
diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc
index ed6763d..068fe03 100644
--- a/cc/surfaces/surface_display_output_surface.cc
+++ b/cc/surfaces/surface_display_output_surface.cc
@@ -25,6 +25,9 @@
   capabilities_.delegated_rendering = true;
   capabilities_.max_frames_pending = 1;
   capabilities_.can_force_reclaim_resources = true;
+  // Frame always needs to be swapped because forced resource reclaiming
+  // destroys the Display's copy.
+  capabilities_.draw_and_swap_full_viewport_every_frame = true;
 }
 
 SurfaceDisplayOutputSurface::~SurfaceDisplayOutputSurface() {
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
index b5c2a63..b9c6bf5 100644
--- a/cc/surfaces/surface_factory_unittest.cc
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -360,6 +360,21 @@
   }
 }
 
+TEST_F(SurfaceFactoryTest, BlankNoIndexIncrement) {
+  SurfaceId surface_id(6);
+  factory_.Create(surface_id);
+  Surface* surface = manager_.GetSurfaceForId(surface_id);
+  ASSERT_NE(nullptr, surface);
+  EXPECT_EQ(2, surface->frame_index());
+  scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+  frame->delegated_frame_data.reset(new DelegatedFrameData);
+
+  factory_.SubmitFrame(surface_id, frame.Pass(),
+                       SurfaceFactory::DrawCallback());
+  EXPECT_EQ(2, surface->frame_index());
+  factory_.Destroy(surface_id);
+}
+
 void DrawCallback(uint32* execute_count,
                   SurfaceDrawStatus* result,
                   SurfaceDrawStatus drawn) {
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc
index 46d1baa..23b73f5 100644
--- a/cc/test/fake_content_layer_client.cc
+++ b/cc/test/fake_content_layer_client.cc
@@ -22,9 +22,9 @@
 void FakeContentLayerClient::PaintContents(
     SkCanvas* canvas,
     const gfx::Rect& paint_rect,
-    ContentLayerClient::GraphicsContextStatus gc_status) {
+    PaintingControlSetting painting_control) {
   last_canvas_ = canvas;
-  last_context_status_ = gc_status;
+  last_painting_control_ = painting_control;
 
   canvas->clipRect(gfx::RectToSkRect(paint_rect));
   for (RectPaintVector::const_iterator it = draw_rects_.begin();
@@ -58,7 +58,7 @@
 scoped_refptr<DisplayItemList>
 FakeContentLayerClient::PaintContentsToDisplayList(
     const gfx::Rect& clip,
-    GraphicsContextStatus gc_status) {
+    PaintingControlSetting painting_control) {
   SkPictureRecorder recorder;
   skia::RefPtr<SkCanvas> canvas;
   skia::RefPtr<SkPicture> picture;
diff --git a/cc/test/fake_content_layer_client.h b/cc/test/fake_content_layer_client.h
index 1060d08..d53d34e 100644
--- a/cc/test/fake_content_layer_client.h
+++ b/cc/test/fake_content_layer_client.h
@@ -27,13 +27,12 @@
   FakeContentLayerClient();
   ~FakeContentLayerClient() override;
 
-  void PaintContents(
-      SkCanvas* canvas,
-      const gfx::Rect& rect,
-      ContentLayerClient::GraphicsContextStatus gc_status) override;
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& rect,
+                     PaintingControlSetting painting_control) override;
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override;
+      PaintingControlSetting painting_control) override;
   bool FillsBoundsCompletely() const override;
 
   void set_fill_with_nonsolid_color(bool nonsolid) {
@@ -56,8 +55,8 @@
 
   SkCanvas* last_canvas() const { return last_canvas_; }
 
-  ContentLayerClient::GraphicsContextStatus last_context_status() const {
-    return last_context_status_;
+  PaintingControlSetting last_painting_control() const {
+    return last_painting_control_;
   }
 
  private:
@@ -68,7 +67,7 @@
   RectPaintVector draw_rects_;
   BitmapVector draw_bitmaps_;
   SkCanvas* last_canvas_;
-  ContentLayerClient::GraphicsContextStatus last_context_status_;
+  PaintingControlSetting last_painting_control_;
 };
 
 }  // namespace cc
diff --git a/cc/test/fake_layer_tree_host_client.h b/cc/test/fake_layer_tree_host_client.h
index 5f7afa5..f5f3504 100644
--- a/cc/test/fake_layer_tree_host_client.h
+++ b/cc/test/fake_layer_tree_host_client.h
@@ -30,12 +30,12 @@
   void SetLayerTreeHost(LayerTreeHost* host) { host_ = host; }
 
   // LayerTreeHostClient implementation.
-  void WillBeginMainFrame(int frame_id) override {}
+  void WillBeginMainFrame() override {}
   void DidBeginMainFrame() override {}
   void BeginMainFrame(const BeginFrameArgs& args) override {}
   void Layout() override {}
-  void ApplyViewportDeltas(const gfx::Vector2d& inner_delta,
-                           const gfx::Vector2d& outer_delta,
+  void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+                           const gfx::Vector2dF& outer_delta,
                            const gfx::Vector2dF& elastic_overscroll_delta,
                            float page_scale,
                            float top_controls_delta) override {}
diff --git a/cc/test/fake_picture_pile_impl.cc b/cc/test/fake_picture_pile_impl.cc
index 420b5d6..bdba092 100644
--- a/cc/test/fake_picture_pile_impl.cc
+++ b/cc/test/fake_picture_pile_impl.cc
@@ -120,8 +120,9 @@
   gfx::Rect bounds(tiling().TileBounds(x, y));
   bounds.Inset(-buffer_pixels(), -buffer_pixels());
 
-  scoped_refptr<Picture> picture(Picture::Create(
-      bounds, &client_, tile_grid_size_, true, Picture::RECORD_NORMALLY));
+  scoped_refptr<Picture> picture(
+      Picture::Create(bounds, &client_, tile_grid_size_, true,
+                      RecordingSource::RECORD_NORMALLY));
   picture_map_[std::pair<int, int>(x, y)].SetPicture(picture);
   EXPECT_TRUE(HasRecordingAt(x, y));
 
diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc
index 1514d83..efe70a0 100644
--- a/cc/test/layer_tree_json_parser.cc
+++ b/cc/test/layer_tree_json_parser.cc
@@ -149,6 +149,23 @@
     new_layer->SetTouchEventHandlerRegion(touch_region);
   }
 
+  if (dict->HasKey("ScrollBlocksOn")) {
+    success &= dict->GetList("ScrollBlocksOn", &list);
+    ScrollBlocksOn blocks;
+    std::string str;
+    for (size_t i = 0; i < list->GetSize(); i++) {
+      success &= list->GetString(i, &str);
+      if (str == "StartTouch")
+        blocks |= ScrollBlocksOnStartTouch;
+      else if (str == "WheelEvent")
+        blocks |= ScrollBlocksOnWheelEvent;
+      else if (str == "ScrollEvent")
+        blocks |= ScrollBlocksOnScrollEvent;
+      else
+        success = false;
+    }
+  }
+
   success &= dict->GetList("DrawTransform", &list);
   double transform[16];
   for (int i = 0; i < 16; ++i)
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index d02b510..ce69079 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -381,9 +381,7 @@
   }
   ~LayerTreeHostClientForTesting() override {}
 
-  void WillBeginMainFrame(int frame_id) override {
-    test_hooks_->WillBeginMainFrame();
-  }
+  void WillBeginMainFrame() override { test_hooks_->WillBeginMainFrame(); }
 
   void DidBeginMainFrame() override { test_hooks_->DidBeginMainFrame(); }
 
@@ -393,8 +391,8 @@
 
   void Layout() override { test_hooks_->Layout(); }
 
-  void ApplyViewportDeltas(const gfx::Vector2d& inner_delta,
-                           const gfx::Vector2d& outer_delta,
+  void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+                           const gfx::Vector2dF& outer_delta,
                            const gfx::Vector2dF& elastic_overscroll_delta,
                            float page_scale,
                            float top_controls_delta) override {
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 4abedd7..c2b18b1 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -65,8 +65,8 @@
   virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl,
                                  base::TimeTicks monotonic_time) {}
   virtual void ApplyViewportDeltas(
-      const gfx::Vector2d& inner_delta,
-      const gfx::Vector2d& outer_delta,
+      const gfx::Vector2dF& inner_delta,
+      const gfx::Vector2dF& outer_delta,
       const gfx::Vector2dF& elastic_overscroll_delta,
       float scale,
       float top_controls_delta) {}
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index 78b8f4a..3562699 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -89,9 +89,6 @@
     return static_cast<RendererType*>(renderer_.get());
   }
 
-  bool UseSkiaGPUBackend() const;
-  bool ExpandedViewport() const;
-
  protected:
   void SetUp() override;
 };
@@ -145,16 +142,6 @@
 }
 
 template<>
-inline bool RendererPixelTest<GLRenderer>::UseSkiaGPUBackend() const {
-  return false;
-}
-
-template<>
-inline bool RendererPixelTest<GLRenderer>::ExpandedViewport() const {
-  return false;
-}
-
-template<>
 inline void RendererPixelTest<GLRendererWithExpandedViewport>::SetUp() {
   SetUpGLRenderer(false, false);
   ForceExpandedViewport(gfx::Size(50, 50));
@@ -162,68 +149,22 @@
 }
 
 template <>
-inline bool
-RendererPixelTest<GLRendererWithExpandedViewport>::UseSkiaGPUBackend() const {
-  return false;
-}
-
-template <>
-inline bool
-RendererPixelTest<GLRendererWithExpandedViewport>::ExpandedViewport() const {
-  return true;
-}
-
-template <>
 inline void RendererPixelTest<GLRendererWithFlippedSurface>::SetUp() {
   SetUpGLRenderer(false, true);
 }
 
 template <>
-inline bool RendererPixelTest<GLRendererWithFlippedSurface>::UseSkiaGPUBackend()
-    const {
-  return false;
-}
-
-template <>
-inline bool RendererPixelTest<GLRendererWithFlippedSurface>::ExpandedViewport()
-    const {
-  return true;
-}
-
-template <>
 inline void RendererPixelTest<SoftwareRenderer>::SetUp() {
   SetUpSoftwareRenderer();
 }
 
 template<>
-inline bool RendererPixelTest<SoftwareRenderer>::UseSkiaGPUBackend() const {
-  return false;
-}
-
-template <>
-inline bool RendererPixelTest<SoftwareRenderer>::ExpandedViewport() const {
-  return false;
-}
-
-template<>
 inline void RendererPixelTest<SoftwareRendererWithExpandedViewport>::SetUp() {
   SetUpSoftwareRenderer();
   ForceExpandedViewport(gfx::Size(50, 50));
   ForceViewportOffset(gfx::Vector2d(10, 20));
 }
 
-template <>
-inline bool RendererPixelTest<
-    SoftwareRendererWithExpandedViewport>::UseSkiaGPUBackend() const {
-  return false;
-}
-
-template <>
-inline bool RendererPixelTest<
-    SoftwareRendererWithExpandedViewport>::ExpandedViewport() const {
-  return true;
-}
-
 typedef RendererPixelTest<GLRenderer> GLRendererPixelTest;
 typedef RendererPixelTest<SoftwareRenderer> SoftwareRendererPixelTest;
 
diff --git a/cc/test/solid_color_content_layer_client.cc b/cc/test/solid_color_content_layer_client.cc
index 701f004..7e97bb8 100644
--- a/cc/test/solid_color_content_layer_client.cc
+++ b/cc/test/solid_color_content_layer_client.cc
@@ -14,7 +14,7 @@
 void SolidColorContentLayerClient::PaintContents(
     SkCanvas* canvas,
     const gfx::Rect& rect,
-    ContentLayerClient::GraphicsContextStatus gc_status) {
+    PaintingControlSetting painting_control) {
   SkPaint paint;
   paint.setStyle(SkPaint::kFill_Style);
   paint.setColor(color_);
@@ -28,7 +28,7 @@
 scoped_refptr<DisplayItemList>
 SolidColorContentLayerClient::PaintContentsToDisplayList(
     const gfx::Rect& clip,
-    GraphicsContextStatus gc_status) {
+    PaintingControlSetting painting_control) {
   NOTIMPLEMENTED();
   return DisplayItemList::Create();
 }
diff --git a/cc/test/solid_color_content_layer_client.h b/cc/test/solid_color_content_layer_client.h
index 93fca84..1ab4c4d 100644
--- a/cc/test/solid_color_content_layer_client.h
+++ b/cc/test/solid_color_content_layer_client.h
@@ -16,13 +16,12 @@
   explicit SolidColorContentLayerClient(SkColor color) : color_(color) {}
 
   // ContentLayerClient implementation.
-  void PaintContents(
-      SkCanvas* canvas,
-      const gfx::Rect& rect,
-      ContentLayerClient::GraphicsContextStatus gc_status) override;
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& rect,
+                     PaintingControlSetting painting_control) override;
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override;
+      PaintingControlSetting painting_control) override;
   bool FillsBoundsCompletely() const override;
 
  private:
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index cd69f92..8217ce0 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -38,7 +38,7 @@
       const TransformNode* clip_transform_node =
           transform_tree.Node(clip_node->data.transform_id);
       const TransformNode* target_node =
-          transform_tree.Node(layer->render_target()->transform_tree_index());
+          transform_tree.Node(transform_node->data.target_id);
 
       gfx::Transform clip_to_target;
       gfx::Transform content_to_target;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 0f48cb2..fa4dd5d 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -43,6 +43,7 @@
 #include "cc/trees/thread_proxy.h"
 #include "cc/trees/tree_synchronizer.h"
 #include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
 
 namespace {
 static base::StaticAtomicSequenceNumber s_layer_tree_host_sequence_number;
@@ -222,6 +223,12 @@
     contents_texture_manager_->ClearAllMemory(resource_provider);
 }
 
+void LayerTreeHost::WillBeginMainFrame() {
+  devtools_instrumentation::WillBeginMainThreadFrame(id(),
+                                                     source_frame_number());
+  client_->WillBeginMainFrame();
+}
+
 void LayerTreeHost::DidBeginMainFrame() {
   client_->DidBeginMainFrame();
 }
@@ -1087,8 +1094,8 @@
     QueueSwapPromise(swap_promise.Pass());
   }
 
-  gfx::Vector2d inner_viewport_scroll_delta;
-  gfx::Vector2d outer_viewport_scroll_delta;
+  gfx::Vector2dF inner_viewport_scroll_delta;
+  gfx::Vector2dF outer_viewport_scroll_delta;
 
   if (root_layer_.get()) {
     for (size_t i = 0; i < info->scrolls.size(); ++i) {
@@ -1131,10 +1138,13 @@
     ApplyPageScaleDeltaFromImplSide(info->page_scale_delta);
     elastic_overscroll_ += info->elastic_overscroll_delta;
     if (!settings_.use_pinch_virtual_viewport) {
+      // TODO(miletus): Make sure either this code path is totally gone,
+      // or revisit the flooring here if the old pinch viewport code path
+      // is causing problems with fractional scroll offset.
       client_->ApplyViewportDeltas(
-          inner_viewport_scroll_delta + outer_viewport_scroll_delta,
-          info->page_scale_delta,
-          info->top_controls_delta);
+          gfx::ToFlooredVector2d(inner_viewport_scroll_delta +
+                                 outer_viewport_scroll_delta),
+          info->page_scale_delta, info->top_controls_delta);
     } else {
       // TODO(ccameron): pass the elastic overscroll here so that input events
       // may be translated appropriately.
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 7db722f..f41e023 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -110,9 +110,7 @@
   void SetLayerTreeHostClientReady();
 
   // LayerTreeHost interface to Proxy.
-  void WillBeginMainFrame() {
-    client_->WillBeginMainFrame(source_frame_number_);
-  }
+  void WillBeginMainFrame();
   void DidBeginMainFrame();
   void BeginMainFrame(const BeginFrameArgs& args);
   void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h
index ac025f2..574325b 100644
--- a/cc/trees/layer_tree_host_client.h
+++ b/cc/trees/layer_tree_host_client.h
@@ -22,15 +22,15 @@
 
 class LayerTreeHostClient {
  public:
-  virtual void WillBeginMainFrame(int frame_id) = 0;
+  virtual void WillBeginMainFrame() = 0;
   // Marks finishing compositing-related tasks on the main thread. In threaded
   // mode, this corresponds to DidCommit().
   virtual void BeginMainFrame(const BeginFrameArgs& args) = 0;
   virtual void DidBeginMainFrame() = 0;
   virtual void Layout() = 0;
   virtual void ApplyViewportDeltas(
-      const gfx::Vector2d& inner_delta,
-      const gfx::Vector2d& outer_delta,
+      const gfx::Vector2dF& inner_delta,
+      const gfx::Vector2dF& outer_delta,
       const gfx::Vector2dF& elastic_overscroll_delta,
       float page_scale,
       float top_controls_delta) = 0;
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h
index 0955b9a..8666617 100644
--- a/cc/trees/layer_tree_host_common.h
+++ b/cc/trees/layer_tree_host_common.h
@@ -151,9 +151,7 @@
 
   struct ScrollUpdateInfo {
     int layer_id;
-    // TODO(miletus) : Use ScrollOffset once LayerTreeHost/Blink fully supports
-    // franctional scroll offset.
-    gfx::Vector2d scroll_delta;
+    gfx::Vector2dF scroll_delta;
   };
 };
 
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index df2b30e..de5f44a 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -56,13 +56,12 @@
  public:
   MockContentLayerClient() {}
   ~MockContentLayerClient() override {}
-  void PaintContents(
-      SkCanvas* canvas,
-      const gfx::Rect& clip,
-      ContentLayerClient::GraphicsContextStatus gc_status) override {}
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& clip,
+                     PaintingControlSetting picture_control) override {}
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override {
+      PaintingControlSetting picture_control) override {
     NOTIMPLEMENTED();
     return DisplayItemList::Create();
   }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 398ef81..672ffe8 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -116,18 +116,14 @@
   gfx::ScrollOffset viewport_in_content_coordinates_;
 };
 
-
 void DidVisibilityChange(LayerTreeHostImpl* id, bool visible) {
   if (visible) {
-    TRACE_EVENT_ASYNC_BEGIN1("webkit",
-                             "LayerTreeHostImpl::SetVisible",
-                             id,
-                             "LayerTreeHostImpl",
-                             id);
+    TRACE_EVENT_ASYNC_BEGIN1("cc", "LayerTreeHostImpl::SetVisible", id,
+                             "LayerTreeHostImpl", id);
     return;
   }
 
-  TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::SetVisible", id);
+  TRACE_EVENT_ASYNC_END0("cc", "LayerTreeHostImpl::SetVisible", id);
 }
 
 size_t GetMaxTransferBufferUsageBytes(
@@ -229,7 +225,8 @@
       gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
       id_(id),
       requires_high_res_to_draw_(false),
-      is_likely_to_require_a_draw_(false) {
+      is_likely_to_require_a_draw_(false),
+      frame_timing_tracker_(FrameTimingTracker::Create()) {
   DCHECK(proxy_->IsImplThread());
   DidVisibilityChange(this, visible_);
   animation_registrar_->set_supports_scroll_animations(
@@ -469,16 +466,39 @@
   return layer_impl != NULL;
 }
 
-bool LayerTreeHostImpl::HaveTouchEventHandlersAt(
-    const gfx::Point& viewport_point) {
+static LayerImpl* NextScrollLayer(LayerImpl* layer) {
+  if (LayerImpl* scroll_parent = layer->scroll_parent())
+    return scroll_parent;
+  return layer->parent();
+}
 
+static ScrollBlocksOn EffectiveScrollBlocksOn(LayerImpl* layer) {
+  ScrollBlocksOn blocks = ScrollBlocksOnNone;
+  for (; layer; layer = NextScrollLayer(layer)) {
+    blocks |= layer->scroll_blocks_on();
+  }
+  return blocks;
+}
+
+bool LayerTreeHostImpl::DoTouchEventsBlockScrollAt(
+    const gfx::Point& viewport_point) {
   gfx::PointF device_viewport_point =
       gfx::ScalePoint(viewport_point, device_scale_factor_);
 
+  // First check if scrolling at this point is required to block on any
+  // touch event handlers.  Note that we must start at the innermost layer
+  // (as opposed to only the layer found to contain a touch handler region
+  // below) to ensure all relevant scroll-blocks-on values are applied.
   LayerImpl* layer_impl =
-      active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion(
-          device_viewport_point);
+      active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
+  ScrollBlocksOn blocking = EffectiveScrollBlocksOn(layer_impl);
+  if (!(blocking & ScrollBlocksOnStartTouch))
+    return false;
 
+  // Now determine if there are actually any handlers at that point.
+  // TODO(rbyers): Consider also honoring touch-action (crbug.com/347272).
+  layer_impl = active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion(
+      device_viewport_point);
   return layer_impl != NULL;
 }
 
@@ -674,6 +694,7 @@
   if (root_surface_has_contributing_layers &&
       root_surface_has_no_visible_damage &&
       active_tree_->LayersWithCopyOutputRequest().empty() &&
+      !output_surface_->capabilities().can_force_reclaim_resources &&
       !hud_wants_to_draw_) {
     TRACE_EVENT0("cc",
                  "LayerTreeHostImpl::CalculateRenderPasses::EmptyDamageRect");
@@ -813,6 +834,18 @@
                             *it,
                             occlusion_tracker,
                             &append_quads_data);
+
+        // For layers that represent themselves, add composite frame timing
+        // requests if the visible rect intersects the requested rect.
+        for (const auto& request : it->frame_timing_requests()) {
+          const gfx::Rect& request_content_rect =
+              it->LayerRectToContentRect(request.rect());
+          if (request_content_rect.Intersects(it->visible_content_rect())) {
+            frame->composite_events.push_back(
+                FrameTimingTracker::FrameAndRectIds(
+                    active_tree_->source_frame_number(), request.id()));
+          }
+        }
       }
 
       ++layers_drawn;
@@ -1438,6 +1471,11 @@
   TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers");
   DCHECK(CanDraw());
 
+  if (!frame->composite_events.empty()) {
+    frame_timing_tracker_->SaveTimeStamps(frame_begin_time,
+                                          frame->composite_events);
+  }
+
   if (frame->has_no_damage) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoDamage", TRACE_EVENT_SCOPE_THREAD);
     DCHECK(!output_surface_->capabilities()
@@ -1577,6 +1615,7 @@
     DestroyTileManager();
     CreateAndSetTileManager();
   }
+  RecreateTreeResources();
 
   // We have released tilings for both active and pending tree.
   // We would not have any content to draw until the pending tree is activated.
@@ -1895,6 +1934,14 @@
   EvictAllUIResources();
 }
 
+void LayerTreeHostImpl::RecreateTreeResources() {
+  active_tree_->RecreateResources();
+  if (pending_tree_)
+    pending_tree_->RecreateResources();
+  if (recycle_tree_)
+    recycle_tree_->RecreateResources();
+}
+
 void LayerTreeHostImpl::CreateAndSetRenderer() {
   DCHECK(!renderer_);
   DCHECK(output_surface_);
@@ -1959,7 +2006,8 @@
   ContextProvider* context_provider = output_surface_->context_provider();
   if (use_gpu_rasterization_ && context_provider) {
     return GpuRasterizer::Create(context_provider, resource_provider_.get(),
-                                 settings_.use_distance_field_text, false,
+                                 settings_.use_distance_field_text,
+                                 settings_.threaded_gpu_rasterization_enabled,
                                  settings_.gpu_rasterization_msaa_sample_count);
   }
   return SoftwareRasterizer::Create();
@@ -2085,8 +2133,12 @@
   resource_provider_ = nullptr;
   output_surface_ = nullptr;
 
-  if (!output_surface->BindToClient(this))
+  if (!output_surface->BindToClient(this)) {
+    // Avoid recreating tree resources because we might not have enough
+    // information to do this yet (eg. we don't have a TileManager at this
+    // point).
     return false;
+  }
 
   output_surface_ = output_surface.Pass();
   resource_provider_ = ResourceProvider::Create(
@@ -2103,6 +2155,7 @@
 
   if (settings_.impl_side_painting)
     CreateAndSetTileManager();
+  RecreateTreeResources();
 
   // Initialize vsync parameters to sane values.
   const base::TimeDelta display_refresh_interval =
@@ -2152,6 +2205,7 @@
   CreateAndSetRenderer();
   EnforceZeroBudget(false);
   CreateAndSetTileManager();
+  RecreateTreeResources();
 
   client_->SetNeedsCommitOnImplThread();
 }
@@ -2171,6 +2225,7 @@
   CreateAndSetRenderer();
   EnforceZeroBudget(true);
   CreateAndSetTileManager();
+  RecreateTreeResources();
 
   client_->SetNeedsCommitOnImplThread();
 }
@@ -2178,6 +2233,10 @@
 void LayerTreeHostImpl::SetViewportSize(const gfx::Size& device_viewport_size) {
   if (device_viewport_size == device_viewport_size_)
     return;
+  TRACE_EVENT_INSTANT2("cc", "LayerTreeHostImpl::SetViewportSize",
+                       TRACE_EVENT_SCOPE_THREAD, "width",
+                       device_viewport_size.width(), "height",
+                       device_viewport_size.height());
 
   if (pending_tree_)
     active_tree_->SetViewportSizeInvalid();
@@ -2255,12 +2314,6 @@
   input_handler_client_ = client;
 }
 
-static LayerImpl* NextScrollLayer(LayerImpl* layer) {
-  if (LayerImpl* scroll_parent = layer->scroll_parent())
-    return scroll_parent;
-  return layer->parent();
-}
-
 LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
     const gfx::PointF& device_viewport_point,
     InputHandler::ScrollInputType type,
@@ -2269,12 +2322,15 @@
     bool* optional_has_ancestor_scroll_handler) const {
   DCHECK(scroll_on_main_thread);
 
+  ScrollBlocksOn block_mode = EffectiveScrollBlocksOn(layer_impl);
+
   // Walk up the hierarchy and look for a scrollable layer.
   LayerImpl* potentially_scrolling_layer_impl = NULL;
   for (; layer_impl; layer_impl = NextScrollLayer(layer_impl)) {
     // The content layer can also block attempts to scroll outside the main
     // thread.
-    ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type);
+    ScrollStatus status =
+        layer_impl->TryScroll(device_viewport_point, type, block_mode);
     if (status == ScrollOnMainThread) {
       *scroll_on_main_thread = true;
       return NULL;
@@ -2284,7 +2340,8 @@
     if (!scroll_layer_impl)
       continue;
 
-    status = scroll_layer_impl->TryScroll(device_viewport_point, type);
+    status =
+        scroll_layer_impl->TryScroll(device_viewport_point, type, block_mode);
     // If any layer wants to divert the scroll event to the main thread, abort.
     if (status == ScrollOnMainThread) {
       *scroll_on_main_thread = true;
@@ -2988,7 +3045,7 @@
   if (!scroll_delta.IsZero()) {
     LayerTreeHostCommon::ScrollUpdateInfo scroll;
     scroll.layer_id = layer_impl->id();
-    scroll.scroll_delta = gfx::Vector2d(scroll_delta.x(), scroll_delta.y());
+    scroll.scroll_delta = gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
     scroll_info->scrolls.push_back(scroll);
   }
 
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index eb84c54..f4052f1 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -18,6 +18,7 @@
 #include "cc/animation/scrollbar_animation_controller.h"
 #include "cc/base/cc_export.h"
 #include "cc/base/synced_property.h"
+#include "cc/debug/frame_timing_tracker.h"
 #include "cc/debug/micro_benchmark_controller_impl.h"
 #include "cc/input/input_handler.h"
 #include "cc/input/layer_scroll_offset_delegate.h"
@@ -167,7 +168,7 @@
   bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point,
                                    InputHandler::ScrollInputType type) override;
   bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) override;
-  bool HaveTouchEventHandlersAt(const gfx::Point& viewport_port) override;
+  bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_port) override;
   scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
       ui::LatencyInfo* latency) override;
   ScrollElasticityHelper* CreateScrollElasticityHelper() override;
@@ -185,6 +186,7 @@
 
     std::vector<gfx::Rect> occluding_screen_space_rects;
     std::vector<gfx::Rect> non_occluding_screen_space_rects;
+    std::vector<FrameTimingTracker::FrameAndRectIds> composite_events;
     RenderPassList render_passes;
     RenderPassIdHashMap render_passes_by_id;
     const LayerImplList* render_surface_layer_list;
@@ -514,6 +516,10 @@
 
   bool prepare_tiles_needed() const { return tile_priorities_dirty_; }
 
+  FrameTimingTracker* frame_timing_tracker() {
+    return frame_timing_tracker_.get();
+  }
+
  protected:
   LayerTreeHostImpl(
       const LayerTreeSettings& settings,
@@ -541,6 +547,7 @@
   void CreateAndSetTileManager();
   void DestroyTileManager();
   void ReleaseTreeResources();
+  void RecreateTreeResources();
   void EnforceZeroBudget(bool zero_budget);
 
   bool UsePendingTreeForSync() const;
@@ -732,6 +739,8 @@
   bool requires_high_res_to_draw_;
   bool is_likely_to_require_a_draw_;
 
+  scoped_ptr<FrameTimingTracker> frame_timing_tracker_;
+
   DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
 };
 
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index b016fff..1c486e3 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -192,13 +192,14 @@
 
   static void ExpectContains(const ScrollAndScaleSet& scroll_info,
                              int id,
-                             const gfx::Vector2d& scroll_delta) {
+                             const gfx::Vector2dF& scroll_delta) {
     int times_encountered = 0;
 
     for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
       if (scroll_info.scrolls[i].layer_id != id)
         continue;
-      EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
+      EXPECT_VECTOR2DF_NEAR(scroll_delta, scroll_info.scrolls[i].scroll_delta,
+                            1.0e-10);
       times_encountered++;
     }
 
@@ -568,22 +569,180 @@
   ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
 }
 
-TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->SetViewportSize(gfx::Size(50, 50));
   DrawFrame();
   LayerImpl* root = host_impl_->active_tree()->root_layer();
 
+  // With registered event handlers, wheel scrolls don't necessarily
+  // have to go to the main thread.
   root->SetHaveWheelEventHandlers(true);
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+  host_impl_->ScrollEnd();
 
-  // With registered event handlers, wheel scrolls have to go to the main
-  // thread.
+  // But typically the scroll-blocks-on mode will require them to.
+  root->SetScrollBlocksOn(ScrollBlocksOnWheelEvent | ScrollBlocksOnStartTouch);
   EXPECT_EQ(InputHandler::ScrollOnMainThread,
             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
 
   // But gesture scrolls can still be handled.
   EXPECT_EQ(InputHandler::ScrollStarted,
             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+
+  // And if the handlers go away, wheel scrolls can again be processed
+  // on impl (despite the scroll-blocks-on mode).
+  root->SetHaveWheelEventHandlers(false);
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+  host_impl_->ScrollEnd();
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
+  LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
+  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  DrawFrame();
+  LayerImpl* root = host_impl_->active_tree()->root_layer();
+
+  LayerImpl* child = 0;
+  {
+    scoped_ptr<LayerImpl> child_layer =
+        LayerImpl::Create(host_impl_->active_tree(), 6);
+    child = child_layer.get();
+    child_layer->SetDrawsContent(true);
+    child_layer->SetPosition(gfx::PointF(0, 20));
+    child_layer->SetBounds(gfx::Size(50, 50));
+    child_layer->SetContentBounds(gfx::Size(50, 50));
+    scroll->AddChild(child_layer.Pass());
+  }
+
+  // Touch handler regions determine whether touch events block scroll.
+  root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
+  EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
+  root->SetScrollBlocksOn(ScrollBlocksOnStartTouch | ScrollBlocksOnWheelEvent);
+  EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
+
+  // But they don't influence the actual handling of the scroll gestures.
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+
+  // It's the union of scroll-blocks-on mode bits across all layers in the
+  // scroll paret chain that matters.
+  EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
+  root->SetScrollBlocksOn(ScrollBlocksOnNone);
+  EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
+  child->SetScrollBlocksOn(ScrollBlocksOnStartTouch);
+  EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
+  SetupScrollAndContentsLayers(gfx::Size(100, 100));
+  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  DrawFrame();
+  LayerImpl* root = host_impl_->active_tree()->root_layer();
+
+  // With registered scroll handlers, scrolls don't generally have to go
+  // to the main thread.
+  root->SetHaveScrollEventHandlers(true);
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+  host_impl_->ScrollEnd();
+
+  // Even the default scroll blocks on mode doesn't require this.
+  root->SetScrollBlocksOn(ScrollBlocksOnWheelEvent | ScrollBlocksOnStartTouch);
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+
+  // But the page can opt in to blocking on scroll event handlers.
+  root->SetScrollBlocksOn(ScrollBlocksOnScrollEvent);
+  EXPECT_EQ(InputHandler::ScrollOnMainThread,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+
+  // Gesture and Wheel scrolls behave identically in this regard.
+  EXPECT_EQ(InputHandler::ScrollOnMainThread,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+
+  // And if the handlers go away, scrolls can again be processed on impl
+  // (despite the scroll-blocks-on mode).
+  root->SetHaveScrollEventHandlers(false);
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
+  host_impl_->SetViewportSize(gfx::Size(50, 50));
+
+  // Create a normal scrollable root layer
+  LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
+  LayerImpl* root_child = root_scroll->children()[0];
+  LayerImpl* root = host_impl_->active_tree()->root_layer();
+  DrawFrame();
+
+  // Create two child scrollable layers
+  LayerImpl* child1 = 0;
+  {
+    scoped_ptr<LayerImpl> scrollable_child_clip_1 =
+        LayerImpl::Create(host_impl_->active_tree(), 6);
+    scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
+        7, gfx::Size(10, 10), scrollable_child_clip_1.get());
+    child1 = scrollable_child_1.get();
+    scrollable_child_1->SetPosition(gfx::Point(5, 5));
+    scrollable_child_1->SetHaveWheelEventHandlers(true);
+    scrollable_child_1->SetHaveScrollEventHandlers(true);
+    scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
+    root_child->AddChild(scrollable_child_clip_1.Pass());
+  }
+
+  LayerImpl* child2 = 0;
+  {
+    scoped_ptr<LayerImpl> scrollable_child_clip_2 =
+        LayerImpl::Create(host_impl_->active_tree(), 8);
+    scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
+        9, gfx::Size(10, 10), scrollable_child_clip_2.get());
+    child2 = scrollable_child_2.get();
+    scrollable_child_2->SetPosition(gfx::Point(5, 20));
+    scrollable_child_2->SetHaveWheelEventHandlers(true);
+    scrollable_child_2->SetHaveScrollEventHandlers(true);
+    scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
+    root_child->AddChild(scrollable_child_clip_2.Pass());
+  }
+
+  // Scroll-blocks-on on a layer affects scrolls that hit that layer.
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+  child1->SetScrollBlocksOn(ScrollBlocksOnScrollEvent);
+  EXPECT_EQ(InputHandler::ScrollOnMainThread,
+            host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture));
+
+  // But not those that hit only other layers.
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+
+  // It's the union of bits set across the scroll ancestor chain that matters.
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Wheel));
+  host_impl_->ScrollEnd();
+  root->SetScrollBlocksOn(ScrollBlocksOnWheelEvent);
+  EXPECT_EQ(InputHandler::ScrollStarted,
+            host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
+  host_impl_->ScrollEnd();
+  EXPECT_EQ(InputHandler::ScrollOnMainThread,
+            host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Wheel));
+  child2->SetScrollBlocksOn(ScrollBlocksOnScrollEvent);
+  EXPECT_EQ(InputHandler::ScrollOnMainThread,
+            host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Wheel));
+  EXPECT_EQ(InputHandler::ScrollOnMainThread,
+            host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
 }
 
 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
@@ -3543,9 +3702,8 @@
 
   // The layer should have scrolled down in its local coordinates.
   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
-  ExpectContains(*scroll_info.get(),
-                 scroll_layer->id(),
-                 gfx::Vector2d(0, gesture_scroll_delta.x()));
+  ExpectContains(*scroll_info.get(), scroll_layer->id(),
+                 gfx::Vector2dF(0, gesture_scroll_delta.x()));
 
   // Reset and scroll down with the wheel.
   scroll_layer->SetScrollDelta(gfx::Vector2dF());
@@ -3606,10 +3764,9 @@
 
     // The child layer should have scrolled down in its local coordinates an
     // amount proportional to the angle between it and the input scroll delta.
-    gfx::Vector2d expected_scroll_delta(
-        0,
-        gesture_scroll_delta.y() *
-            std::cos(MathUtil::Deg2Rad(child_layer_angle)));
+    gfx::Vector2dF expected_scroll_delta(
+        0, gesture_scroll_delta.y() *
+               std::cos(MathUtil::Deg2Rad(child_layer_angle)));
     scoped_ptr<ScrollAndScaleSet> scroll_info =
         host_impl_->ProcessScrollDeltas();
     ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
@@ -3630,17 +3787,16 @@
 
     // The child layer should have scrolled down in its local coordinates an
     // amount proportional to the angle between it and the input scroll delta.
-    gfx::Vector2d expected_scroll_delta(
-        0,
-        -gesture_scroll_delta.x() *
-            std::sin(MathUtil::Deg2Rad(child_layer_angle)));
+    gfx::Vector2dF expected_scroll_delta(
+        0, -gesture_scroll_delta.x() *
+               std::sin(MathUtil::Deg2Rad(child_layer_angle)));
     scoped_ptr<ScrollAndScaleSet> scroll_info =
         host_impl_->ProcessScrollDeltas();
     ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
 
     // The root scroll layer should have scrolled more, since the input scroll
     // delta was mostly orthogonal to the child layer's vertical scroll axis.
-    gfx::Vector2d expected_root_scroll_delta(
+    gfx::Vector2dF expected_root_scroll_delta(
         gesture_scroll_delta.x() *
             std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
         0);
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 1235e15..eecc5a0 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -26,10 +26,9 @@
 
   bool FillsBoundsCompletely() const override { return false; }
 
-  void PaintContents(
-      SkCanvas* canvas,
-      const gfx::Rect& rect,
-      ContentLayerClient::GraphicsContextStatus gc_status) override {
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& rect,
+                     PaintingControlSetting picture_control) override {
     SkPaint paint;
     paint.setStyle(SkPaint::kStroke_Style);
     paint.setStrokeWidth(SkIntToScalar(2));
@@ -49,7 +48,7 @@
 
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override {
+      PaintingControlSetting picture_control) override {
     NOTIMPLEMENTED();
     return DisplayItemList::Create();
   }
@@ -97,9 +96,8 @@
   SkCanvas canvas(bitmap);
   canvas.scale(SkIntToScalar(4), SkIntToScalar(4));
   MaskContentLayerClient client(mask_bounds);
-  client.PaintContents(&canvas,
-                       gfx::Rect(mask_bounds),
-                       ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+  client.PaintContents(&canvas, gfx::Rect(mask_bounds),
+                       ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
   mask->SetBitmap(bitmap);
 
   scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
diff --git a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
index 4d60baf..5d828c5 100644
--- a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
+++ b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
@@ -61,10 +61,9 @@
 
   bool FillsBoundsCompletely() const override { return false; }
 
-  void PaintContents(
-      SkCanvas* canvas,
-      const gfx::Rect& clip,
-      ContentLayerClient::GraphicsContextStatus gc_status) override {
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& clip,
+                     PaintingControlSetting picture_control) override {
     SkPaint paint;
     paint.setColor(SK_ColorBLUE);
     canvas->drawRect(SkRect::MakeWH(layer_rect_.width(),
@@ -82,7 +81,7 @@
 
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override {
+      PaintingControlSetting picture_control) override {
     NOTIMPLEMENTED();
     return DisplayItemList::Create();
   }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index d4bfb6e..cff3b1f 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1104,17 +1104,16 @@
 
   void SetTestLayer(Layer* test_layer) { test_layer_ = test_layer; }
 
-  void PaintContents(
-      SkCanvas* canvas,
-      const gfx::Rect& clip,
-      ContentLayerClient::GraphicsContextStatus gc_status) override {
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& clip,
+                     PaintingControlSetting picture_control) override {
     // Set layer opacity to 0.
     if (test_layer_)
       test_layer_->SetOpacity(0.f);
   }
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
       const gfx::Rect& clip,
-      GraphicsContextStatus gc_status) override {
+      PaintingControlSetting picture_control) override {
     NOTIMPLEMENTED();
     return DisplayItemList::Create();
   }
@@ -2066,7 +2065,7 @@
   }
 
   void AfterTest() override {
-    EXPECT_GE(3, num_will_begin_impl_frame_);
+    EXPECT_GE(num_will_begin_impl_frame_, 3);
     EXPECT_EQ(2, num_send_begin_main_frame_);
   }
 
@@ -2327,17 +2326,16 @@
 
     int paint_count() const { return paint_count_; }
 
-    void PaintContents(
-        SkCanvas* canvas,
-        const gfx::Rect& clip,
-        ContentLayerClient::GraphicsContextStatus gc_status) override {
-      FakeContentLayerClient::PaintContents(canvas, clip, gc_status);
+    void PaintContents(SkCanvas* canvas,
+                       const gfx::Rect& clip,
+                       PaintingControlSetting picture_control) override {
+      FakeContentLayerClient::PaintContents(canvas, clip, picture_control);
       ++paint_count_;
     }
 
     scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
         const gfx::Rect& clip,
-        GraphicsContextStatus gc_status) override {
+        PaintingControlSetting picture_control) override {
       NOTIMPLEMENTED();
       return DisplayItemList::Create();
     }
@@ -2605,16 +2603,15 @@
 
     void set_layer(Layer* layer) { layer_ = layer; }
 
-    void PaintContents(
-        SkCanvas* canvas,
-        const gfx::Rect& clip,
-        ContentLayerClient::GraphicsContextStatus gc_status) override {
+    void PaintContents(SkCanvas* canvas,
+                       const gfx::Rect& clip,
+                       PaintingControlSetting picture_control) override {
       layer_->SetBounds(gfx::Size(2, 2));
     }
 
     scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
         const gfx::Rect& clip,
-        GraphicsContextStatus gc_status) override {
+        PaintingControlSetting picture_control) override {
       NOTIMPLEMENTED();
       return DisplayItemList::Create();
     }
@@ -5518,8 +5515,8 @@
     EndTest();
   }
 
-  void ApplyViewportDeltas(const gfx::Vector2d& inner,
-                           const gfx::Vector2d& outer,
+  void ApplyViewportDeltas(const gfx::Vector2dF& inner,
+                           const gfx::Vector2dF& outer,
                            const gfx::Vector2dF& elastic_overscroll_delta,
                            float scale_delta,
                            float top_controls_delta) override {
@@ -6096,6 +6093,73 @@
 
 MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestOneActivatePerPrepareTiles);
 
+class LayerTreeHostTestFrameTimingRequestsSaveTimestamps
+    : public LayerTreeHostTest {
+ public:
+  LayerTreeHostTestFrameTimingRequestsSaveTimestamps()
+      : check_results_on_commit_(false) {}
+
+  void SetupTree() override {
+    scoped_refptr<FakePictureLayer> root_layer =
+        FakePictureLayer::Create(&client_);
+    root_layer->SetBounds(gfx::Size(200, 200));
+    root_layer->SetIsDrawable(true);
+
+    scoped_refptr<FakePictureLayer> child_layer =
+        FakePictureLayer::Create(&client_);
+    child_layer->SetBounds(gfx::Size(1500, 1500));
+    child_layer->SetIsDrawable(true);
+
+    std::vector<FrameTimingRequest> requests;
+    requests.push_back(FrameTimingRequest(1, gfx::Rect(0, 0, 100, 100)));
+    requests.push_back(FrameTimingRequest(2, gfx::Rect(300, 0, 100, 100)));
+    child_layer->SetFrameTimingRequests(requests);
+
+    root_layer->AddChild(child_layer);
+    layer_tree_host()->SetRootLayer(root_layer);
+    LayerTreeHostTest::SetupTree();
+  }
+
+  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
+    if (!check_results_on_commit_)
+      return;
+
+    // Since in reality, the events will be read by LayerTreeHost during commit,
+    // we check the requests here to ensure that they are correct at the next
+    // commit time (as opposed to checking in DrawLayers for instance).
+    // TODO(vmpstr): Change this to read things from the main thread when this
+    // information is propagated to the main thread (not yet implemented).
+    FrameTimingTracker* tracker = host_impl->frame_timing_tracker();
+    scoped_ptr<FrameTimingTracker::CompositeTimingSet> timing_set =
+        tracker->GroupCountsByRectId();
+    EXPECT_EQ(1u, timing_set->size());
+    auto rect_1_it = timing_set->find(1);
+    EXPECT_TRUE(rect_1_it != timing_set->end());
+    const auto& timing_events = rect_1_it->second;
+    EXPECT_EQ(1u, timing_events.size());
+    EXPECT_EQ(host_impl->active_tree()->source_frame_number(),
+              timing_events[0].frame_id);
+    EXPECT_GT(timing_events[0].timestamp, base::TimeTicks());
+
+    EndTest();
+  }
+
+  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+    check_results_on_commit_ = true;
+    PostSetNeedsCommitToMainThread();
+  }
+
+  void AfterTest() override {}
+
+ private:
+  FakeContentLayerClient client_;
+  bool check_results_on_commit_;
+};
+
+MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestFrameTimingRequestsSaveTimestamps);
+
 class LayerTreeHostTestActivationCausesPrepareTiles : public LayerTreeHostTest {
  public:
   LayerTreeHostTestActivationCausesPrepareTiles()
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index bbdfe6b..e36f6a0 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1096,13 +1096,21 @@
     host_impl->BlockNotifyReadyToActivateForTesting(false);
   }
 
+  void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+    if (!host_impl->settings().impl_side_painting)
+      return;
+    if (host_impl->pending_tree()->source_frame_number() != 1)
+      return;
+    LayerImpl* scroll_layer_impl =
+        host_impl->pending_tree()->root_layer()->children()[0];
+    EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
+  }
+
   void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+    if (host_impl->active_tree()->source_frame_number() != 1)
+      return;
     LayerImpl* scroll_layer_impl =
         host_impl->active_tree()->root_layer()->children()[0];
-    if (scroll_layer_impl->layer_animation_controller()->GetAnimation(
-            Animation::ScrollOffset))
-      return;
-
     EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
     EndTest();
   }
diff --git a/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
index 75eda92..d2014ea 100644
--- a/cc/trees/layer_tree_host_unittest_no_message_loop.cc
+++ b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
@@ -54,12 +54,12 @@
   ~LayerTreeHostNoMessageLoopTest() override {}
 
   // LayerTreeHostClient overrides.
-  void WillBeginMainFrame(int frame_id) override {}
+  void WillBeginMainFrame() override {}
   void BeginMainFrame(const BeginFrameArgs& args) override {}
   void DidBeginMainFrame() override {}
   void Layout() override {}
-  void ApplyViewportDeltas(const gfx::Vector2d& inner_delta,
-                           const gfx::Vector2d& outer_delta,
+  void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+                           const gfx::Vector2dF& outer_delta,
                            const gfx::Vector2dF& elastic_overscroll_delta,
                            float page_scale,
                            float top_controls_delta) override {}
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index 1c20b4c..03a0860 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -429,19 +429,14 @@
         PostSetNeedsCommitToMainThread();
         break;
       case 1:
-        EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(),
-                         gfx::ToFlooredVector2d(scroll_amount_));
-        EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(),
-                         gfx::Vector2dF(fmod(scroll_amount_.x(), 1.0f), 0.0f));
+        EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), scroll_amount_);
+        EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2dF());
         PostSetNeedsCommitToMainThread();
         break;
       case 2:
-        EXPECT_VECTOR_EQ(
-            scroll_layer->BaseScrollOffset(),
-            gfx::ToFlooredVector2d(scroll_amount_ + scroll_amount_));
-        EXPECT_VECTOR_EQ(
-            scroll_layer->ScrollDelta(),
-            gfx::Vector2dF(fmod(2.0f * scroll_amount_.x(), 1.0f), 0.0f));
+        EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(),
+                         (scroll_amount_ + scroll_amount_));
+        EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2dF());
         EndTest();
         break;
     }
@@ -1044,21 +1039,24 @@
     // Set max_scroll_offset = (100, 100).
     scroll_layer->SetBounds(
         gfx::Size(root->bounds().width() + 100, root->bounds().height() + 100));
-    EXPECT_EQ(InputHandler::ScrollStarted,
-              scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f),
-                                      InputHandler::Gesture));
+    EXPECT_EQ(
+        InputHandler::ScrollStarted,
+        scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture,
+                                ScrollBlocksOnNone));
 
     // Set max_scroll_offset = (0, 0).
     scroll_layer->SetBounds(root->bounds());
-    EXPECT_EQ(InputHandler::ScrollIgnored,
-              scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f),
-                                      InputHandler::Gesture));
+    EXPECT_EQ(
+        InputHandler::ScrollIgnored,
+        scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture,
+                                ScrollBlocksOnNone));
 
     // Set max_scroll_offset = (-100, -100).
     scroll_layer->SetBounds(gfx::Size());
-    EXPECT_EQ(InputHandler::ScrollIgnored,
-              scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f),
-                                      InputHandler::Gesture));
+    EXPECT_EQ(
+        InputHandler::ScrollIgnored,
+        scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture,
+                                ScrollBlocksOnNone));
 
     EndTest();
   }
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 97ebb00..80ccf14 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -122,7 +122,12 @@
 
 void LayerTreeImpl::ReleaseResources() {
   if (root_layer_)
-    ReleaseResourcesRecursive(root_layer_.get());
+    ProcessLayersRecursive(root_layer_.get(), &LayerImpl::ReleaseResources);
+}
+
+void LayerTreeImpl::RecreateResources() {
+  if (root_layer_)
+    ProcessLayersRecursive(root_layer_.get(), &LayerImpl::RecreateResources);
 }
 
 void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
@@ -1159,15 +1164,16 @@
   return layers_with_copy_output_request_;
 }
 
-void LayerTreeImpl::ReleaseResourcesRecursive(LayerImpl* current) {
+void LayerTreeImpl::ProcessLayersRecursive(LayerImpl* current,
+                                           void (LayerImpl::*function)()) {
   DCHECK(current);
-  current->ReleaseResources();
+  (current->*function)();
   if (current->mask_layer())
-    ReleaseResourcesRecursive(current->mask_layer());
+    ProcessLayersRecursive(current->mask_layer(), function);
   if (current->replica_layer())
-    ReleaseResourcesRecursive(current->replica_layer());
+    ProcessLayersRecursive(current->replica_layer(), function);
   for (size_t i = 0; i < current->children().size(); ++i)
-    ReleaseResourcesRecursive(current->children()[i]);
+    ProcessLayersRecursive(current->children()[i], function);
 }
 
 template <typename LayerType>
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index a58b645..2329139 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -19,10 +19,16 @@
 #include "cc/resources/ui_resource_client.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+}  // namespace base
 
 namespace cc {
 
@@ -64,6 +70,7 @@
 
   void Shutdown();
   void ReleaseResources();
+  void RecreateResources();
 
   // Methods called by the layer tree that pass-through or access LTHI.
   // ---------------------------------------------------------------------------
@@ -336,7 +343,8 @@
       LayerTreeHostImpl* layer_tree_host_impl,
       scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
       scoped_refptr<SyncedElasticOverscroll> elastic_overscroll);
-  void ReleaseResourcesRecursive(LayerImpl* current);
+  void ProcessLayersRecursive(LayerImpl* current,
+                              void (LayerImpl::*function)());
   float ClampPageScaleFactorToLimits(float page_scale_factor) const;
   void PushPageScaleFactorAndLimits(const float* page_scale_factor,
                                     float min_page_scale_factor,
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index d578daf..07dfc29 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -30,6 +30,7 @@
       gpu_rasterization_enabled(false),
       gpu_rasterization_forced(false),
       gpu_rasterization_msaa_sample_count(0),
+      threaded_gpu_rasterization_enabled(false),
       create_low_res_tiling(false),
       scrollbar_animator(NoAnimator),
       scrollbar_fade_delay_ms(0),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 597a279..8ba859a 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -9,7 +9,9 @@
 #include "cc/base/cc_export.h"
 #include "cc/debug/layer_tree_debug_state.h"
 #include "cc/output/renderer_settings.h"
+#include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkTypeface.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace cc {
@@ -36,6 +38,7 @@
   bool gpu_rasterization_enabled;
   bool gpu_rasterization_forced;
   int gpu_rasterization_msaa_sample_count;
+  bool threaded_gpu_rasterization_enabled;
   bool create_low_res_tiling;
 
   enum ScrollbarAnimator {
@@ -82,6 +85,7 @@
   bool record_full_layer;
   bool use_display_lists;
   bool verify_property_trees;
+  skia::RefPtr<SkTypeface> hud_typeface;
 
   LayerTreeDebugState initial_debug_state;
 };
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 1afd4bd..934e1fc 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -171,10 +171,12 @@
   }
 
   TransformNode* node = data_for_children->transform_tree->back();
+  layer->set_transform_tree_index(node->id);
 
   node->data.flattens = layer->should_flatten_transform();
   node->data.target_id =
       data_from_ancestor.render_target->transform_tree_index();
+  DCHECK_NE(node->data.target_id, -1);
   node->data.is_animated = layer->TransformIsAnimating();
 
   gfx::Transform transform;
@@ -214,7 +216,6 @@
   data_from_ancestor.transform_tree->UpdateScreenSpaceTransform(node->id);
 
   layer->set_offset_to_transform_parent(gfx::Vector2dF());
-  layer->set_transform_tree_index(node->id);
 }
 
 void BuildPropertyTreesInternal(Layer* layer,
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 206af66..2f181fc 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -17,11 +17,17 @@
 #include "cc/base/cc_export.h"
 
 namespace base {
-namespace debug {
+namespace trace_event {
 class TracedValue;
 }
-class SingleThreadTaskRunner;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
 }
+class SingleThreadTaskRunner;
+}  // namespace base
 
 namespace gfx {
 class Rect;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index dc58d39..f913c1f 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -7,6 +7,7 @@
 #include "base/auto_reset.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/devtools_instrumentation.h"
 #include "cc/output/context_provider.h"
 #include "cc/output/output_surface.h"
 #include "cc/quads/draw_quad.h"
@@ -204,6 +205,8 @@
 
   commit_requested_ = false;
   layer_tree_host_->WillCommit();
+  devtools_instrumentation::ScopedCommitTrace commit_task(
+      layer_tree_host_->id());
 
   // Commit immediately.
   {
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 88f1314..5ee43ab 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -796,6 +796,8 @@
   bool updated = layer_tree_host()->UpdateLayers(queue.get());
 
   layer_tree_host()->WillCommit();
+  devtools_instrumentation::ScopedCommitTrace commit_task(
+      layer_tree_host()->id());
 
   // Before calling animate, we set main().animate_requested to false. If it is
   // true now, it means SetNeedAnimate was called again, but during a state when
diff --git a/crypto/openssl_util.cc b/crypto/openssl_util.cc
index f41b55a..8ea1232 100644
--- a/crypto/openssl_util.cc
+++ b/crypto/openssl_util.cc
@@ -48,6 +48,18 @@
  private:
   friend struct DefaultSingletonTraits<OpenSSLInitSingleton>;
   OpenSSLInitSingleton() {
+#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
+    const bool has_neon =
+        (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
+    // CRYPTO_set_NEON_capable is called before |SSL_library_init| because this
+    // stops BoringSSL from probing for NEON support via SIGILL in the case
+    // that getauxval isn't present.
+    CRYPTO_set_NEON_capable(has_neon);
+    // See https://code.google.com/p/chromium/issues/detail?id=341598
+    base::CPU cpu;
+    CRYPTO_set_NEON_functional(!cpu.has_broken_neon());
+#endif
+
     SSL_load_error_strings();
     SSL_library_init();
     int num_locks = CRYPTO_num_locks();
@@ -56,16 +68,6 @@
       locks_.push_back(new base::Lock());
     CRYPTO_set_locking_callback(LockingCallback);
     CRYPTO_THREADID_set_callback(CurrentThreadId);
-
-#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
-    const bool has_neon =
-        (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
-    if (has_neon)
-      CRYPTO_set_NEON_capable(1);
-    // See https://code.google.com/p/chromium/issues/detail?id=341598
-    base::CPU cpu;
-    CRYPTO_set_NEON_functional(!cpu.has_broken_neon());
-#endif
   }
 
   ~OpenSSLInitSingleton() {
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc
index 21598a8..daa04f1 100644
--- a/gin/isolate_holder.cc
+++ b/gin/isolate_holder.cc
@@ -254,6 +254,7 @@
 #endif
   isolate_data_.reset();
   isolate_->Dispose();
+  isolate_ = NULL;
 }
 
 // static
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 448fe05..0896026 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -140,6 +140,7 @@
       "command_buffer/client/fenced_allocator_test.cc",
       "command_buffer/client/gles2_implementation_unittest.cc",
       "command_buffer/client/mapped_memory_unittest.cc",
+      "command_buffer/client/program_info_manager_unittest.cc",
       "command_buffer/client/query_tracker_unittest.cc",
       "command_buffer/client/ring_buffer_test.cc",
       "command_buffer/client/transfer_buffer_unittest.cc",
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index 88bed32..9d3a0f9 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -86,6 +86,7 @@
 #define glGenTransformFeedbacks GLES2_GET_FUN(GenTransformFeedbacks)
 #define glGetActiveAttrib GLES2_GET_FUN(GetActiveAttrib)
 #define glGetActiveUniform GLES2_GET_FUN(GetActiveUniform)
+#define glGetActiveUniformBlockName GLES2_GET_FUN(GetActiveUniformBlockName)
 #define glGetAttachedShaders GLES2_GET_FUN(GetAttachedShaders)
 #define glGetAttribLocation GLES2_GET_FUN(GetAttribLocation)
 #define glGetBooleanv GLES2_GET_FUN(GetBooleanv)
@@ -109,6 +110,7 @@
 #define glGetString GLES2_GET_FUN(GetString)
 #define glGetTexParameterfv GLES2_GET_FUN(GetTexParameterfv)
 #define glGetTexParameteriv GLES2_GET_FUN(GetTexParameteriv)
+#define glGetUniformBlockIndex GLES2_GET_FUN(GetUniformBlockIndex)
 #define glGetUniformfv GLES2_GET_FUN(GetUniformfv)
 #define glGetUniformiv GLES2_GET_FUN(GetUniformiv)
 #define glGetUniformLocation GLES2_GET_FUN(GetUniformLocation)
@@ -148,6 +150,7 @@
 #define glShaderSource GLES2_GET_FUN(ShaderSource)
 #define glShallowFinishCHROMIUM GLES2_GET_FUN(ShallowFinishCHROMIUM)
 #define glShallowFlushCHROMIUM GLES2_GET_FUN(ShallowFlushCHROMIUM)
+#define glOrderingBarrierCHROMIUM GLES2_GET_FUN(OrderingBarrierCHROMIUM)
 #define glStencilFunc GLES2_GET_FUN(StencilFunc)
 #define glStencilFuncSeparate GLES2_GET_FUN(StencilFuncSeparate)
 #define glStencilMask GLES2_GET_FUN(StencilMask)
@@ -254,6 +257,7 @@
 #define glRateLimitOffscreenContextCHROMIUM \
   GLES2_GET_FUN(RateLimitOffscreenContextCHROMIUM)
 #define glGetProgramInfoCHROMIUM GLES2_GET_FUN(GetProgramInfoCHROMIUM)
+#define glGetUniformBlocksCHROMIUM GLES2_GET_FUN(GetUniformBlocksCHROMIUM)
 #define glCreateStreamTextureCHROMIUM GLES2_GET_FUN(CreateStreamTextureCHROMIUM)
 #define glCreateImageCHROMIUM GLES2_GET_FUN(CreateImageCHROMIUM)
 #define glDestroyImageCHROMIUM GLES2_GET_FUN(DestroyImageCHROMIUM)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index b0884b6..dc576d7 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1508,6 +1508,10 @@
     'type': 'Bind',
     'id_mapping': [ 'Buffer' ],
     'gen_func': 'GenBuffersARB',
+    'valid_args': {
+      '3': '4',
+      '4': '4'
+    },
     'unsafe': True,
   },
   'BindFramebuffer': {
@@ -2030,6 +2034,15 @@
       'uint32_t type',
     ],
   },
+  'GetActiveUniformBlockName': {
+    'type': 'Custom',
+    'data_transfer_methods': ['shm'],
+    'cmd_args':
+        'GLidProgram program, GLuint index, uint32_t name_bucket_id, '
+        'void* result',
+    'result': ['int32_t'],
+    'unsafe': True,
+  },
   'GetAttachedShaders': {
     'type': 'Custom',
     'data_transfer_methods': ['shm'],
@@ -2200,7 +2213,27 @@
     'get_len_enum': 'GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE',
     'unit_test': False,
     'extension': True,
-    },
+  },
+  'GetUniformBlockIndex': {
+    'type': 'Custom',
+    'data_transfer_methods': ['shm'],
+    'cmd_args':
+        'GLidProgram program, uint32_t name_bucket_id, GLuint* index',
+    'result': ['GLuint'],
+    'error_return': 'GL_INVALID_INDEX',
+    'unsafe': True,
+  },
+  'GetUniformBlocksCHROMIUM': {
+    'type': 'Custom',
+    'expectation': False,
+    'impl_func': False,
+    'extension': True,
+    'chromium': True,
+    'client_test': False,
+    'cmd_args': 'GLidProgram program, uint32_t bucket_id',
+    'result': ['uint32_t'],
+    'unsafe': True,
+  },
   'GetUniformfv': {
     'type': 'Custom',
     'data_transfer_methods': ['shm'],
@@ -3021,6 +3054,13 @@
     'chromium': True,
     'client_test': False,
   },
+  'OrderingBarrierCHROMIUM': {
+    'impl_func': False,
+    'gen_cmd': False,
+    'extension': True,
+    'chromium': True,
+    'client_test': False,
+  },
   'TraceBeginCHROMIUM': {
     'type': 'Custom',
     'impl_func': False,
diff --git a/gpu/command_buffer/client/client_test_helper.cc b/gpu/command_buffer/client/client_test_helper.cc
index 3c50f6b..258e821 100644
--- a/gpu/command_buffer/client/client_test_helper.cc
+++ b/gpu/command_buffer/client/client_test_helper.cc
@@ -130,6 +130,10 @@
   FlushHelper(put_offset);
 }
 
+void MockClientCommandBuffer::OrderingBarrier(int32 put_offset) {
+  FlushHelper(put_offset);
+}
+
 void MockClientCommandBuffer::DelegateToFake() {
   ON_CALL(*this, DestroyTransferBuffer(_))
       .WillByDefault(Invoke(
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h
index 6778a83..111c4f4 100644
--- a/gpu/command_buffer/client/client_test_helper.h
+++ b/gpu/command_buffer/client/client_test_helper.h
@@ -70,6 +70,7 @@
   MOCK_METHOD1(DestroyTransferBuffer, void(int32 id));
 
   virtual void Flush(int32 put_offset) override;
+  virtual void OrderingBarrier(int32 put_offset) override;
 
   void DelegateToFake();
 };
@@ -80,6 +81,7 @@
   virtual ~MockClientCommandBufferMockFlush();
 
   MOCK_METHOD1(Flush, void(int32 put_offset));
+  MOCK_METHOD1(OrderingBarrier, void(int32 put_offset));
 
   void DelegateToFake();
 };
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc
index a99201e..038ba41 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper.cc
@@ -150,7 +150,7 @@
   if (put_ == total_entry_count_)
     put_ = 0;
 
-  if (usable() && last_put_sent_ != put_) {
+  if (usable()) {
     last_flush_time_ = base::TimeTicks::Now();
     last_put_sent_ = put_;
     command_buffer_->Flush(put_);
@@ -159,6 +159,18 @@
   }
 }
 
+void CommandBufferHelper::OrderingBarrier() {
+  // Wrap put_ before setting the barrier.
+  if (put_ == total_entry_count_)
+    put_ = 0;
+
+  if (usable()) {
+    command_buffer_->OrderingBarrier(put_);
+    ++flush_generation_;
+    CalcImmediateEntries(0);
+  }
+}
+
 #if defined(CMD_HELPER_PERIODIC_FLUSH_CHECK)
 void CommandBufferHelper::PeriodicFlushCheck() {
   base::TimeTicks current_time = base::TimeTicks::Now();
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h
index 053c1c9..3f7fba7 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.h
+++ b/gpu/command_buffer/client/cmd_buffer_helper.h
@@ -66,6 +66,11 @@
   // returns, the command buffer service is aware of all pending commands.
   void Flush();
 
+  // Ensures that commands up to the put pointer will be processed in the
+  // command buffer service before any future commands on other command buffers
+  // sharing a channel.
+  void OrderingBarrier();
+
   // Waits until all the commands have been executed. Returns whether it
   // was successful. The function will fail if the command buffer service has
   // disconnected.
@@ -322,6 +327,7 @@
   int32 token_;
   int32 put_;
   int32 last_put_sent_;
+  int32 last_barrier_put_sent_;
 
 #if defined(CMD_HELPER_PERIODIC_FLUSH_CHECK)
   int commands_issued_;
diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
index 2e807e2..ac83da5 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
@@ -709,4 +709,64 @@
   EXPECT_EQ(error::kNoError, GetError());
 }
 
+TEST_F(CommandBufferHelperTest, TestOrderingBarrierFlushGeneration) {
+  // Explicit flushing only.
+  helper_->SetAutomaticFlushes(false);
+
+  // Generation should change after OrderingBarrier() but not before.
+  uint32 gen1, gen2, gen3;
+
+  gen1 = GetHelperFlushGeneration();
+  AddUniqueCommandWithExpect(error::kNoError, 2);
+  gen2 = GetHelperFlushGeneration();
+  helper_->OrderingBarrier();
+  gen3 = GetHelperFlushGeneration();
+  EXPECT_EQ(gen2, gen1);
+  EXPECT_NE(gen3, gen2);
+
+  helper_->Finish();
+
+  // Check that the commands did happen.
+  Mock::VerifyAndClearExpectations(api_mock_.get());
+
+  // Check the error status.
+  EXPECT_EQ(error::kNoError, GetError());
+}
+
+// Expect Flush() to always call CommandBuffer::Flush().
+TEST_F(CommandBufferHelperTest, TestFlushToCommandBuffer) {
+  // Explicit flushing only.
+  helper_->SetAutomaticFlushes(false);
+
+  int flush_count1, flush_count2, flush_count3;
+
+  flush_count1 = command_buffer_->FlushCount();
+  AddUniqueCommandWithExpect(error::kNoError, 2);
+  helper_->Flush();
+  flush_count2 = command_buffer_->FlushCount();
+  helper_->Flush();
+  flush_count3 = command_buffer_->FlushCount();
+
+  EXPECT_EQ(flush_count2, flush_count1 + 1);
+  EXPECT_EQ(flush_count3, flush_count2 + 1);
+}
+
+// Expect OrderingBarrier() to always call CommandBuffer::OrderingBarrier().
+TEST_F(CommandBufferHelperTest, TestOrderingBarrierToCommandBuffer) {
+  // Explicit flushing only.
+  helper_->SetAutomaticFlushes(false);
+
+  int flush_count1, flush_count2, flush_count3;
+
+  flush_count1 = command_buffer_->FlushCount();
+  AddUniqueCommandWithExpect(error::kNoError, 2);
+  helper_->OrderingBarrier();
+  flush_count2 = command_buffer_->FlushCount();
+  helper_->OrderingBarrier();
+  flush_count3 = command_buffer_->FlushCount();
+
+  EXPECT_EQ(flush_count2, flush_count1 + 1);
+  EXPECT_EQ(flush_count3, flush_count2 + 1);
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc
index 0f15f1d..f10695e 100644
--- a/gpu/command_buffer/client/gl_in_process_context.cc
+++ b/gpu/command_buffer/client/gl_in_process_context.cc
@@ -68,7 +68,7 @@
   size_t GetMappedMemoryLimit() override;
 
 #if defined(OS_ANDROID)
-  virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
+  scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
       uint32 stream_id) override;
 #endif
 
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 503fff0..dfe7a6a 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -338,6 +338,14 @@
   gles2::GetGLContext()->GetActiveUniform(program, index, bufsize, length, size,
                                           type, name);
 }
+void GLES2GetActiveUniformBlockName(GLuint program,
+                                    GLuint index,
+                                    GLsizei bufsize,
+                                    GLsizei* length,
+                                    char* name) {
+  gles2::GetGLContext()->GetActiveUniformBlockName(program, index, bufsize,
+                                                   length, name);
+}
 void GLES2GetAttachedShaders(GLuint program,
                              GLsizei maxcount,
                              GLsizei* count,
@@ -431,6 +439,9 @@
 void GLES2GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
   gles2::GetGLContext()->GetTexParameteriv(target, pname, params);
 }
+GLuint GLES2GetUniformBlockIndex(GLuint program, const char* name) {
+  return gles2::GetGLContext()->GetUniformBlockIndex(program, name);
+}
 void GLES2GetUniformfv(GLuint program, GLint location, GLfloat* params) {
   gles2::GetGLContext()->GetUniformfv(program, location, params);
 }
@@ -578,6 +589,9 @@
 void GLES2ShallowFlushCHROMIUM() {
   gles2::GetGLContext()->ShallowFlushCHROMIUM();
 }
+void GLES2OrderingBarrierCHROMIUM() {
+  gles2::GetGLContext()->OrderingBarrierCHROMIUM();
+}
 void GLES2StencilFunc(GLenum func, GLint ref, GLuint mask) {
   gles2::GetGLContext()->StencilFunc(func, ref, mask);
 }
@@ -1038,6 +1052,12 @@
                                  void* info) {
   gles2::GetGLContext()->GetProgramInfoCHROMIUM(program, bufsize, size, info);
 }
+void GLES2GetUniformBlocksCHROMIUM(GLuint program,
+                                   GLsizei bufsize,
+                                   GLsizei* size,
+                                   void* info) {
+  gles2::GetGLContext()->GetUniformBlocksCHROMIUM(program, bufsize, size, info);
+}
 GLuint GLES2CreateStreamTextureCHROMIUM(GLuint texture) {
   return gles2::GetGLContext()->CreateStreamTextureCHROMIUM(texture);
 }
@@ -1539,6 +1559,10 @@
      reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniform),
     },
     {
+     "glGetActiveUniformBlockName",
+     reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniformBlockName),
+    },
+    {
      "glGetAttachedShaders",
      reinterpret_cast<GLES2FunctionPointer>(glGetAttachedShaders),
     },
@@ -1628,6 +1652,10 @@
      reinterpret_cast<GLES2FunctionPointer>(glGetTexParameteriv),
     },
     {
+     "glGetUniformBlockIndex",
+     reinterpret_cast<GLES2FunctionPointer>(glGetUniformBlockIndex),
+    },
+    {
      "glGetUniformfv",
      reinterpret_cast<GLES2FunctionPointer>(glGetUniformfv),
     },
@@ -1784,6 +1812,10 @@
      reinterpret_cast<GLES2FunctionPointer>(glShallowFlushCHROMIUM),
     },
     {
+     "glOrderingBarrierCHROMIUM",
+     reinterpret_cast<GLES2FunctionPointer>(glOrderingBarrierCHROMIUM),
+    },
+    {
      "glStencilFunc",
      reinterpret_cast<GLES2FunctionPointer>(glStencilFunc),
     },
@@ -2192,6 +2224,10 @@
      reinterpret_cast<GLES2FunctionPointer>(glGetProgramInfoCHROMIUM),
     },
     {
+     "glGetUniformBlocksCHROMIUM",
+     reinterpret_cast<GLES2FunctionPointer>(glGetUniformBlocksCHROMIUM),
+    },
+    {
      "glCreateStreamTextureCHROMIUM",
      reinterpret_cast<GLES2FunctionPointer>(glCreateStreamTextureCHROMIUM),
     },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 2ac4d69..fc0f76d 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -702,6 +702,18 @@
   }
 }
 
+void GetActiveUniformBlockName(GLuint program,
+                               GLuint index,
+                               uint32_t name_bucket_id,
+                               uint32_t result_shm_id,
+                               uint32_t result_shm_offset) {
+  gles2::cmds::GetActiveUniformBlockName* c =
+      GetCmdSpace<gles2::cmds::GetActiveUniformBlockName>();
+  if (c) {
+    c->Init(program, index, name_bucket_id, result_shm_id, result_shm_offset);
+  }
+}
+
 void GetAttachedShaders(GLuint program,
                         uint32_t result_shm_id,
                         uint32_t result_shm_offset,
@@ -921,6 +933,17 @@
   }
 }
 
+void GetUniformBlockIndex(GLuint program,
+                          uint32_t name_bucket_id,
+                          uint32_t index_shm_id,
+                          uint32_t index_shm_offset) {
+  gles2::cmds::GetUniformBlockIndex* c =
+      GetCmdSpace<gles2::cmds::GetUniformBlockIndex>();
+  if (c) {
+    c->Init(program, name_bucket_id, index_shm_id, index_shm_offset);
+  }
+}
+
 void GetUniformfv(GLuint program,
                   GLint location,
                   uint32_t params_shm_id,
@@ -2145,6 +2168,14 @@
   }
 }
 
+void GetUniformBlocksCHROMIUM(GLuint program, uint32_t bucket_id) {
+  gles2::cmds::GetUniformBlocksCHROMIUM* c =
+      GetCmdSpace<gles2::cmds::GetUniformBlocksCHROMIUM>();
+  if (c) {
+    c->Init(program, bucket_id);
+  }
+}
+
 void GetTranslatedShaderSourceANGLE(GLuint shader, uint32_t bucket_id) {
   gles2::cmds::GetTranslatedShaderSourceANGLE* c =
       GetCmdSpace<gles2::cmds::GetTranslatedShaderSourceANGLE>();
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 7ef5444..30f9269 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -702,6 +702,15 @@
         return true;
       }
       return false;
+    case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+      *params = capabilities_.max_uniform_buffer_bindings;
+      return true;
+    case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+      *params = capabilities_.max_transform_feedback_separate_attribs;
+      return true;
+    case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+      *params = capabilities_.uniform_buffer_offset_alignment;
+      return true;
     default:
       return false;
   }
@@ -834,6 +843,13 @@
   // TODO(piman): Add the FreeEverything() logic here.
 }
 
+void GLES2Implementation::OrderingBarrierCHROMIUM() {
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
+  // Flush command buffer at the GPU channel level.  May be implemented as
+  // Flush().
+  helper_->CommandBufferHelper::OrderingBarrier();
+}
+
 void GLES2Implementation::Finish() {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
   FinishHelper();
@@ -1091,6 +1107,35 @@
   return loc;
 }
 
+GLuint GLES2Implementation::GetUniformBlockIndexHelper(
+    GLuint program, const char* name) {
+  typedef cmds::GetUniformBlockIndex::Result Result;
+  Result* result = GetResultAs<Result*>();
+  if (!result) {
+    return GL_INVALID_INDEX;
+  }
+  *result = GL_INVALID_INDEX;
+  SetBucketAsCString(kResultBucketId, name);
+  helper_->GetUniformBlockIndex(
+      program, kResultBucketId, GetResultShmId(), GetResultShmOffset());
+  WaitForCmd();
+  helper_->SetBucketSize(kResultBucketId, 0);
+  return *result;
+}
+
+GLuint GLES2Implementation::GetUniformBlockIndex(
+    GLuint program, const char* name) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
+      << program << ", " << name << ")");
+  TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
+  GLuint index = share_group_->program_info_manager()->GetUniformBlockIndex(
+      this, program, name);
+  GPU_CLIENT_LOG("returned " << index);
+  CheckGLError();
+  return index;
+}
+
 void GLES2Implementation::LinkProgram(GLuint program) {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program << ")");
@@ -2272,6 +2317,69 @@
   CheckGLError();
 }
 
+bool GLES2Implementation::GetActiveUniformBlockNameHelper(
+    GLuint program, GLuint index, GLsizei bufsize,
+    GLsizei* length, char* name) {
+  DCHECK_LE(0, bufsize);
+  // Clear the bucket so if the command fails nothing will be in it.
+  helper_->SetBucketSize(kResultBucketId, 0);
+  typedef cmds::GetActiveUniformBlockName::Result Result;
+  Result* result = GetResultAs<Result*>();
+  if (!result) {
+    return false;
+  }
+  // Set as failed so if the command fails we'll recover.
+  *result = 0;
+  helper_->GetActiveUniformBlockName(program, index, kResultBucketId,
+                                     GetResultShmId(), GetResultShmOffset());
+  WaitForCmd();
+  if (*result) {
+    if (bufsize == 0) {
+      if (length) {
+        *length = 0;
+      }
+    } else if (length || name) {
+      std::vector<int8> str;
+      GetBucketContents(kResultBucketId, &str);
+      DCHECK(str.size() > 0);
+      GLsizei max_size =
+          std::min(bufsize, static_cast<GLsizei>(str.size())) - 1;
+      if (length) {
+        *length = max_size;
+      }
+      if (name) {
+        memcpy(name, &str[0], max_size);
+        name[max_size] = '\0';
+      }
+    }
+  }
+  return *result != 0;
+}
+
+void GLES2Implementation::GetActiveUniformBlockName(
+    GLuint program, GLuint index, GLsizei bufsize,
+    GLsizei* length, char* name) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
+      << program << ", " << index << ", " << bufsize << ", "
+      << static_cast<const void*>(length) << ", "
+      << static_cast<const void*>(name) << ", ");
+  if (bufsize < 0) {
+    SetGLError(GL_INVALID_VALUE, "glGetActiveUniformBlockName", "bufsize < 0");
+    return;
+  }
+  TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
+  bool success =
+      share_group_->program_info_manager()->GetActiveUniformBlockName(
+          this, program, index, bufsize, length, name);
+  if (success) {
+    if (name) {
+      GPU_CLIENT_LOG("  name: " << name);
+    }
+  }
+  CheckGLError();
+}
+
 void GLES2Implementation::GetAttachedShaders(
     GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
@@ -2638,6 +2746,10 @@
 // the old model but possibly not true in the new model if another context has
 // deleted the resource.
 
+// NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
+// used even when Bind has failed. However, the bug is minor compared to the
+// overhead & duplicated checking in client side.
+
 void GLES2Implementation::BindBufferHelper(
     GLenum target, GLuint buffer_id) {
   // TODO(gman): See note #1 above.
@@ -2662,8 +2774,7 @@
       changed = true;
       break;
   }
-  // TODO(gman): There's a bug here. If the target is invalid the ID will not be
-  // used even though it's marked it as used here.
+  // TODO(gman): See note #2 above.
   if (changed) {
     GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(
         this, target, buffer_id, &GLES2Implementation::BindBufferStub);
@@ -2679,8 +2790,7 @@
 void GLES2Implementation::BindBufferBaseHelper(
     GLenum target, GLuint index, GLuint buffer_id) {
   // TODO(zmo): See note #1 above.
-  // TODO(zmo): There's a bug here. If the target or index is invalid the ID
-  // will not be used even though it's marked it as used here.
+  // TODO(zmo): See note #2 above.
   GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(
       this, target, index, buffer_id, &GLES2Implementation::BindBufferBaseStub);
 }
@@ -2696,8 +2806,7 @@
     GLenum target, GLuint index, GLuint buffer_id,
     GLintptr offset, GLsizeiptr size) {
   // TODO(zmo): See note #1 above.
-  // TODO(zmo): There's a bug here. If an arguments is invalid the ID will not
-  // be used even though it's marked it as used here.
+  // TODO(zmo): See note #2 above.
   GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(
       this, target, index, buffer_id, offset, size,
       &GLES2Implementation::BindBufferRangeStub);
@@ -2777,8 +2886,7 @@
       changed = true;
       break;
   }
-  // TODO(gman): There's a bug here. If the target is invalid the ID will not be
-  // used even though it's marked it as used here.
+  // TODO(zmo): See note #2 above.
   if (changed) {
     GetIdHandler(id_namespaces::kRenderbuffers)->MarkAsUsedForBind(
         this, target, renderbuffer,
@@ -2827,8 +2935,7 @@
       changed = true;
       break;
   }
-  // TODO(gman): There's a bug here. If the target is invalid the ID will not be
-  // used. even though it's marked it as used here.
+  // TODO(gman): See note #2 above.
   if (changed) {
     GetIdHandler(id_namespaces::kTextures)->MarkAsUsedForBind(
         this, target, texture, &GLES2Implementation::BindTextureStub);
@@ -2847,7 +2954,6 @@
 }
 
 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array) {
-  // TODO(gman): See note #1 above.
   bool changed = false;
   if (vertex_array_object_manager_->BindVertexArray(array, &changed)) {
     if (changed) {
@@ -2878,8 +2984,7 @@
       changed = true;
       break;
   }
-  // TODO(gman): There's a bug here. If the target is invalid the ID will not be
-  // used even though it's marked it as used here.
+  // TODO(gman): See note #2 above.
   if (changed) {
     GetIdHandler(id_namespaces::kValuebuffers)->MarkAsUsedForBind(
         this, target, valuebuffer,
@@ -3509,6 +3614,47 @@
   memcpy(info, &result[0], result.size());
 }
 
+void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
+    GLuint program, std::vector<int8>* result) {
+  DCHECK(result);
+  // Clear the bucket so if the command fails nothing will be in it.
+  helper_->SetBucketSize(kResultBucketId, 0);
+  helper_->GetUniformBlocksCHROMIUM(program, kResultBucketId);
+  GetBucketContents(kResultBucketId, result);
+}
+
+void GLES2Implementation::GetUniformBlocksCHROMIUM(
+    GLuint program, GLsizei bufsize, GLsizei* size, void* info) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  if (bufsize < 0) {
+    SetGLError(
+        GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "bufsize less than 0.");
+    return;
+  }
+  if (size == NULL) {
+    SetGLError(GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "size is null.");
+    return;
+  }
+  // Make sure they've set size to 0 else the value will be undefined on
+  // lost context.
+  DCHECK_EQ(0, *size);
+  std::vector<int8> result;
+  GetUniformBlocksCHROMIUMHelper(program, &result);
+  if (result.empty()) {
+    return;
+  }
+  *size = result.size();
+  if (!info) {
+    return;
+  }
+  if (static_cast<size_t>(bufsize) < result.size()) {
+    SetGLError(GL_INVALID_OPERATION,
+               "glUniformBlocksCHROMIUM", "bufsize is too small for result.");
+    return;
+  }
+  memcpy(info, &result[0], result.size());
+}
+
 GLuint GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture) {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 470200e..193fbb8 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -220,6 +220,12 @@
   bool GetActiveUniformHelper(
       GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
       GLint* size, GLenum* type, char* name);
+  void GetUniformBlocksCHROMIUMHelper(
+      GLuint program, std::vector<int8>* result);
+  GLuint GetUniformBlockIndexHelper(GLuint program, const char* name);
+  bool GetActiveUniformBlockNameHelper(
+      GLuint program, GLuint index, GLsizei bufsize,
+      GLsizei* length, char* name);
 
   void FreeUnusedSharedMemory();
   void FreeEverything();
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 3a6e5f3..3d6009a 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -255,6 +255,12 @@
                       GLenum* type,
                       char* name) override;
 
+void GetActiveUniformBlockName(GLuint program,
+                               GLuint index,
+                               GLsizei bufsize,
+                               GLsizei* length,
+                               char* name) override;
+
 void GetAttachedShaders(GLuint program,
                         GLsizei maxcount,
                         GLsizei* count,
@@ -327,6 +333,8 @@
 
 void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
 
+GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
+
 void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
 
 void GetUniformiv(GLuint program, GLint location, GLint* params) override;
@@ -431,6 +439,8 @@
 
 void ShallowFlushCHROMIUM() override;
 
+void OrderingBarrierCHROMIUM() override;
+
 void StencilFunc(GLenum func, GLint ref, GLuint mask) override;
 
 void StencilFuncSeparate(GLenum face,
@@ -779,6 +789,11 @@
                             GLsizei* size,
                             void* info) override;
 
+void GetUniformBlocksCHROMIUM(GLuint program,
+                              GLsizei bufsize,
+                              GLsizei* size,
+                              void* info) override;
+
 GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
 
 GLuint CreateImageCHROMIUM(ClientBuffer buffer,
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index c88ba64..52a2cef 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -378,6 +378,8 @@
   static const GLint kMaxVertexUniformVectors = 128;
   static const GLint kNumCompressedTextureFormats = 0;
   static const GLint kNumShaderBinaryFormats = 0;
+  static const GLuint kMaxTransformFeedbackSeparateAttribs = 4;
+  static const GLuint kMaxUniformBufferBindings = 36;
   static const GLuint kStartId = 1024;
   static const GLuint kBuffersStartId =
       GLES2Implementation::kClientSideArrayId + 2 * kNumTestContexts;
@@ -439,6 +441,9 @@
       capabilities.num_compressed_texture_formats =
           kNumCompressedTextureFormats;
       capabilities.num_shader_binary_formats = kNumShaderBinaryFormats;
+      capabilities.max_transform_feedback_separate_attribs =
+          kMaxTransformFeedbackSeparateAttribs;
+      capabilities.max_uniform_buffer_bindings = kMaxUniformBufferBindings;
       capabilities.bind_generates_resource_chromium =
           bind_generates_resource_service ? 1 : 0;
       EXPECT_CALL(*gpu_control_, GetCapabilities())
@@ -2019,6 +2024,108 @@
   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
 }
 
+TEST_F(GLES2ImplementationTest, GetUniformBlocksCHROMIUMGoodArgs) {
+  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
+  const GLuint kProgramId = 123;
+  const char kBad = 0x12;
+  GLsizei size = 0;
+  const Str7 kString = {"foobar"};
+  char buf[20];
+
+  ExpectedMemoryInfo mem1 =
+      GetExpectedMemory(MaxTransferBufferSize());
+  ExpectedMemoryInfo result1 =
+      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
+  ExpectedMemoryInfo result2 =
+      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+
+  memset(buf, kBad, sizeof(buf));
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
+                      SetMemory(mem1.ptr, kString)))
+      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
+      .RetiresOnSaturation();
+
+  struct Cmds {
+    cmd::SetBucketSize set_bucket_size1;
+    cmds::GetUniformBlocksCHROMIUM get_uniform_blocks;
+    cmd::GetBucketStart get_bucket_start;
+    cmd::SetToken set_token1;
+    cmd::SetBucketSize set_bucket_size2;
+  };
+  Cmds expected;
+  expected.set_bucket_size1.Init(kBucketId, 0);
+  expected.get_uniform_blocks.Init(kProgramId, kBucketId);
+  expected.get_bucket_start.Init(
+      kBucketId, result1.id, result1.offset,
+      MaxTransferBufferSize(), mem1.id, mem1.offset);
+  expected.set_token1.Init(GetNextToken());
+  expected.set_bucket_size2.Init(kBucketId, 0);
+  gl_->GetUniformBlocksCHROMIUM(kProgramId, sizeof(buf), &size, &buf);
+  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
+  EXPECT_EQ(sizeof(kString), static_cast<size_t>(size));
+  EXPECT_STREQ(kString.str, buf);
+  EXPECT_EQ(buf[sizeof(kString)], kBad);
+}
+
+TEST_F(GLES2ImplementationTest, GetUniformBlocksCHROMIUMBadArgs) {
+  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
+  const GLuint kProgramId = 123;
+  GLsizei size = 0;
+  const Str7 kString = {"foobar"};
+  char buf[20];
+
+  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
+  ExpectedMemoryInfo result1 =
+      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
+  ExpectedMemoryInfo result2 =
+      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+  ExpectedMemoryInfo result3 =
+      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+  ExpectedMemoryInfo result4 =
+      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
+                      SetMemory(mem1.ptr,  kString)))
+      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
+      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
+      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
+      .RetiresOnSaturation();
+
+  // try bufsize not big enough.
+  struct Cmds {
+    cmd::SetBucketSize set_bucket_size1;
+    cmds::GetUniformBlocksCHROMIUM get_uniform_blocks;
+    cmd::GetBucketStart get_bucket_start;
+    cmd::SetToken set_token1;
+    cmd::SetBucketSize set_bucket_size2;
+  };
+  Cmds expected;
+  expected.set_bucket_size1.Init(kBucketId, 0);
+  expected.get_uniform_blocks.Init(kProgramId, kBucketId);
+  expected.get_bucket_start.Init(
+      kBucketId, result1.id, result1.offset,
+      MaxTransferBufferSize(), mem1.id, mem1.offset);
+  expected.set_token1.Init(GetNextToken());
+  expected.set_bucket_size2.Init(kBucketId, 0);
+  gl_->GetUniformBlocksCHROMIUM(kProgramId, 6, &size, &buf);
+  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
+  ClearCommands();
+
+  // try bad bufsize
+  gl_->GetUniformBlocksCHROMIUM(kProgramId, -1, &size, &buf);
+  EXPECT_TRUE(NoCommandsWritten());
+  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
+  ClearCommands();
+  // try no size ptr.
+  gl_->GetUniformBlocksCHROMIUM(kProgramId, sizeof(buf), NULL, &buf);
+  EXPECT_TRUE(NoCommandsWritten());
+  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
+}
+
 // Test that things are cached
 TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) {
   struct PNameValue {
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 743458b..6dbcdcc 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -55,9 +55,9 @@
     cmds::BindBufferRange cmd;
   };
   Cmds expected;
-  expected.cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 5);
+  expected.cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 4);
 
-  gl_->BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 5);
+  gl_->BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 4);
   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
 }
 
@@ -751,6 +751,7 @@
 }
 // TODO(zmo): Implement unit test for GetActiveAttrib
 // TODO(zmo): Implement unit test for GetActiveUniform
+// TODO(zmo): Implement unit test for GetActiveUniformBlockName
 // TODO(zmo): Implement unit test for GetAttachedShaders
 // TODO(zmo): Implement unit test for GetAttribLocation
 
@@ -983,6 +984,7 @@
   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
   EXPECT_EQ(static_cast<Result::Type>(1), result);
 }
+// TODO(zmo): Implement unit test for GetUniformBlockIndex
 // TODO(zmo): Implement unit test for GetUniformfv
 // TODO(zmo): Implement unit test for GetUniformiv
 // TODO(zmo): Implement unit test for GetUniformLocation
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index c3a2c3e..352ff78 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -186,6 +186,11 @@
                               GLint* size,
                               GLenum* type,
                               char* name) = 0;
+virtual void GetActiveUniformBlockName(GLuint program,
+                                       GLuint index,
+                                       GLsizei bufsize,
+                                       GLsizei* length,
+                                       char* name) = 0;
 virtual void GetAttachedShaders(GLuint program,
                                 GLsizei maxcount,
                                 GLsizei* count,
@@ -240,6 +245,7 @@
                                GLenum pname,
                                GLfloat* params) = 0;
 virtual void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) = 0;
+virtual GLuint GetUniformBlockIndex(GLuint program, const char* name) = 0;
 virtual void GetUniformfv(GLuint program, GLint location, GLfloat* params) = 0;
 virtual void GetUniformiv(GLuint program, GLint location, GLint* params) = 0;
 virtual GLint GetUniformLocation(GLuint program, const char* name) = 0;
@@ -309,6 +315,7 @@
                           const GLint* length) = 0;
 virtual void ShallowFinishCHROMIUM() = 0;
 virtual void ShallowFlushCHROMIUM() = 0;
+virtual void OrderingBarrierCHROMIUM() = 0;
 virtual void StencilFunc(GLenum func, GLint ref, GLuint mask) = 0;
 virtual void StencilFuncSeparate(GLenum face,
                                  GLenum func,
@@ -564,6 +571,10 @@
                                     GLsizei bufsize,
                                     GLsizei* size,
                                     void* info) = 0;
+virtual void GetUniformBlocksCHROMIUM(GLuint program,
+                                      GLsizei bufsize,
+                                      GLsizei* size,
+                                      void* info) = 0;
 virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) = 0;
 virtual GLuint CreateImageCHROMIUM(ClientBuffer buffer,
                                    GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 34a0c42..0ca5199 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -185,6 +185,11 @@
                       GLint* size,
                       GLenum* type,
                       char* name) override;
+void GetActiveUniformBlockName(GLuint program,
+                               GLuint index,
+                               GLsizei bufsize,
+                               GLsizei* length,
+                               char* name) override;
 void GetAttachedShaders(GLuint program,
                         GLsizei maxcount,
                         GLsizei* count,
@@ -235,6 +240,7 @@
 const GLubyte* GetString(GLenum name) override;
 void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) override;
 void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
 void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
 void GetUniformiv(GLuint program, GLint location, GLint* params) override;
 GLint GetUniformLocation(GLuint program, const char* name) override;
@@ -304,6 +310,7 @@
                   const GLint* length) override;
 void ShallowFinishCHROMIUM() override;
 void ShallowFlushCHROMIUM() override;
+void OrderingBarrierCHROMIUM() override;
 void StencilFunc(GLenum func, GLint ref, GLuint mask) override;
 void StencilFuncSeparate(GLenum face,
                          GLenum func,
@@ -551,6 +558,10 @@
                             GLsizei bufsize,
                             GLsizei* size,
                             void* info) override;
+void GetUniformBlocksCHROMIUM(GLuint program,
+                              GLsizei bufsize,
+                              GLsizei* size,
+                              void* info) override;
 GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
 GLuint CreateImageCHROMIUM(ClientBuffer buffer,
                            GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index cf121fc..2a6f88e 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -286,6 +286,12 @@
                                           GLenum* /* type */,
                                           char* /* name */) {
 }
+void GLES2InterfaceStub::GetActiveUniformBlockName(GLuint /* program */,
+                                                   GLuint /* index */,
+                                                   GLsizei /* bufsize */,
+                                                   GLsizei* /* length */,
+                                                   char* /* name */) {
+}
 void GLES2InterfaceStub::GetAttachedShaders(GLuint /* program */,
                                             GLsizei /* maxcount */,
                                             GLsizei* /* count */,
@@ -376,6 +382,10 @@
                                            GLenum /* pname */,
                                            GLint* /* params */) {
 }
+GLuint GLES2InterfaceStub::GetUniformBlockIndex(GLuint /* program */,
+                                                const char* /* name */) {
+  return 0;
+}
 void GLES2InterfaceStub::GetUniformfv(GLuint /* program */,
                                       GLint /* location */,
                                       GLfloat* /* params */) {
@@ -516,6 +526,8 @@
 }
 void GLES2InterfaceStub::ShallowFlushCHROMIUM() {
 }
+void GLES2InterfaceStub::OrderingBarrierCHROMIUM() {
+}
 void GLES2InterfaceStub::StencilFunc(GLenum /* func */,
                                      GLint /* ref */,
                                      GLuint /* mask */) {
@@ -961,6 +973,11 @@
                                                 GLsizei* /* size */,
                                                 void* /* info */) {
 }
+void GLES2InterfaceStub::GetUniformBlocksCHROMIUM(GLuint /* program */,
+                                                  GLsizei /* bufsize */,
+                                                  GLsizei* /* size */,
+                                                  void* /* info */) {
+}
 GLuint GLES2InterfaceStub::CreateStreamTextureCHROMIUM(GLuint /* texture */) {
   return 0;
 }
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index db9b375..da97a87 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -185,6 +185,11 @@
                       GLint* size,
                       GLenum* type,
                       char* name) override;
+void GetActiveUniformBlockName(GLuint program,
+                               GLuint index,
+                               GLsizei bufsize,
+                               GLsizei* length,
+                               char* name) override;
 void GetAttachedShaders(GLuint program,
                         GLsizei maxcount,
                         GLsizei* count,
@@ -235,6 +240,7 @@
 const GLubyte* GetString(GLenum name) override;
 void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) override;
 void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
 void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
 void GetUniformiv(GLuint program, GLint location, GLint* params) override;
 GLint GetUniformLocation(GLuint program, const char* name) override;
@@ -304,6 +310,7 @@
                   const GLint* length) override;
 void ShallowFinishCHROMIUM() override;
 void ShallowFlushCHROMIUM() override;
+void OrderingBarrierCHROMIUM() override;
 void StencilFunc(GLenum func, GLint ref, GLuint mask) override;
 void StencilFuncSeparate(GLenum face,
                          GLenum func,
@@ -551,6 +558,10 @@
                             GLsizei bufsize,
                             GLsizei* size,
                             void* info) override;
+void GetUniformBlocksCHROMIUM(GLuint program,
+                              GLsizei bufsize,
+                              GLsizei* size,
+                              void* info) override;
 GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
 GLuint CreateImageCHROMIUM(ClientBuffer buffer,
                            GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 33bc3ae..df03be5 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -500,6 +500,15 @@
   gl_->GetActiveUniform(program, index, bufsize, length, size, type, name);
 }
 
+void GLES2TraceImplementation::GetActiveUniformBlockName(GLuint program,
+                                                         GLuint index,
+                                                         GLsizei bufsize,
+                                                         GLsizei* length,
+                                                         char* name) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetActiveUniformBlockName");
+  gl_->GetActiveUniformBlockName(program, index, bufsize, length, name);
+}
+
 void GLES2TraceImplementation::GetAttachedShaders(GLuint program,
                                                   GLsizei maxcount,
                                                   GLsizei* count,
@@ -653,6 +662,12 @@
   gl_->GetTexParameteriv(target, pname, params);
 }
 
+GLuint GLES2TraceImplementation::GetUniformBlockIndex(GLuint program,
+                                                      const char* name) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformBlockIndex");
+  return gl_->GetUniformBlockIndex(program, name);
+}
+
 void GLES2TraceImplementation::GetUniformfv(GLuint program,
                                             GLint location,
                                             GLfloat* params) {
@@ -899,6 +914,11 @@
   gl_->ShallowFlushCHROMIUM();
 }
 
+void GLES2TraceImplementation::OrderingBarrierCHROMIUM() {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::OrderingBarrierCHROMIUM");
+  gl_->OrderingBarrierCHROMIUM();
+}
+
 void GLES2TraceImplementation::StencilFunc(GLenum func,
                                            GLint ref,
                                            GLuint mask) {
@@ -1647,6 +1667,14 @@
   gl_->GetProgramInfoCHROMIUM(program, bufsize, size, info);
 }
 
+void GLES2TraceImplementation::GetUniformBlocksCHROMIUM(GLuint program,
+                                                        GLsizei bufsize,
+                                                        GLsizei* size,
+                                                        void* info) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformBlocksCHROMIUM");
+  gl_->GetUniformBlocksCHROMIUM(program, bufsize, size, info);
+}
+
 GLuint GLES2TraceImplementation::CreateStreamTextureCHROMIUM(GLuint texture) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu",
                                 "GLES2Trace::CreateStreamTextureCHROMIUM");
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
index 7196372..04121aa 100644
--- a/gpu/command_buffer/client/program_info_manager.cc
+++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -44,11 +44,23 @@
 ProgramInfoManager::Program::UniformInfo::~UniformInfo() {
 }
 
+ProgramInfoManager::Program::UniformBlock::UniformBlock()
+    : binding(0),
+      data_size(0),
+      referenced_by_vertex_shader(false),
+      referenced_by_fragment_shader(false) {
+}
+
+ProgramInfoManager::Program::UniformBlock::~UniformBlock() {
+}
+
 ProgramInfoManager::Program::Program()
-    : cached_(false),
+    : cached_es2_(false),
       max_attrib_name_length_(0),
       max_uniform_name_length_(0),
-      link_status_(false) {
+      link_status_(false),
+      cached_es3_uniform_blocks_(false),
+      active_uniform_block_max_name_length_(0) {
 }
 
 ProgramInfoManager::Program::~Program() {
@@ -78,6 +90,11 @@
       &uniform_infos_[index] : NULL;
 }
 
+const ProgramInfoManager::Program::UniformBlock*
+ProgramInfoManager::Program::GetUniformBlock(GLuint index) const {
+  return (index < uniform_blocks_.size()) ? &uniform_blocks_[index] : NULL;
+}
+
 GLint ProgramInfoManager::Program::GetUniformLocation(
     const std::string& name) const {
   bool getting_array_location = false;
@@ -125,31 +142,45 @@
     GLenum pname, GLint* params) {
   switch (pname) {
     case GL_LINK_STATUS:
-      *params = link_status_;
+      *params = static_cast<GLint>(link_status_);
       return true;
     case GL_ACTIVE_ATTRIBUTES:
-      *params = attrib_infos_.size();
+      *params = static_cast<GLint>(attrib_infos_.size());
       return true;
     case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
-      *params = max_attrib_name_length_;
+      *params = static_cast<GLint>(max_attrib_name_length_);
       return true;
     case GL_ACTIVE_UNIFORMS:
-      *params = uniform_infos_.size();
+      *params = static_cast<GLint>(uniform_infos_.size());
       return true;
     case GL_ACTIVE_UNIFORM_MAX_LENGTH:
-      *params = max_uniform_name_length_;
+      *params = static_cast<GLint>(max_uniform_name_length_);
+      return true;
+    case GL_ACTIVE_UNIFORM_BLOCKS:
+      *params = static_cast<GLint>(uniform_blocks_.size());
+      return true;
+    case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+      *params = static_cast<GLint>(active_uniform_block_max_name_length_);
       return true;
     default:
+      NOTREACHED();
       break;
   }
   return false;
 }
 
-void ProgramInfoManager::Program::Update(
-    GLES2Implementation* gl,
-    GLuint program,
-    const std::vector<int8>& result) {
-  if (cached_) {
+GLuint ProgramInfoManager::Program::GetUniformBlockIndex(
+    const std::string& name) const {
+  for (size_t ii = 0; ii < uniform_blocks_.size(); ++ii) {
+    if (uniform_blocks_[ii].name == name) {
+      return static_cast<GLuint>(ii);
+    }
+  }
+  return GL_INVALID_INDEX;
+}
+
+void ProgramInfoManager::Program::UpdateES2(const std::vector<int8>& result) {
+  if (cached_es2_) {
     return;
   }
   if (result.empty()) {
@@ -200,12 +231,93 @@
     ++input;
   }
   DCHECK_EQ(header->num_attribs + header->num_uniforms,
-                static_cast<uint32>(input - inputs));
-  cached_ = true;
+            static_cast<uint32>(input - inputs));
+  cached_es2_ = true;
 }
 
-bool ProgramInfoManager::Program::cached() const {
-  return cached_;
+void ProgramInfoManager::Program::UpdateES3UniformBlocks(
+    const std::vector<int8>& result) {
+  if (cached_es3_uniform_blocks_) {
+    return;
+  }
+  if (result.empty()) {
+    // This should only happen on a lost context.
+    return;
+  }
+  uniform_blocks_.clear();
+  active_uniform_block_max_name_length_ = 0;
+
+  // |result| comes from GPU process. We consider it trusted data. Therefore,
+  // no need to check for overflows as the GPU side did the checks already.
+  uint32_t header_size = sizeof(UniformBlocksHeader);
+  DCHECK_GE(result.size(), header_size);
+  const UniformBlocksHeader* header = LocalGetAs<const UniformBlocksHeader*>(
+      result, 0, header_size);
+  DCHECK(header);
+  if (header->num_uniform_blocks == 0) {
+    DCHECK_EQ(result.size(), header_size);
+    // TODO(zmo): Here we can't tell if no uniform blocks are defined, or
+    // the previous link failed.
+    return;
+  }
+  uniform_blocks_.resize(header->num_uniform_blocks);
+
+  uint32_t entry_size = sizeof(UniformBlockInfo) * header->num_uniform_blocks;
+  DCHECK_GE(result.size(), header_size + entry_size);
+  uint32_t data_size = result.size() - header_size - entry_size;
+  DCHECK_LT(0u, data_size);
+  const UniformBlockInfo* entries = LocalGetAs<const UniformBlockInfo*>(
+      result, header_size, entry_size);
+  DCHECK(entries);
+  const char* data = LocalGetAs<const char*>(
+      result, header_size + entry_size, data_size);
+  DCHECK(data);
+
+  uint32_t size = 0;
+  for (uint32_t ii = 0; ii < header->num_uniform_blocks; ++ii) {
+    uniform_blocks_[ii].binding = static_cast<GLuint>(entries[ii].binding);
+    uniform_blocks_[ii].data_size = static_cast<GLuint>(entries[ii].data_size);
+    uniform_blocks_[ii].active_uniform_indices.resize(
+        entries[ii].active_uniforms);
+    uniform_blocks_[ii].referenced_by_vertex_shader = static_cast<GLboolean>(
+        entries[ii].referenced_by_vertex_shader);
+    uniform_blocks_[ii].referenced_by_fragment_shader = static_cast<GLboolean>(
+        entries[ii].referenced_by_fragment_shader);
+    // Uniform block names can't be empty strings.
+    DCHECK_LT(1u, entries[ii].name_length);
+    if (entries[ii].name_length > active_uniform_block_max_name_length_) {
+      active_uniform_block_max_name_length_ = entries[ii].name_length;
+    }
+    size += entries[ii].name_length;
+    DCHECK_GE(data_size, size);
+    uniform_blocks_[ii].name = std::string(data, entries[ii].name_length - 1);
+    data += entries[ii].name_length;
+    size += entries[ii].active_uniforms * sizeof(uint32_t);
+    DCHECK_GE(data_size, size);
+    const uint32_t* indices = reinterpret_cast<const uint32_t*>(data);
+    for (uint32_t uu = 0; uu < entries[ii].active_uniforms; ++uu) {
+      uniform_blocks_[ii].active_uniform_indices[uu] =
+          static_cast<GLuint>(indices[uu]);
+    }
+    indices += entries[ii].active_uniforms;
+    data = reinterpret_cast<const char*>(indices);
+  }
+  DCHECK_EQ(data_size, size);
+  cached_es3_uniform_blocks_ = true;
+}
+
+bool ProgramInfoManager::Program::IsCached(ProgramInfoType type) const {
+  switch (type) {
+    case kES2:
+      return cached_es2_;
+    case kES3UniformBlocks:
+      return cached_es3_uniform_blocks_;
+    case kNone:
+      return true;
+    default:
+      NOTREACHED();
+      return true;
+  }
 }
 
 
@@ -216,29 +328,42 @@
 }
 
 ProgramInfoManager::Program* ProgramInfoManager::GetProgramInfo(
-    GLES2Implementation* gl, GLuint program) {
+    GLES2Implementation* gl, GLuint program, ProgramInfoType type) {
   lock_.AssertAcquired();
   ProgramInfoMap::iterator it = program_infos_.find(program);
   if (it == program_infos_.end()) {
     return NULL;
   }
   Program* info = &it->second;
-  if (info->cached())
+  if (info->IsCached(type))
     return info;
-  std::vector<int8> result;
-  {
-    base::AutoUnlock unlock(lock_);
-    // lock_ can't be held across IPC call or else it may deadlock in pepper.
-    // http://crbug.com/418651
-    gl->GetProgramInfoCHROMIUMHelper(program, &result);
-  }
 
-  it = program_infos_.find(program);
-  if (it == program_infos_.end()) {
-    return NULL;
+  std::vector<int8> result;
+  switch (type) {
+    case kES2:
+      {
+        base::AutoUnlock unlock(lock_);
+        // lock_ can't be held across IPC call or else it may deadlock in
+        // pepper. http://crbug.com/418651
+        gl->GetProgramInfoCHROMIUMHelper(program, &result);
+      }
+      info->UpdateES2(result);
+      break;
+    case kES3UniformBlocks:
+      {
+        base::AutoUnlock unlock(lock_);
+        // lock_ can't be held across IPC call or else it may deadlock in
+        // pepper. http://crbug.com/418651
+
+        // TODO(zmo): Uncomment the below line once GetUniformBlocksCHROMIUM
+        // command is implemented.
+        // gl->GetUniformBlocksCHROMIUMHeler(program, &result);
+      }
+      info->UpdateES3UniformBlocks(result);
+    default:
+      NOTREACHED();
+      return NULL;
   }
-  info = &it->second;
-  info->Update(gl, program, result);
   return info;
 }
 
@@ -259,7 +384,23 @@
 bool ProgramInfoManager::GetProgramiv(
     GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
   base::AutoLock auto_lock(lock_);
-  Program* info = GetProgramInfo(gl, program);
+  ProgramInfoType type = kNone;
+  switch (pname) {
+    case GL_ACTIVE_ATTRIBUTES:
+    case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+    case GL_ACTIVE_UNIFORMS:
+    case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+    case GL_LINK_STATUS:
+      type = kES2;
+      break;
+    case GL_ACTIVE_UNIFORM_BLOCKS:
+    case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+      type = kES3UniformBlocks;
+      break;
+    default:
+      return false;
+  }
+  Program* info = GetProgramInfo(gl, program, type);
   if (!info) {
     return false;
   }
@@ -270,7 +411,7 @@
     GLES2Implementation* gl, GLuint program, const char* name) {
   {
     base::AutoLock auto_lock(lock_);
-    Program* info = GetProgramInfo(gl, program);
+    Program* info = GetProgramInfo(gl, program, kES2);
     if (info) {
       return info->GetAttribLocation(name);
     }
@@ -282,7 +423,7 @@
     GLES2Implementation* gl, GLuint program, const char* name) {
   {
     base::AutoLock auto_lock(lock_);
-    Program* info = GetProgramInfo(gl, program);
+    Program* info = GetProgramInfo(gl, program, kES2);
     if (info) {
       return info->GetUniformLocation(name);
     }
@@ -296,7 +437,7 @@
   // fetched altogether from the service side.  See crbug.com/452104.
   {
     base::AutoLock auto_lock(lock_);
-    Program* info = GetProgramInfo(gl, program);
+    Program* info = GetProgramInfo(gl, program, kNone);
     if (info) {
       GLint possible_loc = info->GetFragDataLocation(name);
       if (possible_loc != -1)
@@ -306,7 +447,7 @@
   GLint loc = gl->GetFragDataLocationHelper(program, name);
   if (loc != -1) {
     base::AutoLock auto_lock(lock_);
-    Program* info = GetProgramInfo(gl, program);
+    Program* info = GetProgramInfo(gl, program, kNone);
     if (info) {
       info->CacheFragDataLocation(name, loc);
     }
@@ -320,7 +461,7 @@
     GLint* size, GLenum* type, char* name) {
   {
     base::AutoLock auto_lock(lock_);
-    Program* info = GetProgramInfo(gl, program);
+    Program* info = GetProgramInfo(gl, program, kES2);
     if (info) {
       const Program::VertexAttrib* attrib_info = info->GetAttribInfo(index);
       if (attrib_info) {
@@ -356,7 +497,7 @@
     GLint* size, GLenum* type, char* name) {
   {
     base::AutoLock auto_lock(lock_);
-    Program* info = GetProgramInfo(gl, program);
+    Program* info = GetProgramInfo(gl, program, kES2);
     if (info) {
       const Program::UniformInfo* uniform_info = info->GetUniformInfo(index);
       if (uniform_info) {
@@ -386,6 +527,119 @@
       program, index, bufsize, length, size, type, name);
 }
 
+GLuint ProgramInfoManager::GetUniformBlockIndex(
+    GLES2Implementation* gl, GLuint program, const char* name) {
+  {
+    base::AutoLock auto_lock(lock_);
+    Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
+    if (info) {
+      return info->GetUniformBlockIndex(name);
+    }
+  }
+  return gl->GetUniformBlockIndexHelper(program, name);
+}
+
+bool ProgramInfoManager::GetActiveUniformBlockName(
+    GLES2Implementation* gl, GLuint program, GLuint index,
+    GLsizei buf_size, GLsizei* length, char* name) {
+  DCHECK_LE(0, buf_size);
+  if (!name) {
+    buf_size = 0;
+  }
+  {
+    base::AutoLock auto_lock(lock_);
+    Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
+    if (info) {
+      const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
+      if (uniform_block) {
+        if (buf_size == 0) {
+          if (length) {
+            *length = 0;
+          }
+        } else if (length || name) {
+          GLsizei max_size = std::min(
+              buf_size - 1, static_cast<GLsizei>(uniform_block->name.size()));
+          if (length) {
+            *length = max_size;
+          }
+          if (name) {
+            memcpy(name, uniform_block->name.data(), max_size);
+            name[max_size] = '\0';
+          }
+        }
+        return true;
+      }
+    }
+  }
+  return gl->GetActiveUniformBlockNameHelper(
+      program, index, buf_size, length, name);
+}
+
+bool ProgramInfoManager::GetActiveUniformBlockiv(
+    GLES2Implementation* gl, GLuint program, GLuint index,
+    GLenum pname, GLint* params) {
+  {
+    base::AutoLock auto_lock(lock_);
+    Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
+    if (info) {
+      const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
+      bool valid_pname;
+      switch (pname) {
+        case GL_UNIFORM_BLOCK_BINDING:
+        case GL_UNIFORM_BLOCK_DATA_SIZE:
+        case GL_UNIFORM_BLOCK_NAME_LENGTH:
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+          valid_pname = true;
+          break;
+        default:
+          valid_pname = false;
+          break;
+      }
+      if (uniform_block && valid_pname && params) {
+        switch (pname) {
+          case GL_UNIFORM_BLOCK_BINDING:
+            *params = static_cast<GLint>(uniform_block->binding);
+            break;
+          case GL_UNIFORM_BLOCK_DATA_SIZE:
+            *params = static_cast<GLint>(uniform_block->data_size);
+            break;
+          case GL_UNIFORM_BLOCK_NAME_LENGTH:
+            *params = static_cast<GLint>(uniform_block->name.size()) + 1;
+            break;
+          case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+            *params = static_cast<GLint>(
+                uniform_block->active_uniform_indices.size());
+            break;
+          case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+            for (size_t ii = 0;
+                 ii < uniform_block->active_uniform_indices.size(); ++ii) {
+              params[ii] = static_cast<GLint>(
+                  uniform_block->active_uniform_indices[ii]);
+            }
+            break;
+          case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+            *params = static_cast<GLint>(
+                uniform_block->referenced_by_vertex_shader);
+            break;
+          case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+            *params = static_cast<GLint>(
+                uniform_block->referenced_by_fragment_shader);
+            break;
+          default:
+            NOTREACHED();
+        }
+        return true;
+      }
+    }
+  }
+  return false;
+  // TODO(zmo): return gl->GetActiveUniformBlockivHelper(
+  //                program, index, pname, params);
+}
+
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/client/program_info_manager.h b/gpu/command_buffer/client/program_info_manager.h
index 712b8ed..efbff73 100644
--- a/gpu/command_buffer/client/program_info_manager.h
+++ b/gpu/command_buffer/client/program_info_manager.h
@@ -5,12 +5,13 @@
 #ifndef GPU_COMMAND_BUFFER_CLIENT_PROGRAM_INFO_MANAGER_H_
 #define GPU_COMMAND_BUFFER_CLIENT_PROGRAM_INFO_MANAGER_H_
 
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
 
 #include <string>
 #include <vector>
 
 #include "base/containers/hash_tables.h"
+#include "base/gtest_prod_util.h"
 #include "base/synchronization/lock.h"
 #include "gles2_impl_export.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
@@ -48,8 +49,30 @@
       GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize,
       GLsizei* length, GLint* size, GLenum* type, char* name);
 
+  GLuint GetUniformBlockIndex(
+      GLES2Implementation* gl, GLuint program, const char* name);
+
+  bool GetActiveUniformBlockName(
+      GLES2Implementation* gl, GLuint program, GLuint index,
+      GLsizei buf_size, GLsizei* length, char* name);
+
+  bool GetActiveUniformBlockiv(
+      GLES2Implementation* gl, GLuint program, GLuint index,
+      GLenum pname, GLint* params);
+
  private:
-  class Program {
+  friend class ProgramInfoManagerTest;
+
+  FRIEND_TEST_ALL_PREFIXES(ProgramInfoManagerTest, UpdateES3UniformBlocks);
+
+  enum ProgramInfoType {
+    kES2,
+    kES3UniformBlocks,
+    kNone,
+  };
+
+  // Need GLES2_IMPL_EXPORT for tests.
+  class GLES2_IMPL_EXPORT Program {
    public:
     struct UniformInfo {
       UniformInfo(GLsizei _size, GLenum _type, const std::string& _name);
@@ -71,6 +94,17 @@
       GLint location;
       std::string name;
     };
+    struct UniformBlock {
+      UniformBlock();
+      ~UniformBlock();
+
+      GLuint binding;
+      GLuint data_size;
+      std::vector<GLuint> active_uniform_indices;
+      GLboolean referenced_by_vertex_shader;
+      GLboolean referenced_by_fragment_shader;
+      std::string name;
+    };
 
     Program();
     ~Program();
@@ -89,15 +123,20 @@
 
     bool GetProgramiv(GLenum pname, GLint* params);
 
-    // Updates the program info after a successful link.
-    void Update(GLES2Implementation* gl,
-                GLuint program,
-                const std::vector<int8>& result);
+    // Gets the index of a uniform block by name.
+    GLuint GetUniformBlockIndex(const std::string& name) const;
+    const UniformBlock* GetUniformBlock(GLuint index) const;
 
-    bool cached() const;
+    // Updates the ES2 only program info after a successful link.
+    void UpdateES2(const std::vector<int8>& result);
+
+    // Updates the ES3 UniformBlock info after a successful link.
+    void UpdateES3UniformBlocks(const std::vector<int8>& result);
+
+    bool IsCached(ProgramInfoType type) const;
 
    private:
-    bool cached_;
+    bool cached_es2_;
 
     GLsizei max_attrib_name_length_;
 
@@ -109,13 +148,23 @@
     // Uniform info by index.
     std::vector<UniformInfo> uniform_infos_;
 
-    base::hash_map<std::string, GLint> frag_data_locations_;
-
     // This is true if glLinkProgram was successful last time it was called.
     bool link_status_;
+
+    // BELOW ARE ES3 ONLY INFORMATION.
+
+    bool cached_es3_uniform_blocks_;
+
+    uint32_t active_uniform_block_max_name_length_;
+
+    // Uniform blocks by index.
+    std::vector<UniformBlock> uniform_blocks_;
+
+    base::hash_map<std::string, GLint> frag_data_locations_;
   };
 
-  Program* GetProgramInfo(GLES2Implementation* gl, GLuint program);
+  Program* GetProgramInfo(
+      GLES2Implementation* gl, GLuint program, ProgramInfoType type);
 
   typedef base::hash_map<GLuint, Program> ProgramInfoMap;
 
diff --git a/gpu/command_buffer/client/program_info_manager_unittest.cc b/gpu/command_buffer/client/program_info_manager_unittest.cc
new file mode 100644
index 0000000..6b0576c
--- /dev/null
+++ b/gpu/command_buffer/client/program_info_manager_unittest.cc
@@ -0,0 +1,184 @@
+// 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 "gpu/command_buffer/client/program_info_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+uint32 ComputeOffset(const void* start, const void* position) {
+  return static_cast<const uint8*>(position) -
+         static_cast<const uint8*>(start);
+}
+
+const GLuint kClientProgramId = 321;
+
+}  // namespace anonymous
+
+namespace gpu {
+namespace gles2 {
+
+class ProgramInfoManagerTest : public testing::Test {
+ public:
+  ProgramInfoManagerTest() {}
+  ~ProgramInfoManagerTest() override {}
+
+ protected:
+  typedef ProgramInfoManager::Program Program;
+
+  struct UniformBlocksData {
+    UniformBlocksHeader header;
+    UniformBlockInfo entry[2];
+    char name0[4];
+    uint32_t indices0[2];
+    char name1[8];
+    uint32_t indices1[1];
+  };
+
+  void SetUp() override {
+    program_info_manager_.reset(new ProgramInfoManager);
+    program_info_manager_->CreateInfo(kClientProgramId);
+    {
+      base::AutoLock auto_lock(program_info_manager_->lock_);
+      program_ = program_info_manager_->GetProgramInfo(
+          NULL, kClientProgramId, ProgramInfoManager::kNone);
+      ASSERT_TRUE(program_ != NULL);
+    }
+  }
+
+  void TearDown() override {}
+
+  void SetupUniformBlocksData(UniformBlocksData* data) {
+    // The names needs to be of size 4*k-1 to avoid padding in the struct Data.
+    // This is a testing only problem.
+    const char* kName[] = { "cow", "chicken" };
+    const uint32_t kIndices0[] = { 1, 2 };
+    const uint32_t kIndices1[] = { 3 };
+    const uint32_t* kIndices[] = { kIndices0, kIndices1 };
+    data->header.num_uniform_blocks = 2;
+    data->entry[0].binding = 0;
+    data->entry[0].data_size = 8;
+    data->entry[0].name_offset = ComputeOffset(data, data->name0);
+    data->entry[0].name_length = arraysize(data->name0);
+    data->entry[0].active_uniforms = arraysize(data->indices0);
+    data->entry[0].active_uniform_offset = ComputeOffset(data, data->indices0);
+    data->entry[0].referenced_by_vertex_shader = static_cast<uint32_t>(true);
+    data->entry[0].referenced_by_fragment_shader = static_cast<uint32_t>(false);
+    data->entry[1].binding = 1;
+    data->entry[1].data_size = 4;
+    data->entry[1].name_offset = ComputeOffset(data, data->name1);
+    data->entry[1].name_length = arraysize(data->name1);
+    data->entry[1].active_uniforms = arraysize(data->indices1);
+    data->entry[1].active_uniform_offset = ComputeOffset(data, data->indices1);
+    data->entry[1].referenced_by_vertex_shader = static_cast<uint32_t>(false);
+    data->entry[1].referenced_by_fragment_shader = static_cast<uint32_t>(true);
+    memcpy(data->name0, kName[0], arraysize(data->name0));
+    data->indices0[0] = kIndices[0][0];
+    data->indices0[1] = kIndices[0][1];
+    memcpy(data->name1, kName[1], arraysize(data->name1));
+    data->indices1[0] = kIndices[1][0];
+  }
+
+  scoped_ptr<ProgramInfoManager> program_info_manager_;
+  Program* program_;
+};
+
+TEST_F(ProgramInfoManagerTest, UpdateES3UniformBlocks) {
+  UniformBlocksData data;
+  SetupUniformBlocksData(&data);
+  const std::string kName[] = { data.name0, data.name1 };
+  const uint32_t* kIndices[] = { data.indices0, data.indices1 };
+  std::vector<int8> result(sizeof(data));
+  memcpy(&result[0], &data, sizeof(data));
+  EXPECT_FALSE(program_->IsCached(ProgramInfoManager::kES3UniformBlocks));
+  program_->UpdateES3UniformBlocks(result);
+  EXPECT_TRUE(program_->IsCached(ProgramInfoManager::kES3UniformBlocks));
+
+  GLint uniform_block_count = 0;
+  EXPECT_TRUE(program_->GetProgramiv(
+      GL_ACTIVE_UNIFORM_BLOCKS, &uniform_block_count));
+  EXPECT_EQ(data.header.num_uniform_blocks,
+            static_cast<uint32_t>(uniform_block_count));
+  GLint max_name_length = 0;
+  EXPECT_TRUE(program_->GetProgramiv(
+      GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_name_length));
+  for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) {
+    EXPECT_EQ(ii, program_->GetUniformBlockIndex(kName[ii]));
+    const Program::UniformBlock* info = program_->GetUniformBlock(ii);
+    EXPECT_TRUE(info != NULL);
+    EXPECT_EQ(data.entry[ii].binding, info->binding);
+    EXPECT_EQ(data.entry[ii].data_size, info->data_size);
+    EXPECT_EQ(data.entry[ii].active_uniforms,
+              info->active_uniform_indices.size());
+    for (uint32_t uu = 0; uu < data.entry[ii].active_uniforms; ++uu) {
+      EXPECT_EQ(kIndices[ii][uu], info->active_uniform_indices[uu]);
+    }
+    EXPECT_EQ(data.entry[ii].referenced_by_vertex_shader,
+              static_cast<GLboolean>(info->referenced_by_vertex_shader));
+    EXPECT_EQ(data.entry[ii].referenced_by_fragment_shader,
+              static_cast<GLboolean>(info->referenced_by_fragment_shader));
+    EXPECT_EQ(kName[ii], info->name);
+    EXPECT_GE(max_name_length, static_cast<GLint>(info->name.size()) + 1);
+  }
+
+  EXPECT_EQ(GL_INVALID_INDEX, program_->GetUniformBlockIndex("BadName"));
+  EXPECT_EQ(NULL, program_->GetUniformBlock(data.header.num_uniform_blocks));
+}
+
+TEST_F(ProgramInfoManagerTest, GetUniformBlockIndexCached) {
+  UniformBlocksData data;
+  SetupUniformBlocksData(&data);
+  std::vector<int8> result(sizeof(data));
+  memcpy(&result[0], &data, sizeof(data));
+  program_->UpdateES3UniformBlocks(result);
+
+  EXPECT_EQ(0u, program_info_manager_->GetUniformBlockIndex(
+      NULL, kClientProgramId, data.name0));
+  EXPECT_EQ(1u, program_info_manager_->GetUniformBlockIndex(
+      NULL, kClientProgramId, data.name1));
+  EXPECT_EQ(GL_INVALID_INDEX, program_info_manager_->GetUniformBlockIndex(
+      NULL, kClientProgramId, "BadName"));
+}
+
+TEST_F(ProgramInfoManagerTest, GetActiveUniformBlockNameCached) {
+  UniformBlocksData data;
+  SetupUniformBlocksData(&data);
+  std::vector<int8> result(sizeof(data));
+  memcpy(&result[0], &data, sizeof(data));
+  program_->UpdateES3UniformBlocks(result);
+
+  GLsizei buf_size = std::max(strlen(data.name0), strlen(data.name1)) + 1;
+  std::vector<char> buffer(buf_size);
+  GLsizei length = 0;
+  EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+      NULL, kClientProgramId, 0, buf_size, &length, &buffer[0]));
+  EXPECT_EQ(static_cast<GLsizei>(strlen(data.name0)), length);
+  EXPECT_STREQ(data.name0, &buffer[0]);
+
+  EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+      NULL, kClientProgramId, 1, buf_size, &length, &buffer[0]));
+  EXPECT_EQ(static_cast<GLsizei>(strlen(data.name1)), length);
+  EXPECT_STREQ(data.name1, &buffer[0]);
+
+  // Test length == NULL.
+  EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+      NULL, kClientProgramId, 0, buf_size, NULL, &buffer[0]));
+  EXPECT_STREQ(data.name0, &buffer[0]);
+
+  // Test buffer == NULL.
+  EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+      NULL, kClientProgramId, 0, buf_size, &length, NULL));
+  EXPECT_EQ(0, length);
+
+  // Test buf_size smaller than string size.
+  buf_size = strlen(data.name0);
+  EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+      NULL, kClientProgramId, 0, buf_size, &length, &buffer[0]));
+  EXPECT_EQ(buf_size, length + 1);
+  EXPECT_STREQ(std::string(data.name0).substr(0, length).c_str(), &buffer[0]);
+}
+
+}  // namespace gles2
+}  // namespace gpu
+
diff --git a/gpu/command_buffer/client/query_tracker_unittest.cc b/gpu/command_buffer/client/query_tracker_unittest.cc
index 53f5195..f6f48ec 100644
--- a/gpu/command_buffer/client/query_tracker_unittest.cc
+++ b/gpu/command_buffer/client/query_tracker_unittest.cc
@@ -161,24 +161,23 @@
   EXPECT_EQ(kToken, query->token());
   EXPECT_EQ(1, query->submit_count());
 
-  // Check CheckResultsAvailable.
-  EXPECT_FALSE(query->CheckResultsAvailable(helper_.get()));
-  EXPECT_FALSE(query->NeverUsed());
-  EXPECT_TRUE(query->Pending());
-
   // Flush only once if no more flushes happened between a call to
   // EndQuery command and CheckResultsAvailable
   // Advance put_ so flush calls in CheckResultsAvailable go through
   // and updates flush_generation count
   helper_->Noop(1);
-  // Set Query in pending state_ to simulate EndQuery command is called
-  query->MarkAsPending(kToken);
-  EXPECT_TRUE(query->Pending());
+
   // Store FlushGeneration count after EndQuery is called
   uint32 gen1 = GetFlushGeneration();
+
+  // Check CheckResultsAvailable.
   EXPECT_FALSE(query->CheckResultsAvailable(helper_.get()));
+  EXPECT_FALSE(query->NeverUsed());
+  EXPECT_TRUE(query->Pending());
+
   uint32 gen2 = GetFlushGeneration();
   EXPECT_NE(gen1, gen2);
+
   // Repeated calls to CheckResultsAvailable should not flush unnecessarily
   EXPECT_FALSE(query->CheckResultsAvailable(helper_.get()));
   gen1 = GetFlushGeneration();
diff --git a/gpu/command_buffer/client/transfer_buffer_unittest.cc b/gpu/command_buffer/client/transfer_buffer_unittest.cc
index 7dac4f5..1a2a4b0 100644
--- a/gpu/command_buffer/client/transfer_buffer_unittest.cc
+++ b/gpu/command_buffer/client/transfer_buffer_unittest.cc
@@ -82,6 +82,7 @@
       .Times(1)
       .RetiresOnSaturation();
   EXPECT_CALL(*command_buffer(), OnFlush()).Times(AtMost(1));
+  EXPECT_CALL(*command_buffer(), Flush(_)).Times(AtMost(1));
   transfer_buffer_.reset();
 }
 
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index dc4ce3a..c415e48 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -77,6 +77,7 @@
 GL_APICALL void         GL_APIENTRY glGenTransformFeedbacks (GLsizeiNotNegative n, GLuint* ids);
 GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, GLint* size, GLenum* type, char* name);
 GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniformBlockName (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* name);
 GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLidProgram program, GLsizeiNotNegative maxcount, GLsizeiOptional* count, GLuint* shaders);
 GL_APICALL GLint        GL_APIENTRY glGetAttribLocation (GLidProgram program, const char* name);
 GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenumGLState pname, GLboolean* params);
@@ -99,6 +100,7 @@
 GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenumStringType name);
 GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenumGetTexParamTarget target, GLenumTextureParameter pname, GLfloat* params);
 GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenumGetTexParamTarget target, GLenumTextureParameter pname, GLint* params);
+GL_APICALL GLuint       GL_APIENTRY glGetUniformBlockIndex (GLidProgram program, const char* name);
 GL_APICALL void         GL_APIENTRY glGetUniformfv (GLidProgram program, GLintUniformLocation location, GLfloat* params);
 GL_APICALL void         GL_APIENTRY glGetUniformiv (GLidProgram program, GLintUniformLocation location, GLint* params);
 GL_APICALL GLint        GL_APIENTRY glGetUniformLocation (GLidProgram program, const char* name);
@@ -138,6 +140,7 @@
 GL_APICALL void         GL_APIENTRY glShaderSource (GLidShader shader, GLsizeiNotNegative count, const GLchar* const* str, const GLint* length);
 GL_APICALL void         GL_APIENTRY glShallowFinishCHROMIUM (void);
 GL_APICALL void         GL_APIENTRY glShallowFlushCHROMIUM (void);
+GL_APICALL void         GL_APIENTRY glOrderingBarrierCHROMIUM (void);
 GL_APICALL void         GL_APIENTRY glStencilFunc (GLenumCmpFunction func, GLint ref, GLuint mask);
 GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenumFaceType face, GLenumCmpFunction func, GLint ref, GLuint mask);
 GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
@@ -242,6 +245,7 @@
 GL_APICALL void         GL_APIENTRY glRequestExtensionCHROMIUM (const char* extension);
 GL_APICALL void         GL_APIENTRY glRateLimitOffscreenContextCHROMIUM (void);
 GL_APICALL void         GL_APIENTRY glGetProgramInfoCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
+GL_APICALL void         GL_APIENTRY glGetUniformBlocksCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
 GL_APICALL GLuint       GL_APIENTRY glCreateStreamTextureCHROMIUM (GLuint texture);
 GL_APICALL GLuint       GL_APIENTRY glCreateImageCHROMIUM (ClientBuffer buffer, GLsizei width, GLsizei height, GLenum internalformat);
 GL_APICALL void         GL_APIENTRY glDestroyImageCHROMIUM (GLuint image_id);
diff --git a/gpu/command_buffer/common/capabilities.cc b/gpu/command_buffer/common/capabilities.cc
index ab33aeb..97c26d8 100644
--- a/gpu/command_buffer/common/capabilities.cc
+++ b/gpu/command_buffer/common/capabilities.cc
@@ -23,6 +23,9 @@
       num_compressed_texture_formats(0),
       num_shader_binary_formats(0),
       bind_generates_resource_chromium(0),
+      max_transform_feedback_separate_attribs(0),
+      max_uniform_buffer_bindings(0),
+      uniform_buffer_offset_alignment(1),
       post_sub_buffer(false),
       egl_image_external(false),
       texture_format_bgra8888(false),
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h
index a465ca2..92c3c19 100644
--- a/gpu/command_buffer/common/capabilities.h
+++ b/gpu/command_buffer/common/capabilities.h
@@ -75,6 +75,9 @@
   int num_compressed_texture_formats;
   int num_shader_binary_formats;
   int bind_generates_resource_chromium;
+  int max_transform_feedback_separate_attribs;
+  int max_uniform_buffer_bindings;
+  int uniform_buffer_offset_alignment;
 
   bool post_sub_buffer;
   bool egl_image_external;
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index d846ec1..b699363 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -90,6 +90,11 @@
   // subsequent Flushes on the same GpuChannel.
   virtual void Flush(int32 put_offset) = 0;
 
+  // As Flush, ensures that on the service side, commands up to put_offset
+  // are processed but before subsequent commands on the same GpuChannel but
+  // flushing to the service may be deferred.
+  virtual void OrderingBarrier(int32 put_offset) = 0;
+
   // The writer calls this to wait until the current token is within a
   // specific range, inclusive. Can return early if an error is generated.
   virtual void WaitForTokenInRange(int32 start, int32 end) = 0;
diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h
index b7366f8..9e1f713 100644
--- a/gpu/command_buffer/common/command_buffer_mock.h
+++ b/gpu/command_buffer/common/command_buffer_mock.h
@@ -25,6 +25,7 @@
   MOCK_METHOD0(GetLastState, State());
   MOCK_METHOD0(GetLastToken, int32());
   MOCK_METHOD1(Flush, void(int32 put_offset));
+  MOCK_METHOD1(OrderingBarrier, void(int32 put_offset));
   MOCK_METHOD2(WaitForTokenInRange, void(int32 start, int32 end));
   MOCK_METHOD2(WaitForGetOffsetInRange, void(int32 start, int32 end));
   MOCK_METHOD1(SetGetBuffer, void(int32 transfer_buffer_id));
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 47c2b68..12b90c9 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -3374,6 +3374,69 @@
               "offset of GetActiveUniform Result type should be "
               "8");
 
+struct GetActiveUniformBlockName {
+  typedef GetActiveUniformBlockName ValueType;
+  static const CommandId kCmdId = kGetActiveUniformBlockName;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+  typedef int32_t Result;
+
+  static uint32_t ComputeSize() {
+    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(GLuint _program,
+            GLuint _index,
+            uint32_t _name_bucket_id,
+            uint32_t _result_shm_id,
+            uint32_t _result_shm_offset) {
+    SetHeader();
+    program = _program;
+    index = _index;
+    name_bucket_id = _name_bucket_id;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(void* cmd,
+            GLuint _program,
+            GLuint _index,
+            uint32_t _name_bucket_id,
+            uint32_t _result_shm_id,
+            uint32_t _result_shm_offset) {
+    static_cast<ValueType*>(cmd)->Init(_program, _index, _name_bucket_id,
+                                       _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t program;
+  uint32_t index;
+  uint32_t name_bucket_id;
+  uint32_t result_shm_id;
+  uint32_t result_shm_offset;
+};
+
+static_assert(sizeof(GetActiveUniformBlockName) == 24,
+              "size of GetActiveUniformBlockName should be 24");
+static_assert(offsetof(GetActiveUniformBlockName, header) == 0,
+              "offset of GetActiveUniformBlockName header should be 0");
+static_assert(offsetof(GetActiveUniformBlockName, program) == 4,
+              "offset of GetActiveUniformBlockName program should be 4");
+static_assert(offsetof(GetActiveUniformBlockName, index) == 8,
+              "offset of GetActiveUniformBlockName index should be 8");
+static_assert(
+    offsetof(GetActiveUniformBlockName, name_bucket_id) == 12,
+    "offset of GetActiveUniformBlockName name_bucket_id should be 12");
+static_assert(offsetof(GetActiveUniformBlockName, result_shm_id) == 16,
+              "offset of GetActiveUniformBlockName result_shm_id should be 16");
+static_assert(
+    offsetof(GetActiveUniformBlockName, result_shm_offset) == 20,
+    "offset of GetActiveUniformBlockName result_shm_offset should be 20");
+
 struct GetAttachedShaders {
   typedef GetAttachedShaders ValueType;
   static const CommandId kCmdId = kGetAttachedShaders;
@@ -4516,6 +4579,61 @@
 static_assert(offsetof(GetTexParameteriv, params_shm_offset) == 16,
               "offset of GetTexParameteriv params_shm_offset should be 16");
 
+struct GetUniformBlockIndex {
+  typedef GetUniformBlockIndex ValueType;
+  static const CommandId kCmdId = kGetUniformBlockIndex;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+  typedef GLuint Result;
+
+  static uint32_t ComputeSize() {
+    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(GLuint _program,
+            uint32_t _name_bucket_id,
+            uint32_t _index_shm_id,
+            uint32_t _index_shm_offset) {
+    SetHeader();
+    program = _program;
+    name_bucket_id = _name_bucket_id;
+    index_shm_id = _index_shm_id;
+    index_shm_offset = _index_shm_offset;
+  }
+
+  void* Set(void* cmd,
+            GLuint _program,
+            uint32_t _name_bucket_id,
+            uint32_t _index_shm_id,
+            uint32_t _index_shm_offset) {
+    static_cast<ValueType*>(cmd)
+        ->Init(_program, _name_bucket_id, _index_shm_id, _index_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t program;
+  uint32_t name_bucket_id;
+  uint32_t index_shm_id;
+  uint32_t index_shm_offset;
+};
+
+static_assert(sizeof(GetUniformBlockIndex) == 20,
+              "size of GetUniformBlockIndex should be 20");
+static_assert(offsetof(GetUniformBlockIndex, header) == 0,
+              "offset of GetUniformBlockIndex header should be 0");
+static_assert(offsetof(GetUniformBlockIndex, program) == 4,
+              "offset of GetUniformBlockIndex program should be 4");
+static_assert(offsetof(GetUniformBlockIndex, name_bucket_id) == 8,
+              "offset of GetUniformBlockIndex name_bucket_id should be 8");
+static_assert(offsetof(GetUniformBlockIndex, index_shm_id) == 12,
+              "offset of GetUniformBlockIndex index_shm_id should be 12");
+static_assert(offsetof(GetUniformBlockIndex, index_shm_offset) == 16,
+              "offset of GetUniformBlockIndex index_shm_offset should be 16");
+
 struct GetUniformfv {
   typedef GetUniformfv ValueType;
   static const CommandId kCmdId = kGetUniformfv;
@@ -10512,6 +10630,45 @@
               "offset of GetProgramInfoCHROMIUM Result num_uniforms should be "
               "8");
 
+struct GetUniformBlocksCHROMIUM {
+  typedef GetUniformBlocksCHROMIUM ValueType;
+  static const CommandId kCmdId = kGetUniformBlocksCHROMIUM;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+  typedef uint32_t Result;
+
+  static uint32_t ComputeSize() {
+    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(GLuint _program, uint32_t _bucket_id) {
+    SetHeader();
+    program = _program;
+    bucket_id = _bucket_id;
+  }
+
+  void* Set(void* cmd, GLuint _program, uint32_t _bucket_id) {
+    static_cast<ValueType*>(cmd)->Init(_program, _bucket_id);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t program;
+  uint32_t bucket_id;
+};
+
+static_assert(sizeof(GetUniformBlocksCHROMIUM) == 12,
+              "size of GetUniformBlocksCHROMIUM should be 12");
+static_assert(offsetof(GetUniformBlocksCHROMIUM, header) == 0,
+              "offset of GetUniformBlocksCHROMIUM header should be 0");
+static_assert(offsetof(GetUniformBlocksCHROMIUM, program) == 4,
+              "offset of GetUniformBlocksCHROMIUM program should be 4");
+static_assert(offsetof(GetUniformBlocksCHROMIUM, bucket_id) == 8,
+              "offset of GetUniformBlocksCHROMIUM bucket_id should be 8");
+
 struct GetTranslatedShaderSourceANGLE {
   typedef GetTranslatedShaderSourceANGLE ValueType;
   static const CommandId kCmdId = kGetTranslatedShaderSourceANGLE;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 804bebc..5174384 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -1095,6 +1095,24 @@
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
+TEST_F(GLES2FormatTest, GetActiveUniformBlockName) {
+  cmds::GetActiveUniformBlockName& cmd =
+      *GetBufferAs<cmds::GetActiveUniformBlockName>();
+  void* next_cmd =
+      cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLuint>(12),
+              static_cast<uint32_t>(13), static_cast<uint32_t>(14),
+              static_cast<uint32_t>(15));
+  EXPECT_EQ(static_cast<uint32_t>(cmds::GetActiveUniformBlockName::kCmdId),
+            cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+  EXPECT_EQ(static_cast<uint32_t>(13), cmd.name_bucket_id);
+  EXPECT_EQ(static_cast<uint32_t>(14), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32_t>(15), cmd.result_shm_offset);
+  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
 TEST_F(GLES2FormatTest, GetAttachedShaders) {
   cmds::GetAttachedShaders& cmd = *GetBufferAs<cmds::GetAttachedShaders>();
   void* next_cmd =
@@ -1415,6 +1433,21 @@
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
+TEST_F(GLES2FormatTest, GetUniformBlockIndex) {
+  cmds::GetUniformBlockIndex& cmd = *GetBufferAs<cmds::GetUniformBlockIndex>();
+  void* next_cmd =
+      cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12),
+              static_cast<uint32_t>(13), static_cast<uint32_t>(14));
+  EXPECT_EQ(static_cast<uint32_t>(cmds::GetUniformBlockIndex::kCmdId),
+            cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<uint32_t>(12), cmd.name_bucket_id);
+  EXPECT_EQ(static_cast<uint32_t>(13), cmd.index_shm_id);
+  EXPECT_EQ(static_cast<uint32_t>(14), cmd.index_shm_offset);
+  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
 TEST_F(GLES2FormatTest, GetUniformfv) {
   cmds::GetUniformfv& cmd = *GetBufferAs<cmds::GetUniformfv>();
   void* next_cmd =
@@ -3667,6 +3700,19 @@
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
+TEST_F(GLES2FormatTest, GetUniformBlocksCHROMIUM) {
+  cmds::GetUniformBlocksCHROMIUM& cmd =
+      *GetBufferAs<cmds::GetUniformBlocksCHROMIUM>();
+  void* next_cmd =
+      cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12));
+  EXPECT_EQ(static_cast<uint32_t>(cmds::GetUniformBlocksCHROMIUM::kCmdId),
+            cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+  EXPECT_EQ(static_cast<uint32_t>(12), cmd.bucket_id);
+  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
 TEST_F(GLES2FormatTest, GetTranslatedShaderSourceANGLE) {
   cmds::GetTranslatedShaderSourceANGLE& cmd =
       *GetBufferAs<cmds::GetTranslatedShaderSourceANGLE>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index df996d8..76364b7 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -87,195 +87,198 @@
   OP(GenTransformFeedbacksImmediate)           /* 328 */ \
   OP(GetActiveAttrib)                          /* 329 */ \
   OP(GetActiveUniform)                         /* 330 */ \
-  OP(GetAttachedShaders)                       /* 331 */ \
-  OP(GetAttribLocation)                        /* 332 */ \
-  OP(GetBooleanv)                              /* 333 */ \
-  OP(GetBufferParameteriv)                     /* 334 */ \
-  OP(GetError)                                 /* 335 */ \
-  OP(GetFloatv)                                /* 336 */ \
-  OP(GetFragDataLocation)                      /* 337 */ \
-  OP(GetFramebufferAttachmentParameteriv)      /* 338 */ \
-  OP(GetIntegerv)                              /* 339 */ \
-  OP(GetInternalformativ)                      /* 340 */ \
-  OP(GetProgramiv)                             /* 341 */ \
-  OP(GetProgramInfoLog)                        /* 342 */ \
-  OP(GetRenderbufferParameteriv)               /* 343 */ \
-  OP(GetSamplerParameterfv)                    /* 344 */ \
-  OP(GetSamplerParameteriv)                    /* 345 */ \
-  OP(GetShaderiv)                              /* 346 */ \
-  OP(GetShaderInfoLog)                         /* 347 */ \
-  OP(GetShaderPrecisionFormat)                 /* 348 */ \
-  OP(GetShaderSource)                          /* 349 */ \
-  OP(GetString)                                /* 350 */ \
-  OP(GetTexParameterfv)                        /* 351 */ \
-  OP(GetTexParameteriv)                        /* 352 */ \
-  OP(GetUniformfv)                             /* 353 */ \
-  OP(GetUniformiv)                             /* 354 */ \
-  OP(GetUniformLocation)                       /* 355 */ \
-  OP(GetVertexAttribfv)                        /* 356 */ \
-  OP(GetVertexAttribiv)                        /* 357 */ \
-  OP(GetVertexAttribPointerv)                  /* 358 */ \
-  OP(Hint)                                     /* 359 */ \
-  OP(InvalidateFramebufferImmediate)           /* 360 */ \
-  OP(InvalidateSubFramebufferImmediate)        /* 361 */ \
-  OP(IsBuffer)                                 /* 362 */ \
-  OP(IsEnabled)                                /* 363 */ \
-  OP(IsFramebuffer)                            /* 364 */ \
-  OP(IsProgram)                                /* 365 */ \
-  OP(IsRenderbuffer)                           /* 366 */ \
-  OP(IsSampler)                                /* 367 */ \
-  OP(IsShader)                                 /* 368 */ \
-  OP(IsSync)                                   /* 369 */ \
-  OP(IsTexture)                                /* 370 */ \
-  OP(IsTransformFeedback)                      /* 371 */ \
-  OP(LineWidth)                                /* 372 */ \
-  OP(LinkProgram)                              /* 373 */ \
-  OP(PauseTransformFeedback)                   /* 374 */ \
-  OP(PixelStorei)                              /* 375 */ \
-  OP(PolygonOffset)                            /* 376 */ \
-  OP(ReadBuffer)                               /* 377 */ \
-  OP(ReadPixels)                               /* 378 */ \
-  OP(ReleaseShaderCompiler)                    /* 379 */ \
-  OP(RenderbufferStorage)                      /* 380 */ \
-  OP(ResumeTransformFeedback)                  /* 381 */ \
-  OP(SampleCoverage)                           /* 382 */ \
-  OP(SamplerParameterf)                        /* 383 */ \
-  OP(SamplerParameterfvImmediate)              /* 384 */ \
-  OP(SamplerParameteri)                        /* 385 */ \
-  OP(SamplerParameterivImmediate)              /* 386 */ \
-  OP(Scissor)                                  /* 387 */ \
-  OP(ShaderBinary)                             /* 388 */ \
-  OP(ShaderSourceBucket)                       /* 389 */ \
-  OP(StencilFunc)                              /* 390 */ \
-  OP(StencilFuncSeparate)                      /* 391 */ \
-  OP(StencilMask)                              /* 392 */ \
-  OP(StencilMaskSeparate)                      /* 393 */ \
-  OP(StencilOp)                                /* 394 */ \
-  OP(StencilOpSeparate)                        /* 395 */ \
-  OP(TexImage2D)                               /* 396 */ \
-  OP(TexImage3D)                               /* 397 */ \
-  OP(TexParameterf)                            /* 398 */ \
-  OP(TexParameterfvImmediate)                  /* 399 */ \
-  OP(TexParameteri)                            /* 400 */ \
-  OP(TexParameterivImmediate)                  /* 401 */ \
-  OP(TexStorage3D)                             /* 402 */ \
-  OP(TexSubImage2D)                            /* 403 */ \
-  OP(TexSubImage3D)                            /* 404 */ \
-  OP(TransformFeedbackVaryingsBucket)          /* 405 */ \
-  OP(Uniform1f)                                /* 406 */ \
-  OP(Uniform1fvImmediate)                      /* 407 */ \
-  OP(Uniform1i)                                /* 408 */ \
-  OP(Uniform1ivImmediate)                      /* 409 */ \
-  OP(Uniform1ui)                               /* 410 */ \
-  OP(Uniform1uivImmediate)                     /* 411 */ \
-  OP(Uniform2f)                                /* 412 */ \
-  OP(Uniform2fvImmediate)                      /* 413 */ \
-  OP(Uniform2i)                                /* 414 */ \
-  OP(Uniform2ivImmediate)                      /* 415 */ \
-  OP(Uniform2ui)                               /* 416 */ \
-  OP(Uniform2uivImmediate)                     /* 417 */ \
-  OP(Uniform3f)                                /* 418 */ \
-  OP(Uniform3fvImmediate)                      /* 419 */ \
-  OP(Uniform3i)                                /* 420 */ \
-  OP(Uniform3ivImmediate)                      /* 421 */ \
-  OP(Uniform3ui)                               /* 422 */ \
-  OP(Uniform3uivImmediate)                     /* 423 */ \
-  OP(Uniform4f)                                /* 424 */ \
-  OP(Uniform4fvImmediate)                      /* 425 */ \
-  OP(Uniform4i)                                /* 426 */ \
-  OP(Uniform4ivImmediate)                      /* 427 */ \
-  OP(Uniform4ui)                               /* 428 */ \
-  OP(Uniform4uivImmediate)                     /* 429 */ \
-  OP(UniformMatrix2fvImmediate)                /* 430 */ \
-  OP(UniformMatrix2x3fvImmediate)              /* 431 */ \
-  OP(UniformMatrix2x4fvImmediate)              /* 432 */ \
-  OP(UniformMatrix3fvImmediate)                /* 433 */ \
-  OP(UniformMatrix3x2fvImmediate)              /* 434 */ \
-  OP(UniformMatrix3x4fvImmediate)              /* 435 */ \
-  OP(UniformMatrix4fvImmediate)                /* 436 */ \
-  OP(UniformMatrix4x2fvImmediate)              /* 437 */ \
-  OP(UniformMatrix4x3fvImmediate)              /* 438 */ \
-  OP(UseProgram)                               /* 439 */ \
-  OP(ValidateProgram)                          /* 440 */ \
-  OP(VertexAttrib1f)                           /* 441 */ \
-  OP(VertexAttrib1fvImmediate)                 /* 442 */ \
-  OP(VertexAttrib2f)                           /* 443 */ \
-  OP(VertexAttrib2fvImmediate)                 /* 444 */ \
-  OP(VertexAttrib3f)                           /* 445 */ \
-  OP(VertexAttrib3fvImmediate)                 /* 446 */ \
-  OP(VertexAttrib4f)                           /* 447 */ \
-  OP(VertexAttrib4fvImmediate)                 /* 448 */ \
-  OP(VertexAttribI4i)                          /* 449 */ \
-  OP(VertexAttribI4ivImmediate)                /* 450 */ \
-  OP(VertexAttribI4ui)                         /* 451 */ \
-  OP(VertexAttribI4uivImmediate)               /* 452 */ \
-  OP(VertexAttribIPointer)                     /* 453 */ \
-  OP(VertexAttribPointer)                      /* 454 */ \
-  OP(Viewport)                                 /* 455 */ \
-  OP(BlitFramebufferCHROMIUM)                  /* 456 */ \
-  OP(RenderbufferStorageMultisampleCHROMIUM)   /* 457 */ \
-  OP(RenderbufferStorageMultisampleEXT)        /* 458 */ \
-  OP(FramebufferTexture2DMultisampleEXT)       /* 459 */ \
-  OP(TexStorage2DEXT)                          /* 460 */ \
-  OP(GenQueriesEXTImmediate)                   /* 461 */ \
-  OP(DeleteQueriesEXTImmediate)                /* 462 */ \
-  OP(BeginQueryEXT)                            /* 463 */ \
-  OP(BeginTransformFeedback)                   /* 464 */ \
-  OP(EndQueryEXT)                              /* 465 */ \
-  OP(EndTransformFeedback)                     /* 466 */ \
-  OP(InsertEventMarkerEXT)                     /* 467 */ \
-  OP(PushGroupMarkerEXT)                       /* 468 */ \
-  OP(PopGroupMarkerEXT)                        /* 469 */ \
-  OP(GenVertexArraysOESImmediate)              /* 470 */ \
-  OP(DeleteVertexArraysOESImmediate)           /* 471 */ \
-  OP(IsVertexArrayOES)                         /* 472 */ \
-  OP(BindVertexArrayOES)                       /* 473 */ \
-  OP(SwapBuffers)                              /* 474 */ \
-  OP(GetMaxValueInBufferCHROMIUM)              /* 475 */ \
-  OP(EnableFeatureCHROMIUM)                    /* 476 */ \
-  OP(ResizeCHROMIUM)                           /* 477 */ \
-  OP(GetRequestableExtensionsCHROMIUM)         /* 478 */ \
-  OP(RequestExtensionCHROMIUM)                 /* 479 */ \
-  OP(GetProgramInfoCHROMIUM)                   /* 480 */ \
-  OP(GetTranslatedShaderSourceANGLE)           /* 481 */ \
-  OP(PostSubBufferCHROMIUM)                    /* 482 */ \
-  OP(TexImageIOSurface2DCHROMIUM)              /* 483 */ \
-  OP(CopyTextureCHROMIUM)                      /* 484 */ \
-  OP(DrawArraysInstancedANGLE)                 /* 485 */ \
-  OP(DrawElementsInstancedANGLE)               /* 486 */ \
-  OP(VertexAttribDivisorANGLE)                 /* 487 */ \
-  OP(GenMailboxCHROMIUM)                       /* 488 */ \
-  OP(ProduceTextureCHROMIUMImmediate)          /* 489 */ \
-  OP(ProduceTextureDirectCHROMIUMImmediate)    /* 490 */ \
-  OP(ConsumeTextureCHROMIUMImmediate)          /* 491 */ \
-  OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 492 */ \
-  OP(BindUniformLocationCHROMIUMBucket)        /* 493 */ \
-  OP(GenValuebuffersCHROMIUMImmediate)         /* 494 */ \
-  OP(DeleteValuebuffersCHROMIUMImmediate)      /* 495 */ \
-  OP(IsValuebufferCHROMIUM)                    /* 496 */ \
-  OP(BindValuebufferCHROMIUM)                  /* 497 */ \
-  OP(SubscribeValueCHROMIUM)                   /* 498 */ \
-  OP(PopulateSubscribedValuesCHROMIUM)         /* 499 */ \
-  OP(UniformValuebufferCHROMIUM)               /* 500 */ \
-  OP(BindTexImage2DCHROMIUM)                   /* 501 */ \
-  OP(ReleaseTexImage2DCHROMIUM)                /* 502 */ \
-  OP(TraceBeginCHROMIUM)                       /* 503 */ \
-  OP(TraceEndCHROMIUM)                         /* 504 */ \
-  OP(AsyncTexSubImage2DCHROMIUM)               /* 505 */ \
-  OP(AsyncTexImage2DCHROMIUM)                  /* 506 */ \
-  OP(WaitAsyncTexImage2DCHROMIUM)              /* 507 */ \
-  OP(WaitAllAsyncTexImage2DCHROMIUM)           /* 508 */ \
-  OP(DiscardFramebufferEXTImmediate)           /* 509 */ \
-  OP(LoseContextCHROMIUM)                      /* 510 */ \
-  OP(InsertSyncPointCHROMIUM)                  /* 511 */ \
-  OP(WaitSyncPointCHROMIUM)                    /* 512 */ \
-  OP(DrawBuffersEXTImmediate)                  /* 513 */ \
-  OP(DiscardBackbufferCHROMIUM)                /* 514 */ \
-  OP(ScheduleOverlayPlaneCHROMIUM)             /* 515 */ \
-  OP(SwapInterval)                             /* 516 */ \
-  OP(MatrixLoadfCHROMIUMImmediate)             /* 517 */ \
-  OP(MatrixLoadIdentityCHROMIUM)               /* 518 */ \
-  OP(BlendBarrierKHR)                          /* 519 */
+  OP(GetActiveUniformBlockName)                /* 331 */ \
+  OP(GetAttachedShaders)                       /* 332 */ \
+  OP(GetAttribLocation)                        /* 333 */ \
+  OP(GetBooleanv)                              /* 334 */ \
+  OP(GetBufferParameteriv)                     /* 335 */ \
+  OP(GetError)                                 /* 336 */ \
+  OP(GetFloatv)                                /* 337 */ \
+  OP(GetFragDataLocation)                      /* 338 */ \
+  OP(GetFramebufferAttachmentParameteriv)      /* 339 */ \
+  OP(GetIntegerv)                              /* 340 */ \
+  OP(GetInternalformativ)                      /* 341 */ \
+  OP(GetProgramiv)                             /* 342 */ \
+  OP(GetProgramInfoLog)                        /* 343 */ \
+  OP(GetRenderbufferParameteriv)               /* 344 */ \
+  OP(GetSamplerParameterfv)                    /* 345 */ \
+  OP(GetSamplerParameteriv)                    /* 346 */ \
+  OP(GetShaderiv)                              /* 347 */ \
+  OP(GetShaderInfoLog)                         /* 348 */ \
+  OP(GetShaderPrecisionFormat)                 /* 349 */ \
+  OP(GetShaderSource)                          /* 350 */ \
+  OP(GetString)                                /* 351 */ \
+  OP(GetTexParameterfv)                        /* 352 */ \
+  OP(GetTexParameteriv)                        /* 353 */ \
+  OP(GetUniformBlockIndex)                     /* 354 */ \
+  OP(GetUniformfv)                             /* 355 */ \
+  OP(GetUniformiv)                             /* 356 */ \
+  OP(GetUniformLocation)                       /* 357 */ \
+  OP(GetVertexAttribfv)                        /* 358 */ \
+  OP(GetVertexAttribiv)                        /* 359 */ \
+  OP(GetVertexAttribPointerv)                  /* 360 */ \
+  OP(Hint)                                     /* 361 */ \
+  OP(InvalidateFramebufferImmediate)           /* 362 */ \
+  OP(InvalidateSubFramebufferImmediate)        /* 363 */ \
+  OP(IsBuffer)                                 /* 364 */ \
+  OP(IsEnabled)                                /* 365 */ \
+  OP(IsFramebuffer)                            /* 366 */ \
+  OP(IsProgram)                                /* 367 */ \
+  OP(IsRenderbuffer)                           /* 368 */ \
+  OP(IsSampler)                                /* 369 */ \
+  OP(IsShader)                                 /* 370 */ \
+  OP(IsSync)                                   /* 371 */ \
+  OP(IsTexture)                                /* 372 */ \
+  OP(IsTransformFeedback)                      /* 373 */ \
+  OP(LineWidth)                                /* 374 */ \
+  OP(LinkProgram)                              /* 375 */ \
+  OP(PauseTransformFeedback)                   /* 376 */ \
+  OP(PixelStorei)                              /* 377 */ \
+  OP(PolygonOffset)                            /* 378 */ \
+  OP(ReadBuffer)                               /* 379 */ \
+  OP(ReadPixels)                               /* 380 */ \
+  OP(ReleaseShaderCompiler)                    /* 381 */ \
+  OP(RenderbufferStorage)                      /* 382 */ \
+  OP(ResumeTransformFeedback)                  /* 383 */ \
+  OP(SampleCoverage)                           /* 384 */ \
+  OP(SamplerParameterf)                        /* 385 */ \
+  OP(SamplerParameterfvImmediate)              /* 386 */ \
+  OP(SamplerParameteri)                        /* 387 */ \
+  OP(SamplerParameterivImmediate)              /* 388 */ \
+  OP(Scissor)                                  /* 389 */ \
+  OP(ShaderBinary)                             /* 390 */ \
+  OP(ShaderSourceBucket)                       /* 391 */ \
+  OP(StencilFunc)                              /* 392 */ \
+  OP(StencilFuncSeparate)                      /* 393 */ \
+  OP(StencilMask)                              /* 394 */ \
+  OP(StencilMaskSeparate)                      /* 395 */ \
+  OP(StencilOp)                                /* 396 */ \
+  OP(StencilOpSeparate)                        /* 397 */ \
+  OP(TexImage2D)                               /* 398 */ \
+  OP(TexImage3D)                               /* 399 */ \
+  OP(TexParameterf)                            /* 400 */ \
+  OP(TexParameterfvImmediate)                  /* 401 */ \
+  OP(TexParameteri)                            /* 402 */ \
+  OP(TexParameterivImmediate)                  /* 403 */ \
+  OP(TexStorage3D)                             /* 404 */ \
+  OP(TexSubImage2D)                            /* 405 */ \
+  OP(TexSubImage3D)                            /* 406 */ \
+  OP(TransformFeedbackVaryingsBucket)          /* 407 */ \
+  OP(Uniform1f)                                /* 408 */ \
+  OP(Uniform1fvImmediate)                      /* 409 */ \
+  OP(Uniform1i)                                /* 410 */ \
+  OP(Uniform1ivImmediate)                      /* 411 */ \
+  OP(Uniform1ui)                               /* 412 */ \
+  OP(Uniform1uivImmediate)                     /* 413 */ \
+  OP(Uniform2f)                                /* 414 */ \
+  OP(Uniform2fvImmediate)                      /* 415 */ \
+  OP(Uniform2i)                                /* 416 */ \
+  OP(Uniform2ivImmediate)                      /* 417 */ \
+  OP(Uniform2ui)                               /* 418 */ \
+  OP(Uniform2uivImmediate)                     /* 419 */ \
+  OP(Uniform3f)                                /* 420 */ \
+  OP(Uniform3fvImmediate)                      /* 421 */ \
+  OP(Uniform3i)                                /* 422 */ \
+  OP(Uniform3ivImmediate)                      /* 423 */ \
+  OP(Uniform3ui)                               /* 424 */ \
+  OP(Uniform3uivImmediate)                     /* 425 */ \
+  OP(Uniform4f)                                /* 426 */ \
+  OP(Uniform4fvImmediate)                      /* 427 */ \
+  OP(Uniform4i)                                /* 428 */ \
+  OP(Uniform4ivImmediate)                      /* 429 */ \
+  OP(Uniform4ui)                               /* 430 */ \
+  OP(Uniform4uivImmediate)                     /* 431 */ \
+  OP(UniformMatrix2fvImmediate)                /* 432 */ \
+  OP(UniformMatrix2x3fvImmediate)              /* 433 */ \
+  OP(UniformMatrix2x4fvImmediate)              /* 434 */ \
+  OP(UniformMatrix3fvImmediate)                /* 435 */ \
+  OP(UniformMatrix3x2fvImmediate)              /* 436 */ \
+  OP(UniformMatrix3x4fvImmediate)              /* 437 */ \
+  OP(UniformMatrix4fvImmediate)                /* 438 */ \
+  OP(UniformMatrix4x2fvImmediate)              /* 439 */ \
+  OP(UniformMatrix4x3fvImmediate)              /* 440 */ \
+  OP(UseProgram)                               /* 441 */ \
+  OP(ValidateProgram)                          /* 442 */ \
+  OP(VertexAttrib1f)                           /* 443 */ \
+  OP(VertexAttrib1fvImmediate)                 /* 444 */ \
+  OP(VertexAttrib2f)                           /* 445 */ \
+  OP(VertexAttrib2fvImmediate)                 /* 446 */ \
+  OP(VertexAttrib3f)                           /* 447 */ \
+  OP(VertexAttrib3fvImmediate)                 /* 448 */ \
+  OP(VertexAttrib4f)                           /* 449 */ \
+  OP(VertexAttrib4fvImmediate)                 /* 450 */ \
+  OP(VertexAttribI4i)                          /* 451 */ \
+  OP(VertexAttribI4ivImmediate)                /* 452 */ \
+  OP(VertexAttribI4ui)                         /* 453 */ \
+  OP(VertexAttribI4uivImmediate)               /* 454 */ \
+  OP(VertexAttribIPointer)                     /* 455 */ \
+  OP(VertexAttribPointer)                      /* 456 */ \
+  OP(Viewport)                                 /* 457 */ \
+  OP(BlitFramebufferCHROMIUM)                  /* 458 */ \
+  OP(RenderbufferStorageMultisampleCHROMIUM)   /* 459 */ \
+  OP(RenderbufferStorageMultisampleEXT)        /* 460 */ \
+  OP(FramebufferTexture2DMultisampleEXT)       /* 461 */ \
+  OP(TexStorage2DEXT)                          /* 462 */ \
+  OP(GenQueriesEXTImmediate)                   /* 463 */ \
+  OP(DeleteQueriesEXTImmediate)                /* 464 */ \
+  OP(BeginQueryEXT)                            /* 465 */ \
+  OP(BeginTransformFeedback)                   /* 466 */ \
+  OP(EndQueryEXT)                              /* 467 */ \
+  OP(EndTransformFeedback)                     /* 468 */ \
+  OP(InsertEventMarkerEXT)                     /* 469 */ \
+  OP(PushGroupMarkerEXT)                       /* 470 */ \
+  OP(PopGroupMarkerEXT)                        /* 471 */ \
+  OP(GenVertexArraysOESImmediate)              /* 472 */ \
+  OP(DeleteVertexArraysOESImmediate)           /* 473 */ \
+  OP(IsVertexArrayOES)                         /* 474 */ \
+  OP(BindVertexArrayOES)                       /* 475 */ \
+  OP(SwapBuffers)                              /* 476 */ \
+  OP(GetMaxValueInBufferCHROMIUM)              /* 477 */ \
+  OP(EnableFeatureCHROMIUM)                    /* 478 */ \
+  OP(ResizeCHROMIUM)                           /* 479 */ \
+  OP(GetRequestableExtensionsCHROMIUM)         /* 480 */ \
+  OP(RequestExtensionCHROMIUM)                 /* 481 */ \
+  OP(GetProgramInfoCHROMIUM)                   /* 482 */ \
+  OP(GetUniformBlocksCHROMIUM)                 /* 483 */ \
+  OP(GetTranslatedShaderSourceANGLE)           /* 484 */ \
+  OP(PostSubBufferCHROMIUM)                    /* 485 */ \
+  OP(TexImageIOSurface2DCHROMIUM)              /* 486 */ \
+  OP(CopyTextureCHROMIUM)                      /* 487 */ \
+  OP(DrawArraysInstancedANGLE)                 /* 488 */ \
+  OP(DrawElementsInstancedANGLE)               /* 489 */ \
+  OP(VertexAttribDivisorANGLE)                 /* 490 */ \
+  OP(GenMailboxCHROMIUM)                       /* 491 */ \
+  OP(ProduceTextureCHROMIUMImmediate)          /* 492 */ \
+  OP(ProduceTextureDirectCHROMIUMImmediate)    /* 493 */ \
+  OP(ConsumeTextureCHROMIUMImmediate)          /* 494 */ \
+  OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 495 */ \
+  OP(BindUniformLocationCHROMIUMBucket)        /* 496 */ \
+  OP(GenValuebuffersCHROMIUMImmediate)         /* 497 */ \
+  OP(DeleteValuebuffersCHROMIUMImmediate)      /* 498 */ \
+  OP(IsValuebufferCHROMIUM)                    /* 499 */ \
+  OP(BindValuebufferCHROMIUM)                  /* 500 */ \
+  OP(SubscribeValueCHROMIUM)                   /* 501 */ \
+  OP(PopulateSubscribedValuesCHROMIUM)         /* 502 */ \
+  OP(UniformValuebufferCHROMIUM)               /* 503 */ \
+  OP(BindTexImage2DCHROMIUM)                   /* 504 */ \
+  OP(ReleaseTexImage2DCHROMIUM)                /* 505 */ \
+  OP(TraceBeginCHROMIUM)                       /* 506 */ \
+  OP(TraceEndCHROMIUM)                         /* 507 */ \
+  OP(AsyncTexSubImage2DCHROMIUM)               /* 508 */ \
+  OP(AsyncTexImage2DCHROMIUM)                  /* 509 */ \
+  OP(WaitAsyncTexImage2DCHROMIUM)              /* 510 */ \
+  OP(WaitAllAsyncTexImage2DCHROMIUM)           /* 511 */ \
+  OP(DiscardFramebufferEXTImmediate)           /* 512 */ \
+  OP(LoseContextCHROMIUM)                      /* 513 */ \
+  OP(InsertSyncPointCHROMIUM)                  /* 514 */ \
+  OP(WaitSyncPointCHROMIUM)                    /* 515 */ \
+  OP(DrawBuffersEXTImmediate)                  /* 516 */ \
+  OP(DiscardBackbufferCHROMIUM)                /* 517 */ \
+  OP(ScheduleOverlayPlaneCHROMIUM)             /* 518 */ \
+  OP(SwapInterval)                             /* 519 */ \
+  OP(MatrixLoadfCHROMIUMImmediate)             /* 520 */ \
+  OP(MatrixLoadIdentityCHROMIUM)               /* 521 */ \
+  OP(BlendBarrierKHR)                          /* 522 */
 
 enum CommandId {
   kStartPoint = cmd::kLastCommonId,  // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
index 2389dc1..9b6b7e2 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
@@ -77,13 +77,16 @@
 AsyncPixelTransferManager* AsyncPixelTransferManager::Create(
     gfx::GLContext* context) {
   DCHECK(context->IsCurrent(NULL));
+  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
+
   // Threaded mailbox uses EGLImage which conflicts with EGL uploader.
   // The spec only allows one EGL image per sibling group, but currently the
   // image handle cannot be shared between the threaded mailbox code and
   // AsyncPixelTransferManagerEGL.
   bool uses_threaded_mailboxes =
-      base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableThreadedTextureMailboxes);
+      cl->HasSwitch(switches::kEnableThreadedTextureMailboxes);
+  // TexImage2D orphans the EGLImage used for threaded mailbox sharing.
+  bool use_teximage2d_over_texsubimage2d = !uses_threaded_mailboxes;
   switch (gfx::GetGLImplementation()) {
     case gfx::kGLImplementationEGLGLES2:
       DCHECK(context);
@@ -93,15 +96,16 @@
           context->HasExtension("EGL_KHR_image_base") &&
           context->HasExtension("EGL_KHR_gl_texture_2D_image") &&
           context->HasExtension("GL_OES_EGL_image") &&
-          !uses_threaded_mailboxes &&
-          AllowTransferThreadForGpu()) {
+          !uses_threaded_mailboxes && AllowTransferThreadForGpu()) {
         TRACE_EVENT0("gpu", "AsyncPixelTransferManager_CreateWithThread");
         return new AsyncPixelTransferManagerEGL;
       }
-      return new AsyncPixelTransferManagerIdle;
+      return new AsyncPixelTransferManagerIdle(
+          use_teximage2d_over_texsubimage2d);
     case gfx::kGLImplementationOSMesaGL: {
       TRACE_EVENT0("gpu", "AsyncPixelTransferManager_CreateIdle");
-      return new AsyncPixelTransferManagerIdle;
+      return new AsyncPixelTransferManagerIdle(
+          use_teximage2d_over_texsubimage2d);
     }
     case gfx::kGLImplementationMockGL:
       return new AsyncPixelTransferManagerStub;
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
index 2ed4f7d..b44b477 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
@@ -183,9 +183,8 @@
   base::TimeTicks begin_time(base::TimeTicks::Now());
   gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
 
-  // If it's a full texture update, use glTexImage2D as it's faster.
-  // TODO(epenner): Make this configurable (http://crbug.com/259924)
-  if (tex_params.xoffset == 0 &&
+  if (shared_state_->use_teximage2d_over_texsubimage2d &&
+      tex_params.xoffset == 0 &&
       tex_params.yoffset == 0 &&
       tex_params.target == define_params_.target &&
       tex_params.level  == define_params_.level &&
@@ -234,8 +233,11 @@
 
 AsyncPixelTransferManagerIdle::Task::~Task() {}
 
-AsyncPixelTransferManagerIdle::SharedState::SharedState()
-    : texture_upload_count(0) {}
+AsyncPixelTransferManagerIdle::SharedState::SharedState(
+    bool use_teximage2d_over_texsubimage2d)
+    : use_teximage2d_over_texsubimage2d(use_teximage2d_over_texsubimage2d),
+      texture_upload_count(0) {
+}
 
 AsyncPixelTransferManagerIdle::SharedState::~SharedState() {}
 
@@ -250,8 +252,9 @@
   }
 }
 
-AsyncPixelTransferManagerIdle::AsyncPixelTransferManagerIdle()
-  : shared_state_() {
+AsyncPixelTransferManagerIdle::AsyncPixelTransferManagerIdle(
+    bool use_teximage2d_over_texsubimage2d)
+    : shared_state_(use_teximage2d_over_texsubimage2d) {
 }
 
 AsyncPixelTransferManagerIdle::~AsyncPixelTransferManagerIdle() {}
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h
index 8aba7ff..41a77b3 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h
@@ -13,7 +13,8 @@
 
 class AsyncPixelTransferManagerIdle : public AsyncPixelTransferManager {
  public:
-  AsyncPixelTransferManagerIdle();
+  explicit AsyncPixelTransferManagerIdle(
+      bool use_teximage2d_over_texsubimage2d);
   ~AsyncPixelTransferManagerIdle() override;
 
   // AsyncPixelTransferManager implementation:
@@ -43,10 +44,11 @@
 
   // State shared between Managers and Delegates.
   struct SharedState {
-    SharedState();
+    explicit SharedState(bool use_teximage2d_over_texsubimage2d);
     ~SharedState();
     void ProcessNotificationTasks();
 
+    const bool use_teximage2d_over_texsubimage2d;
     int texture_upload_count;
     base::TimeDelta total_texture_upload_time;
     std::list<Task> tasks;
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
index e756a46..b0cc463 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
@@ -28,7 +28,7 @@
     case gfx::kGLImplementationOSMesaGL:
     case gfx::kGLImplementationDesktopGL:
     case gfx::kGLImplementationEGLGLES2:
-      return new AsyncPixelTransferManagerIdle;
+      return new AsyncPixelTransferManagerIdle(true);
     case gfx::kGLImplementationMockGL:
       return new AsyncPixelTransferManagerStub;
     default:
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
index 6f7c5d1..dcc7e18 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
@@ -18,7 +18,7 @@
     case gfx::kGLImplementationOSMesaGL:
     case gfx::kGLImplementationDesktopGL:
     case gfx::kGLImplementationAppleGL:
-      return new AsyncPixelTransferManagerIdle;
+      return new AsyncPixelTransferManagerIdle(true);
     case gfx::kGLImplementationMockGL:
       return new AsyncPixelTransferManagerStub;
     default:
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
index 3bf32c0..dc106e8 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
@@ -18,7 +18,7 @@
     case gfx::kGLImplementationOSMesaGL:
     case gfx::kGLImplementationDesktopGL:
     case gfx::kGLImplementationEGLGLES2:
-      return new AsyncPixelTransferManagerIdle;
+      return new AsyncPixelTransferManagerIdle(true);
     case gfx::kGLImplementationMockGL:
       return new AsyncPixelTransferManagerStub;
     default:
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index 21e2ae4..f2444b3 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -79,6 +79,10 @@
     put_offset_change_callback_.Run();
 }
 
+void CommandBufferService::OrderingBarrier(int32 put_offset) {
+  Flush(put_offset);
+}
+
 void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) {
   DCHECK_EQ(-1, ring_buffer_id_);
   DCHECK_EQ(put_offset_, get_offset_);  // Only if it's empty.
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
index 69b9ad7..28a5f6f 100644
--- a/gpu/command_buffer/service/command_buffer_service.h
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -52,6 +52,7 @@
   State GetLastState() override;
   int32 GetLastToken() override;
   void Flush(int32 put_offset) override;
+  void OrderingBarrier(int32 put_offset) override;
   void WaitForTokenInRange(int32 start, int32 end) override;
   void WaitForGetOffsetInRange(int32 start, int32 end) override;
   void SetGetBuffer(int32 transfer_buffer_id) override;
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 5706086..803b121 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -17,6 +17,10 @@
 #include "ui/gl/gl_fence.h"
 #include "ui/gl/gl_implementation.h"
 
+#if !defined(OS_MACOSX)
+#include "ui/gl/gl_fence_egl.h"
+#endif
+
 namespace gpu {
 namespace gles2 {
 
@@ -1020,6 +1024,12 @@
       texture_format_validators_[GL_RG_EXT].AddValue(GL_HALF_FLOAT_OES);
     }
   }
+
+#if !defined(OS_MACOSX)
+  if (workarounds_.ignore_egl_sync_failures) {
+    gfx::GLFenceEGL::SetIgnoreFailures();
+  }
+#endif
 }
 
 void FeatureInfo::AddExtensionString(const char* s) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index f37c61a..9b8e635 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1163,16 +1163,16 @@
       GLuint client_id, GLint location, const char* name);
 
   error::Error GetAttribLocationHelper(
-    GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
-    const std::string& name_str);
+      GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
+      const std::string& name_str);
 
   error::Error GetUniformLocationHelper(
-    GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
-    const std::string& name_str);
+      GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
+      const std::string& name_str);
 
   error::Error GetFragDataLocationHelper(
-    GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
-    const std::string& name_str);
+      GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
+      const std::string& name_str);
 
   // Wrapper for glShaderSource.
   void DoShaderSource(
@@ -2842,6 +2842,14 @@
   DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
   DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
                 &caps.bind_generates_resource_chromium);
+  if (unsafe_es3_apis_enabled()) {
+    DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
+                  &caps.max_transform_feedback_separate_attribs);
+    DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
+                  &caps.max_uniform_buffer_bindings);
+    DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
+                  &caps.uniform_buffer_offset_alignment);
+  }
 
   caps.egl_image_external =
       feature_info_->feature_flags().oes_egl_image_external;
@@ -7051,14 +7059,17 @@
     GLuint client_id, GLsizei count, const char** data, const GLint* length) {
   std::string str;
   for (GLsizei ii = 0; ii < count; ++ii) {
-    str.append(data[ii]);
+    if (length && length[ii] > 0)
+      str.append(data[ii], length[ii]);
+    else
+      str.append(data[ii]);
   }
   Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
   if (!shader) {
     return;
   }
   // Note: We don't actually call glShaderSource here. We wait until
-  // the call to glCompileShader.
+  // we actually compile the shader.
   shader->set_source(str);
 }
 
@@ -7086,6 +7097,10 @@
         vertex_translator_.get() : fragment_translator_.get();
   }
 
+  shader->RequestCompile();
+
+  // TODO(dyen): Currently we compile immediately when glCompileShader is
+  // requested. Eventually this should be deffered to the linker stage.
   shader->DoCompile(
      translator,
      feature_info_->feature_flags().angle_translated_shader_source ?
@@ -8186,6 +8201,39 @@
       c.program, c.location_shm_id, c.location_shm_offset, name_str);
 }
 
+error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
+    uint32 immediate_data_size, const void* cmd_data) {
+  if (!unsafe_es3_apis_enabled())
+    return error::kUnknownCommand;
+  const gles2::cmds::GetUniformBlockIndex& c =
+      *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
+  Bucket* bucket = GetBucket(c.name_bucket_id);
+  if (!bucket) {
+    return error::kInvalidArguments;
+  }
+  std::string name_str;
+  if (!bucket->GetAsString(&name_str)) {
+    return error::kInvalidArguments;
+  }
+  GLuint* index = GetSharedMemoryAs<GLuint*>(
+      c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
+  if (!index) {
+    return error::kOutOfBounds;
+  }
+  // Require the client to init this in case the context is lost and we are no
+  // longer executing commands.
+  if (*index != GL_INVALID_INDEX) {
+    return error::kGenericError;
+  }
+  Program* program = GetProgramInfoNotShader(
+      c.program, "glGetUniformBlockIndex");
+  if (!program) {
+    return error::kNoError;
+  }
+  *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
+  return error::kNoError;
+}
+
 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
                                                const void* cmd_data) {
   const gles2::cmds::GetString& c =
@@ -9682,6 +9730,59 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
+    uint32 immediate_data_size, const void* cmd_data) {
+  if (!unsafe_es3_apis_enabled())
+    return error::kUnknownCommand;
+  const gles2::cmds::GetActiveUniformBlockName& c =
+      *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
+  GLuint program_id = c.program;
+  GLuint index = c.index;
+  uint32 name_bucket_id = c.name_bucket_id;
+  typedef cmds::GetActiveUniformBlockName::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result));
+  if (!result) {
+    return error::kOutOfBounds;
+  }
+  // Check that the client initialized the result.
+  if (*result != 0) {
+    return error::kInvalidArguments;
+  }
+  Program* program = GetProgramInfoNotShader(
+      program_id, "glGetActiveUniformBlockName");
+  if (!program) {
+    return error::kNoError;
+  }
+  GLuint service_id = program->service_id();
+  GLint link_status = GL_FALSE;
+  glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
+  if (link_status != GL_TRUE) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+        "glGetActiveActiveUniformBlockName", "program not linked");
+    return error::kNoError;
+  }
+  GLint max_length = 0;
+  glGetProgramiv(
+      service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
+  // Increase one so &buffer[0] is always valid.
+  GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
+  std::vector<char> buffer(buf_size);
+  GLsizei length = 0;
+  glGetActiveUniformBlockName(
+      service_id, index, buf_size, &length, &buffer[0]);
+  if (length == 0) {
+    *result = 0;
+    return error::kNoError;
+  }
+  *result = 1;
+  Bucket* bucket = CreateBucket(name_bucket_id);
+  DCHECK_GT(buf_size, length);
+  DCHECK_EQ(0, buffer[length]);
+  bucket->SetFromString(&buffer[0]);
+  return error::kNoError;
+}
+
 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
                                                      const void* cmd_data) {
   const gles2::cmds::GetActiveAttrib& c =
@@ -10016,6 +10117,25 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
+    uint32 immediate_data_size, const void* cmd_data) {
+  if (!unsafe_es3_apis_enabled())
+    return error::kUnknownCommand;
+  const gles2::cmds::GetUniformBlocksCHROMIUM& c =
+      *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
+  GLuint program_id = static_cast<GLuint>(c.program);
+  uint32 bucket_id = c.bucket_id;
+  Bucket* bucket = CreateBucket(bucket_id);
+  bucket->SetSize(sizeof(UniformBlocksHeader));  // in case we fail.
+  Program* program = NULL;
+  program = GetProgram(program_id);
+  if (!program || !program->IsValid()) {
+    return error::kNoError;
+  }
+  program->GetUniformBlocks(bucket);
+  return error::kNoError;
+}
+
 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
   switch (reset_status_) {
     case GL_NO_ERROR:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
index 2b6a38f..99f26e9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
@@ -85,10 +85,10 @@
 
 TEST_P(GLES2DecoderTest1, BindBufferRangeValidArgs) {
   EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2,
-                                    kServiceBufferId, 4, 5));
+                                    kServiceBufferId, 4, 4));
   SpecializedSetup<cmds::BindBufferRange, 0>(true);
   cmds::BindBufferRange cmd;
-  cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_, 4, 5);
+  cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_, 4, 4);
   decoder_->set_unsafe_es3_apis_enabled(true);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
@@ -98,12 +98,12 @@
 
 TEST_P(GLES2DecoderTest1, BindBufferRangeValidArgsNewId) {
   EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2,
-                                    kNewServiceId, 4, 5));
+                                    kNewServiceId, 4, 4));
   EXPECT_CALL(*gl_, GenBuffersARB(1, _))
       .WillOnce(SetArgumentPointee<1>(kNewServiceId));
   SpecializedSetup<cmds::BindBufferRange, 0>(true);
   cmds::BindBufferRange cmd;
-  cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 5);
+  cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 4);
   decoder_->set_unsafe_es3_apis_enabled(true);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
@@ -1208,6 +1208,8 @@
 
 // TODO(gman): GetActiveUniform
 
+// TODO(gman): GetActiveUniformBlockName
+
 // TODO(gman): GetAttachedShaders
 
 // TODO(gman): GetAttribLocation
@@ -1953,6 +1955,4 @@
   EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
   EXPECT_EQ(0u, result->size);
 }
-// TODO(gman): GetUniformfv
-
 #endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index 2947723..60d147b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -12,6 +12,10 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
 #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
 
+// TODO(gman): GetUniformBlockIndex
+
+// TODO(gman): GetUniformfv
+
 // TODO(gman): GetUniformiv
 
 // TODO(gman): GetUniformLocation
@@ -1497,33 +1501,4 @@
   decoder_->set_unsafe_es3_apis_enabled(false);
   EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 }
-
-TEST_P(GLES2DecoderTest2, VertexAttribI4ivImmediateValidArgs) {
-  cmds::VertexAttribI4ivImmediate& cmd =
-      *GetImmediateAs<cmds::VertexAttribI4ivImmediate>();
-  SpecializedSetup<cmds::VertexAttribI4ivImmediate, 0>(true);
-  GLint temp[4] = {
-      0,
-  };
-  cmd.Init(1, &temp[0]);
-  EXPECT_CALL(*gl_, VertexAttribI4iv(1, reinterpret_cast<GLint*>(
-                                            ImmediateDataAddress(&cmd))));
-  decoder_->set_unsafe_es3_apis_enabled(true);
-  EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
-  EXPECT_EQ(GL_NO_ERROR, GetGLError());
-  decoder_->set_unsafe_es3_apis_enabled(false);
-  EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp)));
-}
-
-TEST_P(GLES2DecoderTest2, VertexAttribI4uiValidArgs) {
-  EXPECT_CALL(*gl_, VertexAttribI4ui(1, 2, 3, 4, 5));
-  SpecializedSetup<cmds::VertexAttribI4ui, 0>(true);
-  cmds::VertexAttribI4ui cmd;
-  cmd.Init(1, 2, 3, 4, 5);
-  decoder_->set_unsafe_es3_apis_enabled(true);
-  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
-  EXPECT_EQ(GL_NO_ERROR, GetGLError());
-  decoder_->set_unsafe_es3_apis_enabled(false);
-  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
-}
 #endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
index 2eb4e58..6421985 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -12,6 +12,35 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
 #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
 
+TEST_P(GLES2DecoderTest3, VertexAttribI4ivImmediateValidArgs) {
+  cmds::VertexAttribI4ivImmediate& cmd =
+      *GetImmediateAs<cmds::VertexAttribI4ivImmediate>();
+  SpecializedSetup<cmds::VertexAttribI4ivImmediate, 0>(true);
+  GLint temp[4] = {
+      0,
+  };
+  cmd.Init(1, &temp[0]);
+  EXPECT_CALL(*gl_, VertexAttribI4iv(1, reinterpret_cast<GLint*>(
+                                            ImmediateDataAddress(&cmd))));
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp)));
+}
+
+TEST_P(GLES2DecoderTest3, VertexAttribI4uiValidArgs) {
+  EXPECT_CALL(*gl_, VertexAttribI4ui(1, 2, 3, 4, 5));
+  SpecializedSetup<cmds::VertexAttribI4ui, 0>(true);
+  cmds::VertexAttribI4ui cmd;
+  cmd.Init(1, 2, 3, 4, 5);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
 TEST_P(GLES2DecoderTest3, VertexAttribI4uivImmediateValidArgs) {
   cmds::VertexAttribI4uivImmediate& cmd =
       *GetImmediateAs<cmds::VertexAttribI4uivImmediate>();
@@ -113,6 +142,8 @@
 
 // TODO(gman): GetProgramInfoCHROMIUM
 
+// TODO(gman): GetUniformBlocksCHROMIUM
+
 // TODO(gman): GetTranslatedShaderSourceANGLE
 // TODO(gman): PostSubBufferCHROMIUM
 // TODO(gman): TexImageIOSurface2DCHROMIUM
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
index 5eda0a9..c0e2364 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
@@ -81,6 +81,47 @@
   EXPECT_EQ(0u, info->num_uniforms);
 }
 
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlocksCHROMIUMValidArgs) {
+  const uint32 kBucketId = 123;
+  GetUniformBlocksCHROMIUM cmd;
+  cmd.Init(client_program_id_, kBucketId);
+  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+      .WillOnce(SetArgPointee<2>(GL_TRUE))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_,
+              GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _))
+      .WillOnce(SetArgPointee<2>(0))
+      .RetiresOnSaturation();
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+  EXPECT_EQ(sizeof(UniformBlocksHeader), bucket->size());
+  UniformBlocksHeader* header =
+      bucket->GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
+  EXPECT_TRUE(header != NULL);
+  EXPECT_EQ(0u, header->num_uniform_blocks);
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlocksCHROMIUMInvalidArgs) {
+  const uint32 kBucketId = 123;
+  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+  EXPECT_TRUE(bucket == NULL);
+  GetUniformBlocksCHROMIUM cmd;
+  cmd.Init(kInvalidClientId, kBucketId);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  bucket = decoder_->GetBucket(kBucketId);
+  ASSERT_TRUE(bucket != NULL);
+  EXPECT_EQ(sizeof(UniformBlocksHeader), bucket->size());
+  UniformBlocksHeader* header =
+      bucket->GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
+  ASSERT_TRUE(header != NULL);
+  EXPECT_EQ(0u, header->num_uniform_blocks);
+}
+
 TEST_P(GLES2DecoderWithShaderTest, GetUniformivSucceeds) {
   GetUniformiv::Result* result =
       static_cast<GetUniformiv::Result*>(shared_memory_address_);
@@ -530,6 +571,116 @@
   EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 }
 
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockNameSucceeds) {
+  const uint32 kBucketId = 123;
+  GetActiveUniformBlockName cmd;
+  typedef GetActiveUniformBlockName::Result Result;
+  Result* result = static_cast<Result*>(shared_memory_address_);
+  *result = 0;
+  cmd.Init(client_program_id_,
+           0,
+           kBucketId,
+           shared_memory_id_,
+           shared_memory_offset_);
+  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+      .WillOnce(SetArgPointee<2>(GL_TRUE))
+      .RetiresOnSaturation();
+  const char kName[] = "HolyCow";
+  const GLsizei kMaxLength = strlen(kName) + 1;
+  EXPECT_CALL(*gl_,
+              GetProgramiv(kServiceProgramId,
+                           GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, _))
+      .WillOnce(SetArgPointee<2>(kMaxLength))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_,
+              GetActiveUniformBlockName(kServiceProgramId, 0, _, _, _))
+      .WillOnce(DoAll(SetArgPointee<3>(strlen(kName)),
+                      SetArrayArgument<4>(kName, kName + strlen(kName) + 1)))
+      .RetiresOnSaturation();
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_NE(0, *result);
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+  ASSERT_TRUE(bucket != NULL);
+  EXPECT_EQ(0,
+            memcmp(bucket->GetData(0, bucket->size()), kName, bucket->size()));
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockNameUnlinkedProgram) {
+  const uint32 kBucketId = 123;
+  GetActiveUniformBlockName cmd;
+  typedef GetActiveUniformBlockName::Result Result;
+  Result* result = static_cast<Result*>(shared_memory_address_);
+  *result = 0;
+  cmd.Init(client_program_id_,
+           0,
+           kBucketId,
+           shared_memory_id_,
+           shared_memory_offset_);
+  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+      .WillOnce(SetArgPointee<2>(GL_FALSE))
+      .RetiresOnSaturation();
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(0, *result);
+  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+       GetActiveUniformBlockNameResultNotInitFails) {
+  const uint32 kBucketId = 123;
+  GetActiveUniformBlockName cmd;
+  typedef GetActiveUniformBlockName::Result Result;
+  Result* result = static_cast<Result*>(shared_memory_address_);
+  *result = 1;
+  cmd.Init(client_program_id_,
+           0,
+           kBucketId,
+           shared_memory_id_,
+           shared_memory_offset_);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockNameBadProgramFails) {
+  const uint32 kBucketId = 123;
+  GetActiveUniformBlockName cmd;
+  typedef GetActiveUniformBlockName::Result Result;
+  Result* result = static_cast<Result*>(shared_memory_address_);
+  *result = 0;
+  cmd.Init(kInvalidClientId,
+           0,
+           kBucketId,
+           shared_memory_id_,
+           shared_memory_offset_);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(0, *result);
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+       GetActiveUniformBlockNameBadSharedMemoryFails) {
+  const uint32 kBucketId = 123;
+  GetActiveUniformBlockName cmd;
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  cmd.Init(client_program_id_,
+           0,
+           kBucketId,
+           kInvalidSharedMemoryId,
+           shared_memory_offset_);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+  cmd.Init(client_program_id_,
+           0,
+           kBucketId,
+           shared_memory_id_,
+           kInvalidSharedMemoryOffset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
 TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribSucceeds) {
   const GLuint kAttribIndex = 1;
   const uint32 kBucketId = 123;
@@ -927,6 +1078,58 @@
   EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 }
 
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlockIndex) {
+  const uint32 kBucketId = 123;
+  const GLuint kIndex = 10;
+  const char* kName = "color";
+  typedef GetUniformBlockIndex::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  SetBucketAsCString(kBucketId, kName);
+  *result = GL_INVALID_INDEX;
+  GetUniformBlockIndex cmd;
+  cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset);
+  EXPECT_CALL(*gl_, GetUniformBlockIndex(kServiceProgramId, StrEq(kName)))
+      .WillOnce(Return(kIndex))
+      .RetiresOnSaturation();
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(kIndex, *result);
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlockIndexInvalidArgs) {
+  const uint32 kBucketId = 123;
+  typedef GetUniformBlockIndex::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  *result = GL_INVALID_INDEX;
+  GetUniformBlockIndex cmd;
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  // Check no bucket
+  cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_INDEX, *result);
+  // Check bad program id.
+  const char* kName = "color";
+  SetBucketAsCString(kBucketId, kName);
+  cmd.Init(kInvalidClientId, kBucketId, kSharedMemoryId, kSharedMemoryOffset);
+  *result = GL_INVALID_INDEX;
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_INDEX, *result);
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+  // Check bad memory
+  cmd.Init(client_program_id_,
+           kBucketId,
+           kInvalidSharedMemoryId,
+           kSharedMemoryOffset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+  cmd.Init(client_program_id_,
+           kBucketId,
+           kSharedMemoryId,
+           kInvalidSharedMemoryOffset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
 TEST_P(GLES2DecoderWithShaderTest, GetUniformLocation) {
   const uint32 kBucketId = 123;
   const char* kNonExistentName = "foobar";
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 7a6556b..5db80b0 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -631,6 +631,10 @@
   QueueTask(task);
 }
 
+void InProcessCommandBuffer::OrderingBarrier(int32 put_offset) {
+  Flush(put_offset);
+}
+
 void InProcessCommandBuffer::WaitForTokenInRange(int32 start, int32 end) {
   CheckSequencedThread();
   while (!InRange(start, end, GetLastToken()) &&
diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h
index ab68f15..3be3602 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.h
+++ b/gpu/command_buffer/service/in_process_command_buffer.h
@@ -92,6 +92,7 @@
   State GetLastState() override;
   int32 GetLastToken() override;
   void Flush(int32 put_offset) override;
+  void OrderingBarrier(int32 put_offset) override;
   void WaitForTokenInRange(int32 start, int32 end) override;
   void WaitForGetOffsetInRange(int32 start, int32 end) override;
   void SetGetBuffer(int32 shm_id) override;
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.cc b/gpu/command_buffer/service/mailbox_manager_sync.cc
index b12e9b4..4f24bd7 100644
--- a/gpu/command_buffer/service/mailbox_manager_sync.cc
+++ b/gpu/command_buffer/service/mailbox_manager_sync.cc
@@ -59,7 +59,7 @@
       sync_points.pop();
     }
     // Need to use EGL fences since we are likely not in a single share group.
-    linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
+    linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL));
     if (fence.get()) {
       std::pair<SyncPointToFenceMap::iterator, bool> result =
           sync_point_to_fence.insert(std::make_pair(sync_point, fence));
diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc
index 4bf16e3..1e8e11b 100644
--- a/gpu/command_buffer/service/memory_program_cache.cc
+++ b/gpu/command_buffer/service/memory_program_cache.cc
@@ -180,12 +180,12 @@
     const ShaderCacheCallback& shader_callback) {
   char a_sha[kHashLength];
   char b_sha[kHashLength];
-  DCHECK(shader_a && !shader_a->signature_source().empty() &&
-         shader_b && !shader_b->signature_source().empty());
+  DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
+         shader_b && !shader_b->last_compiled_source().empty());
   ComputeShaderHash(
-      shader_a->signature_source(), translator_a, a_sha);
+      shader_a->last_compiled_source(), translator_a, a_sha);
   ComputeShaderHash(
-      shader_b->signature_source(), translator_b, b_sha);
+      shader_b->last_compiled_source(), translator_b, b_sha);
 
   char sha[kHashLength];
   ComputeProgramHash(a_sha,
@@ -256,12 +256,12 @@
 
   char a_sha[kHashLength];
   char b_sha[kHashLength];
-  DCHECK(shader_a && !shader_a->signature_source().empty() &&
-         shader_b && !shader_b->signature_source().empty());
+  DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
+         shader_b && !shader_b->last_compiled_source().empty());
   ComputeShaderHash(
-      shader_a->signature_source(), translator_a, a_sha);
+      shader_a->last_compiled_source(), translator_a, a_sha);
   ComputeShaderHash(
-      shader_b->signature_source(), translator_b, b_sha);
+      shader_b->last_compiled_source(), translator_b, b_sha);
 
   char sha[kHashLength];
   ComputeProgramHash(a_sha,
diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc
index 7c39028..8f8c430 100644
--- a/gpu/command_buffer/service/memory_program_cache_unittest.cc
+++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc
@@ -196,9 +196,9 @@
                                        base::Unretained(this)));
 
   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
-      vertex_shader_->signature_source(),
+      vertex_shader_->last_compiled_source(),
       NULL,
-      fragment_shader_->signature_source(),
+      fragment_shader_->last_compiled_source(),
       NULL,
       NULL));
   EXPECT_EQ(1, shader_cache_count());
@@ -221,9 +221,9 @@
                                        base::Unretained(this)));
 
   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
-      vertex_shader_->signature_source(),
+      vertex_shader_->last_compiled_source(),
       NULL,
-      fragment_shader_->signature_source(),
+      fragment_shader_->last_compiled_source(),
       NULL,
       NULL));
   EXPECT_EQ(1, shader_cache_count());
@@ -232,9 +232,9 @@
 
   cache_->LoadProgram(shader_cache_shader());
   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
-      vertex_shader_->signature_source(),
+      vertex_shader_->last_compiled_source(),
       NULL,
-      fragment_shader_->signature_source(),
+      fragment_shader_->last_compiled_source(),
       NULL,
       NULL));
 }
@@ -396,7 +396,7 @@
                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
                                        base::Unretained(this)));
 
-  const std::string vertex_orig_source = vertex_shader_->signature_source();
+  const std::string vertex_orig_source = vertex_shader_->last_compiled_source();
   vertex_shader_->set_source("different!");
   TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
@@ -488,7 +488,7 @@
   const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1;
 
   // save old source and modify for new program
-  const std::string& old_source = fragment_shader_->signature_source();
+  const std::string& old_source = fragment_shader_->last_compiled_source();
   fragment_shader_->set_source("al sdfkjdk");
   TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
 
@@ -512,15 +512,15 @@
                                        base::Unretained(this)));
 
   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
-      vertex_shader_->signature_source(),
+      vertex_shader_->last_compiled_source(),
       NULL,
-      fragment_shader_->signature_source(),
+      fragment_shader_->last_compiled_source(),
       NULL,
       NULL));
   EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
       old_source,
       NULL,
-      fragment_shader_->signature_source(),
+      fragment_shader_->last_compiled_source(),
       NULL,
       NULL));
 }
@@ -543,9 +543,9 @@
                                        base::Unretained(this)));
 
   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
-      vertex_shader_->signature_source(),
+      vertex_shader_->last_compiled_source(),
       NULL,
-      fragment_shader_->signature_source(),
+      fragment_shader_->last_compiled_source(),
       NULL,
       NULL));
 }
@@ -567,9 +567,9 @@
                                        base::Unretained(this)));
 
   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
-      vertex_shader_->signature_source(),
+      vertex_shader_->last_compiled_source(),
       NULL,
-      fragment_shader_->signature_source(),
+      fragment_shader_->last_compiled_source(),
       NULL,
       NULL));
 
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index d866504..1f6b2d4 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -562,12 +562,12 @@
   bool link = true;
   ProgramCache* cache = manager_->program_cache_;
   if (cache) {
-    DCHECK(!attached_shaders_[0]->signature_source().empty() &&
-           !attached_shaders_[1]->signature_source().empty());
+    DCHECK(!attached_shaders_[0]->last_compiled_source().empty() &&
+           !attached_shaders_[1]->last_compiled_source().empty());
     ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
-        attached_shaders_[0]->signature_source(),
+        attached_shaders_[0]->last_compiled_source(),
         vertex_translator,
-        attached_shaders_[1]->signature_source(),
+        attached_shaders_[1]->last_compiled_source(),
         fragment_translator,
         &bind_attrib_location_map_);
 
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc
index 2707b90..90b1576 100644
--- a/gpu/command_buffer/service/shader_manager.cc
+++ b/gpu/command_buffer/service/shader_manager.cc
@@ -26,6 +26,7 @@
 
 Shader::Shader(GLuint service_id, GLenum shader_type)
       : use_count_(0),
+        shader_state_(kShaderStateWaiting),
         service_id_(service_id),
         shader_type_(shader_type),
         valid_(false) {
@@ -34,13 +35,28 @@
 Shader::~Shader() {
 }
 
+void Shader::RequestCompile() {
+  shader_state_ = kShaderStateCompileRequested;
+  last_compiled_source_ = source_;
+}
+
 void Shader::DoCompile(ShaderTranslatorInterface* translator,
                        TranslatedShaderSourceType type) {
+  // We require that RequestCompile() must be called before DoCompile(),
+  // so we can return early if the shader state is not what we expect.
+  if (shader_state_ != kShaderStateCompileRequested) {
+    return;
+  }
+
+  // Signify the shader has been compiled, whether or not it is valid
+  // is dependent on the |valid_| member variable.
+  shader_state_ = kShaderStateCompiled;
+
   // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
   // glShaderSource and then glCompileShader.
-  const char* source_for_driver = source_.c_str();
+  const char* source_for_driver = last_compiled_source_.c_str();
   if (translator) {
-    valid_ = translator->Translate(source_,
+    valid_ = translator->Translate(last_compiled_source_,
                                    &log_info_,
                                    &translated_source_,
                                    &attrib_map_,
@@ -50,7 +66,6 @@
     if (!valid_) {
       return;
     }
-    signature_source_ = source_;
     source_for_driver = translated_source_.c_str();
   }
 
@@ -61,13 +76,14 @@
     glGetShaderiv(service_id_,
                   GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
                   &max_len);
-    scoped_ptr<char[]> buffer(new char[max_len]);
+    translated_source_.resize(max_len);
     GLint len = 0;
     glGetTranslatedShaderSourceANGLE(
-        service_id_, max_len, &len, buffer.get());
+        service_id_, translated_source_.size(),
+        &len, &translated_source_.at(0));
     DCHECK(max_len == 0 || len < max_len);
-    DCHECK(len == 0 || buffer[len] == '\0');
-    translated_source_ = std::string(buffer.get(), len);
+    DCHECK(len == 0 || translated_source_[len] == '\0');
+    translated_source_.resize(len);
   }
 
   GLint status = GL_FALSE;
@@ -78,17 +94,17 @@
     // All translated shaders must compile.
     GLint max_len = 0;
     glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
-    scoped_ptr<char[]> buffer(new char[max_len]);
+    log_info_.resize(max_len);
     GLint len = 0;
-    glGetShaderInfoLog(service_id_, max_len, &len, buffer.get());
+    glGetShaderInfoLog(service_id_, log_info_.size(), &len, &log_info_.at(0));
     DCHECK(max_len == 0 || len < max_len);
-    DCHECK(len == 0 || buffer[len] == '\0');
+    DCHECK(len == 0 || log_info_[len] == '\0');
     valid_ = false;
-    log_info_ = std::string(buffer.get(), len);
+    log_info_.resize(len);
     LOG_IF(ERROR, translator)
         << "Shader translator allowed/produced an invalid shader "
         << "unless the driver is buggy:"
-        << "\n--original-shader--\n" << source_
+        << "\n--original-shader--\n" << last_compiled_source_
         << "\n--translated-shader--\n" << source_for_driver
         << "\n--info-log--\n" << log_info_;
   }
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index c726767..11f567d 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -29,9 +29,21 @@
     kGL,  // GL or GLES
   };
 
+  enum ShaderState {
+    kShaderStateWaiting,
+    kShaderStateCompileRequested,
+    kShaderStateCompiled, // Signifies compile happened, not valid compile.
+  };
+
+  void RequestCompile();
+
   void DoCompile(ShaderTranslatorInterface* translator,
                  TranslatedShaderSourceType type);
 
+  ShaderState shader_state() const {
+    return shader_state_;
+  }
+
   GLuint service_id() const {
     return service_id_;
   }
@@ -52,8 +64,8 @@
     return translated_source_;
   }
 
-  const std::string& signature_source() const {
-    return signature_source_;
+  const std::string& last_compiled_source() const {
+    return last_compiled_source_;
   }
 
   const sh::Attribute* GetAttribInfo(const std::string& name) const;
@@ -73,7 +85,7 @@
   }
 
   bool valid() const {
-    return valid_;
+    return shader_state_ == kShaderStateCompiled && valid_;
   }
 
   bool IsDeleted() const {
@@ -131,8 +143,12 @@
 
   int use_count_;
 
+  // The current state of the shader.
+  ShaderState shader_state_;
+
   // The shader this Shader is tracking.
   GLuint service_id_;
+
   // Type of shader - GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
   GLenum shader_type_;
 
@@ -143,7 +159,7 @@
   std::string source_;
 
   // The source the last compile used.
-  std::string signature_source_;
+  std::string last_compiled_source_;
 
   // The translated shader source.
   std::string translated_source_;
diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc
index 4218d50..f5f6206 100644
--- a/gpu/command_buffer/service/shader_manager_unittest.cc
+++ b/gpu/command_buffer/service/shader_manager_unittest.cc
@@ -127,16 +127,30 @@
   EXPECT_FALSE(shader1->InUse());
   EXPECT_TRUE(shader1->source().empty());
   EXPECT_TRUE(shader1->log_info().empty());
-  EXPECT_TRUE(shader1->signature_source().empty());
+  EXPECT_TRUE(shader1->last_compiled_source().empty());
   EXPECT_TRUE(shader1->translated_source().empty());
   EXPECT_EQ(0u, shader1->attrib_map().size());
   EXPECT_EQ(0u, shader1->uniform_map().size());
   EXPECT_EQ(0u, shader1->varying_map().size());
+  EXPECT_EQ(Shader::kShaderStateWaiting, shader1->shader_state());
 
   // Check we can set its source.
   shader1->set_source(kClient1Source);
   EXPECT_STREQ(kClient1Source, shader1->source().c_str());
-  EXPECT_TRUE(shader1->signature_source().empty());
+  EXPECT_TRUE(shader1->last_compiled_source().empty());
+
+  // Check that DoCompile() will not work if RequestCompile() was not called.
+  MockShaderTranslator translator;
+  shader1->DoCompile(&translator, Shader::kANGLE);
+  EXPECT_EQ(Shader::kShaderStateWaiting, shader1->shader_state());
+  EXPECT_FALSE(shader1->valid());
+
+  // Check RequestCompile() will update the state and last compiled source, but
+  // still keep the actual compile state invalid.
+  shader1->RequestCompile();
+  EXPECT_EQ(Shader::kShaderStateCompileRequested, shader1->shader_state());
+  EXPECT_STREQ(kClient1Source, shader1->last_compiled_source().c_str());
+  EXPECT_FALSE(shader1->valid());
 
   // Check DoCompile() will set compilation states, log, translated source,
   // shader variables, and name mapping.
@@ -168,7 +182,7 @@
   EXPECT_TRUE(shader1->valid());
   // When compilation succeeds, no log is recorded.
   EXPECT_STREQ("", shader1->log_info().c_str());
-  EXPECT_STREQ(kClient1Source, shader1->signature_source().c_str());
+  EXPECT_STREQ(kClient1Source, shader1->last_compiled_source().c_str());
   EXPECT_STREQ(kTranslatedSource.c_str(), shader1->translated_source().c_str());
 
   // Check varying infos got copied.
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc
index 878490c..98d738d 100644
--- a/gpu/command_buffer/service/shader_translator.cc
+++ b/gpu/command_buffer/service/shader_translator.cc
@@ -123,7 +123,6 @@
     compiler_ = ShConstructCompiler(
         shader_type, shader_spec, shader_output, resources);
   }
-  compiler_options_ = *resources;
   implementation_is_glsl_es_ = (glsl_implementation_type == kGlslES);
   driver_bug_workarounds_ = driver_bug_workarounds;
   return compiler_ != NULL;
diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h
index 6075896..ef25ebb 100644
--- a/gpu/command_buffer/service/shader_translator.h
+++ b/gpu/command_buffer/service/shader_translator.h
@@ -110,7 +110,6 @@
   int GetCompileOptions() const;
 
   ShHandle compiler_;
-  ShBuiltInResources compiler_options_;
   bool implementation_is_glsl_es_;
   ShCompileOptions driver_bug_workarounds_;
   ObserverList<DestructionObserver> destruction_observers_;
diff --git a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc
index 621e6a1..174edaa 100644
--- a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc
+++ b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc
@@ -23,23 +23,23 @@
               const base::Closure& release_callback);
 
   // implement gfx::GLImage
-  virtual void Destroy(bool have_context) override;
-  virtual gfx::Size GetSize() override;
-  virtual bool BindTexImage(unsigned target) override;
-  virtual void ReleaseTexImage(unsigned target) override;
-  virtual bool CopyTexImage(unsigned target) override;
-  virtual void WillUseTexImage() override;
-  virtual void DidUseTexImage() override {}
-  virtual void WillModifyTexImage() override {}
-  virtual void DidModifyTexImage() override {}
-  virtual bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
-                                    int z_order,
-                                    gfx::OverlayTransform transform,
-                                    const gfx::Rect& bounds_rect,
-                                    const gfx::RectF& crop_rect) override;
+  void Destroy(bool have_context) override;
+  gfx::Size GetSize() override;
+  bool BindTexImage(unsigned target) override;
+  void ReleaseTexImage(unsigned target) override;
+  bool CopyTexImage(unsigned target) override;
+  void WillUseTexImage() override;
+  void DidUseTexImage() override {}
+  void WillModifyTexImage() override {}
+  void DidModifyTexImage() override {}
+  bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+                            int z_order,
+                            gfx::OverlayTransform transform,
+                            const gfx::Rect& bounds_rect,
+                            const gfx::RectF& crop_rect) override;
 
  private:
-  virtual ~GLImageImpl();
+  ~GLImageImpl() override;
 
   scoped_refptr<gfx::SurfaceTexture> surface_texture_;
   base::Closure release_callback_;
diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc
index 550e0cd..6cd0acf 100644
--- a/gpu/command_buffer/service/test_helper.cc
+++ b/gpu/command_buffer/service/test_helper.cc
@@ -790,6 +790,7 @@
         .WillOnce(SetArgumentPointee<2>(GL_TRUE))
         .RetiresOnSaturation();
   }
+  shader->RequestCompile();
   shader->DoCompile(&translator, Shader::kGL);
 }
 
diff --git a/gpu/command_buffer/tests/gl_program_unittest.cc b/gpu/command_buffer/tests/gl_program_unittest.cc
index aec95b2..186b28b 100644
--- a/gpu/command_buffer/tests/gl_program_unittest.cc
+++ b/gpu/command_buffer/tests/gl_program_unittest.cc
@@ -121,6 +121,35 @@
   GLTestHelper::CheckGLError("no errors", __LINE__);
 }
 
+TEST_F(GLProgramTest, ShaderLengthSpecified) {
+  const std::string valid_shader_str = SHADER(
+      attribute vec4 a_position;
+      void main()
+      {
+         gl_Position = a_position;
+      }
+  );
+
+  const std::string invalid_shader = valid_shader_str + "invalid suffix";
+
+  // Compiling invalid program should fail.
+  const char* invalid_shader_strings[] = { invalid_shader.c_str() };
+  GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+  glShaderSource(vs, 1, invalid_shader_strings, NULL);
+  glCompileShader(vs);
+
+  GLint compile_state = 0;
+  glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_state);
+  EXPECT_EQ(GL_FALSE, compile_state);
+
+  // Compiling program cutting off invalid parts should succeed.
+  const GLint lengths[] = { valid_shader_str.length() };
+  glShaderSource(vs, 1, invalid_shader_strings, lengths);
+  glCompileShader(vs);
+  glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_state);
+  EXPECT_EQ(GL_TRUE, compile_state);
+}
+
 TEST_F(GLProgramTest, UniformsInCurrentProgram) {
   static const char* v_shader_str = SHADER(
       attribute vec4 a_position;
diff --git a/gpu/command_buffer/tests/gl_unittests_android.cc b/gpu/command_buffer/tests/gl_unittests_android.cc
index d3517a6..9bdd503 100644
--- a/gpu/command_buffer/tests/gl_unittests_android.cc
+++ b/gpu/command_buffer/tests/gl_unittests_android.cc
@@ -22,13 +22,9 @@
 
 class GLSurfaceTextureTest : public testing::Test {
  protected:
-  virtual void SetUp() override {
-    gl_.Initialize(GLManager::Options());
-  }
+  void SetUp() override { gl_.Initialize(GLManager::Options()); }
 
-  virtual void TearDown() override {
-    gl_.Destroy();
-  }
+  void TearDown() override { gl_.Destroy(); }
 
   GLManager gl_;
 };
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 26be952..382bcba 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
 {
   "name": "gpu driver bug list",
   // Please update the version number whenever you change this file.
-  "version": "7.14",
+  "version": "7.15",
   "entries": [
     {
       "id": 1,
@@ -1118,6 +1118,22 @@
       "features": [
         "use_non_zero_size_for_client_side_stream_buffers"
       ]
+    },
+    {
+      "id": 99,
+      "description": "Qualcomm driver before Lollipop deletes egl sync objects after context destruction",
+      "cr_bugs": [453857],
+      "os": {
+        "type": "android",
+        "version": {
+          "op": "<",
+          "value": "5.0.0"
+        }
+      },
+      "gl_vendor": "Qualcomm.*",
+      "features": [
+        "ignore_egl_sync_failures"
+      ]
     }
   ]
 }
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 77d721b..f03b7a2 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -58,6 +58,8 @@
          gl_begin_gl_end_on_fbo_change_to_backbuffer)        \
   GPU_OP(GL_CLEAR_BROKEN,                                    \
          gl_clear_broken)                                    \
+  GPU_OP(IGNORE_EGL_SYNC_FAILURES,                           \
+         ignore_egl_sync_failures)                           \
   GPU_OP(INIT_GL_POSITION_IN_VERTEX_SHADER,                  \
          init_gl_position_in_vertex_shader)                  \
   GPU_OP(INIT_TEXTURE_MAX_ANISOTROPY,                        \
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc
index 04f66fa..a5686a9 100644
--- a/gpu/config/gpu_info_collector_win.cc
+++ b/gpu/config/gpu_info_collector_win.cc
@@ -8,6 +8,7 @@
 #include "third_party/re2/re2/re2.h"
 
 #include <windows.h>
+#include <cfgmgr32.h>
 #include <d3d9.h>
 #include <d3d11.h>
 #include <dxgi.h>
@@ -363,6 +364,24 @@
       base::Bind(CollectD3D11SupportOnWorkerThread),
       false);
 }
+
+void DeviceIDToVendorAndDevice(const std::wstring& id,
+                               uint32* vendor_id,
+                               uint32* device_id) {
+  *vendor_id = 0;
+  *device_id = 0;
+  if (id.length() < 21)
+    return;
+  base::string16 vendor_id_string = id.substr(8, 4);
+  base::string16 device_id_string = id.substr(17, 4);
+  int vendor = 0;
+  int device = 0;
+  base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor);
+  base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device);
+  *vendor_id = vendor;
+  *device_id = device;
+}
+
 }  // namespace anonymous
 
 #if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD)
@@ -380,17 +399,35 @@
                                        GPUInfo* gpu_info) {
   TRACE_EVENT0("gpu", "CollectDriverInfoD3D");
 
+  // Display adapter class GUID from
+  // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
+  GUID display_class = {0x4d36e968,
+                        0xe325,
+                        0x11ce,
+                        {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
+
   // create device info for the display device
-  HDEVINFO device_info = SetupDiGetClassDevsW(
-      NULL, device_id.c_str(), NULL,
-      DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
+  HDEVINFO device_info =
+      SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT);
   if (device_info == INVALID_HANDLE_VALUE) {
     LOG(ERROR) << "Creating device info failed";
     return kCollectInfoNonFatalFailure;
   }
 
+  struct GPUDriver {
+    GPUInfo::GPUDevice device;
+    std::string driver_vendor;
+    std::string driver_version;
+    std::string driver_date;
+  };
+
+  std::vector<GPUDriver> drivers;
+
+  int primary_device = -1;
+  bool found_amd = false;
+  bool found_intel = false;
+
   DWORD index = 0;
-  bool found = false;
   SP_DEVINFO_DATA device_info_data;
   device_info_data.cbSize = sizeof(device_info_data);
   while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) {
@@ -429,35 +466,85 @@
         result = RegQueryValueExW(
             key, L"ProviderName", NULL, NULL,
             reinterpret_cast<LPBYTE>(value), &dwcb_data);
-        if (result == ERROR_SUCCESS) {
+        if (result == ERROR_SUCCESS)
           driver_vendor = base::UTF16ToASCII(std::wstring(value));
-          if (driver_vendor == "Advanced Micro Devices, Inc." ||
-              driver_vendor == "ATI Technologies Inc.") {
-            // We are conservative and assume that in the absence of a clear
-            // signal the videocard is assumed to be switchable. Additionally,
-            // some switchable systems with Intel GPUs aren't correctly
-            // detected, so always count them.
-            GetAMDVideocardInfo(gpu_info);
-            if (!gpu_info->amd_switchable &&
-                gpu_info->gpu.vendor_id == 0x8086) {
-              gpu_info->amd_switchable = true;
-              gpu_info->secondary_gpus.push_back(gpu_info->gpu);
-              gpu_info->gpu.vendor_id = 0x1002;
-              gpu_info->gpu.device_id = 0;  // Unknown discrete AMD GPU.
-            }
-          }
+
+        wchar_t new_device_id[MAX_DEVICE_ID_LEN];
+        CONFIGRET status = CM_Get_Device_ID(
+            device_info_data.DevInst, new_device_id, MAX_DEVICE_ID_LEN, 0);
+
+        if (status == CR_SUCCESS) {
+          GPUDriver driver;
+
+          driver.driver_vendor = driver_vendor;
+          driver.driver_version = driver_version;
+          driver.driver_date = driver_date;
+          std::wstring id = new_device_id;
+
+          if (id.compare(0, device_id.size(), device_id) == 0)
+            primary_device = drivers.size();
+
+          uint32 vendor_id = 0, device_id = 0;
+          DeviceIDToVendorAndDevice(id, &vendor_id, &device_id);
+          driver.device.vendor_id = vendor_id;
+          driver.device.device_id = device_id;
+          drivers.push_back(driver);
+
+          if (vendor_id == 0x8086)
+            found_intel = true;
+          if (vendor_id == 0x1002)
+            found_amd = true;
         }
 
-        gpu_info->driver_vendor = driver_vendor;
-        gpu_info->driver_version = driver_version;
-        gpu_info->driver_date = driver_date;
-        found = true;
         RegCloseKey(key);
-        break;
       }
     }
   }
   SetupDiDestroyDeviceInfoList(device_info);
+  bool found = false;
+  if (found_amd && found_intel) {
+    // AMD Switchable system found.
+    for (const auto& driver : drivers) {
+      if (driver.device.vendor_id == 0x8086) {
+        gpu_info->gpu = driver.device;
+      }
+
+      if (driver.device.vendor_id == 0x1002) {
+        gpu_info->driver_vendor = driver.driver_vendor;
+        gpu_info->driver_version = driver.driver_version;
+        gpu_info->driver_date = driver.driver_date;
+      }
+    }
+    GetAMDVideocardInfo(gpu_info);
+
+    if (!gpu_info->amd_switchable) {
+      // Some machines aren't properly detected as AMD switchable, but count
+      // them anyway.
+      gpu_info->amd_switchable = true;
+      for (const auto& driver : drivers) {
+        if (driver.device.vendor_id == 0x1002) {
+          gpu_info->gpu = driver.device;
+        } else {
+          gpu_info->secondary_gpus.push_back(driver.device);
+        }
+      }
+    }
+    found = true;
+  } else {
+    for (size_t i = 0; i < drivers.size(); ++i) {
+      const GPUDriver& driver = drivers[i];
+      if (static_cast<int>(i) == primary_device) {
+        found = true;
+        gpu_info->gpu = driver.device;
+        gpu_info->driver_vendor = driver.driver_vendor;
+        gpu_info->driver_version = driver.driver_version;
+        gpu_info->driver_date = driver.driver_date;
+      } else {
+        gpu_info->secondary_gpus.push_back(driver.device);
+      }
+    }
+  }
+
   return found ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
 }
 
@@ -551,13 +638,7 @@
   }
 
   if (id.length() > 20) {
-    int vendor = 0, device = 0;
-    std::wstring vendor_string = id.substr(8, 4);
-    std::wstring device_string = id.substr(17, 4);
-    base::HexStringToInt(base::UTF16ToASCII(vendor_string), &vendor);
-    base::HexStringToInt(base::UTF16ToASCII(device_string), &device);
-    *vendor_id = vendor;
-    *device_id = device;
+    DeviceIDToVendorAndDevice(id, vendor_id, device_id);
     if (*vendor_id != 0 && *device_id != 0)
       return kCollectInfoSuccess;
   }
@@ -609,13 +690,8 @@
     return kCollectInfoNonFatalFailure;
   }
 
-  int vendor_id = 0, device_id = 0;
-  base::string16 vendor_id_string = id.substr(8, 4);
-  base::string16 device_id_string = id.substr(17, 4);
-  base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor_id);
-  base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device_id);
-  gpu_info->gpu.vendor_id = vendor_id;
-  gpu_info->gpu.device_id = device_id;
+  DeviceIDToVendorAndDevice(id, &gpu_info->gpu.vendor_id,
+                            &gpu_info->gpu.device_id);
   // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
   if (!CollectDriverInfoD3D(id, gpu_info)) {
     gpu_info->basic_info_state = kCollectInfoNonFatalFailure;
diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
index b822056..93afd1a 100644
--- a/gpu/config/software_rendering_list_json.cc
+++ b/gpu/config/software_rendering_list_json.cc
@@ -18,7 +18,7 @@
 {
   "name": "software rendering list",
   // Please update the version number whenever you change this file.
-  "version": "9.16",
+  "version": "9.17",
   "entries": [
     {
       "id": 1,
@@ -621,22 +621,6 @@
       ]
     },
     {
-      "id": 62,
-      "description": "Accelerated 2D canvas buggy on old Qualcomm Adreno",
-      "cr_bugs": [161575],
-      "os": {
-        "type": "android"
-      },
-      "gl_renderer": ".*Adreno.*",
-      "driver_version": {
-        "op": "<",
-        "value": "4.1"
-      },
-      "features": [
-        "accelerated_2d_canvas"
-      ]
-    },
-    {
       "id": 64,
       "description": "Hardware video decode is only supported in win7+",
       "cr_bugs": [159458],
@@ -1035,7 +1019,7 @@
     },
     {
       "id": 96,
-      "description": "GPU rasterization whitelist",
+      "description": "Blacklist GPU raster/canvas on all except known good GPUs and newer Android releases",
       "cr_bugs": [362779,424970],
       "os": {
         "type": "android"
@@ -1090,7 +1074,8 @@
         }
       ],
       "features": [
-        "gpu_rasterization"
+        "gpu_rasterization",
+        "accelerated_2d_canvas"
       ]
     },
     {
@@ -1110,11 +1095,15 @@
     },
     {
       "id": 100,
-      "description": "GPU rasterization is blacklisted on Nexus 10",
+      "description": "GPU rasterization and canvas is blacklisted on Nexus 10",
       "cr_bugs": [407144],
+      "os": {
+        "type": "android"
+      },
       "gl_renderer": ".*Mali-T604.*",
       "features": [
-        "gpu_rasterization"
+        "gpu_rasterization",
+        "accelerated_2d_canvas"
       ]
     },
     {
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 138d858..73a1059 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -178,6 +178,7 @@
         'command_buffer/client/fenced_allocator_test.cc',
         'command_buffer/client/gles2_implementation_unittest.cc',
         'command_buffer/client/mapped_memory_unittest.cc',
+        'command_buffer/client/program_info_manager_unittest.cc',
         'command_buffer/client/query_tracker_unittest.cc',
         'command_buffer/client/ring_buffer_test.cc',
         'command_buffer/client/transfer_buffer_unittest.cc',
diff --git a/gpu/gpu_unittests.isolate b/gpu/gpu_unittests.isolate
index 3380606..48fb1c5 100644
--- a/gpu/gpu_unittests.isolate
+++ b/gpu/gpu_unittests.isolate
@@ -21,6 +21,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
         'files': [
           '../testing/xvfb.py',
@@ -37,6 +39,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
       },
     }],
@@ -49,6 +53,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
       },
     }],
diff --git a/gpu/ipc/gpu_command_buffer_traits_multi.h b/gpu/ipc/gpu_command_buffer_traits_multi.h
index 8201f32..2f834a0 100644
--- a/gpu/ipc/gpu_command_buffer_traits_multi.h
+++ b/gpu/ipc/gpu_command_buffer_traits_multi.h
@@ -42,6 +42,9 @@
   IPC_STRUCT_TRAITS_MEMBER(num_compressed_texture_formats)
   IPC_STRUCT_TRAITS_MEMBER(num_shader_binary_formats)
   IPC_STRUCT_TRAITS_MEMBER(bind_generates_resource_chromium)
+  IPC_STRUCT_TRAITS_MEMBER(max_transform_feedback_separate_attribs)
+  IPC_STRUCT_TRAITS_MEMBER(max_uniform_buffer_bindings)
+  IPC_STRUCT_TRAITS_MEMBER(uniform_buffer_offset_alignment)
   IPC_STRUCT_TRAITS_MEMBER(post_sub_buffer)
   IPC_STRUCT_TRAITS_MEMBER(egl_image_external)
   IPC_STRUCT_TRAITS_MEMBER(texture_format_bgra8888)
diff --git a/mojo/common/trace_controller_impl.cc b/mojo/common/trace_controller_impl.cc
index 098dfb3..4409b30 100644
--- a/mojo/common/trace_controller_impl.cc
+++ b/mojo/common/trace_controller_impl.cc
@@ -4,7 +4,7 @@
 
 #include "mojo/common/trace_controller_impl.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "mojo/public/cpp/application/application_connection.h"
 #include "mojo/public/cpp/application/application_impl.h"
 
diff --git a/mojo/common/tracing_impl.cc b/mojo/common/tracing_impl.cc
index 9c4c276..3ef474c 100644
--- a/mojo/common/tracing_impl.cc
+++ b/mojo/common/tracing_impl.cc
@@ -4,7 +4,7 @@
 
 #include "mojo/common/tracing_impl.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "mojo/common/trace_controller_impl.h"
 #include "mojo/public/cpp/application/application_connection.h"
 #include "mojo/public/cpp/application/application_impl.h"
diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc
index e8d3690..494ff3d 100644
--- a/mojo/gles2/command_buffer_client_impl.cc
+++ b/mojo/gles2/command_buffer_client_impl.cc
@@ -180,6 +180,11 @@
   command_buffer_->Flush(put_offset);
 }
 
+void CommandBufferClientImpl::OrderingBarrier(int32_t put_offset) {
+  // TODO(jamesr): Implement this more efficiently.
+  Flush(put_offset);
+}
+
 void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
   TryUpdateState();
   while (!InRange(start, end, last_state_.token) &&
diff --git a/mojo/gles2/command_buffer_client_impl.h b/mojo/gles2/command_buffer_client_impl.h
index dcedb52..6bcacb2 100644
--- a/mojo/gles2/command_buffer_client_impl.h
+++ b/mojo/gles2/command_buffer_client_impl.h
@@ -42,14 +42,15 @@
   // CommandBuffer implementation:
   bool Initialize() override;
   State GetLastState() override;
-  int32 GetLastToken() override;
-  void Flush(int32 put_offset) override;
-  void WaitForTokenInRange(int32 start, int32 end) override;
-  void WaitForGetOffsetInRange(int32 start, int32 end) override;
-  void SetGetBuffer(int32 shm_id) override;
+  int32_t GetLastToken() override;
+  void Flush(int32_t put_offset) override;
+  void OrderingBarrier(int32_t put_offset) override;
+  void WaitForTokenInRange(int32_t start, int32_t end) override;
+  void WaitForGetOffsetInRange(int32_t start, int32_t end) override;
+  void SetGetBuffer(int32_t shm_id) override;
   scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
-                                                  int32* id) override;
-  void DestroyTransferBuffer(int32 id) override;
+                                                  int32_t* id) override;
+  void DestroyTransferBuffer(int32_t id) override;
 
   // gpu::GpuControl implementation:
   gpu::Capabilities GetCapabilities() override;
@@ -96,8 +97,8 @@
   State last_state_;
   mojo::ScopedSharedBufferHandle shared_state_handle_;
   gpu::CommandBufferSharedState* shared_state_;
-  int32 last_put_offset_;
-  int32 next_transfer_buffer_id_;
+  int32_t last_put_offset_;
+  int32_t next_transfer_buffer_id_;
 
   const MojoAsyncWaiter* async_waiter_;
 };
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc
index 0a109b8..d1ad338 100644
--- a/net/android/network_change_notifier_android.cc
+++ b/net/android/network_change_notifier_android.cc
@@ -77,20 +77,16 @@
                          // We're only interested in tunnel interface changes.
                          base::Bind(NotifyNetworkChangeNotifierObservers)) {}
 
-  virtual ~DnsConfigServiceThread() {
-    Stop();
-  }
+  ~DnsConfigServiceThread() override { Stop(); }
 
-  virtual void Init() override {
+  void Init() override {
     address_tracker_.Init();
     dns_config_service_ = DnsConfigService::CreateSystemService();
     dns_config_service_->WatchConfig(
         base::Bind(&NetworkChangeNotifier::SetDnsConfig));
   }
 
-  virtual void CleanUp() override {
-    dns_config_service_.reset();
-  }
+  void CleanUp() override { dns_config_service_.reset(); }
 
   static void NotifyNetworkChangeNotifierObservers() {
     NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
diff --git a/net/android/network_change_notifier_android.h b/net/android/network_change_notifier_android.h
index 0d90a56..f6d43d0 100644
--- a/net/android/network_change_notifier_android.h
+++ b/net/android/network_change_notifier_android.h
@@ -42,17 +42,17 @@
     : public NetworkChangeNotifier,
       public NetworkChangeNotifierDelegateAndroid::Observer {
  public:
-  virtual ~NetworkChangeNotifierAndroid();
+  ~NetworkChangeNotifierAndroid() override;
 
   // NetworkChangeNotifier:
-  virtual ConnectionType GetCurrentConnectionType() const override;
+  ConnectionType GetCurrentConnectionType() const override;
   // Requires ACCESS_WIFI_STATE permission in order to provide precise WiFi link
   // speed.
-  virtual double GetCurrentMaxBandwidth() const override;
+  double GetCurrentMaxBandwidth() const override;
 
   // NetworkChangeNotifierDelegateAndroid::Observer:
-  virtual void OnConnectionTypeChanged() override;
-  virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps) override;
+  void OnConnectionTypeChanged() override;
+  void OnMaxBandwidthChanged(double max_bandwidth_mbps) override;
 
   static bool Register(JNIEnv* env);
 
diff --git a/net/android/network_change_notifier_android_unittest.cc b/net/android/network_change_notifier_android_unittest.cc
index 54e5583..83dd70e 100644
--- a/net/android/network_change_notifier_android_unittest.cc
+++ b/net/android/network_change_notifier_android_unittest.cc
@@ -25,11 +25,9 @@
       : type_notifications_count_(0), max_bandwidth_notifications_count_(0) {}
 
   // NetworkChangeNotifierDelegateAndroid::Observer:
-  virtual void OnConnectionTypeChanged() override {
-    type_notifications_count_++;
-  }
+  void OnConnectionTypeChanged() override { type_notifications_count_++; }
 
-  virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps) override {
+  void OnMaxBandwidthChanged(double max_bandwidth_mbps) override {
     max_bandwidth_notifications_count_++;
   }
 
@@ -49,7 +47,7 @@
   NetworkChangeNotifierObserver() : notifications_count_(0) {}
 
   // NetworkChangeNotifier::Observer:
-  virtual void OnConnectionTypeChanged(
+  void OnConnectionTypeChanged(
       NetworkChangeNotifier::ConnectionType connection_type) override {
     notifications_count_++;
   }
@@ -68,7 +66,7 @@
  protected:
   typedef NetworkChangeNotifier::ConnectionType ConnectionType;
 
-  virtual ~BaseNetworkChangeNotifierAndroidTest() {}
+  ~BaseNetworkChangeNotifierAndroidTest() override {}
 
   void RunTest(
       const base::Callback<int(void)>& notifications_count_getter,
@@ -148,7 +146,7 @@
     delegate_.AddObserver(&other_delegate_observer_);
   }
 
-  virtual ~NetworkChangeNotifierDelegateAndroidTest() {
+  ~NetworkChangeNotifierDelegateAndroidTest() override {
     delegate_.RemoveObserver(&delegate_observer_);
     delegate_.RemoveObserver(&other_delegate_observer_);
   }
diff --git a/net/android/network_change_notifier_factory_android.h b/net/android/network_change_notifier_factory_android.h
index d443fcd..035a84e 100644
--- a/net/android/network_change_notifier_factory_android.h
+++ b/net/android/network_change_notifier_factory_android.h
@@ -26,10 +26,10 @@
   NetworkChangeNotifierFactoryAndroid();
 
   // Must be called on the JNI thread.
-  virtual ~NetworkChangeNotifierFactoryAndroid();
+  ~NetworkChangeNotifierFactoryAndroid() override;
 
   // NetworkChangeNotifierFactory:
-  virtual NetworkChangeNotifier* CreateInstance() override;
+  NetworkChangeNotifier* CreateInstance() override;
 
  private:
   // Delegate passed to the instances created by this class.
diff --git a/net/base/file_stream_context.cc b/net/base/file_stream_context.cc
index 5acaab6..fc2af1b 100644
--- a/net/base/file_stream_context.cc
+++ b/net/base/file_stream_context.cc
@@ -77,6 +77,12 @@
 
   orphaned_ = true;
 
+#if defined(OS_WIN)
+  // Clean up weak pointers here to ensure that they are destroyed on the
+  // same thread where they were created.
+  weak_ptr_factory_.InvalidateWeakPtrs();
+#endif
+
   if (!async_in_progress_) {
     CloseAndDelete();
   } else if (file_.IsValid()) {
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h
index 82a2412..4f01d9d 100644
--- a/net/base/file_stream_context.h
+++ b/net/base/file_stream_context.h
@@ -28,6 +28,7 @@
 #define NET_BASE_FILE_STREAM_CONTEXT_H_
 
 #include "base/files/file.h"
+#include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/move.h"
 #include "base/task_runner.h"
@@ -159,6 +160,35 @@
   virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
                              DWORD bytes_read,
                              DWORD error) override;
+
+  // The ReadFile call on Windows can execute synchonously at times.
+  // http://support.microsoft.com/kb/156932. This ends up blocking the calling
+  // thread which is undesirable. To avoid this we execute the ReadFile call
+  // on a worker thread.
+  // The |context| parameter is a weak pointer instance passed to the worker
+  // pool.
+  // The |file| parameter is the handle to the file being read.
+  // The |buf| parameter is the buffer where we want the ReadFile to read the
+  // data into.
+  // The |buf_len| parameter contains the number of bytes to be read.
+  // The |overlapped| parameter is a pointer to the OVERLAPPED structure being
+  // used.
+  // The |origin_thread_loop| is a MessageLoopProxy instance used to post tasks
+  // back to the originating thread.
+  static void ReadAsync(
+      const base::WeakPtr<FileStream::Context>& context,
+      HANDLE file,
+      scoped_refptr<net::IOBuffer> buf,
+      int buf_len,
+      OVERLAPPED* overlapped,
+      scoped_refptr<base::MessageLoopProxy> origin_thread_loop);
+
+  // This callback executes on the main calling thread. It informs the caller
+  // about the result of the ReadFile call.
+  // The |os_error| parameter contains the value of the last error returned by
+  // the ReadFile API.
+  void ReadAsyncResult(DWORD os_error);
+
 #elif defined(OS_POSIX)
   // ReadFileImpl() is a simple wrapper around read() that handles EINTR
   // signals and calls RecordAndMapError() to map errno to net error codes.
@@ -179,6 +209,8 @@
   base::MessageLoopForIO::IOContext io_context_;
   CompletionCallback callback_;
   scoped_refptr<IOBuffer> in_flight_buf_;
+  // WeakPtrFactory for posting tasks back to |this|.
+  base::WeakPtrFactory<Context> weak_ptr_factory_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(Context);
diff --git a/net/base/file_stream_context_win.cc b/net/base/file_stream_context_win.cc
index 85a5968..d225ee3 100644
--- a/net/base/file_stream_context_win.cc
+++ b/net/base/file_stream_context_win.cc
@@ -8,9 +8,12 @@
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
 #include "base/metrics/histogram.h"
 #include "base/profiler/scoped_tracker.h"
 #include "base/task_runner.h"
+#include "base/threading/worker_pool.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 
@@ -37,7 +40,8 @@
     : io_context_(),
       async_in_progress_(false),
       orphaned_(false),
-      task_runner_(task_runner) {
+      task_runner_(task_runner),
+      weak_ptr_factory_(this) {
   io_context_.handler = this;
   memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
 }
@@ -48,7 +52,8 @@
       file_(file.Pass()),
       async_in_progress_(false),
       orphaned_(false),
-      task_runner_(task_runner) {
+      task_runner_(task_runner),
+      weak_ptr_factory_(this) {
   io_context_.handler = this;
   memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
   if (file_.IsValid()) {
@@ -69,20 +74,16 @@
 
   DCHECK(!async_in_progress_);
 
-  DWORD bytes_read;
-  if (!ReadFile(file_.GetPlatformFile(), buf->data(), buf_len,
-                &bytes_read, &io_context_.overlapped)) {
-    IOResult error = IOResult::FromOSError(GetLastError());
-    if (error.os_error == ERROR_HANDLE_EOF)
-      return 0;  // Report EOF by returning 0 bytes read.
-    if (error.os_error == ERROR_IO_PENDING)
-      IOCompletionIsPending(callback, buf);
-    else
-      LOG(WARNING) << "ReadFile failed: " << error.os_error;
-    return static_cast<int>(error.result);
-  }
-
   IOCompletionIsPending(callback, buf);
+
+  base::WorkerPool::PostTask(
+      FROM_HERE,
+      base::Bind(&FileStream::Context::ReadAsync,
+                 weak_ptr_factory_.GetWeakPtr(), file_.GetPlatformFile(),
+                 make_scoped_refptr(buf), buf_len, &io_context_.overlapped,
+                 base::MessageLoop::current()->message_loop_proxy()),
+      false);
+
   return ERR_IO_PENDING;
 }
 
@@ -165,4 +166,34 @@
   temp_callback.Run(result);
 }
 
+// static
+void FileStream::Context::ReadAsync(
+    const base::WeakPtr<FileStream::Context>& context,
+    HANDLE file,
+    scoped_refptr<net::IOBuffer> buf,
+    int buf_len,
+    OVERLAPPED* overlapped,
+    scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
+  DWORD bytes_read = 0;
+  if (!ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped)) {
+    origin_thread_loop->PostTask(
+        FROM_HERE, base::Bind(&FileStream::Context::ReadAsyncResult, context,
+                              ::GetLastError()));
+  }
+}
+
+void FileStream::Context::ReadAsyncResult(DWORD os_error) {
+  IOResult error = IOResult::FromOSError(os_error);
+  if (error.os_error == ERROR_HANDLE_EOF) {
+    // Report EOF by returning 0 bytes read.
+    OnIOCompleted(&io_context_, 0, error.os_error);
+  } else if (error.os_error != ERROR_IO_PENDING) {
+    // We don't need to inform the caller about ERROR_PENDING_IO as that was
+    // already done when the ReadFile call was queued to the worker pool.
+    if (error.os_error)
+      LOG(WARNING) << "ReadFile failed: " << error.os_error;
+    OnIOCompleted(&io_context_, 0, error.os_error);
+  }
+}
+
 }  // namespace net
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index fc9257e..8b47ecc 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -546,6 +546,25 @@
 
   const CompletionCallback& callback() const { return callback_; }
 
+  void ValidateWrittenData() {
+    TestCompletionCallback callback;
+    int rv = 0;
+    for (;;) {
+      scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
+      rv = stream_->Read(buf.get(), buf->size(), callback.callback());
+      if (rv == ERR_IO_PENDING) {
+        base::MessageLoop::ScopedNestableTaskAllower allow(
+            base::MessageLoop::current());
+        rv = callback.WaitForResult();
+      }
+      EXPECT_LE(0, rv);
+      if (rv <= 0)
+        break;
+      *total_bytes_read_ += rv;
+      data_read_->append(buf->data(), rv);
+    }
+  }
+
  private:
   void OnComplete(int result) {
     DCHECK_LT(0, result);
@@ -577,22 +596,6 @@
             base::MessageLoop::current());
         EXPECT_LE(0, callback64.WaitForResult());
       }
-
-      TestCompletionCallback callback;
-      for (;;) {
-        scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
-        rv = stream_->Read(buf.get(), buf->size(), callback.callback());
-        if (rv == ERR_IO_PENDING) {
-          base::MessageLoop::ScopedNestableTaskAllower allow(
-              base::MessageLoop::current());
-          rv = callback.WaitForResult();
-        }
-        EXPECT_LE(0, rv);
-        if (rv <= 0)
-          break;
-        *total_bytes_read_ += rv;
-        data_read_->append(buf->data(), rv);
-      }
     }
 
     result_ = *total_bytes_written_;
@@ -646,6 +649,8 @@
   EXPECT_LT(0, rv);
   EXPECT_EQ(kTestDataSize, total_bytes_written);
 
+  callback.ValidateWrittenData();
+
   stream.reset();
 
   EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
diff --git a/net/base/filename_util_unittest.cc b/net/base/filename_util_unittest.cc
index 9d91fb7..4a8c4b5 100644
--- a/net/base/filename_util_unittest.cc
+++ b/net/base/filename_util_unittest.cc
@@ -116,48 +116,56 @@
 };
 
 static const base::FilePath::CharType* kSafePortableRelativePaths[] = {
-  FILE_PATH_LITERAL("a/a"),
+    FILE_PATH_LITERAL("a/a"),
 #if defined(OS_WIN)
-  FILE_PATH_LITERAL("a\\a"),
+    FILE_PATH_LITERAL("a\\a"),
 #endif
 };
 
 TEST(FilenameUtilTest, IsSafePortablePathComponent) {
-  for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
-    EXPECT_TRUE(IsSafePortablePathComponent(base::FilePath(
-        kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
+  for (size_t i = 0; i < arraysize(kSafePortableBasenames); ++i) {
+    EXPECT_TRUE(
+        IsSafePortablePathComponent(base::FilePath(kSafePortableBasenames[i])))
+        << kSafePortableBasenames[i];
   }
-  for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
-    EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
-        kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
+  for (size_t i = 0; i < arraysize(kUnsafePortableBasenames); ++i) {
+    EXPECT_FALSE(IsSafePortablePathComponent(
+        base::FilePath(kUnsafePortableBasenames[i])))
+        << kUnsafePortableBasenames[i];
   }
-  for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
-    EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
-        kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
+  for (size_t i = 0; i < arraysize(kSafePortableRelativePaths); ++i) {
+    EXPECT_FALSE(IsSafePortablePathComponent(
+        base::FilePath(kSafePortableRelativePaths[i])))
+        << kSafePortableRelativePaths[i];
   }
 }
 
 TEST(FilenameUtilTest, IsSafePortableRelativePath) {
   base::FilePath safe_dirname(FILE_PATH_LITERAL("a"));
-  for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
-    EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
-        kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
-    EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
-        kSafePortableBasenames[i])))) << kSafePortableBasenames[i];
+  for (size_t i = 0; i < arraysize(kSafePortableBasenames); ++i) {
+    EXPECT_TRUE(
+        IsSafePortableRelativePath(base::FilePath(kSafePortableBasenames[i])))
+        << kSafePortableBasenames[i];
+    EXPECT_TRUE(IsSafePortableRelativePath(
+        safe_dirname.Append(base::FilePath(kSafePortableBasenames[i]))))
+        << kSafePortableBasenames[i];
   }
-  for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
-    EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
-        kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
-    EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
-        kSafePortableRelativePaths[i])))) << kSafePortableRelativePaths[i];
+  for (size_t i = 0; i < arraysize(kSafePortableRelativePaths); ++i) {
+    EXPECT_TRUE(IsSafePortableRelativePath(
+        base::FilePath(kSafePortableRelativePaths[i])))
+        << kSafePortableRelativePaths[i];
+    EXPECT_TRUE(IsSafePortableRelativePath(
+        safe_dirname.Append(base::FilePath(kSafePortableRelativePaths[i]))))
+        << kSafePortableRelativePaths[i];
   }
-  for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
-    EXPECT_FALSE(IsSafePortableRelativePath(base::FilePath(
-        kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
-    if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) {
-      EXPECT_FALSE(IsSafePortableRelativePath(safe_dirname.Append(
-          base::FilePath(kUnsafePortableBasenames[i]))))
+  for (size_t i = 0; i < arraysize(kUnsafePortableBasenames); ++i) {
+    EXPECT_FALSE(
+        IsSafePortableRelativePath(base::FilePath(kUnsafePortableBasenames[i])))
         << kUnsafePortableBasenames[i];
+    if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) {
+      EXPECT_FALSE(IsSafePortableRelativePath(
+          safe_dirname.Append(base::FilePath(kUnsafePortableBasenames[i]))))
+          << kUnsafePortableBasenames[i];
     }
   }
 }
@@ -168,19 +176,18 @@
 #if defined(OS_WIN)
     {L"C:\\foo\\bar.txt", "file:///C:/foo/bar.txt"},
     {L"\\\\some computer\\foo\\bar.txt",
-     "file://some%20computer/foo/bar.txt"}, // UNC
+     "file://some%20computer/foo/bar.txt"},  // UNC
     {L"D:\\Name;with%some symbols*#",
      "file:///D:/Name%3Bwith%25some%20symbols*%23"},
     // issue 14153: To be tested with the OS default codepage other than 1252.
     {L"D:\\latin1\\caf\x00E9\x00DD.txt",
      "file:///D:/latin1/caf%C3%A9%C3%9D.txt"},
-    {L"D:\\otherlatin\\caf\x0119.txt",
-     "file:///D:/otherlatin/caf%C4%99.txt"},
+    {L"D:\\otherlatin\\caf\x0119.txt", "file:///D:/otherlatin/caf%C4%99.txt"},
     {L"D:\\greek\\\x03B1\x03B2\x03B3.txt",
      "file:///D:/greek/%CE%B1%CE%B2%CE%B3.txt"},
     {L"D:\\Chinese\\\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
      "file:///D:/Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD%91"
-         "%E9%A1%B5.doc"},
+     "%E9%A1%B5.doc"},
     {L"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt",  // Math alphabet "AB"
      "file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
 #elif defined(OS_POSIX)
@@ -195,7 +202,7 @@
     {L"/greek/\x03B1\x03B2\x03B3.txt", "file:///greek/%CE%B1%CE%B2%CE%B3.txt"},
     {L"/Chinese/\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
      "file:///Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD"
-         "%91%E9%A1%B5.doc"},
+     "%91%E9%A1%B5.doc"},
     {L"/plane1/\x1D400\x1D401.txt",  // Math alphabet "AB"
      "file:///plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
 #endif
@@ -205,8 +212,8 @@
   base::FilePath output;
   for (size_t i = 0; i < arraysize(round_trip_cases); i++) {
     // convert to the file URL
-    GURL file_url(FilePathToFileURL(
-                      WStringAsFilePath(round_trip_cases[i].file)));
+    GURL file_url(
+        FilePathToFileURL(WStringAsFilePath(round_trip_cases[i].file)));
     EXPECT_EQ(round_trip_cases[i].url, file_url.spec());
 
     // Back to the filename.
@@ -239,13 +246,13 @@
     {L"/foo/bar.txt", "file:////foo////bar.txt"},
     {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
     {L"/c:/foo/bar.txt", "file:c:/foo/bar.txt"},
-    // We get these wrong because GURL turns back slashes into forward
-    // slashes.
-    //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
-    //{L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
-    //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
-    //{L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
-    //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
+//  We get these wrong because GURL turns back slashes into forward
+//  slashes.
+//  {L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
+//  {L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
+//  {L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
+//  {L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
+//  {L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
 #endif
   };
   for (size_t i = 0; i < arraysize(url_cases); i++) {
@@ -253,14 +260,13 @@
     EXPECT_EQ(url_cases[i].file, FilePathAsWString(output));
   }
 
-  // Unfortunately, UTF8ToWide discards invalid UTF8 input.
+// Unfortunately, UTF8ToWide discards invalid UTF8 input.
 #ifdef BUG_878908_IS_FIXED
   // Test that no conversion happens if the UTF-8 input is invalid, and that
   // the input is preserved in UTF-8
   const char invalid_utf8[] = "file:///d:/Blah/\xff.doc";
   const wchar_t invalid_wide[] = L"D:\\Blah\\\xff.doc";
-  EXPECT_TRUE(FileURLToFilePath(
-      GURL(std::string(invalid_utf8)), &output));
+  EXPECT_TRUE(FileURLToFilePath(GURL(std::string(invalid_utf8)), &output));
   EXPECT_EQ(std::wstring(invalid_wide), output);
 #endif
 
@@ -288,144 +294,88 @@
     const base::FilePath::CharType* expected_filename;
   } safe_tests[] = {
 #if defined(OS_WIN)
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
-      FILE_PATH_LITERAL("C:\\foo\\bar.htm")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\bar.html"),
-      FILE_PATH_LITERAL("C:\\foo\\bar.html")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\bar"),
-      FILE_PATH_LITERAL("C:\\foo\\bar.htm")
-    },
-    {
-      "image/png",
-      FILE_PATH_LITERAL("C:\\bar.html"),
-      FILE_PATH_LITERAL("C:\\bar.html")
-    },
-    {
-      "image/png",
-      FILE_PATH_LITERAL("C:\\bar"),
-      FILE_PATH_LITERAL("C:\\bar.png")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
-      FILE_PATH_LITERAL("C:\\foo\\bar.exe")
-    },
-    {
-      "image/gif",
-      FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
-      FILE_PATH_LITERAL("C:\\foo\\bar.exe")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\google.com"),
-      FILE_PATH_LITERAL("C:\\foo\\google.com")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\con.htm"),
-      FILE_PATH_LITERAL("C:\\foo\\_con.htm")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\con"),
-      FILE_PATH_LITERAL("C:\\foo\\_con.htm")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
-      FILE_PATH_LITERAL("C:\\foo\\harmless.download")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
-      FILE_PATH_LITERAL("C:\\foo\\harmless.download")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
-      FILE_PATH_LITERAL("C:\\foo\\harmless.download")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
-      FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")
-    },
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
+     FILE_PATH_LITERAL("C:\\foo\\bar.htm")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\bar.html"),
+     FILE_PATH_LITERAL("C:\\foo\\bar.html")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\bar"),
+     FILE_PATH_LITERAL("C:\\foo\\bar.htm")},
+    {"image/png",
+     FILE_PATH_LITERAL("C:\\bar.html"),
+     FILE_PATH_LITERAL("C:\\bar.html")},
+    {"image/png",
+     FILE_PATH_LITERAL("C:\\bar"),
+     FILE_PATH_LITERAL("C:\\bar.png")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
+     FILE_PATH_LITERAL("C:\\foo\\bar.exe")},
+    {"image/gif",
+     FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
+     FILE_PATH_LITERAL("C:\\foo\\bar.exe")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\google.com"),
+     FILE_PATH_LITERAL("C:\\foo\\google.com")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\con.htm"),
+     FILE_PATH_LITERAL("C:\\foo\\_con.htm")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\con"),
+     FILE_PATH_LITERAL("C:\\foo\\_con.htm")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
+     FILE_PATH_LITERAL("C:\\foo\\harmless.download")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
+     FILE_PATH_LITERAL("C:\\foo\\harmless.download")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
+     FILE_PATH_LITERAL("C:\\foo\\harmless.download")},
+    {"text/html",
+     FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
+     FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")},
     // Allow extension synonyms.
-    {
-      "image/jpeg",
-      FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
-      FILE_PATH_LITERAL("C:\\foo\\bar.jpg")
-    },
-    {
-      "image/jpeg",
-      FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
-      FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")
-    },
-#else  // !defined(OS_WIN)
-    {
-      "text/html",
-      FILE_PATH_LITERAL("/foo/bar.htm"),
-      FILE_PATH_LITERAL("/foo/bar.htm")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("/foo/bar.html"),
-      FILE_PATH_LITERAL("/foo/bar.html")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("/foo/bar"),
-      FILE_PATH_LITERAL("/foo/bar.html")
-    },
-    {
-      "image/png",
-      FILE_PATH_LITERAL("/bar.html"),
-      FILE_PATH_LITERAL("/bar.html")
-    },
-    {
-      "image/png",
-      FILE_PATH_LITERAL("/bar"),
-      FILE_PATH_LITERAL("/bar.png")
-    },
-    {
-      "image/gif",
-      FILE_PATH_LITERAL("/foo/bar.exe"),
-      FILE_PATH_LITERAL("/foo/bar.exe")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("/foo/google.com"),
-      FILE_PATH_LITERAL("/foo/google.com")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("/foo/con.htm"),
-      FILE_PATH_LITERAL("/foo/con.htm")
-    },
-    {
-      "text/html",
-      FILE_PATH_LITERAL("/foo/con"),
-      FILE_PATH_LITERAL("/foo/con.html")
-    },
+    {"image/jpeg",
+     FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
+     FILE_PATH_LITERAL("C:\\foo\\bar.jpg")},
+    {"image/jpeg",
+     FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
+     FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")},
+#else   // !defined(OS_WIN)
+    {"text/html",
+     FILE_PATH_LITERAL("/foo/bar.htm"),
+     FILE_PATH_LITERAL("/foo/bar.htm")},
+    {"text/html",
+     FILE_PATH_LITERAL("/foo/bar.html"),
+     FILE_PATH_LITERAL("/foo/bar.html")},
+    {"text/html",
+     FILE_PATH_LITERAL("/foo/bar"),
+     FILE_PATH_LITERAL("/foo/bar.html")},
+    {"image/png",
+     FILE_PATH_LITERAL("/bar.html"),
+     FILE_PATH_LITERAL("/bar.html")},
+    {"image/png", FILE_PATH_LITERAL("/bar"), FILE_PATH_LITERAL("/bar.png")},
+    {"image/gif",
+     FILE_PATH_LITERAL("/foo/bar.exe"),
+     FILE_PATH_LITERAL("/foo/bar.exe")},
+    {"text/html",
+     FILE_PATH_LITERAL("/foo/google.com"),
+     FILE_PATH_LITERAL("/foo/google.com")},
+    {"text/html",
+     FILE_PATH_LITERAL("/foo/con.htm"),
+     FILE_PATH_LITERAL("/foo/con.htm")},
+    {"text/html",
+     FILE_PATH_LITERAL("/foo/con"),
+     FILE_PATH_LITERAL("/foo/con.html")},
     // Allow extension synonyms.
-    {
-      "image/jpeg",
-      FILE_PATH_LITERAL("/bar.jpg"),
-      FILE_PATH_LITERAL("/bar.jpg")
-    },
-    {
-      "image/jpeg",
-      FILE_PATH_LITERAL("/bar.jpeg"),
-      FILE_PATH_LITERAL("/bar.jpeg")
-    },
+    {"image/jpeg",
+     FILE_PATH_LITERAL("/bar.jpg"),
+     FILE_PATH_LITERAL("/bar.jpg")},
+    {"image/jpeg",
+     FILE_PATH_LITERAL("/bar.jpeg"),
+     FILE_PATH_LITERAL("/bar.jpeg")},
 #endif  // !defined(OS_WIN)
   };
 
@@ -442,392 +392,287 @@
   // parameters and that Content-Disposition headers are properly
   // handled including failovers when the header is malformed.
   const GenerateFilenameCase selection_tests[] = {
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=test.html",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=\"test.html\"",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename= \"test.html\"",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename   =   \"test.html\"",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    { // filename is whitespace.  Should failover to URL host
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=  ",
-      "",
-      "",
-      "",
-      L"",
-      L"www.google.com"
-    },
-    { // No filename.
-      __LINE__,
-      "http://www.google.com/path/test.html",
-      "attachment",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    { // Ditto
-      __LINE__,
-      "http://www.google.com/path/test.html",
-      "attachment;",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    { // No C-D
-      __LINE__,
-      "http://www.google.com/",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"www.google.com"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/test.html",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    { // Now that we use src/url's ExtractFileName, this case falls back to
-      // the hostname. If this behavior is not desirable, we'd better change
-      // ExtractFileName (in url_parse.cc).
-      __LINE__,
-      "http://www.google.com/path/",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"www.google.com"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/path",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"path"
-    },
-    {
-      __LINE__,
-      "file:///",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"download"
-    },
-    {
-      __LINE__,
-      "file:///path/testfile",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"testfile"
-    },
-    {
-      __LINE__,
-      "non-standard-scheme:",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"download"
-    },
-    { // C-D should override default
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename =\"test.html\"",
-      "",
-      "",
-      "",
-      L"download",
-      L"test.html"
-    },
-    { // But the URL shouldn't
-      __LINE__,
-      "http://www.google.com/",
-      "",
-      "",
-      "",
-      "",
-      L"download",
-      L"download"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=\"../test.html\"",
-      "",
-      "",
-      "",
-      L"",
-      L"-test.html"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=\"..\\test.html\"",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=\"..\\\\test.html\"",
-      "",
-      "",
-      "",
-      L"",
-      L"-test.html"
-    },
-    { // Filename disappears after leading and trailing periods are removed.
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=\"..\"",
-      "",
-      "",
-      "",
-      L"default",
-      L"default"
-    },
-    { // C-D specified filename disappears.  Failover to final filename.
-      __LINE__,
-      "http://www.google.com/test.html",
-      "attachment; filename=\"..\"",
-      "",
-      "",
-      "",
-      L"default",
-      L"default"
-    },
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename=test.html",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename=\"test.html\"",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename= \"test.html\"",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename   =   \"test.html\"",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {// filename is whitespace.  Should failover to URL host
+     __LINE__,
+     "http://www.google.com/",
+     "attachment; filename=  ",
+     "",
+     "",
+     "",
+     L"",
+     L"www.google.com"},
+    {// No filename.
+     __LINE__,
+     "http://www.google.com/path/test.html",
+     "attachment",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {// Ditto
+     __LINE__,
+     "http://www.google.com/path/test.html",
+     "attachment;",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {// No C-D
+     __LINE__,
+     "http://www.google.com/",
+     "",
+     "",
+     "",
+     "",
+     L"",
+     L"www.google.com"},
+    {__LINE__,
+     "http://www.google.com/test.html",
+     "",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {// Now that we use src/url's ExtractFileName, this case falls back to
+     // the hostname. If this behavior is not desirable, we'd better change
+     // ExtractFileName (in url_parse.cc).
+     __LINE__,
+     "http://www.google.com/path/",
+     "",
+     "",
+     "",
+     "",
+     L"",
+     L"www.google.com"},
+    {__LINE__, "http://www.google.com/path", "", "", "", "", L"", L"path"},
+    {__LINE__, "file:///", "", "", "", "", L"", L"download"},
+    {__LINE__, "file:///path/testfile", "", "", "", "", L"", L"testfile"},
+    {__LINE__, "non-standard-scheme:", "", "", "", "", L"", L"download"},
+    {// C-D should override default
+     __LINE__,
+     "http://www.google.com/",
+     "attachment; filename =\"test.html\"",
+     "",
+     "",
+     "",
+     L"download",
+     L"test.html"},
+    {// But the URL shouldn't
+     __LINE__,
+     "http://www.google.com/",
+     "",
+     "",
+     "",
+     "",
+     L"download",
+     L"download"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename=\"../test.html\"",
+     "",
+     "",
+     "",
+     L"",
+     L"-test.html"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename=\"..\\test.html\"",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename=\"..\\\\test.html\"",
+     "",
+     "",
+     "",
+     L"",
+     L"-test.html"},
+    {// Filename disappears after leading and trailing periods are removed.
+     __LINE__,
+     "http://www.google.com/",
+     "attachment; filename=\"..\"",
+     "",
+     "",
+     "",
+     L"default",
+     L"default"},
+    {// C-D specified filename disappears.  Failover to final filename.
+     __LINE__,
+     "http://www.google.com/test.html",
+     "attachment; filename=\"..\"",
+     "",
+     "",
+     "",
+     L"default",
+     L"default"},
     // Below is a small subset of cases taken from HttpContentDisposition tests.
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=\"%EC%98%88%EC%88%A0%20"
-      "%EC%98%88%EC%88%A0.jpg\"",
-      "",
-      "",
-      "",
-      L"",
-      L"\uc608\uc220 \uc608\uc220.jpg"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
-      "",
-      "",
-      "",
-      "",
-      L"download",
-      L"\uc608\uc220 \uc608\uc220.jpg"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment;",
-      "",
-      "",
-      "",
-      L"\uB2E4\uC6B4\uB85C\uB4DC",
-      L"\uB2E4\uC6B4\uB85C\uB4DC"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/",
-      "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
-      "D13=2Epng?=\"",
-      "",
-      "",
-      "",
-      L"download",
-      L"\u82b8\u88533.png"
-    },
-    {
-      __LINE__,
-      "http://www.example.com/images?id=3",
-      "attachment; filename=caf\xc3\xa9.png",
-      "iso-8859-1",
-      "",
-      "",
-      L"",
-      L"caf\u00e9.png"
-    },
-    {
-      __LINE__,
-      "http://www.example.com/images?id=3",
-      "attachment; filename=caf\xe5.png",
-      "windows-1253",
-      "",
-      "",
-      L"",
-      L"caf\u03b5.png"
-    },
-    {
-      __LINE__,
-      "http://www.example.com/file?id=3",
-      "attachment; name=\xcf\xc2\xd4\xd8.zip",
-      "GBK",
-      "",
-      "",
-      L"",
-      L"\u4e0b\u8f7d.zip"
-    },
-    { // Invalid C-D header. Extracts filename from url.
-      __LINE__,
-      "http://www.google.com/test.html",
-      "attachment; filename==?iiso88591?Q?caf=EG?=",
-      "",
-      "",
-      "",
-      L"",
-      L"test.html"
-    },
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename=\"%EC%98%88%EC%88%A0%20"
+     "%EC%98%88%EC%88%A0.jpg\"",
+     "",
+     "",
+     "",
+     L"",
+     L"\uc608\uc220 \uc608\uc220.jpg"},
+    {__LINE__,
+     "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
+     "",
+     "",
+     "",
+     "",
+     L"download",
+     L"\uc608\uc220 \uc608\uc220.jpg"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment;",
+     "",
+     "",
+     "",
+     L"\uB2E4\uC6B4\uB85C\uB4DC",
+     L"\uB2E4\uC6B4\uB85C\uB4DC"},
+    {__LINE__,
+     "http://www.google.com/",
+     "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
+     "D13=2Epng?=\"",
+     "",
+     "",
+     "",
+     L"download",
+     L"\u82b8\u88533.png"},
+    {__LINE__,
+     "http://www.example.com/images?id=3",
+     "attachment; filename=caf\xc3\xa9.png",
+     "iso-8859-1",
+     "",
+     "",
+     L"",
+     L"caf\u00e9.png"},
+    {__LINE__,
+     "http://www.example.com/images?id=3",
+     "attachment; filename=caf\xe5.png",
+     "windows-1253",
+     "",
+     "",
+     L"",
+     L"caf\u03b5.png"},
+    {__LINE__,
+     "http://www.example.com/file?id=3",
+     "attachment; name=\xcf\xc2\xd4\xd8.zip",
+     "GBK",
+     "",
+     "",
+     L"",
+     L"\u4e0b\u8f7d.zip"},
+    {// Invalid C-D header. Extracts filename from url.
+     __LINE__,
+     "http://www.google.com/test.html",
+     "attachment; filename==?iiso88591?Q?caf=EG?=",
+     "",
+     "",
+     "",
+     L"",
+     L"test.html"},
     // about: and data: URLs
-    {
-      __LINE__,
-      "about:chrome",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"download"
-    },
-    {
-      __LINE__,
-      "data:,looks/like/a.path",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"download"
-    },
-    {
-      __LINE__,
-      "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
-      "",
-      "",
-      "",
-      "",
-      L"",
-      L"download"
-    },
-    {
-      __LINE__,
-      "data:,looks/like/a.path",
-      "",
-      "",
-      "",
-      "",
-      L"default_filename_is_given",
-      L"default_filename_is_given"
-    },
-    {
-      __LINE__,
-      "data:,looks/like/a.path",
-      "",
-      "",
-      "",
-      "",
-      L"\u65e5\u672c\u8a9e",  // Japanese Kanji.
-      L"\u65e5\u672c\u8a9e"
-    },
-    { // The filename encoding is specified by the referrer charset.
-      __LINE__,
-      "http://example.com/V%FDvojov%E1%20psychologie.doc",
-      "",
-      "iso-8859-1",
-      "",
-      "",
-      L"",
-      L"V\u00fdvojov\u00e1 psychologie.doc"
-    },
-    { // Suggested filename takes precedence over URL
-      __LINE__,
-      "http://www.google.com/test",
-      "",
-      "",
-      "suggested",
-      "",
-      L"",
-      L"suggested"
-    },
-    { // The content-disposition has higher precedence over the suggested name.
-      __LINE__,
-      "http://www.google.com/test",
-      "attachment; filename=test.html",
-      "",
-      "suggested",
-      "",
-      L"",
-      L"test.html"
-    },
-    {
-      __LINE__,
-      "http://www.google.com/test",
-      "attachment; filename=test",
-      "utf-8",
-      "",
-      "image/png",
-      L"",
-      L"test"
-    },
+    {__LINE__, "about:chrome", "", "", "", "", L"", L"download"},
+    {__LINE__, "data:,looks/like/a.path", "", "", "", "", L"", L"download"},
+    {__LINE__,
+     "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
+     "",
+     "",
+     "",
+     "",
+     L"",
+     L"download"},
+    {__LINE__,
+     "data:,looks/like/a.path",
+     "",
+     "",
+     "",
+     "",
+     L"default_filename_is_given",
+     L"default_filename_is_given"},
+    {__LINE__,
+     "data:,looks/like/a.path",
+     "",
+     "",
+     "",
+     "",
+     L"\u65e5\u672c\u8a9e",  // Japanese Kanji.
+     L"\u65e5\u672c\u8a9e"},
+    {// The filename encoding is specified by the referrer charset.
+     __LINE__,
+     "http://example.com/V%FDvojov%E1%20psychologie.doc",
+     "",
+     "iso-8859-1",
+     "",
+     "",
+     L"",
+     L"V\u00fdvojov\u00e1 psychologie.doc"},
+    {// Suggested filename takes precedence over URL
+     __LINE__,
+     "http://www.google.com/test",
+     "",
+     "",
+     "suggested",
+     "",
+     L"",
+     L"suggested"},
+    {// The content-disposition has higher precedence over the suggested name.
+     __LINE__,
+     "http://www.google.com/test",
+     "attachment; filename=test.html",
+     "",
+     "suggested",
+     "",
+     L"",
+     L"test.html"},
+    {__LINE__,
+     "http://www.google.com/test",
+     "attachment; filename=test",
+     "utf-8",
+     "",
+     "image/png",
+     L"",
+     L"test"},
 #if 0
     { // The filename encoding doesn't match the referrer charset, the system
       // charset, or UTF-8.
@@ -843,108 +688,95 @@
     },
 #endif
     // Raw 8bit characters in C-D
-    {
-      __LINE__,
-      "http://www.example.com/images?id=3",
-      "attachment; filename=caf\xc3\xa9.png",
-      "iso-8859-1",
-      "",
-      "image/png",
-      L"",
-      L"caf\u00e9.png"
-    },
-    {
-      __LINE__,
-      "http://www.example.com/images?id=3",
-      "attachment; filename=caf\xe5.png",
-      "windows-1253",
-      "",
-      "image/png",
-      L"",
-      L"caf\u03b5.png"
-    },
-    { // No 'filename' keyword in the disposition, use the URL
-      __LINE__,
-      "http://www.evil.com/my_download.txt",
-      "a_file_name.txt",
-      "",
-      "",
-      "text/plain",
-      L"download",
-      L"my_download.txt"
-    },
-    { // Spaces in the disposition file name
-      __LINE__,
-      "http://www.frontpagehacker.com/a_download.exe",
-      "filename=My Downloaded File.exe",
-      "",
-      "",
-      "application/octet-stream",
-      L"download",
-      L"My Downloaded File.exe"
-    },
-    { // % encoded
-      __LINE__,
-      "http://www.examples.com/",
-      "attachment; "
-      "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
-      "",
-      "",
-      "image/jpeg",
-      L"download",
-      L"\uc608\uc220 \uc608\uc220.jpg"
-    },
-    { // name= parameter
-      __LINE__,
-      "http://www.examples.com/q.cgi?id=abc",
-      "attachment; name=abc de.pdf",
-      "",
-      "",
-      "application/octet-stream",
-      L"download",
-      L"abc de.pdf"
-    },
-    {
-      __LINE__,
-      "http://www.example.com/path",
-      "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
-      "",
-      "",
-      "image/png",
-      L"download",
-      L"\x82b8\x8853" L"3.png"
-    },
-    { // The following two have invalid CD headers and filenames come from the
-      // URL.
-      __LINE__,
-      "http://www.example.com/test%20123",
-      "attachment; filename==?iiso88591?Q?caf=EG?=",
-      "",
-      "",
-      "image/jpeg",
-      L"download",
-      L"test 123" JPEG_EXT
-    },
-    {
-      __LINE__,
-      "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
-      "malformed_disposition",
-      "",
-      "",
-      "image/jpeg",
-      L"download",
-      L"\uc608\uc220 \uc608\uc220.jpg"
-    },
-    { // Invalid C-D. No filename from URL. Falls back to 'download'.
-      __LINE__,
-      "http://www.google.com/path1/path2/",
-      "attachment; filename==?iso88591?Q?caf=E3?",
-      "",
-      "",
-      "image/jpeg",
-      L"download",
-      L"download" JPEG_EXT
-    },
+    {__LINE__,
+     "http://www.example.com/images?id=3",
+     "attachment; filename=caf\xc3\xa9.png",
+     "iso-8859-1",
+     "",
+     "image/png",
+     L"",
+     L"caf\u00e9.png"},
+    {__LINE__,
+     "http://www.example.com/images?id=3",
+     "attachment; filename=caf\xe5.png",
+     "windows-1253",
+     "",
+     "image/png",
+     L"",
+     L"caf\u03b5.png"},
+    {// No 'filename' keyword in the disposition, use the URL
+     __LINE__,
+     "http://www.evil.com/my_download.txt",
+     "a_file_name.txt",
+     "",
+     "",
+     "text/plain",
+     L"download",
+     L"my_download.txt"},
+    {// Spaces in the disposition file name
+     __LINE__,
+     "http://www.frontpagehacker.com/a_download.exe",
+     "filename=My Downloaded File.exe",
+     "",
+     "",
+     "application/octet-stream",
+     L"download",
+     L"My Downloaded File.exe"},
+    {// % encoded
+     __LINE__,
+     "http://www.examples.com/",
+     "attachment; "
+     "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
+     "",
+     "",
+     "image/jpeg",
+     L"download",
+     L"\uc608\uc220 \uc608\uc220.jpg"},
+    {// name= parameter
+     __LINE__,
+     "http://www.examples.com/q.cgi?id=abc",
+     "attachment; name=abc de.pdf",
+     "",
+     "",
+     "application/octet-stream",
+     L"download",
+     L"abc de.pdf"},
+    {__LINE__,
+     "http://www.example.com/path",
+     "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
+     "",
+     "",
+     "image/png",
+     L"download",
+     L"\x82b8\x8853"
+     L"3.png"},
+    {// The following two have invalid CD headers and filenames come from the
+     // URL.
+     __LINE__,
+     "http://www.example.com/test%20123",
+     "attachment; filename==?iiso88591?Q?caf=EG?=",
+     "",
+     "",
+     "image/jpeg",
+     L"download",
+     L"test 123" JPEG_EXT},
+    {__LINE__,
+     "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
+     "malformed_disposition",
+     "",
+     "",
+     "image/jpeg",
+     L"download",
+     L"\uc608\uc220 \uc608\uc220.jpg"},
+    {// Invalid C-D. No filename from URL. Falls back to 'download'.
+     __LINE__,
+     "http://www.google.com/path1/path2/",
+     "attachment; filename==?iso88591?Q?caf=E3?",
+     "",
+     "",
+     "image/jpeg",
+     L"download",
+     L"download" JPEG_EXT},
   };
 
   // Tests filename generation.  Once the correct filename is
@@ -1067,7 +899,7 @@
      "text/plain",
      L"download",
      L"my-cat.jpg"},
-    // Windows specific tests
+// Windows specific tests
 #if defined(OS_WIN)
     {__LINE__,
      "http://www.goodguy.com/evil.exe",
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index a7fe9f3..e9b4e1a 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -359,6 +359,7 @@
   "audio/mp3",
   "audio/x-mp3",
   "audio/mpeg",
+  "audio/aac",
 
 #if defined(ENABLE_MPEG2TS_STREAM_PARSER)
   // MPEG-2 TS.
diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc
index a28c8b6..b5335b6 100644
--- a/net/base/mime_util_unittest.cc
+++ b/net/base/mime_util_unittest.cc
@@ -231,6 +231,7 @@
   EXPECT_TRUE(IsSupportedMediaMimeType("audio/mp3"));
   EXPECT_TRUE(IsSupportedMediaMimeType("audio/x-mp3"));
   EXPECT_TRUE(IsSupportedMediaMimeType("audio/mpeg"));
+  EXPECT_TRUE(IsSupportedMediaMimeType("audio/aac"));
 
 #if defined(ENABLE_MPEG2TS_STREAM_PARSER)
   EXPECT_TRUE(IsSupportedMediaMimeType("video/mp2t"));
@@ -246,6 +247,7 @@
   EXPECT_FALSE(IsSupportedMediaMimeType("audio/mp3"));
   EXPECT_FALSE(IsSupportedMediaMimeType("audio/x-mp3"));
   EXPECT_FALSE(IsSupportedMediaMimeType("audio/mpeg"));
+  EXPECT_FALSE(IsSupportedMediaMimeType("audio/aac"));
 #endif  // USE_PROPRIETARY_CODECS
   EXPECT_FALSE(IsSupportedMediaMimeType("video/mp3"));
 
diff --git a/net/base/net_util_linux.cc b/net/base/net_util_linux.cc
index 36c9eb7..a348912 100644
--- a/net/base/net_util_linux.cc
+++ b/net/base/net_util_linux.cc
@@ -18,6 +18,7 @@
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/string_util.h"
@@ -68,11 +69,7 @@
 namespace internal {
 
 inline const unsigned char* GetIPAddressData(const IPAddressNumber& ip) {
-#if defined(OS_ANDROID)
-  return ip.begin();
-#else
-  return ip.data();
-#endif
+  return vector_as_array(&ip);
 }
 
 // Gets the connection type for interface |ifname| by checking for wireless
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc
index 0512594..03cc4c0 100644
--- a/net/base/network_change_notifier_win.cc
+++ b/net/base/network_change_notifier_win.cc
@@ -227,7 +227,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "NetworkChangeNotifierWin_OnObjectSignaled"));
+          "418183 NetworkChangeNotifierWin::OnObjectSignaled"));
 
   DCHECK(CalledOnValidThread());
   DCHECK(is_watching_);
diff --git a/net/base/upload_file_element_reader.cc b/net/base/upload_file_element_reader.cc
index 9be9117..864584d 100644
--- a/net/base/upload_file_element_reader.cc
+++ b/net/base/upload_file_element_reader.cc
@@ -174,12 +174,15 @@
   }
 
   // If the underlying file has been changed and the expected file modification
-  // time is set, treat it as error. Note that the expected modification time
-  // from WebKit is based on time_t precision. So we have to convert both to
-  // time_t to compare. This check is used for sliced files.
+  // time is set, treat it as error. Note that |expected_modification_time_| may
+  // have gone through multiple conversion steps involving loss of precision
+  // (including conversion to time_t). Therefore the check below only verifies
+  // that the timestamps are within one second of each other. This check is used
+  // for sliced files.
   if (!expected_modification_time_.is_null() &&
-      expected_modification_time_.ToTimeT() !=
-      file_info->last_modified.ToTimeT()) {
+      (expected_modification_time_ - file_info->last_modified)
+              .magnitude()
+              .InSeconds() != 0) {
     callback.Run(ERR_UPLOAD_FILE_CHANGED);
     return;
   }
diff --git a/net/base/upload_file_element_reader_unittest.cc b/net/base/upload_file_element_reader_unittest.cc
index b0374ac..719ce1e 100644
--- a/net/base/upload_file_element_reader_unittest.cc
+++ b/net/base/upload_file_element_reader_unittest.cc
@@ -210,25 +210,33 @@
   // Expect one second before the actual modification time to simulate change.
   const base::Time expected_modification_time =
       info.last_modified - base::TimeDelta::FromSeconds(1);
-  reader_.reset(
-      new UploadFileElementReader(base::MessageLoopProxy::current().get(),
-                                  temp_file_path_,
-                                  0,
-                                  kuint64max,
-                                  expected_modification_time));
+  reader_.reset(new UploadFileElementReader(
+      base::MessageLoopProxy::current().get(), temp_file_path_, 0, kuint64max,
+      expected_modification_time));
   TestCompletionCallback init_callback;
   ASSERT_EQ(ERR_IO_PENDING, reader_->Init(init_callback.callback()));
   EXPECT_EQ(ERR_UPLOAD_FILE_CHANGED, init_callback.WaitForResult());
 }
 
+TEST_F(UploadFileElementReaderTest, InexactExpectedTimeStamp) {
+  base::File::Info info;
+  ASSERT_TRUE(base::GetFileInfo(temp_file_path_, &info));
+
+  const base::Time expected_modification_time =
+      info.last_modified - base::TimeDelta::FromMilliseconds(900);
+  reader_.reset(new UploadFileElementReader(
+      base::MessageLoopProxy::current().get(), temp_file_path_, 0, kuint64max,
+      expected_modification_time));
+  TestCompletionCallback init_callback;
+  ASSERT_EQ(ERR_IO_PENDING, reader_->Init(init_callback.callback()));
+  EXPECT_EQ(OK, init_callback.WaitForResult());
+}
+
 TEST_F(UploadFileElementReaderTest, WrongPath) {
   const base::FilePath wrong_path(FILE_PATH_LITERAL("wrong_path"));
   reader_.reset(
       new UploadFileElementReader(base::MessageLoopProxy::current().get(),
-                                  wrong_path,
-                                  0,
-                                  kuint64max,
-                                  base::Time()));
+                                  wrong_path, 0, kuint64max, base::Time()));
   TestCompletionCallback init_callback;
   ASSERT_EQ(ERR_IO_PENDING, reader_->Init(init_callback.callback()));
   EXPECT_EQ(ERR_FILE_NOT_FOUND, init_callback.WaitForResult());
diff --git a/net/cert/cert_verify_proc_android.h b/net/cert/cert_verify_proc_android.h
index 7002718..6830df6 100644
--- a/net/cert/cert_verify_proc_android.h
+++ b/net/cert/cert_verify_proc_android.h
@@ -15,18 +15,18 @@
  public:
   CertVerifyProcAndroid();
 
-  virtual bool SupportsAdditionalTrustAnchors() const override;
+  bool SupportsAdditionalTrustAnchors() const override;
 
  protected:
-  virtual ~CertVerifyProcAndroid();
+  ~CertVerifyProcAndroid() override;
 
  private:
-  virtual int VerifyInternal(X509Certificate* cert,
-                             const std::string& hostname,
-                             int flags,
-                             CRLSet* crl_set,
-                             const CertificateList& additional_trust_anchors,
-                             CertVerifyResult* verify_result) override;
+  int VerifyInternal(X509Certificate* cert,
+                     const std::string& hostname,
+                     int flags,
+                     CRLSet* crl_set,
+                     const CertificateList& additional_trust_anchors,
+                     CertVerifyResult* verify_result) override;
 };
 
 }  // namespace net
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc
index 7099225..388d0fc 100644
--- a/net/cert/cert_verify_proc_mac.cc
+++ b/net/cert/cert_verify_proc_mac.cc
@@ -175,12 +175,21 @@
   return noErr;
 }
 
-// Saves some information about the certificate chain |cert_chain| in
-// |*verify_result|. The caller MUST initialize |*verify_result| before
-// calling this function.
+// Stores the constructed certificate chain |cert_chain| and information about
+// the signature algorithms used into |*verify_result|. If the leaf cert in
+// |cert_chain| contains a weak (MD2, MD4, MD5, SHA-1) signature, stores that
+// in |*leaf_is_weak|.
 void GetCertChainInfo(CFArrayRef cert_chain,
                       CSSM_TP_APPLE_EVIDENCE_INFO* chain_info,
-                      CertVerifyResult* verify_result) {
+                      CertVerifyResult* verify_result,
+                      bool* leaf_is_weak) {
+  *leaf_is_weak = false;
+  verify_result->verified_cert = nullptr;
+  verify_result->has_md2 = false;
+  verify_result->has_md4 = false;
+  verify_result->has_md5 = false;
+  verify_result->has_sha1 = false;
+
   SecCertificateRef verified_cert = NULL;
   std::vector<SecCertificateRef> verified_chain;
   for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
@@ -223,10 +232,16 @@
     const CSSM_OID* alg_oid = &sig_algorithm->algorithm;
     if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA)) {
       verify_result->has_md2 = true;
+      if (i == 0)
+        *leaf_is_weak = true;
     } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA)) {
       verify_result->has_md4 = true;
+      if (i == 0)
+        *leaf_is_weak = true;
     } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA)) {
       verify_result->has_md5 = true;
+      if (i == 0)
+        *leaf_is_weak = true;
     } else if (CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA) ||
                CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
                CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
@@ -234,6 +249,8 @@
                CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
                CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) {
       verify_result->has_sha1 = true;
+      if (i == 0)
+        *leaf_is_weak = true;
     }
   }
   if (!verified_cert)
@@ -446,80 +463,6 @@
   return OK;
 }
 
-// OS X ships with both "GTE CyberTrust Global Root" and "Baltimore CyberTrust
-// Root" as part of its trusted root store. However, a cross-certified version
-// of the "Baltimore CyberTrust Root" exists that chains to "GTE CyberTrust
-// Global Root". When OS X/Security.framework attempts to evaluate such a
-// certificate chain, it disregards the "Baltimore CyberTrust Root" that exists
-// within Keychain and instead attempts to terminate the chain in the "GTE
-// CyberTrust Global Root". However, the GTE root is scheduled to be removed in
-// a future OS X update (for sunsetting purposes), and once removed, such
-// chains will fail validation, even though a trust anchor still exists.
-//
-// Rather than over-generalizing a solution that may mask a number of TLS
-// misconfigurations, attempt to specifically match the affected
-// cross-certified certificate and remove it from certificate chain processing.
-bool IsBadBaltimoreGTECertificate(SecCertificateRef cert) {
-  // Matches the GTE-signed Baltimore CyberTrust Root
-  // https://cacert.omniroot.com/Baltimore-to-GTE-04-12.pem
-  static const SHA1HashValue kBadBaltimoreHashNew =
-    { { 0x4D, 0x34, 0xEA, 0x92, 0x76, 0x4B, 0x3A, 0x31, 0x49, 0x11,
-        0x99, 0x52, 0xF4, 0x19, 0x30, 0xCA, 0x11, 0x34, 0x83, 0x61 } };
-  // Matches the legacy GTE-signed Baltimore CyberTrust Root
-  // https://cacert.omniroot.com/gte-2-2025.pem
-  static const SHA1HashValue kBadBaltimoreHashOld =
-    { { 0x54, 0xD8, 0xCB, 0x49, 0x1F, 0xA1, 0x6D, 0xF8, 0x87, 0xDC,
-        0x94, 0xA9, 0x34, 0xCC, 0x83, 0x6B, 0xDA, 0xA8, 0xA3, 0x69 } };
-
-  SHA1HashValue fingerprint = X509Certificate::CalculateFingerprint(cert);
-
-  return fingerprint.Equals(kBadBaltimoreHashNew) ||
-         fingerprint.Equals(kBadBaltimoreHashOld);
-}
-
-// Attempts to re-verify |cert_array| after adjusting the inputs to work around
-// known issues in OS X. To be used if BuildAndEvaluateSecTrustRef fails to
-// return a positive result for verification.
-//
-// This function should only be called while the Mac Security Services lock is
-// held.
-void RetrySecTrustEvaluateWithAdjustedChain(
-    CFArrayRef cert_array,
-    CFArrayRef trust_policies,
-    int flags,
-    ScopedCFTypeRef<SecTrustRef>* trust_ref,
-    SecTrustResultType* trust_result,
-    ScopedCFTypeRef<CFArrayRef>* verified_chain,
-    CSSM_TP_APPLE_EVIDENCE_INFO** chain_info) {
-  CFIndex count = CFArrayGetCount(*verified_chain);
-  CFIndex slice_point = 0;
-
-  for (CFIndex i = 1; i < count; ++i) {
-    SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
-        const_cast<void*>(CFArrayGetValueAtIndex(*verified_chain, i)));
-    if (cert == NULL)
-      return;  // Strange times; can't fix things up.
-
-    if (IsBadBaltimoreGTECertificate(cert)) {
-      slice_point = i;
-      break;
-    }
-  }
-  if (slice_point == 0)
-    return;  // Nothing to do.
-
-  ScopedCFTypeRef<CFMutableArrayRef> adjusted_cert_array(
-      CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks));
-  // Note: This excludes the certificate at |slice_point|.
-  CFArrayAppendArray(adjusted_cert_array, cert_array,
-                     CFRangeMake(0, slice_point));
-
-  // Ignore the result; failure will preserve the old verification results.
-  BuildAndEvaluateSecTrustRef(
-      adjusted_cert_array, trust_policies, flags, trust_ref, trust_result,
-      verified_chain, chain_info);
-}
-
 }  // namespace
 
 CertVerifyProcMac::CertVerifyProcMac() {}
@@ -547,7 +490,8 @@
   // array of certificates, the first of which is the certificate we're
   // verifying, and the subsequent (optional) certificates are used for
   // chain building.
-  ScopedCFTypeRef<CFArrayRef> cert_array(cert->CreateOSCertChainForCert());
+  ScopedCFTypeRef<CFMutableArrayRef> cert_array(
+      cert->CreateOSCertChainForCert());
 
   // Serialize all calls that may use the Keychain, to work around various
   // issues in OS X 10.6+ with multi-threaded access to Security.framework.
@@ -557,17 +501,106 @@
   SecTrustResultType trust_result = kSecTrustResultDeny;
   ScopedCFTypeRef<CFArrayRef> completed_chain;
   CSSM_TP_APPLE_EVIDENCE_INFO* chain_info = NULL;
+  bool candidate_untrusted = true;
+  bool candidate_weak = false;
 
-  int rv = BuildAndEvaluateSecTrustRef(
-      cert_array, trust_policies, flags, &trust_ref, &trust_result,
-      &completed_chain, &chain_info);
-  if (rv != OK)
-    return rv;
-  if (trust_result != kSecTrustResultUnspecified &&
-      trust_result != kSecTrustResultProceed) {
-    RetrySecTrustEvaluateWithAdjustedChain(
-        cert_array, trust_policies, flags, &trust_ref, &trust_result,
-        &completed_chain, &chain_info);
+  // OS X lacks proper path discovery; it will take the input certs and never
+  // backtrack the graph attempting to discover valid paths.
+  // This can create issues in some situations:
+  // - When OS X changes the trust store, there may be a chain
+  //     A -> B -> C -> D
+  //   where OS X trusts D (on some versions) and trusts C (on some versions).
+  //   If a server supplies a chain A, B, C (cross-signed by D), then this chain
+  //   will successfully validate on systems that trust D, but fail for systems
+  //   that trust C. If the server supplies a chain of A -> B, then it forces
+  //   all clients to fetch C (via AIA) if they trust D, and not all clients
+  //   (notably, Firefox and Android) will do this, thus breaking them.
+  //   An example of this is the Verizon Business Services root - GTE CyberTrust
+  //   and Baltimore CyberTrust roots represent old and new roots that cause
+  //   issues depending on which version of OS X being used.
+  //
+  // - A server may be (misconfigured) to send an expired intermediate
+  //   certificate. On platforms with path discovery, the graph traversal
+  //   will back up to immediately before this intermediate, and then
+  //   attempt an AIA fetch or retrieval from local store. However, OS X
+  //   does not do this, and thus prevents access. While this is ostensibly
+  //   a server misconfiguration issue, the fact that it works on other
+  //   platforms is a jarring inconsistency for users.
+  //
+  // - When OS X trusts both C and D (simultaneously), it's possible that the
+  //   version of C signed by D is signed using a weak algorithm (e.g. SHA-1),
+  //   while the version of C in the trust store's signature doesn't matter.
+  //   Since a 'strong' chain exists, it would be desirable to prefer this
+  //   chain.
+  //
+  // - A variant of the above example, it may be that the version of B sent by
+  //   the server is signed using a weak algorithm, but the version of B
+  //   present in the AIA of A is signed using a strong algorithm. Since a
+  //   'strong' chain exists, it would be desirable to prefer this chain.
+  //
+  // Because of this, the code below first attempts to validate the peer's
+  // identity using the supplied chain. If it is not trusted (e.g. the OS only
+  // trusts C, but the version of C signed by D was sent, and D is not trusted),
+  // or if it contains a weak chain, it will begin lopping off certificates
+  // from the end of the chain and attempting to verify. If a stronger, trusted
+  // chain is found, it is used, otherwise, the algorithm continues until only
+  // the peer's certificate remains.
+  //
+  // This does cause a performance hit for these users, but only in cases where
+  // OS X is building weaker chains than desired, or when it would otherwise
+  // fail the connection.
+  while (CFArrayGetCount(cert_array) > 0) {
+    ScopedCFTypeRef<SecTrustRef> temp_ref;
+    SecTrustResultType temp_trust_result = kSecTrustResultDeny;
+    ScopedCFTypeRef<CFArrayRef> temp_chain;
+    CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL;
+
+    int rv = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, flags,
+                                         &temp_ref, &temp_trust_result,
+                                         &temp_chain, &temp_chain_info);
+    if (rv != OK)
+      return rv;
+
+    CertVerifyResult temp_verify_result;
+    bool leaf_is_weak = false;
+    GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result,
+                     &leaf_is_weak);
+
+    bool untrusted = (temp_trust_result != kSecTrustResultUnspecified &&
+                      temp_trust_result != kSecTrustResultProceed);
+    bool weak_chain =
+        !leaf_is_weak &&
+        (temp_verify_result.has_md2 || temp_verify_result.has_md4 ||
+         temp_verify_result.has_md5 || temp_verify_result.has_sha1);
+    // Set the result to the current chain if:
+    // - This is the first verification attempt. This ensures that if
+    //   everything is awful (e.g. it may just be an untrusted cert), that
+    //   what is reported is exactly what was sent by the server
+    // - If the current chain is trusted, and the old chain was not trusted,
+    //   then prefer this chain. This ensures that if there is at least a
+    //   valid path to a trust anchor, it's preferred over reporting an error.
+    // - If the current chain is trusted, and the old chain is trusted, but
+    //   the old chain contained weak algorithms while the current chain only
+    //   contains strong algorithms, then prefer the current chain over the
+    //   old chain.
+    //
+    // Note: If the leaf certificate itself is weak, then the only
+    // consideration is whether or not there is a trusted chain. That's
+    // because no amount of path discovery will fix a weak leaf.
+    if (!trust_ref || (!untrusted && (candidate_untrusted ||
+                                      (candidate_weak && !weak_chain)))) {
+      trust_ref = temp_ref;
+      trust_result = temp_trust_result;
+      completed_chain = temp_chain;
+      chain_info = temp_chain_info;
+
+      candidate_untrusted = untrusted;
+      candidate_weak = weak_chain;
+    }
+    // Short-circuit when a current, trusted chain is found.
+    if (!untrusted && !weak_chain)
+      break;
+    CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1);
   }
 
   if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED)
@@ -576,7 +609,9 @@
   if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set))
     verify_result->cert_status |= CERT_STATUS_REVOKED;
 
-  GetCertChainInfo(completed_chain, chain_info, verify_result);
+  bool leaf_is_weak_unused = false;
+  GetCertChainInfo(completed_chain, chain_info, verify_result,
+                   &leaf_is_weak_unused);
 
   // As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits
   // is encountered, CSSM returns CSSMERR_TP_VERIFY_ACTION_FAILED and adds
diff --git a/net/cert/x509_certificate.h b/net/cert/x509_certificate.h
index c1a4f6d..6c0f0e9 100644
--- a/net/cert/x509_certificate.h
+++ b/net/cert/x509_certificate.h
@@ -251,12 +251,12 @@
   // Does this certificate's usage allow SSL client authentication?
   bool SupportsSSLClientAuth() const;
 
-  // Returns a new CFArrayRef containing this certificate and its intermediate
-  // certificates in the form expected by Security.framework and Keychain
-  // Services, or NULL on failure.
+  // Returns a new CFMutableArrayRef containing this certificate and its
+  // intermediate certificates in the form expected by Security.framework
+  // and Keychain Services, or NULL on failure.
   // The first item in the array will be this certificate, followed by its
   // intermediates, if any.
-  CFArrayRef CreateOSCertChainForCert() const;
+  CFMutableArrayRef CreateOSCertChainForCert() const;
 #endif
 
   // Do any of the given issuer names appear in this cert's chain of trust?
diff --git a/net/cert/x509_certificate_mac.cc b/net/cert/x509_certificate_mac.cc
index f8bfe12..10cfb56 100644
--- a/net/cert/x509_certificate_mac.cc
+++ b/net/cert/x509_certificate_mac.cc
@@ -449,7 +449,7 @@
   return true;
 }
 
-CFArrayRef X509Certificate::CreateOSCertChainForCert() const {
+CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const {
   CFMutableArrayRef cert_list =
       CFArrayCreateMutable(kCFAllocatorDefault, 0,
                            &kCFTypeArrayCallBacks);
diff --git a/net/disk_cache/blockfile/block_files.cc b/net/disk_cache/blockfile/block_files.cc
index 9aa8f0f..f46a937 100644
--- a/net/disk_cache/blockfile/block_files.cc
+++ b/net/disk_cache/blockfile/block_files.cc
@@ -656,11 +656,11 @@
   if (file_size < file_header.Size())
     return false;  // file_size > 2GB is also an error.
 
-  const int kMinBlockSize = 36;
-  const int kMaxBlockSize = 4096;
+  const int kMinHeaderBlockSize = 36;
+  const int kMaxHeaderBlockSize = 4096;
   BlockFileHeader* header = file_header.Header();
-  if (header->entry_size < kMinBlockSize ||
-      header->entry_size > kMaxBlockSize || header->num_entries < 0)
+  if (header->entry_size < kMinHeaderBlockSize ||
+      header->entry_size > kMaxHeaderBlockSize || header->num_entries < 0)
     return false;
 
   // Make sure that we survive crashes.
diff --git a/net/dns/dns_config_service_posix.cc b/net/dns/dns_config_service_posix.cc
index 4f6888b..135f3fd 100644
--- a/net/dns/dns_config_service_posix.cc
+++ b/net/dns/dns_config_service_posix.cc
@@ -64,7 +64,7 @@
     NetworkChangeNotifier::AddNetworkChangeObserver(this);
   }
 
-  virtual ~DnsConfigWatcher() {
+  ~DnsConfigWatcher() override {
     NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
   }
 
@@ -73,8 +73,7 @@
     return true;
   }
 
-  virtual void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type)
-      override {
+  void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
     if (!callback_.is_null() && type != NetworkChangeNotifier::CONNECTION_NONE)
       callback_.Run(true);
   }
diff --git a/net/dns/dns_config_service_win.cc b/net/dns/dns_config_service_win.cc
index b0da34e..8d0ac54 100644
--- a/net/dns/dns_config_service_win.cc
+++ b/net/dns/dns_config_service_win.cc
@@ -312,7 +312,8 @@
   void OnObjectSignaled() {
     // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
     tracked_objects::ScopedTracker tracking_profile(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION("RegistryWatcher_OnObjectSignaled"));
+        FROM_HERE_WITH_EXPLICIT_FUNCTION(
+            "418183 RegistryWatcher::OnObjectSignaled"));
 
     DCHECK(CalledOnValidThread());
     DCHECK(!callback_.is_null());
diff --git a/net/dns/dns_hosts.cc b/net/dns/dns_hosts.cc
index b4d213b..697ea14 100644
--- a/net/dns/dns_hosts.cc
+++ b/net/dns/dns_hosts.cc
@@ -131,7 +131,6 @@
                              DnsHosts* dns_hosts,
                              ParseHostsCommaMode comma_mode) {
   CHECK(dns_hosts);
-  DnsHosts& hosts = *dns_hosts;
 
   StringPiece ip_text;
   IPAddressNumber ip;
@@ -156,9 +155,9 @@
     } else {
       DnsHostsKey key(parser.token().as_string(), family);
       base::StringToLowerASCII(&key.first);
-      IPAddressNumber& mapped_ip = hosts[key];
-      if (mapped_ip.empty())
-        mapped_ip = ip;
+      IPAddressNumber* mapped_ip = &(*dns_hosts)[key];
+      if (mapped_ip->empty())
+        *mapped_ip = ip;
       // else ignore this entry (first hit counts)
     }
   }
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 2b308c7..ef6adb8 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -239,11 +239,6 @@
   return OK;
 }
 
-int FtpNetworkTransaction::RestartIgnoringLastError(
-    const CompletionCallback& callback) {
-  return ERR_NOT_IMPLEMENTED;
-}
-
 int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info,
                                  const CompletionCallback& callback,
                                  const BoundNetLog& net_log) {
@@ -1033,16 +1028,18 @@
 
 int FtpNetworkTransaction::ProcessResponseRETR(
     const FtpCtrlResponse& response) {
+  // Resource type should be either filled in by DetectTypecode() or
+  // detected with CWD. RETR is sent only when the resource is a file.
+  DCHECK_EQ(RESOURCE_TYPE_FILE, resource_type_);
+
   switch (GetErrorClass(response.status_code)) {
     case ERROR_CLASS_INITIATED:
       // We want the client to start reading the response at this point.
       // It got here either through Start or RestartWithAuth. We want that
       // method to complete. Not setting next state here will make DoLoop exit
       // and in turn make Start/RestartWithAuth complete.
-      resource_type_ = RESOURCE_TYPE_FILE;
       break;
     case ERROR_CLASS_OK:
-      resource_type_ = RESOURCE_TYPE_FILE;
       next_state_ = STATE_CTRL_WRITE_QUIT;
       break;
     case ERROR_CLASS_INFO_NEEDED:
@@ -1056,10 +1053,6 @@
       return Stop(ERR_UNEXPECTED);
   }
 
-  // We should be sure about our resource type now. Otherwise we risk
-  // an infinite loop (RETR can later send CWD, and CWD can later send RETR).
-  DCHECK_NE(RESOURCE_TYPE_UNKNOWN, resource_type_);
-
   return OK;
 }
 
@@ -1095,6 +1088,7 @@
       break;
     case ERROR_CLASS_PERMANENT_ERROR:
       // It's possible that SIZE failed because the path is a directory.
+      // TODO(xunjieli): Add a test for this case.
       if (resource_type_ == RESOURCE_TYPE_UNKNOWN &&
           response.status_code != 550) {
         return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
@@ -1104,6 +1098,9 @@
       NOTREACHED();
       return Stop(ERR_UNEXPECTED);
   }
+
+  // If the resource is known beforehand to be a file, RETR should be issued,
+  // otherwise do CWD which will detect the resource type.
   if (resource_type_ == RESOURCE_TYPE_FILE)
     EstablishDataConnection(STATE_CTRL_WRITE_RETR);
   else
@@ -1119,13 +1116,14 @@
 }
 
 int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
-  // We should never issue CWD if we know the target resource is a file.
+  // CWD should be invoked only when the resource is not a file.
   DCHECK_NE(RESOURCE_TYPE_FILE, resource_type_);
 
   switch (GetErrorClass(response.status_code)) {
     case ERROR_CLASS_INITIATED:
       return Stop(ERR_INVALID_RESPONSE);
     case ERROR_CLASS_OK:
+      resource_type_ = RESOURCE_TYPE_DIRECTORY;
       EstablishDataConnection(STATE_CTRL_WRITE_LIST);
       break;
     case ERROR_CLASS_INFO_NEEDED:
@@ -1158,9 +1156,7 @@
     return Stop(ERR_FILE_NOT_FOUND);
   }
 
-  // We are here because SIZE failed and we are not sure what the resource
-  // type is. It could still be file, and SIZE could fail because of
-  // an access error (http://crbug.com/56734). Try RETR just to be sure.
+  // If it is not a directory, it is probably a file.
   resource_type_ = RESOURCE_TYPE_FILE;
 
   EstablishDataConnection(STATE_CTRL_WRITE_RETR);
@@ -1182,6 +1178,10 @@
 
 int FtpNetworkTransaction::ProcessResponseLIST(
     const FtpCtrlResponse& response) {
+  // Resource type should be either filled in by DetectTypecode() or
+  // detected with CWD. LIST is sent only when the resource is a directory.
+  DCHECK_EQ(RESOURCE_TYPE_DIRECTORY, resource_type_);
+
   switch (GetErrorClass(response.status_code)) {
     case ERROR_CLASS_INITIATED:
       // We want the client to start reading the response at this point.
diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h
index fc94ae7..6bf01bd 100644
--- a/net/ftp/ftp_network_transaction.h
+++ b/net/ftp/ftp_network_transaction.h
@@ -33,8 +33,7 @@
                         ClientSocketFactory* socket_factory);
   ~FtpNetworkTransaction() override;
 
-  virtual int Stop(int error);
-  virtual int RestartIgnoringLastError(const CompletionCallback& callback);
+  int Stop(int error);
 
   // FtpTransaction methods:
   int Start(const FtpRequestInfo* request_info,
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index ede22d3..79e1687 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -918,7 +918,7 @@
 
 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithTypecode) {
   FtpSocketDataProviderDirectoryListing ctrl_socket;
-  ExecuteTransaction(&ctrl_socket, "ftp://host;type=d", OK);
+  ExecuteTransaction(&ctrl_socket, "ftp://host/;type=d", OK);
 
   EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
   EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
diff --git a/net/http/http_atom_list.h b/net/http/http_atom_list.h
deleted file mode 100644
index 4dac9fb..0000000
--- a/net/http/http_atom_list.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-HTTP_ATOM(ACCEPT)
-HTTP_ATOM(ACCEPT_CHARSET)
-HTTP_ATOM(ACCEPT_ENCODING)
-HTTP_ATOM(ACCEPT_LANGUAGE)
-HTTP_ATOM(ACCEPT_RANGES)
-HTTP_ATOM(AGE)
-HTTP_ATOM(ALLOW)
-HTTP_ATOM(AUTHORIZATION)
-HTTP_ATOM(CACHE_CONTROL)
-HTTP_ATOM(CONNECTION)
-HTTP_ATOM(CONTENT_BASE)
-HTTP_ATOM(CONTENT_DISPOSITION)
-HTTP_ATOM(CONTENT_ENCODING)
-HTTP_ATOM(CONTENT_LANGUAGE)
-HTTP_ATOM(CONTENT_LENGTH)
-HTTP_ATOM(CONTENT_LOCATION)
-HTTP_ATOM(CONTENT_MD5)
-HTTP_ATOM(CONTENT_RANGE)
-HTTP_ATOM(CONTENT_TRANSFER_ENCODING)
-HTTP_ATOM(CONTENT_TYPE)
-HTTP_ATOM(COOKIE)
-HTTP_ATOM(DATE)
-HTTP_ATOM(DERIVED_FROM)
-HTTP_ATOM(ETAG)
-HTTP_ATOM(EXPECT)
-HTTP_ATOM(EXPIRES)
-HTTP_ATOM(FORWARDED)
-HTTP_ATOM(FROM)
-HTTP_ATOM(HOST)
-HTTP_ATOM(IF_MATCH)
-HTTP_ATOM(IF_MODIFIED_SINCE)
-HTTP_ATOM(IF_NONE_MATCH)
-HTTP_ATOM(IF_RANGE)
-HTTP_ATOM(IF_UNMODIFIED_SINCE)
-HTTP_ATOM(LAST_MODIFIED)
-HTTP_ATOM(LINK)
-HTTP_ATOM(LOCATION)
-HTTP_ATOM(MAX_FORWARDS)
-HTTP_ATOM(MESSAGE_ID)
-HTTP_ATOM(PRAGMA)
-HTTP_ATOM(PROXY_AUTHENTICATE)
-HTTP_ATOM(PROXY_AUTHORIZATION)
-HTTP_ATOM(PROXY_CONNECTION)
-HTTP_ATOM(RANGE)
-HTTP_ATOM(REFERER)
-HTTP_ATOM(REFRESH)
-HTTP_ATOM(RETRY_AFTER)
-HTTP_ATOM(SERVER)
-HTTP_ATOM(SET_COOKIE)
-HTTP_ATOM(TITLE)
-HTTP_ATOM(TRANSFER_ENCODING)
-HTTP_ATOM(UPGRADE)
-HTTP_ATOM(USER_AGENT)
-HTTP_ATOM(VARY)
-HTTP_ATOM(VIA)
-HTTP_ATOM(WARNING)
-HTTP_ATOM(WWW_AUTHENTICATE)
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 3376051..3908d74 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -97,7 +97,7 @@
       enable_user_alternate_protocol_ports(false),
       quic_crypto_client_stream_factory(NULL),
       proxy_delegate(NULL) {
-  quic_supported_versions.push_back(QUIC_VERSION_23);
+  quic_supported_versions.push_back(QUIC_VERSION_24);
 }
 
 HttpNetworkSession::Params::~Params() {}
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 8f33e20..69a3aa5 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -571,7 +571,8 @@
 }
 
 bool HttpNetworkTransaction::UsingHttpProxyWithoutTunnel() const {
-  return (proxy_info_.is_http() || proxy_info_.is_https()) &&
+  return (proxy_info_.is_http() || proxy_info_.is_https() ||
+          proxy_info_.is_quic()) &&
          !(request_->url.SchemeIs("https") || request_->url.SchemeIsWSOrWSS());
 }
 
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 1c70393..c3eab76 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -8508,8 +8508,9 @@
   HostPortPair http_host_port_pair("www.google.com", 80);
   HttpServerProperties& http_server_properties =
       *session->http_server_properties();
-  EXPECT_FALSE(
-      http_server_properties.HasAlternateProtocol(http_host_port_pair));
+  AlternateProtocolInfo alternate =
+      http_server_properties.GetAlternateProtocol(http_host_port_pair);
+  EXPECT_EQ(alternate.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
 
   EXPECT_EQ(OK, callback.WaitForResult());
 
@@ -8524,12 +8525,10 @@
   ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
   EXPECT_EQ("hello world", response_data);
 
-  ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
-  const AlternateProtocolInfo alternate =
-      http_server_properties.GetAlternateProtocol(http_host_port_pair);
-  AlternateProtocolInfo expected_alternate(
-      443, AlternateProtocolFromNextProto(GetParam()), 1);
-  EXPECT_TRUE(expected_alternate.Equals(alternate));
+  alternate = http_server_properties.GetAlternateProtocol(http_host_port_pair);
+  EXPECT_EQ(443, alternate.port);
+  EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()), alternate.protocol);
+  EXPECT_EQ(1.0, alternate.probability);
 }
 
 TEST_P(HttpNetworkTransactionTest,
@@ -8583,11 +8582,10 @@
   ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
   EXPECT_EQ("hello world", response_data);
 
-  ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
-      HostPortPair::FromURL(request.url)));
   const AlternateProtocolInfo alternate =
       http_server_properties->GetAlternateProtocol(
           HostPortPair::FromURL(request.url));
+  EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternate.protocol);
   EXPECT_TRUE(alternate.is_broken);
 }
 
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index 9c8a531..b97c957 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -128,6 +128,10 @@
 }
 
 void HttpProxyConnectJob::OnIOComplete(int result) {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "455884 HttpProxyConnectJob::OnIOComplete"));
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING) {
     NotifyProxyDelegateOfCompletion(rv);
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h
index 840a359..dcb4cdc 100644
--- a/net/http/http_server_properties.h
+++ b/net/http/http_server_properties.h
@@ -13,6 +13,7 @@
 #include "base/time/time.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_export.h"
+#include "net/base/net_util.h"
 #include "net/quic/quic_bandwidth.h"
 #include "net/socket/next_proto.h"
 #include "net/spdy/spdy_framer.h"  // TODO(willchan): Reconsider this.
@@ -147,7 +148,6 @@
 typedef base::MRUCache<
     HostPortPair, AlternateProtocolInfo> AlternateProtocolMap;
 typedef base::MRUCache<HostPortPair, SettingsMap> SpdySettingsMap;
-typedef std::map<HostPortPair, SupportsQuic> SupportsQuicMap;
 typedef base::MRUCache<HostPortPair, ServerNetworkStats> ServerNetworkStatsMap;
 
 extern const char kAlternateProtocolHeader[];
@@ -190,11 +190,9 @@
   virtual void MaybeForceHTTP11(const HostPortPair& server,
                                 SSLConfig* ssl_config) = 0;
 
-  // Returns true if |server| has an Alternate-Protocol header.
-  virtual bool HasAlternateProtocol(const HostPortPair& server) = 0;
-
-  // Returns the Alternate-Protocol and port for |server|.
-  // HasAlternateProtocol(server) must be true.
+  // Returns the AlternateProtocol for |server| if it has probability equal to
+  // or exceeding threshold, or else the forced AlternateProtocol if there is
+  // one, or else one with UNINITIALIZED_ALTERNATE_PROTOCOL.
   virtual AlternateProtocolInfo GetAlternateProtocol(
       const HostPortPair& server) = 0;
 
@@ -249,15 +247,10 @@
   // Returns all persistent SPDY settings.
   virtual const SpdySettingsMap& spdy_settings_map() const = 0;
 
-  // TODO(rtenneti): Make SupportsQuic a global (instead of per host_port_pair).
-  virtual SupportsQuic GetSupportsQuic(
-      const HostPortPair& host_port_pair) const = 0;
+  virtual bool GetSupportsQuic(IPAddressNumber* last_address) const = 0;
 
-  virtual void SetSupportsQuic(const HostPortPair& host_port_pair,
-                               bool used_quic,
-                               const std::string& address) = 0;
-
-  virtual const SupportsQuicMap& supports_quic_map() const = 0;
+  virtual void SetSupportsQuic(bool used_quic,
+                               const IPAddressNumber& last_address) = 0;
 
   virtual void SetServerNetworkStats(const HostPortPair& host_port_pair,
                                      ServerNetworkStats stats) = 0;
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
index a53e73f..9f17afc 100644
--- a/net/http/http_server_properties_impl.cc
+++ b/net/http/http_server_properties_impl.cc
@@ -102,12 +102,9 @@
 }
 
 void HttpServerPropertiesImpl::InitializeSupportsQuic(
-    SupportsQuicMap* supports_quic_map) {
-  for (SupportsQuicMap::reverse_iterator it = supports_quic_map->rbegin();
-       it != supports_quic_map->rend();
-       ++it) {
-    supports_quic_map_.insert(std::make_pair(it->first, it->second));
-  }
+    IPAddressNumber* last_address) {
+  if (last_address)
+    last_quic_address_ = *last_address;
 }
 
 void HttpServerPropertiesImpl::InitializeServerNetworkStats(
@@ -164,7 +161,7 @@
   alternate_protocol_map_.Clear();
   canonical_host_to_origin_map_.clear();
   spdy_settings_map_.Clear();
-  supports_quic_map_.clear();
+  last_quic_address_.clear();
   server_network_stats_map_.Clear();
 }
 
@@ -179,10 +176,7 @@
   if (spdy_host_port != spdy_servers_map_.end() && spdy_host_port->second)
     return true;
 
-  if (!HasAlternateProtocol(host_port_pair))
-    return false;
-
-  AlternateProtocolInfo info = GetAlternateProtocol(host_port_pair);
+  const AlternateProtocolInfo info = GetAlternateProtocol(host_port_pair);
   return info.protocol == QUIC;
 }
 
@@ -228,16 +222,6 @@
   }
 }
 
-bool HttpServerPropertiesImpl::HasAlternateProtocol(
-    const HostPortPair& server) {
-  if (g_forced_alternate_protocol)
-    return true;
-  AlternateProtocolMap::const_iterator it =
-      GetAlternateProtocolIterator(server);
-  return it != alternate_protocol_map_.end() &&
-         it->second.probability >= alternate_protocol_probability_threshold_;
-}
-
 std::string HttpServerPropertiesImpl::GetCanonicalSuffix(
     const std::string& host) {
   // If this host ends with a canonical suffix, then return the canonical
@@ -251,19 +235,19 @@
   return std::string();
 }
 
-AlternateProtocolInfo
-HttpServerPropertiesImpl::GetAlternateProtocol(
+AlternateProtocolInfo HttpServerPropertiesImpl::GetAlternateProtocol(
     const HostPortPair& server) {
-  DCHECK(HasAlternateProtocol(server));
-
   AlternateProtocolMap::const_iterator it =
       GetAlternateProtocolIterator(server);
-  if (it != alternate_protocol_map_.end())
+  if (it != alternate_protocol_map_.end() &&
+      it->second.probability >= alternate_protocol_probability_threshold_)
     return it->second;
 
-  // We must be forcing an alternate.
-  DCHECK(g_forced_alternate_protocol);
-  return *g_forced_alternate_protocol;
+  if (g_forced_alternate_protocol)
+    return *g_forced_alternate_protocol;
+
+  AlternateProtocolInfo uninitialized_alternate_protocol;
+  return uninitialized_alternate_protocol;
 }
 
 void HttpServerPropertiesImpl::SetAlternateProtocol(
@@ -322,24 +306,26 @@
 void HttpServerPropertiesImpl::SetBrokenAlternateProtocol(
     const HostPortPair& server) {
   AlternateProtocolMap::iterator it = alternate_protocol_map_.Get(server);
+  const AlternateProtocolInfo alternate = GetAlternateProtocol(server);
   if (it == alternate_protocol_map_.end()) {
-    if (!HasAlternateProtocol(server)) {
+    if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) {
       LOG(DFATAL) << "Trying to mark unknown alternate protocol broken.";
       return;
     }
     // This server's alternate protocol information is coming from a canonical
     // server. Add an entry in the map for this server explicitly so that
     // it can be marked as broken.
-    it = alternate_protocol_map_.Put(server, GetAlternateProtocol(server));
+    it = alternate_protocol_map_.Put(server, alternate);
   }
   it->second.is_broken = true;
-  int count = ++broken_alternate_protocol_map_[server];
+  const BrokenAlternateProtocolEntry entry(server, alternate.port,
+                                           alternate.protocol);
+  int count = ++broken_alternate_protocol_map_[entry];
   base::TimeDelta delay =
       base::TimeDelta::FromSeconds(kBrokenAlternateProtocolDelaySecs);
-  BrokenAlternateProtocolEntry entry;
-  entry.server = server;
-  entry.when = base::TimeTicks::Now() + delay * (1 << (count - 1));
-  broken_alternate_protocol_list_.push_back(entry);
+  base::TimeTicks when = base::TimeTicks::Now() + delay * (1 << (count - 1));
+  broken_alternate_protocol_list_.push_back(
+      BrokenAlternateProtocolEntryWithTime(entry, when));
 
   // Do not leave this host as canonical so that we don't infer the other
   // hosts are also broken without testing them first.
@@ -354,12 +340,22 @@
 
 bool HttpServerPropertiesImpl::WasAlternateProtocolRecentlyBroken(
     const HostPortPair& server) {
-  return ContainsKey(broken_alternate_protocol_map_, server);
+  const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server);
+  if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+    return false;
+  const BrokenAlternateProtocolEntry entry(server, alternate_protocol.port,
+                                           alternate_protocol.protocol);
+  return ContainsKey(broken_alternate_protocol_map_, entry);
 }
 
 void HttpServerPropertiesImpl::ConfirmAlternateProtocol(
     const HostPortPair& server) {
-  broken_alternate_protocol_map_.erase(server);
+  const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server);
+  if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+    return;
+  const BrokenAlternateProtocolEntry entry(server, alternate_protocol.port,
+                                           alternate_protocol.protocol);
+  broken_alternate_protocol_map_.erase(entry);
 }
 
 void HttpServerPropertiesImpl::ClearAlternateProtocol(
@@ -423,26 +419,22 @@
   return spdy_settings_map_;
 }
 
-SupportsQuic HttpServerPropertiesImpl::GetSupportsQuic(
-    const HostPortPair& host_port_pair) const {
-  SupportsQuicMap::const_iterator it = supports_quic_map_.find(host_port_pair);
-  if (it == supports_quic_map_.end()) {
-    CR_DEFINE_STATIC_LOCAL(SupportsQuic, kEmptySupportsQuic, ());
-    return kEmptySupportsQuic;
+bool HttpServerPropertiesImpl::GetSupportsQuic(
+    IPAddressNumber* last_address) const {
+  if (last_quic_address_.empty())
+    return false;
+
+  *last_address = last_quic_address_;
+  return true;
+}
+
+void HttpServerPropertiesImpl::SetSupportsQuic(bool used_quic,
+                                               const IPAddressNumber& address) {
+  if (!used_quic) {
+    last_quic_address_.clear();
+  } else {
+    last_quic_address_ = address;
   }
-  return it->second;
-}
-
-void HttpServerPropertiesImpl::SetSupportsQuic(
-    const HostPortPair& host_port_pair,
-    bool used_quic,
-    const std::string& address) {
-  SupportsQuic supports_quic(used_quic, address);
-  supports_quic_map_.insert(std::make_pair(host_port_pair, supports_quic));
-}
-
-const SupportsQuicMap& HttpServerPropertiesImpl::supports_quic_map() const {
-  return supports_quic_map_;
 }
 
 void HttpServerPropertiesImpl::SetServerNetworkStats(
@@ -513,12 +505,14 @@
 void HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings() {
   base::TimeTicks now = base::TimeTicks::Now();
   while (!broken_alternate_protocol_list_.empty()) {
-    BrokenAlternateProtocolEntry entry =
+    BrokenAlternateProtocolEntryWithTime entry_with_time =
         broken_alternate_protocol_list_.front();
-    if (now < entry.when) {
+    if (now < entry_with_time.when) {
       break;
     }
 
+    const BrokenAlternateProtocolEntry& entry =
+        entry_with_time.broken_alternate_protocol_entry;
     ClearAlternateProtocol(entry.server);
     broken_alternate_protocol_list_.pop_front();
   }
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h
index 8d251a2..5c84226 100644
--- a/net/http/http_server_properties_impl.h
+++ b/net/http/http_server_properties_impl.h
@@ -5,6 +5,7 @@
 #ifndef NET_HTTP_HTTP_SERVER_PROPERTIES_IMPL_H_
 #define NET_HTTP_HTTP_SERVER_PROPERTIES_IMPL_H_
 
+#include <deque>
 #include <map>
 #include <set>
 #include <string>
@@ -43,7 +44,7 @@
 
   void InitializeSpdySettingsServers(SpdySettingsMap* spdy_settings_map);
 
-  void InitializeSupportsQuic(SupportsQuicMap* supports_quic_map);
+  void InitializeSupportsQuic(IPAddressNumber* last_address);
 
   void InitializeServerNetworkStats(
       ServerNetworkStatsMap* server_network_stats_map);
@@ -79,7 +80,6 @@
   void SetHTTP11Required(const HostPortPair& server) override;
   void MaybeForceHTTP11(const HostPortPair& server,
                         SSLConfig* ssl_config) override;
-  bool HasAlternateProtocol(const HostPortPair& server) override;
   AlternateProtocolInfo GetAlternateProtocol(
       const HostPortPair& server) override;
   void SetAlternateProtocol(const HostPortPair& server,
@@ -101,12 +101,8 @@
   void ClearSpdySettings(const HostPortPair& host_port_pair) override;
   void ClearAllSpdySettings() override;
   const SpdySettingsMap& spdy_settings_map() const override;
-  SupportsQuic GetSupportsQuic(
-      const HostPortPair& host_port_pair) const override;
-  void SetSupportsQuic(const HostPortPair& host_port_pair,
-                       bool used_quic,
-                       const std::string& address) override;
-  const SupportsQuicMap& supports_quic_map() const override;
+  bool GetSupportsQuic(IPAddressNumber* last_address) const override;
+  void SetSupportsQuic(bool used_quic, const IPAddressNumber& address) override;
   void SetServerNetworkStats(const HostPortPair& host_port_pair,
                              ServerNetworkStats stats) override;
   const ServerNetworkStats* GetServerNetworkStats(
@@ -120,16 +116,48 @@
   typedef std::map<HostPortPair, HostPortPair> CanonicalHostMap;
   typedef std::vector<std::string> CanonicalSufficList;
   typedef std::set<HostPortPair> Http11ServerHostPortSet;
-  // List of broken host:ports and the times when they can be expired.
+
+  // Server, port, and AlternateProtocol: an entity that can be broken.  (Once
+  // we use AlternativeService, the same AltSvc can be broken for one server but
+  // not for another depending on what certificate it can offer.)
   struct BrokenAlternateProtocolEntry {
+    BrokenAlternateProtocolEntry(const BrokenAlternateProtocolEntry&) = default;
+    BrokenAlternateProtocolEntry(const HostPortPair& server,
+                                 uint16 port,
+                                 AlternateProtocol protocol)
+        : server(server), port(port), protocol(protocol) {}
+
+    bool operator<(const BrokenAlternateProtocolEntry& other) const {
+      if (!server.Equals(other.server))
+        return server < other.server;
+      if (port != other.port)
+        return port < other.port;
+      return protocol < other.protocol;
+    }
+
     HostPortPair server;
+    uint16 port;
+    AlternateProtocol protocol;
+  };
+  // BrokenAlternateProtocolEntry with expiration time.
+  struct BrokenAlternateProtocolEntryWithTime {
+    BrokenAlternateProtocolEntryWithTime(
+        const BrokenAlternateProtocolEntry& broken_alternate_protocol_entry,
+        base::TimeTicks when)
+        : broken_alternate_protocol_entry(broken_alternate_protocol_entry),
+          when(when) {}
+
+    BrokenAlternateProtocolEntry broken_alternate_protocol_entry;
     base::TimeTicks when;
   };
-  typedef std::list<BrokenAlternateProtocolEntry>
+  // Deque of BrokenAlternateProtocolEntryWithTime items, ordered by expiration
+  // time.
+  typedef std::deque<BrokenAlternateProtocolEntryWithTime>
       BrokenAlternateProtocolList;
-  // Map from host:port to the number of times alternate protocol has
-  // been marked broken.
-  typedef std::map<HostPortPair, int> BrokenAlternateProtocolMap;
+  // Map from (server, alternate protocol and port) to the number of
+  // times that alternate protocol has been marked broken for that server.
+  typedef std::map<BrokenAlternateProtocolEntry, int>
+      BrokenAlternateProtocolMap;
 
   // Return the iterator for |server|, or for its canonical host, or end.
   AlternateProtocolMap::const_iterator GetAlternateProtocolIterator(
@@ -149,8 +177,8 @@
   BrokenAlternateProtocolList broken_alternate_protocol_list_;
   BrokenAlternateProtocolMap broken_alternate_protocol_map_;
 
+  IPAddressNumber last_quic_address_;
   SpdySettingsMap spdy_settings_map_;
-  SupportsQuicMap supports_quic_map_;
   ServerNetworkStatsMap server_network_stats_map_;
   // Contains a map of servers which could share the same alternate protocol.
   // Map from a Canonical host/port (host is some postfix of host names) to an
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc
index be5e6b9..d6c2c1c 100644
--- a/net/http/http_server_properties_impl_unittest.cc
+++ b/net/http/http_server_properties_impl_unittest.cc
@@ -27,6 +27,11 @@
 
 class HttpServerPropertiesImplTest : public testing::Test {
  protected:
+  bool HasAlternateProtocol(const HostPortPair& server) {
+    const AlternateProtocolInfo alternate = impl_.GetAlternateProtocol(server);
+    return alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL;
+  }
+
   HttpServerPropertiesImpl impl_;
 };
 
@@ -219,23 +224,23 @@
 
 TEST_F(AlternateProtocolServerPropertiesTest, Basic) {
   HostPortPair test_host_port_pair("foo", 80);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
   impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
   const AlternateProtocolInfo alternate =
       impl_.GetAlternateProtocol(test_host_port_pair);
   EXPECT_EQ(443, alternate.port);
   EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
 
   impl_.Clear();
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, DefaultProbabilityExcluded) {
   HostPortPair test_host_port_pair("foo", 80);
   impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, .99);
 
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, Probability) {
@@ -244,7 +249,7 @@
   HostPortPair test_host_port_pair("foo", 80);
   impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, .5);
 
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
   const AlternateProtocolInfo alternate =
       impl_.GetAlternateProtocol(test_host_port_pair);
   EXPECT_EQ(443, alternate.port);
@@ -258,7 +263,7 @@
   HostPortPair test_host_port_pair("foo", 80);
 
   impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, .5);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
@@ -284,8 +289,8 @@
   EXPECT_EQ(1234, it->second.port);
   EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
 
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair1));
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair2));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair1));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair2));
   alternate = impl_.GetAlternateProtocol(test_host_port_pair1);
   EXPECT_TRUE(alternate.is_broken);
   alternate = impl_.GetAlternateProtocol(test_host_port_pair2);
@@ -293,26 +298,6 @@
   EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
 }
 
-TEST_F(AlternateProtocolServerPropertiesTest, MRUOfHasAlternateProtocol) {
-  HostPortPair test_host_port_pair1("foo1", 80);
-  impl_.SetAlternateProtocol(test_host_port_pair1, 443, NPN_SPDY_3, 1.0);
-  HostPortPair test_host_port_pair2("foo2", 80);
-  impl_.SetAlternateProtocol(test_host_port_pair2, 1234, NPN_SPDY_3, 1.0);
-
-  const AlternateProtocolMap& map = impl_.alternate_protocol_map();
-  AlternateProtocolMap::const_iterator it = map.begin();
-  EXPECT_TRUE(it->first.Equals(test_host_port_pair2));
-  EXPECT_EQ(1234, it->second.port);
-  EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
-
-  // HasAlternateProtocol should reorder the AlternateProtocol map.
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair1));
-  it = map.begin();
-  EXPECT_TRUE(it->first.Equals(test_host_port_pair1));
-  EXPECT_EQ(443, it->second.port);
-  EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
-}
-
 TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternateProtocol) {
   HostPortPair test_host_port_pair1("foo1", 80);
   impl_.SetAlternateProtocol(test_host_port_pair1, 443, NPN_SPDY_3, 1.0);
@@ -340,7 +325,7 @@
   HostPortPair test_host_port_pair("foo", 80);
   impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
   impl_.SetBrokenAlternateProtocol(test_host_port_pair);
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
   AlternateProtocolInfo alternate =
       impl_.GetAlternateProtocol(test_host_port_pair);
   EXPECT_TRUE(alternate.is_broken);
@@ -354,12 +339,12 @@
   HostPortPair test_host_port_pair("foo", 80);
   impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
   impl_.SetBrokenAlternateProtocol(test_host_port_pair);
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
   AlternateProtocolInfo alternate =
       impl_.GetAlternateProtocol(test_host_port_pair);
   EXPECT_TRUE(alternate.is_broken);
   impl_.ClearAlternateProtocol(test_host_port_pair);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, Forced) {
@@ -370,7 +355,7 @@
 
   // Verify the forced protocol.
   HostPortPair test_host_port_pair("foo", 80);
-  EXPECT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_TRUE(HasAlternateProtocol(test_host_port_pair));
   AlternateProtocolInfo alternate =
       impl_.GetAlternateProtocol(test_host_port_pair);
   EXPECT_EQ(default_protocol.port, alternate.port);
@@ -378,7 +363,7 @@
 
   // Verify the real protocol overrides the forced protocol.
   impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
   alternate = impl_.GetAlternateProtocol(test_host_port_pair);
   EXPECT_EQ(443, alternate.port);
   EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
@@ -389,22 +374,22 @@
 
   // Verify the forced protocol is off.
   HostPortPair test_host_port_pair2("bar", 80);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair2));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair2));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
   HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 
   HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(canonical_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(canonical_port_pair));
 
   AlternateProtocolInfo canonical_protocol(1234, QUIC, 1);
 
   impl_.SetAlternateProtocol(canonical_port_pair, canonical_protocol.port,
                              canonical_protocol.protocol, 1.0);
   // Verify the forced protocol.
-  ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
   AlternateProtocolInfo alternate =
       impl_.GetAlternateProtocol(test_host_port_pair);
   EXPECT_EQ(canonical_protocol.port, alternate.port);
@@ -427,8 +412,8 @@
   impl_.SetAlternateProtocol(canonical_port_pair, canonical_protocol.port,
                              canonical_protocol.protocol,
                              canonical_protocol.probability);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(canonical_port_pair));
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(canonical_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, CanonicalAboveThreshold) {
@@ -441,8 +426,8 @@
   impl_.SetAlternateProtocol(canonical_port_pair, canonical_protocol.port,
                              canonical_protocol.protocol,
                              canonical_protocol.probability);
-  EXPECT_TRUE(impl_.HasAlternateProtocol(canonical_port_pair));
-  EXPECT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_TRUE(HasAlternateProtocol(canonical_port_pair));
+  EXPECT_TRUE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) {
@@ -456,7 +441,7 @@
                              canonical_protocol.probability);
 
   impl_.ClearAlternateProtocol(canonical_port_pair);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken) {
@@ -470,7 +455,7 @@
                              canonical_protocol.probability);
 
   impl_.SetBrokenAlternateProtocol(canonical_port_pair);
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken2) {
@@ -500,7 +485,7 @@
                              canonical_protocol.probability);
 
   impl_.Clear();
-  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+  EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
 }
 
 typedef HttpServerPropertiesImplTest SpdySettingsServerPropertiesTest;
@@ -695,37 +680,37 @@
 TEST_F(SupportsQuicServerPropertiesTest, Initialize) {
   HostPortPair quic_server_google("www.google.com", 443);
 
-  // Check by initializing empty SupportsQuic.
-  SupportsQuicMap supports_quic_map;
-  impl_.InitializeSupportsQuic(&supports_quic_map);
-  SupportsQuic supports_quic = impl_.GetSupportsQuic(quic_server_google);
-  EXPECT_FALSE(supports_quic.used_quic);
-  EXPECT_EQ("", supports_quic.address);
+  // Check by initializing empty address.
+  IPAddressNumber initial_address;
+  impl_.InitializeSupportsQuic(&initial_address);
 
-  // Check by initializing with www.google.com:443.
-  SupportsQuic supports_quic1(true, "foo");
-  supports_quic_map.insert(std::make_pair(quic_server_google, supports_quic1));
-  impl_.InitializeSupportsQuic(&supports_quic_map);
+  IPAddressNumber address;
+  EXPECT_FALSE(impl_.GetSupportsQuic(&address));
+  EXPECT_TRUE(address.empty());
 
-  SupportsQuic supports_quic2 = impl_.GetSupportsQuic(quic_server_google);
-  EXPECT_TRUE(supports_quic2.used_quic);
-  EXPECT_EQ("foo", supports_quic2.address);
+  // Check by initializing with a valid address.
+  CHECK(ParseIPLiteralToNumber("127.0.0.1", &initial_address));
+  impl_.InitializeSupportsQuic(&initial_address);
+
+  EXPECT_TRUE(impl_.GetSupportsQuic(&address));
+  EXPECT_EQ(initial_address, address);
 }
 
 TEST_F(SupportsQuicServerPropertiesTest, SetSupportsQuic) {
-  HostPortPair test_host_port_pair("foo", 80);
-  SupportsQuic supports_quic = impl_.GetSupportsQuic(test_host_port_pair);
-  EXPECT_FALSE(supports_quic.used_quic);
-  EXPECT_EQ("", supports_quic.address);
-  impl_.SetSupportsQuic(test_host_port_pair, true, "foo");
-  SupportsQuic supports_quic1 = impl_.GetSupportsQuic(test_host_port_pair);
-  EXPECT_TRUE(supports_quic1.used_quic);
-  EXPECT_EQ("foo", supports_quic1.address);
+  IPAddressNumber address;
+  EXPECT_FALSE(impl_.GetSupportsQuic(&address));
+  EXPECT_TRUE(address.empty());
+
+  IPAddressNumber actual_address;
+  CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+  impl_.SetSupportsQuic(true, actual_address);
+
+  EXPECT_TRUE(impl_.GetSupportsQuic(&address));
+  EXPECT_EQ(actual_address, address);
 
   impl_.Clear();
-  SupportsQuic supports_quic2 = impl_.GetSupportsQuic(test_host_port_pair);
-  EXPECT_FALSE(supports_quic2.used_quic);
-  EXPECT_EQ("", supports_quic2.address);
+
+  EXPECT_FALSE(impl_.GetSupportsQuic(&address));
 }
 
 typedef HttpServerPropertiesImplTest ServerNetworkStatsServerPropertiesTest;
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index c02518d..d6bfb38 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -50,6 +50,20 @@
 // Persist 200 ServerNetworkStats.
 const int kMaxServerNetworkStatsHostsToPersist = 200;
 
+const char kVersionKey[] = "version";
+const char kServersKey[] = "servers";
+const char kSupportsSpdyKey[] = "supports_spdy";
+const char kSettingsKey[] = "settings";
+const char kSupportsQuicKey[] = "supports_quic";
+const char kUsedQuicKey[] = "used_quic";
+const char kAddressKey[] = "address";
+const char kAlternateProtocolKey[] = "alternate_protocol";
+const char kPortKey[] = "port";
+const char kProtocolKey[] = "protocol_str";
+const char kProbabilityKey[] = "probability";
+const char kNetworkStatsKey[] = "network_stats";
+const char kSrttKey[] = "srtt";
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -113,7 +127,7 @@
     version_number = kVersionNumber;
   DCHECK_LE(version_number, kVersionNumber);
   if (version_number <= kVersionNumber)
-    http_server_properties_dict->SetInteger("version", version_number);
+    http_server_properties_dict->SetInteger(kVersionKey, version_number);
 }
 
 // This is required for conformance with the HttpServerProperties interface.
@@ -166,12 +180,6 @@
   http_server_properties_impl_->MaybeForceHTTP11(server, ssl_config);
 }
 
-bool HttpServerPropertiesManager::HasAlternateProtocol(
-    const HostPortPair& server) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
-  return http_server_properties_impl_->HasAlternateProtocol(server);
-}
-
 AlternateProtocolInfo HttpServerPropertiesManager::GetAlternateProtocol(
     const HostPortPair& server) {
   DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
@@ -268,28 +276,20 @@
   return http_server_properties_impl_->spdy_settings_map();
 }
 
-SupportsQuic HttpServerPropertiesManager::GetSupportsQuic(
-    const HostPortPair& host_port_pair) const {
+bool HttpServerPropertiesManager::GetSupportsQuic(
+    IPAddressNumber* last_address) const {
   DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
-  return http_server_properties_impl_->GetSupportsQuic(host_port_pair);
+  return http_server_properties_impl_->GetSupportsQuic(last_address);
 }
 
 void HttpServerPropertiesManager::SetSupportsQuic(
-    const HostPortPair& host_port_pair,
     bool used_quic,
-    const std::string& address) {
+    const IPAddressNumber& address) {
   DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
-  http_server_properties_impl_->SetSupportsQuic(
-      host_port_pair, used_quic, address);
+  http_server_properties_impl_->SetSupportsQuic(used_quic, address);
   ScheduleUpdatePrefsOnNetworkThread();
 }
 
-const SupportsQuicMap& HttpServerPropertiesManager::supports_quic_map()
-    const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
-  return http_server_properties_impl_->supports_quic_map();
-}
-
 void HttpServerPropertiesManager::SetServerNetworkStats(
     const HostPortPair& host_port_pair,
     ServerNetworkStats stats) {
@@ -343,7 +343,7 @@
       *pref_service_->GetDictionary(path_);
 
   int version = kMissingVersion;
-  if (!http_server_properties_dict.GetIntegerWithoutPathExpansion("version",
+  if (!http_server_properties_dict.GetIntegerWithoutPathExpansion(kVersionKey,
                                                                   &version)) {
     DVLOG(1) << "Missing version. Clearing all properties.";
     return;
@@ -353,18 +353,20 @@
   // http_server_properties_dict["servers"][server].
   const base::DictionaryValue* servers_dict = NULL;
   if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
-          "servers", &servers_dict)) {
+          kServersKey, &servers_dict)) {
     DVLOG(1) << "Malformed http_server_properties for servers.";
     return;
   }
 
+  IPAddressNumber* addr = new IPAddressNumber;
+  ReadSupportsQuic(http_server_properties_dict, addr);
+
   // String is host/port pair of spdy server.
   scoped_ptr<StringVector> spdy_servers(new StringVector);
   scoped_ptr<SpdySettingsMap> spdy_settings_map(
       new SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
   scoped_ptr<AlternateProtocolMap> alternate_protocol_map(
       new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist));
-  scoped_ptr<SupportsQuicMap> supports_quic_map(new SupportsQuicMap());
   scoped_ptr<ServerNetworkStatsMap> server_network_stats_map(
       new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist));
 
@@ -388,123 +390,17 @@
 
     // Get if server supports Spdy.
     bool supports_spdy = false;
-    if ((server_pref_dict->GetBoolean("supports_spdy", &supports_spdy)) &&
+    if ((server_pref_dict->GetBoolean(kSupportsSpdyKey, &supports_spdy)) &&
         supports_spdy) {
       spdy_servers->push_back(server_str);
     }
 
-    // Get SpdySettings.
-    DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
-    const base::DictionaryValue* spdy_settings_dict = NULL;
-    if (server_pref_dict->GetDictionaryWithoutPathExpansion(
-            "settings", &spdy_settings_dict)) {
-      SettingsMap settings_map;
-      for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
-           !dict_it.IsAtEnd();
-           dict_it.Advance()) {
-        const std::string& id_str = dict_it.key();
-        int id = 0;
-        if (!base::StringToInt(id_str, &id)) {
-          DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str;
-          NOTREACHED();
-          continue;
-        }
-        int value = 0;
-        if (!dict_it.value().GetAsInteger(&value)) {
-          DVLOG(1) << "Malformed value in SpdySettings for server: "
-                   << server_str;
-          NOTREACHED();
-          continue;
-        }
-        SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
-        settings_map[static_cast<SpdySettingsIds>(id)] = flags_and_value;
-      }
-      spdy_settings_map->Put(server, settings_map);
-    }
-
-    // Get alternate_protocol server.
-    DCHECK(alternate_protocol_map->Peek(server) ==
-           alternate_protocol_map->end());
-    const base::DictionaryValue* port_alternate_protocol_dict = NULL;
-    if (server_pref_dict->GetDictionaryWithoutPathExpansion(
-            "alternate_protocol", &port_alternate_protocol_dict)) {
-      int port = 0;
-      if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion(
-              "port", &port) ||
-          !IsPortValid(port)) {
-        DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
-        detected_corrupted_prefs = true;
-        continue;
-      }
-      std::string protocol_str;
-      if (!port_alternate_protocol_dict->GetStringWithoutPathExpansion(
-              "protocol_str", &protocol_str)) {
-        DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
-        detected_corrupted_prefs = true;
-        continue;
-      }
-      AlternateProtocol protocol = AlternateProtocolFromString(protocol_str);
-      if (!IsAlternateProtocolValid(protocol)) {
-        DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
-        detected_corrupted_prefs = true;
-        continue;
-      }
-
-      double probability = 1;
-      if (port_alternate_protocol_dict->HasKey("probability") &&
-          !port_alternate_protocol_dict->GetDoubleWithoutPathExpansion(
-              "probability", &probability)) {
-        DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
-        detected_corrupted_prefs = true;
-        continue;
-      }
-
-      AlternateProtocolInfo port_alternate_protocol(static_cast<uint16>(port),
-                                                    protocol, probability);
-      alternate_protocol_map->Put(server, port_alternate_protocol);
-    }
-
-    // Get SupportsQuic.
-    DCHECK(supports_quic_map->find(server) == supports_quic_map->end());
-    const base::DictionaryValue* supports_quic_dict = NULL;
-    if (server_pref_dict->GetDictionaryWithoutPathExpansion(
-            "supports_quic", &supports_quic_dict)) {
-      bool used_quic = 0;
-      if (!supports_quic_dict->GetBooleanWithoutPathExpansion(
-              "used_quic", &used_quic)) {
-        DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
-        detected_corrupted_prefs = true;
-        continue;
-      }
-      std::string address;
-      if (!supports_quic_dict->GetStringWithoutPathExpansion(
-              "address", &address)) {
-        DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
-        detected_corrupted_prefs = true;
-        continue;
-      }
-      SupportsQuic supports_quic(used_quic, address);
-      supports_quic_map->insert(std::make_pair(server, supports_quic));
-    }
-
-    // Get ServerNetworkStats.
-    DCHECK(server_network_stats_map->Peek(server) ==
-           server_network_stats_map->end());
-    const base::DictionaryValue* server_network_stats_dict = NULL;
-    if (server_pref_dict->GetDictionaryWithoutPathExpansion(
-            "network_stats", &server_network_stats_dict)) {
-      int srtt;
-      if (!server_network_stats_dict->GetIntegerWithoutPathExpansion("srtt",
-                                                                     &srtt)) {
-        DVLOG(1) << "Malformed ServerNetworkStats for server: " << server_str;
-        detected_corrupted_prefs = true;
-        continue;
-      }
-      ServerNetworkStats server_network_stats;
-      server_network_stats.srtt = base::TimeDelta::FromInternalValue(srtt);
-      // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
-      // bandwidth_estimate.
-      server_network_stats_map->Put(server, server_network_stats);
+    AddToSpdySettingsMap(server, *server_pref_dict, spdy_settings_map.get());
+    if (!AddToAlternateProtocolMap(server, *server_pref_dict,
+                                   alternate_protocol_map.get()) ||
+        !AddToNetworkStatsMap(server, *server_pref_dict,
+                              server_network_stats_map.get())) {
+      detected_corrupted_prefs = true;
     }
   }
 
@@ -514,17 +410,159 @@
           &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
           base::Unretained(this), base::Owned(spdy_servers.release()),
           base::Owned(spdy_settings_map.release()),
-          base::Owned(alternate_protocol_map.release()),
-          base::Owned(supports_quic_map.release()),
+          base::Owned(alternate_protocol_map.release()), base::Owned(addr),
           base::Owned(server_network_stats_map.release()),
           detected_corrupted_prefs));
 }
 
+void HttpServerPropertiesManager::AddToSpdySettingsMap(
+    const HostPortPair& server,
+    const base::DictionaryValue& server_pref_dict,
+    SpdySettingsMap* spdy_settings_map) {
+  // Get SpdySettings.
+  DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
+  const base::DictionaryValue* spdy_settings_dict = NULL;
+  if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
+          kSettingsKey, &spdy_settings_dict)) {
+    return;
+  }
+  SettingsMap settings_map;
+  for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
+       !dict_it.IsAtEnd(); dict_it.Advance()) {
+    const std::string& id_str = dict_it.key();
+    int id = 0;
+    if (!base::StringToInt(id_str, &id)) {
+      DVLOG(1) << "Malformed id in SpdySettings for server: "
+               << server.ToString();
+      NOTREACHED();
+      continue;
+    }
+    int value = 0;
+    if (!dict_it.value().GetAsInteger(&value)) {
+      DVLOG(1) << "Malformed value in SpdySettings for server: "
+               << server.ToString();
+      NOTREACHED();
+      continue;
+    }
+    SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
+    settings_map[static_cast<SpdySettingsIds>(id)] = flags_and_value;
+  }
+  spdy_settings_map->Put(server, settings_map);
+}
+
+AlternateProtocolInfo HttpServerPropertiesManager::ParseAlternateProtocolDict(
+    const base::DictionaryValue& alternate_protocol_dict,
+    const std::string& server_str) {
+  AlternateProtocolInfo alternate_protocol;
+  int port = 0;
+  if (!alternate_protocol_dict.GetInteger(kPortKey, &port) ||
+      !IsPortValid(port)) {
+    DVLOG(1) << "Malformed AltSvc port for server: " << server_str;
+    return alternate_protocol;
+  }
+  alternate_protocol.port = static_cast<uint16>(port);
+
+  double probability = 1.0;
+  if (alternate_protocol_dict.HasKey(kProbabilityKey) &&
+      !alternate_protocol_dict.GetDoubleWithoutPathExpansion(kProbabilityKey,
+                                                             &probability)) {
+    DVLOG(1) << "Malformed AltSvc probability for server: " << server_str;
+    return alternate_protocol;
+  }
+  alternate_protocol.probability = probability;
+
+  std::string protocol_str;
+  if (!alternate_protocol_dict.GetStringWithoutPathExpansion(kProtocolKey,
+                                                             &protocol_str)) {
+    DVLOG(1) << "Malformed AltSvc protocol string for server: " << server_str;
+    return alternate_protocol;
+  }
+  AlternateProtocol protocol = AlternateProtocolFromString(protocol_str);
+  if (!IsAlternateProtocolValid(protocol)) {
+    DVLOG(1) << "Invalid AltSvc protocol string for server: " << server_str;
+    return alternate_protocol;
+  }
+  alternate_protocol.protocol = protocol;
+
+  return alternate_protocol;
+}
+
+bool HttpServerPropertiesManager::AddToAlternateProtocolMap(
+    const HostPortPair& server,
+    const base::DictionaryValue& server_pref_dict,
+    AlternateProtocolMap* alternate_protocol_map) {
+  // Get alternate_protocol server.
+  DCHECK(alternate_protocol_map->Peek(server) == alternate_protocol_map->end());
+  const base::DictionaryValue* alternate_protocol_dict = NULL;
+  if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
+          kAlternateProtocolKey, &alternate_protocol_dict)) {
+    return true;
+  }
+  AlternateProtocolInfo alternate_protocol =
+      ParseAlternateProtocolDict(*alternate_protocol_dict, server.ToString());
+  if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+    return false;
+  alternate_protocol_map->Put(server, alternate_protocol);
+  return true;
+}
+
+bool HttpServerPropertiesManager::ReadSupportsQuic(
+    const base::DictionaryValue& http_server_properties_dict,
+    IPAddressNumber* last_quic_address) {
+  const base::DictionaryValue* supports_quic_dict = NULL;
+  if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
+          kSupportsQuicKey, &supports_quic_dict)) {
+    return true;
+  }
+  bool used_quic = false;
+  if (!supports_quic_dict->GetBooleanWithoutPathExpansion(kUsedQuicKey,
+                                                          &used_quic)) {
+    DVLOG(1) << "Malformed SupportsQuic";
+    return false;
+  }
+  if (!used_quic)
+    return false;
+
+  std::string address;
+  if (!supports_quic_dict->GetStringWithoutPathExpansion(kAddressKey,
+                                                         &address) ||
+      !ParseIPLiteralToNumber(address, last_quic_address)) {
+    DVLOG(1) << "Malformed SupportsQuic";
+    return false;
+  }
+  return true;
+}
+
+bool HttpServerPropertiesManager::AddToNetworkStatsMap(
+    const HostPortPair& server,
+    const base::DictionaryValue& server_pref_dict,
+    ServerNetworkStatsMap* network_stats_map) {
+  DCHECK(network_stats_map->Peek(server) == network_stats_map->end());
+  const base::DictionaryValue* server_network_stats_dict = NULL;
+  if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
+          kNetworkStatsKey, &server_network_stats_dict)) {
+    return true;
+  }
+  int srtt;
+  if (!server_network_stats_dict->GetIntegerWithoutPathExpansion(kSrttKey,
+                                                                 &srtt)) {
+    DVLOG(1) << "Malformed ServerNetworkStats for server: "
+             << server.ToString();
+    return false;
+  }
+  ServerNetworkStats server_network_stats;
+  server_network_stats.srtt = base::TimeDelta::FromInternalValue(srtt);
+  // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
+  // bandwidth_estimate.
+  network_stats_map->Put(server, server_network_stats);
+  return true;
+}
+
 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
     StringVector* spdy_servers,
     SpdySettingsMap* spdy_settings_map,
     AlternateProtocolMap* alternate_protocol_map,
-    SupportsQuicMap* supports_quic_map,
+    IPAddressNumber* last_quic_address,
     ServerNetworkStatsMap* server_network_stats_map,
     bool detected_corrupted_prefs) {
   // Preferences have the master data because admins might have pushed new
@@ -546,7 +584,7 @@
   http_server_properties_impl_->InitializeAlternateProtocolServers(
       alternate_protocol_map);
 
-  http_server_properties_impl_->InitializeSupportsQuic(supports_quic_map);
+  http_server_properties_impl_->InitializeSupportsQuic(last_quic_address);
 
   http_server_properties_impl_->InitializeServerNetworkStats(
       server_network_stats_map);
@@ -623,14 +661,6 @@
     ++count;
   }
 
-  SupportsQuicMap* supports_quic_map = new SupportsQuicMap();
-  const SupportsQuicMap& main_supports_quic_map =
-      http_server_properties_impl_->supports_quic_map();
-  for (SupportsQuicMap::const_iterator it = main_supports_quic_map.begin();
-       it != main_supports_quic_map.end(); ++it) {
-    supports_quic_map->insert(std::make_pair(it->first, it->second));
-  }
-
   ServerNetworkStatsMap* server_network_stats_map =
       new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist);
   const ServerNetworkStatsMap& main_server_network_stats_map =
@@ -641,13 +671,15 @@
     server_network_stats_map->Put(it->first, it->second);
   }
 
+  IPAddressNumber* last_quic_addr = new IPAddressNumber;
+  http_server_properties_impl_->GetSupportsQuic(last_quic_addr);
   // Update the preferences on the pref thread.
   pref_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
           &HttpServerPropertiesManager::UpdatePrefsOnPrefThread, pref_weak_ptr_,
           base::Owned(spdy_server_list), base::Owned(spdy_settings_map),
-          base::Owned(alternate_protocol_map), base::Owned(supports_quic_map),
+          base::Owned(alternate_protocol_map), base::Owned(last_quic_addr),
           base::Owned(server_network_stats_map), completion));
 }
 
@@ -682,7 +714,7 @@
     base::ListValue* spdy_server_list,
     SpdySettingsMap* spdy_settings_map,
     AlternateProtocolMap* alternate_protocol_map,
-    SupportsQuicMap* supports_quic_map,
+    IPAddressNumber* last_quic_address,
     ServerNetworkStatsMap* server_network_stats_map,
     const base::Closure& completion) {
   typedef std::map<HostPortPair, ServerPref> ServerPrefMap;
@@ -697,14 +729,7 @@
        ++list_it) {
     if ((*list_it)->GetAsString(&s)) {
       HostPortPair server = HostPortPair::FromString(s);
-
-      ServerPrefMap::iterator it = server_pref_map.find(server);
-      if (it == server_pref_map.end()) {
-        ServerPref server_pref(true, NULL, NULL, NULL, NULL);
-        server_pref_map[server] = server_pref;
-      } else {
-        it->second.supports_spdy = true;
-      }
+      server_pref_map[server].supports_spdy = true;
     }
   }
 
@@ -712,14 +737,7 @@
   for (SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
        map_it != spdy_settings_map->end(); ++map_it) {
     const HostPortPair& server = map_it->first;
-
-    ServerPrefMap::iterator it = server_pref_map.find(server);
-    if (it == server_pref_map.end()) {
-      ServerPref server_pref(false, &map_it->second, NULL, NULL, NULL);
-      server_pref_map[server] = server_pref;
-    } else {
-      it->second.settings_map = &map_it->second;
-    }
+    server_pref_map[server].settings_map = &map_it->second;
   }
 
   // Add AlternateProtocol servers to server_pref_map.
@@ -731,28 +749,7 @@
     if (!IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
       continue;
     }
-
-    ServerPrefMap::iterator it = server_pref_map.find(server);
-    if (it == server_pref_map.end()) {
-      ServerPref server_pref(false, NULL, &map_it->second, NULL, NULL);
-      server_pref_map[server] = server_pref;
-    } else {
-      it->second.alternate_protocol = &map_it->second;
-    }
-  }
-
-  // Add SupportsQuic servers to server_pref_map.
-  for (SupportsQuicMap::const_iterator map_it = supports_quic_map->begin();
-       map_it != supports_quic_map->end(); ++map_it) {
-    const HostPortPair& server = map_it->first;
-
-    ServerPrefMap::iterator it = server_pref_map.find(server);
-    if (it == server_pref_map.end()) {
-      ServerPref server_pref(false, NULL, NULL, &map_it->second, NULL);
-      server_pref_map[server] = server_pref;
-    } else {
-      it->second.supports_quic = &map_it->second;
-    }
+    server_pref_map[server].alternate_protocol = &map_it->second;
   }
 
   // Add ServerNetworkStats servers to server_pref_map.
@@ -760,14 +757,7 @@
            server_network_stats_map->begin();
        map_it != server_network_stats_map->end(); ++map_it) {
     const HostPortPair& server = map_it->first;
-
-    ServerPrefMap::iterator it = server_pref_map.find(server);
-    if (it == server_pref_map.end()) {
-      ServerPref server_pref(false, NULL, NULL, NULL, &map_it->second);
-      server_pref_map[server] = server_pref;
-    } else {
-      it->second.server_network_stats = &map_it->second;
-    }
+    server_pref_map[server].server_network_stats = &map_it->second;
   }
 
   // Persist properties to the |path_|.
@@ -783,69 +773,22 @@
 
     // Save supports_spdy.
     if (server_pref.supports_spdy)
-      server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy);
-
-    // Save SPDY settings.
-    if (server_pref.settings_map) {
-      base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
-      for (SettingsMap::const_iterator it = server_pref.settings_map->begin();
-           it != server_pref.settings_map->end(); ++it) {
-        SpdySettingsIds id = it->first;
-        uint32 value = it->second.second;
-        std::string key = base::StringPrintf("%u", id);
-        spdy_settings_dict->SetInteger(key, value);
-      }
-      server_pref_dict->SetWithoutPathExpansion("settings", spdy_settings_dict);
-    }
-
-    // Save alternate_protocol.
-    const AlternateProtocolInfo* port_alternate_protocol =
-        server_pref.alternate_protocol;
-    if (port_alternate_protocol && !port_alternate_protocol->is_broken) {
-      base::DictionaryValue* port_alternate_protocol_dict =
-          new base::DictionaryValue;
-      port_alternate_protocol_dict->SetInteger("port",
-                                               port_alternate_protocol->port);
-      const char* protocol_str =
-          AlternateProtocolToString(port_alternate_protocol->protocol);
-      port_alternate_protocol_dict->SetString("protocol_str", protocol_str);
-      port_alternate_protocol_dict->SetDouble(
-          "probability", port_alternate_protocol->probability);
-      server_pref_dict->SetWithoutPathExpansion(
-          "alternate_protocol", port_alternate_protocol_dict);
-    }
-
-    // Save supports_quic.
-    if (server_pref.supports_quic) {
-      base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
-      const SupportsQuic* supports_quic = server_pref.supports_quic;
-      supports_quic_dict->SetBoolean("used_quic", supports_quic->used_quic);
-      supports_quic_dict->SetString("address", supports_quic->address);
-      server_pref_dict->SetWithoutPathExpansion(
-          "supports_quic", supports_quic_dict);
-    }
-
-    // Save ServerNetworkStats.
-    if (server_pref.server_network_stats) {
-      base::DictionaryValue* server_network_stats_dict =
-          new base::DictionaryValue;
-      const ServerNetworkStats* server_network_stats =
-          server_pref.server_network_stats;
-      // Becasue JSON doesn't support int64, persist int64 as a string.
-      server_network_stats_dict->SetInteger(
-          "srtt",
-          static_cast<int>(server_network_stats->srtt.ToInternalValue()));
-      // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
-      // bandwidth_estimate.
-      server_pref_dict->SetWithoutPathExpansion("network_stats",
-                                                server_network_stats_dict);
-    }
+      server_pref_dict->SetBoolean(kSupportsSpdyKey, server_pref.supports_spdy);
+    SaveSpdySettingsToServerPrefs(server_pref.settings_map, server_pref_dict);
+    SaveAlternateProtocolToServerPrefs(server_pref.alternate_protocol,
+                                       server_pref_dict);
+    SaveNetworkStatsToServerPrefs(server_pref.server_network_stats,
+                                  server_pref_dict);
 
     servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
   }
 
-  http_server_properties_dict.SetWithoutPathExpansion("servers", servers_dict);
+  http_server_properties_dict.SetWithoutPathExpansion(kServersKey,
+                                                      servers_dict);
   SetVersion(&http_server_properties_dict, kVersionNumber);
+
+  SaveSupportsQuicToPrefs(last_quic_address, &http_server_properties_dict);
+
   setting_prefs_ = true;
   pref_service_->Set(path_, http_server_properties_dict);
   setting_prefs_ = false;
@@ -858,6 +801,72 @@
     completion.Run();
 }
 
+void HttpServerPropertiesManager::SaveSpdySettingsToServerPrefs(
+    const SettingsMap* settings_map,
+    base::DictionaryValue* server_pref_dict) {
+  if (!settings_map) {
+    return;
+  }
+  base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
+  for (SettingsMap::const_iterator it = settings_map->begin();
+       it != settings_map->end(); ++it) {
+    SpdySettingsIds id = it->first;
+    uint32 value = it->second.second;
+    std::string key = base::StringPrintf("%u", id);
+    spdy_settings_dict->SetInteger(key, value);
+  }
+  server_pref_dict->SetWithoutPathExpansion(kSettingsKey, spdy_settings_dict);
+}
+
+void HttpServerPropertiesManager::SaveAlternateProtocolToServerPrefs(
+    const AlternateProtocolInfo* port_alternate_protocol,
+    base::DictionaryValue* server_pref_dict) {
+  if (!port_alternate_protocol || port_alternate_protocol->is_broken)
+    return;
+
+  base::DictionaryValue* port_alternate_protocol_dict =
+      new base::DictionaryValue;
+  port_alternate_protocol_dict->SetInteger(kPortKey,
+                                           port_alternate_protocol->port);
+  const char* protocol_str =
+      AlternateProtocolToString(port_alternate_protocol->protocol);
+  port_alternate_protocol_dict->SetString(kProtocolKey, protocol_str);
+  port_alternate_protocol_dict->SetDouble(kProbabilityKey,
+                                          port_alternate_protocol->probability);
+  server_pref_dict->SetWithoutPathExpansion(kAlternateProtocolKey,
+                                            port_alternate_protocol_dict);
+}
+
+void HttpServerPropertiesManager::SaveSupportsQuicToPrefs(
+    const IPAddressNumber* last_quic_address,
+    base::DictionaryValue* http_server_properties_dict) {
+  if (!last_quic_address || last_quic_address->empty())
+    return;
+
+  base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
+  supports_quic_dict->SetBoolean(kUsedQuicKey, true);
+  supports_quic_dict->SetString(kAddressKey,
+                                IPAddressToString(*last_quic_address));
+  http_server_properties_dict->SetWithoutPathExpansion(kSupportsQuicKey,
+                                                       supports_quic_dict);
+}
+
+void HttpServerPropertiesManager::SaveNetworkStatsToServerPrefs(
+    const ServerNetworkStats* server_network_stats,
+    base::DictionaryValue* server_pref_dict) {
+  if (!server_network_stats)
+    return;
+
+  base::DictionaryValue* server_network_stats_dict = new base::DictionaryValue;
+  // Becasue JSON doesn't support int64, persist int64 as a string.
+  server_network_stats_dict->SetInteger(
+      kSrttKey, static_cast<int>(server_network_stats->srtt.ToInternalValue()));
+  // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
+  // bandwidth_estimate.
+  server_pref_dict->SetWithoutPathExpansion(kNetworkStatsKey,
+                                            server_network_stats_dict);
+}
+
 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
   DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
   if (!setting_prefs_)
diff --git a/net/http/http_server_properties_manager.h b/net/http/http_server_properties_manager.h
index 00e5a13..b71671a 100644
--- a/net/http/http_server_properties_manager.h
+++ b/net/http/http_server_properties_manager.h
@@ -86,7 +86,6 @@
   void SetHTTP11Required(const HostPortPair& server) override;
   void MaybeForceHTTP11(const HostPortPair& server,
                         SSLConfig* ssl_config) override;
-  bool HasAlternateProtocol(const HostPortPair& server) override;
   AlternateProtocolInfo GetAlternateProtocol(
       const HostPortPair& server) override;
   void SetAlternateProtocol(const HostPortPair& server,
@@ -108,12 +107,9 @@
   void ClearSpdySettings(const HostPortPair& host_port_pair) override;
   void ClearAllSpdySettings() override;
   const SpdySettingsMap& spdy_settings_map() const override;
-  SupportsQuic GetSupportsQuic(
-      const HostPortPair& host_port_pair) const override;
-  void SetSupportsQuic(const HostPortPair& host_port_pair,
-                       bool used_quic,
-                       const std::string& address) override;
-  const SupportsQuicMap& supports_quic_map() const override;
+  bool GetSupportsQuic(IPAddressNumber* last_address) const override;
+  void SetSupportsQuic(bool used_quic,
+                       const IPAddressNumber& last_address) override;
   void SetServerNetworkStats(const HostPortPair& host_port_pair,
                              ServerNetworkStats stats) override;
   const ServerNetworkStats* GetServerNetworkStats(
@@ -145,7 +141,7 @@
       std::vector<std::string>* spdy_servers,
       SpdySettingsMap* spdy_settings_map,
       AlternateProtocolMap* alternate_protocol_map,
-      SupportsQuicMap* supports_quic_map,
+      IPAddressNumber* last_quic_address,
       ServerNetworkStatsMap* server_network_stats_map,
       bool detected_corrupted_prefs);
 
@@ -174,13 +170,41 @@
   void UpdatePrefsOnPrefThread(base::ListValue* spdy_server_list,
                                SpdySettingsMap* spdy_settings_map,
                                AlternateProtocolMap* alternate_protocol_map,
-                               SupportsQuicMap* supports_quic_map,
+                               IPAddressNumber* last_quic_address,
                                ServerNetworkStatsMap* server_network_stats_map,
                                const base::Closure& completion);
 
  private:
   void OnHttpServerPropertiesChanged();
 
+  bool ReadSupportsQuic(const base::DictionaryValue& server_dict,
+                        IPAddressNumber* last_quic_address);
+  void AddToSpdySettingsMap(const HostPortPair& server,
+                            const base::DictionaryValue& server_dict,
+                            SpdySettingsMap* spdy_settings_map);
+  AlternateProtocolInfo ParseAlternateProtocolDict(
+      const base::DictionaryValue& alternate_protocol_dict,
+      const std::string& server_str);
+  bool AddToAlternateProtocolMap(const HostPortPair& server,
+                                 const base::DictionaryValue& server_dict,
+                                 AlternateProtocolMap* alternate_protocol_map);
+  bool AddToNetworkStatsMap(const HostPortPair& server,
+                            const base::DictionaryValue& server_dict,
+                            ServerNetworkStatsMap* network_stats_map);
+
+  void SaveSpdySettingsToServerPrefs(const SettingsMap* spdy_settings_map,
+                                     base::DictionaryValue* server_pref_dict);
+  void SaveAlternateProtocolToServerPrefs(
+      const AlternateProtocolInfo* port_alternate_protocol,
+      base::DictionaryValue* server_pref_dict);
+  void SaveNetworkStatsToServerPrefs(
+      const ServerNetworkStats* server_network_stats,
+      base::DictionaryValue* server_pref_dict);
+
+  void SaveSupportsQuicToPrefs(
+      const IPAddressNumber* last_quic_address,
+      base::DictionaryValue* http_server_properties_dict);
+
   // -----------
   // Pref thread
   // -----------
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index d021fc5..f2e3649 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -5,6 +5,7 @@
 #include "net/http/http_server_properties_manager.h"
 
 #include "base/basictypes.h"
+#include "base/json/json_writer.h"
 #include "base/message_loop/message_loop.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/testing_pref_service.h"
@@ -74,14 +75,14 @@
                void(std::vector<std::string>* spdy_servers,
                     SpdySettingsMap* spdy_settings_map,
                     AlternateProtocolMap* alternate_protocol_map,
-                    SupportsQuicMap* supports_quic_map,
+                    IPAddressNumber* last_quic_address,
                     ServerNetworkStatsMap* server_network_stats_map,
                     bool detected_corrupted_prefs));
   MOCK_METHOD5(UpdatePrefsOnPref,
                void(base::ListValue* spdy_server_list,
                     SpdySettingsMap* spdy_settings_map,
                     AlternateProtocolMap* alternate_protocol_map,
-                    SupportsQuicMap* supports_quic_map,
+                    IPAddressNumber* last_quic_address,
                     ServerNetworkStatsMap* server_network_stats_map));
 
  private:
@@ -134,6 +135,12 @@
                        UpdatePrefsFromCacheOnNetworkThreadConcrete));
   }
 
+  bool HasAlternateProtocol(const HostPortPair& server) {
+    const AlternateProtocolInfo alternate =
+        http_server_props_manager_->GetAlternateProtocol(server);
+    return alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL;
+  }
+
   //base::RunLoop loop_;
   TestingPrefServiceSimple pref_service_;
   scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;
@@ -163,12 +170,6 @@
   server_pref_dict->SetWithoutPathExpansion("alternate_protocol",
                                             alternate_protocol);
 
-  // Set up SupportsQuic for www.google.com:80.
-  base::DictionaryValue* supports_quic = new base::DictionaryValue;
-  supports_quic->SetBoolean("used_quic", true);
-  supports_quic->SetString("address", "foo");
-  server_pref_dict->SetWithoutPathExpansion("supports_quic", supports_quic);
-
   // Set up ServerNetworkStats for www.google.com:80.
   base::DictionaryValue* stats = new base::DictionaryValue;
   stats->SetInteger("srtt", 10);
@@ -192,12 +193,6 @@
   server_pref_dict1->SetWithoutPathExpansion("alternate_protocol",
                                              alternate_protocol1);
 
-  // Set up SupportsQuic for mail.google.com:80
-  base::DictionaryValue* supports_quic1 = new base::DictionaryValue;
-  supports_quic1->SetBoolean("used_quic", false);
-  supports_quic1->SetString("address", "bar");
-  server_pref_dict1->SetWithoutPathExpansion("supports_quic", supports_quic1);
-
   // Set up ServerNetworkStats for mail.google.com:80.
   base::DictionaryValue* stats1 = new base::DictionaryValue;
   stats1->SetInteger("srtt", 20);
@@ -210,6 +205,11 @@
       new base::DictionaryValue;
   HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
   http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
+  base::DictionaryValue* supports_quic = new base::DictionaryValue;
+  supports_quic->SetBoolean("used_quic", true);
+  supports_quic->SetString("address", "127.0.0.1");
+  http_server_properties_dict->SetWithoutPathExpansion("supports_quic",
+                                                       supports_quic);
 
   // Set the same value for kHttpServerProperties multiple times.
   pref_service_.SetManagedPref(kTestHttpServerProperties,
@@ -230,8 +230,6 @@
       HostPortPair::FromString("foo.google.com:1337")));
 
   // Verify AlternateProtocol.
-  ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(google_server));
-  ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(mail_server));
   AlternateProtocolInfo port_alternate_protocol =
       http_server_props_manager_->GetAlternateProtocol(google_server);
   EXPECT_EQ(443, port_alternate_protocol.port);
@@ -242,13 +240,9 @@
   EXPECT_EQ(NPN_SPDY_3_1, port_alternate_protocol.protocol);
 
   // Verify SupportsQuic.
-  SupportsQuic supports_quic2 =
-      http_server_props_manager_->GetSupportsQuic(google_server);
-  EXPECT_TRUE(supports_quic2.used_quic);
-  EXPECT_EQ("foo", supports_quic2.address);
-  supports_quic2 = http_server_props_manager_->GetSupportsQuic(mail_server);
-  EXPECT_FALSE(supports_quic2.used_quic);
-  EXPECT_EQ("bar", supports_quic2.address);
+  IPAddressNumber last_address;
+  EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&last_address));
+  EXPECT_EQ("127.0.0.1", IPAddressToString(last_address));
 
   // Verify ServerNetworkStats.
   const ServerNetworkStats* stats2 =
@@ -276,12 +270,6 @@
   server_pref_dict->SetWithoutPathExpansion("alternate_protocol",
                                             alternate_protocol);
 
-  // Set up SupportsQuic for www.google.com:65536.
-  base::DictionaryValue* supports_quic = new base::DictionaryValue;
-  supports_quic->SetBoolean("used_quic", true);
-  supports_quic->SetString("address", "foo");
-  server_pref_dict->SetWithoutPathExpansion("supports_quic", supports_quic);
-
   // Set up ServerNetworkStats for www.google.com:65536.
   base::DictionaryValue* stats = new base::DictionaryValue;
   stats->SetInteger("srtt", 10);
@@ -307,11 +295,8 @@
   // Verify that nothing is set.
   EXPECT_FALSE(http_server_props_manager_->SupportsRequestPriority(
       HostPortPair::FromString("www.google.com:65536")));
-  EXPECT_FALSE(http_server_props_manager_->HasAlternateProtocol(
-      HostPortPair::FromString("www.google.com:65536")));
-  SupportsQuic supports_quic2 = http_server_props_manager_->GetSupportsQuic(
-      HostPortPair::FromString("www.google.com:65536"));
-  EXPECT_FALSE(supports_quic2.used_quic);
+  EXPECT_FALSE(
+      HasAlternateProtocol(HostPortPair::FromString("www.google.com:65536")));
   const ServerNetworkStats* stats1 =
       http_server_props_manager_->GetServerNetworkStats(
           HostPortPair::FromString("www.google.com:65536"));
@@ -352,8 +337,8 @@
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   // Verify AlternateProtocol is not set.
-  EXPECT_FALSE(http_server_props_manager_->HasAlternateProtocol(
-      HostPortPair::FromString("www.google.com:80")));
+  EXPECT_FALSE(
+      HasAlternateProtocol(HostPortPair::FromString("www.google.com:80")));
 }
 
 TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) {
@@ -477,12 +462,11 @@
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 }
 
-TEST_F(HttpServerPropertiesManagerTest, HasAlternateProtocol) {
+TEST_F(HttpServerPropertiesManagerTest, GetAlternateProtocol) {
   ExpectPrefsUpdate();
 
   HostPortPair spdy_server_mail("mail.google.com", 80);
-  EXPECT_FALSE(
-      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
+  EXPECT_FALSE(HasAlternateProtocol(spdy_server_mail));
   http_server_props_manager_->SetAlternateProtocol(spdy_server_mail, 443,
                                                    NPN_SPDY_3, 1.0);
 
@@ -490,32 +474,29 @@
   base::RunLoop().RunUntilIdle();
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
-  ASSERT_TRUE(
-      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
-  AlternateProtocolInfo port_alternate_protocol =
+  const AlternateProtocolInfo alternate_protocol =
       http_server_props_manager_->GetAlternateProtocol(spdy_server_mail);
-  EXPECT_EQ(443, port_alternate_protocol.port);
-  EXPECT_EQ(NPN_SPDY_3, port_alternate_protocol.protocol);
+  EXPECT_EQ(443, alternate_protocol.port);
+  EXPECT_EQ(NPN_SPDY_3, alternate_protocol.protocol);
+  EXPECT_EQ(1.0, alternate_protocol.probability);
 }
 
 TEST_F(HttpServerPropertiesManagerTest, SupportsQuic) {
   ExpectPrefsUpdate();
 
-  HostPortPair quic_server_mail("mail.google.com", 80);
-  SupportsQuic supports_quic =
-      http_server_props_manager_->GetSupportsQuic(quic_server_mail);
-  EXPECT_FALSE(supports_quic.used_quic);
-  EXPECT_EQ("", supports_quic.address);
-  http_server_props_manager_->SetSupportsQuic(quic_server_mail, true, "foo");
+  IPAddressNumber address;
+  EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address));
+
+  IPAddressNumber actual_address;
+  CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+  http_server_props_manager_->SetSupportsQuic(true, actual_address);
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
-  SupportsQuic supports_quic1 =
-      http_server_props_manager_->GetSupportsQuic(quic_server_mail);
-  EXPECT_TRUE(supports_quic1.used_quic);
-  EXPECT_EQ("foo", supports_quic1.address);
+  EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
+  EXPECT_EQ(actual_address, address);
 }
 
 TEST_F(HttpServerPropertiesManagerTest, ServerNetworkStats) {
@@ -545,7 +526,9 @@
   http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
   http_server_props_manager_->SetAlternateProtocol(spdy_server_mail, 443,
                                                    NPN_SPDY_3, 1.0);
-  http_server_props_manager_->SetSupportsQuic(spdy_server_mail, true, "foo");
+  IPAddressNumber actual_address;
+  CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+  http_server_props_manager_->SetSupportsQuic(true, actual_address);
   ServerNetworkStats stats;
   stats.srtt = base::TimeDelta::FromMicroseconds(10);
   http_server_props_manager_->SetServerNetworkStats(spdy_server_mail, stats);
@@ -561,12 +544,10 @@
 
   EXPECT_TRUE(
       http_server_props_manager_->SupportsRequestPriority(spdy_server_mail));
-  EXPECT_TRUE(
-      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
-  SupportsQuic supports_quic =
-      http_server_props_manager_->GetSupportsQuic(spdy_server_mail);
-  EXPECT_TRUE(supports_quic.used_quic);
-  EXPECT_EQ("foo", supports_quic.address);
+  EXPECT_TRUE(HasAlternateProtocol(spdy_server_mail));
+  IPAddressNumber address;
+  EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
+  EXPECT_EQ(actual_address, address);
   const ServerNetworkStats* stats1 =
       http_server_props_manager_->GetServerNetworkStats(spdy_server_mail);
   EXPECT_EQ(10, stats1->srtt.ToInternalValue());
@@ -591,12 +572,8 @@
 
   EXPECT_FALSE(
       http_server_props_manager_->SupportsRequestPriority(spdy_server_mail));
-  EXPECT_FALSE(
-      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
-  SupportsQuic supports_quic1 =
-      http_server_props_manager_->GetSupportsQuic(spdy_server_mail);
-  EXPECT_FALSE(supports_quic1.used_quic);
-  EXPECT_EQ("", supports_quic1.address);
+  EXPECT_FALSE(HasAlternateProtocol(spdy_server_mail));
+  EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address));
   const ServerNetworkStats* stats2 =
       http_server_props_manager_->GetServerNetworkStats(spdy_server_mail);
   EXPECT_EQ(NULL, stats2);
@@ -629,11 +606,6 @@
 
   // Set the preference for mail.google.com server.
   base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue;
-  // Set up SupportsQuic for mail.google.com:80
-  base::DictionaryValue* supports_quic = new base::DictionaryValue;
-  supports_quic->SetBoolean("used_quic", true);
-  supports_quic->SetString("address", "bar");
-  server_pref_dict1->SetWithoutPathExpansion("supports_quic", supports_quic);
 
   // Set the server preference for mail.google.com:80.
   servers_dict->SetWithoutPathExpansion("mail.google.com:80",
@@ -644,6 +616,13 @@
   HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
   http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
 
+  // Set up SupportsQuic for 127.0.0.1
+  base::DictionaryValue* supports_quic = new base::DictionaryValue;
+  supports_quic->SetBoolean("used_quic", true);
+  supports_quic->SetString("address", "127.0.0.1");
+  http_server_properties_dict->SetWithoutPathExpansion("supports_quic",
+                                                       supports_quic);
+
   // Set up the pref.
   pref_service_.SetManagedPref(kTestHttpServerProperties,
                                http_server_properties_dict);
@@ -654,8 +633,6 @@
   // Verify AlternateProtocol.
   for (int i = 0; i < 200; ++i) {
     std::string server = StringPrintf("www.google.com:%d", i);
-    ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
-        HostPortPair::FromString(server)));
     AlternateProtocolInfo port_alternate_protocol =
         http_server_props_manager_->GetAlternateProtocol(
             HostPortPair::FromString(server));
@@ -664,10 +641,67 @@
   }
 
   // Verify SupportsQuic.
-  SupportsQuic supports_quic1 = http_server_props_manager_->GetSupportsQuic(
-      HostPortPair::FromString("mail.google.com:80"));
-  EXPECT_TRUE(supports_quic1.used_quic);
-  EXPECT_EQ("bar", supports_quic1.address);
+  IPAddressNumber address;
+  ASSERT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
+  EXPECT_EQ("127.0.0.1", IPAddressToString(address));
+}
+
+TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
+  const HostPortPair server_www("www.google.com", 80);
+  const HostPortPair server_mail("mail.google.com", 80);
+
+  // Set alternate protocol.
+  http_server_props_manager_->SetAlternateProtocol(server_www, 443, NPN_SPDY_3,
+                                                   1.0);
+  http_server_props_manager_->SetAlternateProtocol(server_mail, 444,
+                                                   NPN_SPDY_3_1, 0.2);
+
+  // Set ServerNetworkStats.
+  ServerNetworkStats stats;
+  stats.srtt = base::TimeDelta::FromInternalValue(42);
+  http_server_props_manager_->SetServerNetworkStats(server_mail, stats);
+
+  // Set SupportsQuic.
+  IPAddressNumber actual_address;
+  CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+  http_server_props_manager_->SetSupportsQuic(true, actual_address);
+
+  // Update cache.
+  ExpectPrefsUpdate();
+  ExpectCacheUpdate();
+  http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
+  base::RunLoop().RunUntilIdle();
+
+  // Verify preferences.
+  const char expected_json[] = "{"
+    "\"servers\":{"
+      "\"mail.google.com:80\":{"
+        "\"alternate_protocol\":{"
+          "\"port\":444,\"probability\":0.2,\"protocol_str\":\"npn-spdy/3.1\""
+        "},"
+        "\"network_stats\":{"
+          "\"srtt\":42"
+        "}"
+      "},"
+      "\"www.google.com:80\":{"
+        "\"alternate_protocol\":{"
+          "\"port\":443,\"probability\":1.0,\"protocol_str\":\"npn-spdy/3\""
+        "}"
+      "}"
+    "},"
+    "\"supports_quic\":{"
+      "\"address\":\"127.0.0.1\",\"used_quic\":true"
+    "},"
+    "\"version\":3"
+  "}";
+
+  const base::Value* http_server_properties =
+      pref_service_.GetUserPref(kTestHttpServerProperties);
+  ASSERT_NE(nullptr, http_server_properties);
+  std::string preferences_json;
+  EXPECT_TRUE(
+      base::JSONWriter::Write(http_server_properties, &preferences_json));
+  EXPECT_EQ(expected_json, preferences_json);
 }
 
 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) {
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index f84b80c..754372b 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -86,14 +86,6 @@
   if (mapping_rules)
     mapping_rules->RewriteHost(&host_port);
 
-  if (http_server_properties->HasAlternateProtocol(host_port)) {
-    const AlternateProtocolInfo existing_alternate =
-        http_server_properties->GetAlternateProtocol(host_port);
-    // If we think the alternate protocol is broken, don't change it.
-    if (existing_alternate.is_broken)
-      return;
-  }
-
   http_server_properties->SetAlternateProtocol(
       host_port, static_cast<uint16>(port), protocol, probability);
 }
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index 9e932ee..235122d 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -24,11 +24,10 @@
 
 GURL UpgradeUrlToHttps(const GURL& original_url, int port) {
   GURL::Replacements replacements;
-  // new_sheme and new_port need to be in scope here because GURL::Replacements
-  // references the memory contained by them directly.
-  const std::string new_scheme = "https";
+  // new_port needs to be in scope here because GURL::Replacements references
+  // the memory contained by it directly.
   const std::string new_port = base::IntToString(port);
-  replacements.SetSchemeStr(new_scheme);
+  replacements.SetSchemeStr("https");
   replacements.SetPortStr(new_port);
   return original_url.ReplaceComponents(replacements);
 }
@@ -175,8 +174,7 @@
 AlternateProtocolInfo HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
     const GURL& original_url,
     GURL* alternate_url) {
-  const AlternateProtocolInfo kNoAlternateProtocol =
-      AlternateProtocolInfo(0,  UNINITIALIZED_ALTERNATE_PROTOCOL, 0);
+  const AlternateProtocolInfo kNoAlternateProtocol;
 
   if (!session_->params().use_alternate_protocols)
     return kNoAlternateProtocol;
@@ -185,19 +183,17 @@
     return kNoAlternateProtocol;
 
   HostPortPair origin = HostPortPair::FromURL(original_url);
-
   HttpServerProperties& http_server_properties =
       *session_->http_server_properties();
-  if (!http_server_properties.HasAlternateProtocol(origin))
-    return kNoAlternateProtocol;
-
-  AlternateProtocolInfo alternate =
+  const AlternateProtocolInfo alternate =
       http_server_properties.GetAlternateProtocol(origin);
+
+  if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+    return kNoAlternateProtocol;
   if (alternate.is_broken) {
     HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_BROKEN);
     return kNoAlternateProtocol;
   }
-
   if (!IsAlternateProtocolValid(alternate.protocol)) {
     NOTREACHED();
     return kNoAlternateProtocol;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 45a0970..8729dfb 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/logging.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -436,6 +437,10 @@
 }
 
 void HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "455884 HttpStreamFactoryImpl::Job::OnIOComplete"));
   RunLoop(result);
 }
 
diff --git a/net/interfaces/BUILD.gn b/net/interfaces/BUILD.gn
new file mode 100644
index 0000000..03a0778
--- /dev/null
+++ b/net/interfaces/BUILD.gn
@@ -0,0 +1,12 @@
+# 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("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni")
+
+mojom("interfaces") {
+  sources = [
+    "host_resolver_service.mojom",
+    "proxy_resolver_service.mojom",
+  ]
+}
diff --git a/net/interfaces/host_resolver_service.mojom b/net/interfaces/host_resolver_service.mojom
new file mode 100644
index 0000000..c8acc38
--- /dev/null
+++ b/net/interfaces/host_resolver_service.mojom
@@ -0,0 +1,55 @@
+// 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.
+
+// WARNING! Do NOT use this mojom. It is intended as a temporary interface to
+// implement out-of-process proxy resolution. If you wish to use a Mojo DNS
+// service, contact amistry@/sammc@ and net-dev to discuss a permanent Mojo DNS
+// interface.
+
+// Put Mojo definitions into their own namespace to avoid collisions with C++
+// definitions.
+// TODO(amistry): Resolve the conflict between these two sets of definitions.
+module net.interfaces;
+
+// Mirror of net::AddressFamily.
+enum AddressFamily {
+  UNSPECIFIED,
+  IPV4,
+  IPV6,
+};
+
+// Mirror of net::HostResolver::RequestInfo.
+struct HostResolverRequestInfo {
+  string host;
+  uint16 port;
+  AddressFamily address_family;
+  bool is_my_ip_address;
+};
+
+// Mirror of net::IPEndPoint.
+struct IPEndPoint {
+  // IP address as a numeric value from most to least significant byte.
+  // Will be of length 4 for IPv4 addresses and 16 for IPv6.
+  array<uint8> address;
+  uint16 port;
+};
+
+// Mirror of net::AddressList.
+struct AddressList {
+  array<IPEndPoint> addresses;
+};
+
+interface HostResolverService {
+  // Use a HostResolverRequestClient instead of returning a result so we can
+  // cancel in-flight requests by destroying the client.  IPC requests in Mojo
+  // cannot be cancelled directly.
+  // TODO(amistry): Add BoundNetLog.
+  Resolve(HostResolverRequestInfo request_info,
+          HostResolverRequestClient client);
+};
+
+interface HostResolverRequestClient {
+  // |error| is a value in net::Error.
+  ReportResult(int32 error, AddressList? result);
+};
diff --git a/net/interfaces/proxy_resolver_service.mojom b/net/interfaces/proxy_resolver_service.mojom
new file mode 100644
index 0000000..2cb7a0b
--- /dev/null
+++ b/net/interfaces/proxy_resolver_service.mojom
@@ -0,0 +1,48 @@
+// 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.
+
+// Put Mojo definitions into their own namespace to avoid collisions with C++
+// definitions.
+// TODO(amistry): Resolve the conflict between these two sets of definitions.
+module net.interfaces;
+
+import "host_resolver_service.mojom";
+
+// Mirror of net::ProxyServer::Scheme.
+enum ProxyScheme {
+  INVALID,
+  DIRECT,
+  HTTP,
+  SOCKS4,
+  SOCKS5,
+  HTTPS,
+  QUIC,
+};
+
+// Mirror of net::ProxyServer.
+struct ProxyServer {
+  ProxyScheme scheme;
+  string host;
+  uint16 port;
+};
+
+interface ProxyResolverService {
+  SetPacScript(string data) => (int32 result);
+
+  // Use a ProxyResolverRequestClient instead of returning a result so we can
+  // receive load state updates and cancel in-flight requests by destroying the
+  // client.
+  // TODO(amistry): Add BoundNetLog.
+  GetProxyForUrl(string url, ProxyResolverRequestClient client);
+};
+
+interface ProxyResolverRequestClient {
+  ReportResult(int32 error, array<ProxyServer>? proxy_servers);
+};
+
+interface ProxyResolverFactory {
+  // TODO(amistry): Add NetLog and ProxyResolverErrorObserver.
+  CreateResolver(ProxyResolverService& resolver,
+                 HostResolverService host_resolver);
+};
diff --git a/net/net.gyp b/net/net.gyp
index 834a4c6..cd381e0 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -837,6 +837,7 @@
         'cookies/cookie_monster_perftest.cc',
         'disk_cache/blockfile/disk_cache_perftest.cc',
         'proxy/proxy_resolver_perftest.cc',
+        'udp/udp_socket_perftest.cc',
         'websockets/websocket_frame_perftest.cc',
       ],
       'conditions': [
@@ -1203,6 +1204,22 @@
         },
       ],
     }],
+    ['use_v8_in_net == 1 and OS != "android"', {
+      'targets': [
+        {
+          # GN version: //net/interfaces
+          'target_name': 'net_interfaces',
+          'type': 'static_library',
+          'sources': [
+            'interfaces/host_resolver_service.mojom',
+            'interfaces/proxy_resolver_service.mojom',
+          ],
+          'includes': [
+            '../third_party/mojo/mojom_bindings_generator.gypi',
+          ],
+        },
+      ],
+    }],
     ['OS != "ios" and OS != "android"', {
       'targets': [
         # iOS doesn't have the concept of simple executables, these targets
diff --git a/net/net.gypi b/net/net.gypi
index 5b5a5f9..e3f0ee1 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -607,7 +607,6 @@
       'http/disk_cache_based_quic_server_info.h',
       'http/failing_http_transaction_factory.cc',
       'http/failing_http_transaction_factory.h',
-      'http/http_atom_list.h',
       'http/http_auth.cc',
       'http/http_auth.h',
       'http/http_auth_cache.cc',
diff --git a/net/net_unittests.isolate b/net/net_unittests.isolate
index e062a7d..877c21e 100644
--- a/net/net_unittests.isolate
+++ b/net/net_unittests.isolate
@@ -19,6 +19,8 @@
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
           '--lsan=<(lsan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
         'files': [
           '../testing/test_env.py',
@@ -32,6 +34,13 @@
         'read_only': 1,
       },
     }],
+    ['OS=="mac" and asan==1', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/net_unittests.dSYM/',
+        ],
+      },
+    }],
     ['OS=="win" and (fastbuild==0 or fastbuild==1)', {
       'variables': {
         'files': [
diff --git a/net/proxy/polling_proxy_config_service.cc b/net/proxy/polling_proxy_config_service.cc
index 611ea59..7c086db 100644
--- a/net/proxy/polling_proxy_config_service.cc
+++ b/net/proxy/polling_proxy_config_service.cc
@@ -9,6 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/observer_list.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/worker_pool.h"
 #include "net/proxy/proxy_config.h"
@@ -113,6 +114,11 @@
 
   // Called after the worker thread has finished retrieving a configuration.
   void GetConfigCompleted(const ProxyConfig& config) {
+    // TODO(pkasting): Remove ScopedTracker below once crbug.com/455942 is
+    // fixed.
+    tracked_objects::ScopedTracker tracking_profile(
+        FROM_HERE_WITH_EXPLICIT_FUNCTION(
+            "455942 PollingProxyConfigService::Core::GetConfigCompleted"));
     DCHECK(poll_task_outstanding_);
     poll_task_outstanding_ = false;
 
diff --git a/net/proxy/proxy_config_service_android.cc b/net/proxy/proxy_config_service_android.cc
index 80e3b92..503388a 100644
--- a/net/proxy/proxy_config_service_android.cc
+++ b/net/proxy/proxy_config_service_android.cc
@@ -302,12 +302,12 @@
     explicit JNIDelegateImpl(Delegate* delegate) : delegate_(delegate) {}
 
     // ProxyConfigServiceAndroid::JNIDelegate overrides.
-    virtual void ProxySettingsChangedTo(JNIEnv* env,
-                                        jobject jself,
-                                        jstring jhost,
-                                        jint jport,
-                                        jstring jpac_url,
-                                        jobjectArray jexclusion_list) override {
+    void ProxySettingsChangedTo(JNIEnv* env,
+                                jobject jself,
+                                jstring jhost,
+                                jint jport,
+                                jstring jpac_url,
+                                jobjectArray jexclusion_list) override {
       std::string host = ConvertJavaStringToUTF8(env, jhost);
       std::string pac_url;
       if (jpac_url)
@@ -318,7 +318,7 @@
       delegate_->ProxySettingsChangedTo(host, jport, pac_url, exclusion_list);
     }
 
-    virtual void ProxySettingsChanged(JNIEnv* env, jobject self) override {
+    void ProxySettingsChanged(JNIEnv* env, jobject self) override {
       delegate_->ProxySettingsChanged();
     }
 
diff --git a/net/proxy/proxy_config_service_android.h b/net/proxy/proxy_config_service_android.h
index cb15bc5..64e6b49 100644
--- a/net/proxy/proxy_config_service_android.h
+++ b/net/proxy/proxy_config_service_android.h
@@ -59,7 +59,7 @@
       const scoped_refptr<base::SequencedTaskRunner>& network_task_runner,
       const scoped_refptr<base::SequencedTaskRunner>& jni_task_runner);
 
-  virtual ~ProxyConfigServiceAndroid();
+  ~ProxyConfigServiceAndroid() override;
 
   // Register JNI bindings.
   static bool Register(JNIEnv* env);
@@ -71,9 +71,9 @@
 
   // ProxyConfigService:
   // Called only on the network thread.
-  virtual void AddObserver(Observer* observer) override;
-  virtual void RemoveObserver(Observer* observer) override;
-  virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) override;
+  void AddObserver(Observer* observer) override;
+  void RemoveObserver(Observer* observer) override;
+  ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) override;
 
  private:
   friend class ProxyConfigServiceAndroidTestBase;
diff --git a/net/proxy/proxy_config_service_android_unittest.cc b/net/proxy/proxy_config_service_android_unittest.cc
index 41f2387..2e4f7bb 100644
--- a/net/proxy/proxy_config_service_android_unittest.cc
+++ b/net/proxy/proxy_config_service_android_unittest.cc
@@ -23,7 +23,7 @@
   TestObserver() : availability_(ProxyConfigService::CONFIG_UNSET) {}
 
   // ProxyConfigService::Observer:
-  virtual void OnProxyConfigChanged(
+  void OnProxyConfigChanged(
       const ProxyConfig& config,
       ProxyConfigService::ConfigAvailability availability) override {
     config_ = config;
@@ -59,17 +59,15 @@
                  base::Bind(&ProxyConfigServiceAndroidTestBase::GetProperty,
                             base::Unretained(this))) {}
 
-  virtual ~ProxyConfigServiceAndroidTestBase() {}
+  ~ProxyConfigServiceAndroidTestBase() override {}
 
   // testing::Test:
-  virtual void SetUp() override {
+  void SetUp() override {
     message_loop_->RunUntilIdle();
     service_.AddObserver(&observer_);
   }
 
-  virtual void TearDown() override {
-    service_.RemoveObserver(&observer_);
-  }
+  void TearDown() override { service_.RemoveObserver(&observer_); }
 
   void ClearConfiguration() {
     configuration_.clear();
diff --git a/net/proxy/proxy_config_service_win.cc b/net/proxy/proxy_config_service_win.cc
index 6547659..df9014e 100644
--- a/net/proxy/proxy_config_service_win.cc
+++ b/net/proxy/proxy_config_service_win.cc
@@ -116,7 +116,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "ProxyConfigServiceWin_OnObjectSignaled"));
+          "418183 ProxyConfigServiceWin::OnObjectSignaled"));
 
   // Figure out which registry key signalled this change.
   RegKeyList::iterator it =
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index a62732d..bd7d825 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/strings/string_util.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/values.h"
@@ -1479,6 +1480,10 @@
 void ProxyService::OnProxyConfigChanged(
     const ProxyConfig& config,
     ProxyConfigService::ConfigAvailability availability) {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455942 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "455942 ProxyService::OnProxyConfigChanged"));
   // Retrieve the current proxy configuration from the ProxyConfigService.
   // If a configuration is not available yet, we will get called back later
   // by our ProxyConfigService::Observer once it changes.
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 5219d1e..3c85ca4 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -102,6 +102,21 @@
   scoped_ptr<SocketDataProvider> socket_data_;
 };
 
+class ProxyHeadersHandler {
+ public:
+  ProxyHeadersHandler() : was_called_(false) {}
+
+  bool was_called() { return was_called_; }
+
+  void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
+                                HttpRequestHeaders* request_headers) {
+    was_called_ = true;
+  }
+
+ private:
+  bool was_called_;
+};
+
 class QuicNetworkTransactionTest
     : public PlatformTest,
       public ::testing::WithParamInterface<QuicVersion> {
@@ -269,11 +284,11 @@
   }
 
   void SendRequestAndExpectQuicResponse(const std::string& expected) {
-    scoped_ptr<HttpNetworkTransaction> trans(
-        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
-    RunTransaction(trans.get());
-    CheckWasQuicResponse(trans);
-    CheckResponseData(trans.get(), expected);
+    SendRequestAndExpectQuicResponseMaybeFromProxy(expected, false);
+  }
+
+  void SendRequestAndExpectQuicResponseFromProxy(const std::string& expected) {
+    SendRequestAndExpectQuicResponseMaybeFromProxy(expected, true);
   }
 
   void AddQuicAlternateProtocolMapping(
@@ -284,17 +299,14 @@
   }
 
   void ExpectBrokenAlternateProtocolMapping() {
-    ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
-        HostPortPair::FromURL(request_.url)));
     const AlternateProtocolInfo alternate =
         session_->http_server_properties()->GetAlternateProtocol(
             HostPortPair::FromURL(request_.url));
+    EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternate.protocol);
     EXPECT_TRUE(alternate.is_broken);
   }
 
   void ExpectQuicAlternateProtocolMapping() {
-    ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
-        HostPortPair::FromURL(request_.url)));
     const AlternateProtocolInfo alternate =
         session_->http_server_properties()->GetAlternateProtocol(
             HostPortPair::FromURL(request_.url));
@@ -324,6 +336,22 @@
   HttpRequestInfo request_;
   CapturingBoundNetLog net_log_;
   StaticSocketDataProvider hanging_data_;
+
+ private:
+  void SendRequestAndExpectQuicResponseMaybeFromProxy(
+      const std::string& expected,
+      bool used_proxy) {
+    scoped_ptr<HttpNetworkTransaction> trans(
+        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
+    ProxyHeadersHandler proxy_headers_handler;
+    trans->SetBeforeProxyHeadersSentCallback(
+        base::Bind(&ProxyHeadersHandler::OnBeforeProxyHeadersSent,
+                   base::Unretained(&proxy_headers_handler)));
+    RunTransaction(trans.get());
+    CheckWasQuicResponse(trans);
+    CheckResponseData(trans.get(), expected);
+    EXPECT_EQ(used_proxy, proxy_headers_handler.was_called());
+  }
 };
 
 INSTANTIATE_TEST_CASE_P(Version, QuicNetworkTransactionTest,
@@ -414,7 +442,7 @@
 
   CreateSession();
 
-  SendRequestAndExpectQuicResponse("hello!");
+  SendRequestAndExpectQuicResponseFromProxy("hello!");
 }
 
 TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index f957c18..3e0f4e3 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -63,9 +63,6 @@
 // Set the maximum number of undecryptable packets the connection will store.
 const int32 kMaxUndecryptablePackets = 100;
 
-const char kDummyHostname[] = "quic.global.props";
-const uint16 kDummyPort = 0;
-
 void HistogramCreateSessionFailure(enum CreateSessionFailure error) {
   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error,
                             CREATION_ERROR_MAX);
@@ -619,11 +616,8 @@
 void QuicStreamFactory::set_require_confirmation(bool require_confirmation) {
   require_confirmation_ = require_confirmation;
   if (http_server_properties_ && (!(local_address_ == IPEndPoint()))) {
-    // TODO(rtenneti): Delete host_port_pair and persist data in globals.
-    HostPortPair host_port_pair(kDummyHostname, kDummyPort);
-    http_server_properties_->SetSupportsQuic(
-        host_port_pair, !require_confirmation,
-        local_address_.ToStringWithoutPort());
+    http_server_properties_->SetSupportsQuic(!require_confirmation,
+                                             local_address_.address());
   }
 }
 
@@ -1002,11 +996,9 @@
   socket->GetLocalAddress(&local_address_);
   if (check_persisted_supports_quic_ && http_server_properties_) {
     check_persisted_supports_quic_ = false;
-    // TODO(rtenneti): Delete host_port_pair and persist data in globals.
-    HostPortPair host_port_pair(kDummyHostname, kDummyPort);
-    SupportsQuic supports_quic(true, local_address_.ToStringWithoutPort());
-    if (http_server_properties_->GetSupportsQuic(
-            host_port_pair).Equals(supports_quic)) {
+    IPAddressNumber last_address;
+    if (http_server_properties_->GetSupportsQuic(&last_address) &&
+        last_address == local_address_.address()) {
       require_confirmation_ = false;
     }
   }
@@ -1249,7 +1241,9 @@
   const HostPortPair& server = server_id.host_port_pair();
   // Don't try to change the alternate-protocol state, if the
   // alternate-protocol state is unknown.
-  if (!http_server_properties_->HasAlternateProtocol(server))
+  const AlternateProtocolInfo alternate =
+      http_server_properties_->GetAlternateProtocol(server);
+  if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
     return;
 
   // TODO(rch):  In the special case where the session has received no
@@ -1258,8 +1252,6 @@
   // session connected until the handshake has been confirmed.
   HistogramBrokenAlternateProtocolLocation(
       BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY);
-  AlternateProtocolInfo alternate =
-      http_server_properties_->GetAlternateProtocol(server);
   DCHECK_EQ(QUIC, alternate.protocol);
 
   // Since the session was active, there's no longer an
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 4092365..4052828 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -1126,6 +1126,10 @@
 
 void ClientSocketPoolBaseHelper::InvokeUserCallback(
     ClientSocketHandle* handle) {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "455884 ClientSocketPoolBaseHelper::InvokeUserCallback"));
   PendingCallbackMap::iterator it = pending_callback_map_.find(handle);
 
   // Exit if the request has already been cancelled.
diff --git a/net/socket/socks_client_socket_pool.cc b/net/socket/socks_client_socket_pool.cc
index e11b7a4..e431227 100644
--- a/net/socket/socks_client_socket_pool.cc
+++ b/net/socket/socks_client_socket_pool.cc
@@ -76,6 +76,9 @@
 }
 
 void SOCKSConnectJob::OnIOComplete(int result) {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION("455884 SOCKSConnectJob::OnIOComplete"));
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING)
     NotifyDelegateOfCompletion(rv);  // Deletes |this|
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 483c5e7..011474f 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -2288,7 +2288,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile1(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "SSLClientSocketNSS::Core::DoReadCallback"));
+          "418183 SSLClientSocketNSS::Core::DoReadCallback"));
   PostOrRunCallback(
       FROM_HERE,
       base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 7734d64..bfc37e6 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -247,6 +247,9 @@
 }
 
 void SSLConnectJob::OnIOComplete(int result) {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION("455884 SSLConnectJob::OnIOComplete"));
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING)
     NotifyDelegateOfCompletion(rv);  // Deletes |this|.
diff --git a/net/socket/stream_listen_socket.cc b/net/socket/stream_listen_socket.cc
index abb5fbc..619070d 100644
--- a/net/socket/stream_listen_socket.cc
+++ b/net/socket/stream_listen_socket.cc
@@ -249,7 +249,8 @@
 void StreamListenSocket::OnObjectSignaled(HANDLE object) {
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("StreamListenSocket_OnObjectSignaled"));
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 StreamListenSocket::OnObjectSignaled"));
 
   WSANETWORKEVENTS ev;
   if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) {
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc
index 8eda581..8e719f0 100644
--- a/net/socket/tcp_client_socket.cc
+++ b/net/socket/tcp_client_socket.cc
@@ -327,7 +327,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "TCPClientSocket::DidCompleteReadWrite"));
+          "418183 TCPClientSocket::DidCompleteReadWrite"));
   callback.Run(result);
 }
 
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index 0031c63..538c8d7 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -250,7 +250,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "TCPSocketWin_Core_ReadDelegate_OnObjectSignaled"));
+          "418183 TCPSocketWin::Core::ReadDelegate::OnObjectSignaled"));
 
   DCHECK_EQ(object, core_->read_overlapped_.hEvent);
   if (core_->socket_) {
@@ -268,7 +268,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "TCPSocketWin_Core_WriteDelegate_OnObjectSignaled"));
+          "418183 TCPSocketWin::Core::WriteDelegate::OnObjectSignaled"));
 
   DCHECK_EQ(object, core_->write_overlapped_.hEvent);
   if (core_->socket_)
@@ -774,7 +774,8 @@
 void TCPSocketWin::OnObjectSignaled(HANDLE object) {
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("TCPSocketWin_OnObjectSignaled"));
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418383 TCPSocketWin::OnObjectSignaled"));
 
   WSANETWORKEVENTS ev;
   if (WSAEnumNetworkEvents(socket_, accept_event_, &ev) == SOCKET_ERROR) {
@@ -963,6 +964,10 @@
   DCHECK(!read_callback_.is_null());
   int result;
 
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 TCPSocketWin::DidCompleteConnect1"));
   WSANETWORKEVENTS events;
   int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
                                 &events);
@@ -972,6 +977,11 @@
     os_error = WSAGetLastError();
     result = MapSystemError(os_error);
   } else if (events.lNetworkEvents & FD_CONNECT) {
+    // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is
+    // fixed.
+    tracked_objects::ScopedTracker tracking_profile2(
+        FROM_HERE_WITH_EXPLICIT_FUNCTION(
+            "418183 TCPSocketWin::DidCompleteConnect2"));
     os_error = events.iErrorCode[FD_CONNECT_BIT];
     result = MapConnectError(os_error);
   } else {
@@ -979,10 +989,18 @@
     result = ERR_UNEXPECTED;
   }
 
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+  tracked_objects::ScopedTracker tracking_profile3(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 TCPSocketWin::DidCompleteConnect3"));
   connect_os_error_ = os_error;
   DoConnectComplete(result);
   waiting_connect_ = false;
 
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+  tracked_objects::ScopedTracker tracking_profile4(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "418183 TCPSocketWin::DidCompleteConnect4"));
   DCHECK_NE(result, ERR_IO_PENDING);
   base::ResetAndReturn(&read_callback_).Run(result);
 }
@@ -1030,6 +1048,9 @@
   DCHECK(waiting_read_);
   DCHECK(!read_callback_.is_null());
 
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION("418183 TCPSocketWin::DidSignalRead1"));
   int os_error = 0;
   WSANETWORKEVENTS network_events;
   int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
@@ -1038,6 +1059,11 @@
     os_error = WSAGetLastError();
     rv = MapSystemError(os_error);
   } else if (network_events.lNetworkEvents) {
+    // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is
+    // fixed.
+    tracked_objects::ScopedTracker tracking_profile2(
+        FROM_HERE_WITH_EXPLICIT_FUNCTION(
+            "418183 TCPSocketWin::DidSignalRead2"));
     DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0);
     // If network_events.lNetworkEvents is FD_CLOSE and
     // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful
@@ -1058,6 +1084,11 @@
     if (rv == ERR_IO_PENDING)
       return;
   } else {
+    // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is
+    // fixed.
+    tracked_objects::ScopedTracker tracking_profile3(
+        FROM_HERE_WITH_EXPLICIT_FUNCTION(
+            "418183 TCPSocketWin::DidSignalRead3"));
     // This may happen because Read() may succeed synchronously and
     // consume all the received data without resetting the event object.
     core_->WatchForRead();
@@ -1068,10 +1099,10 @@
   core_->read_iobuffer_ = NULL;
   core_->read_buffer_length_ = 0;
 
-  DCHECK_NE(rv, ERR_IO_PENDING);
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("TCPSocketWin::DidSignalRead"));
+  tracked_objects::ScopedTracker tracking_profile4(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION("418183 TCPSocketWin::DidSignalRead4"));
+  DCHECK_NE(rv, ERR_IO_PENDING);
   base::ResetAndReturn(&read_callback_).Run(rv);
 }
 
diff --git a/net/test/spawned_test_server/remote_test_server.h b/net/test/spawned_test_server/remote_test_server.h
index de12e4e..a8b8bb2 100644
--- a/net/test/spawned_test_server/remote_test_server.h
+++ b/net/test/spawned_test_server/remote_test_server.h
@@ -29,7 +29,7 @@
                    const SSLOptions& ssl_options,
                    const base::FilePath& document_root);
 
-  virtual ~RemoteTestServer();
+  ~RemoteTestServer() override;
 
   // Starts the Python test server on the host, instead of on the device, and
   // blocks until the server is ready.
diff --git a/net/test/spawned_test_server/spawner_communicator.cc b/net/test/spawned_test_server/spawner_communicator.cc
index 53484ea..bb1b445 100644
--- a/net/test/spawned_test_server/spawner_communicator.cc
+++ b/net/test/spawned_test_server/spawner_communicator.cc
@@ -47,7 +47,7 @@
     data_received_->clear();
   }
 
-  virtual ~SpawnerRequestData() {}
+  ~SpawnerRequestData() override {}
 
   bool DoesRequestIdMatch(int request_id) const {
     return request_id_ == request_id;
diff --git a/net/test/spawned_test_server/spawner_communicator.h b/net/test/spawned_test_server/spawner_communicator.h
index 549ad91..ba8bfca 100644
--- a/net/test/spawned_test_server/spawner_communicator.h
+++ b/net/test/spawned_test_server/spawner_communicator.h
@@ -61,7 +61,7 @@
 class SpawnerCommunicator : public net::URLRequest::Delegate {
  public:
   explicit SpawnerCommunicator(uint16 port);
-  virtual ~SpawnerCommunicator();
+  ~SpawnerCommunicator() override;
 
   // Starts an instance of the Python test server on the host/ machine.
   // If successfully started, returns true, setting |*port| to the port
@@ -100,8 +100,8 @@
                                              std::string* data_received);
 
   // URLRequest::Delegate methods. Called on the IO thread.
-  virtual void OnResponseStarted(URLRequest* request) override;
-  virtual void OnReadCompleted(URLRequest* request, int num_bytes) override;
+  void OnResponseStarted(URLRequest* request) override;
+  void OnReadCompleted(URLRequest* request, int num_bytes) override;
 
   // Reads Result from the response. Called on the IO thread.
   void ReadResult(URLRequest* request);
diff --git a/net/test/url_request/url_request_mock_http_job.cc b/net/test/url_request/url_request_mock_http_job.cc
index 9e63c25..e0905f2 100644
--- a/net/test/url_request/url_request_mock_http_job.cc
+++ b/net/test/url_request/url_request_mock_http_job.cc
@@ -122,16 +122,6 @@
 }
 
 // static
-void URLRequestMockHTTPJob::AddHostnameToFileHandler(
-    const std::string& hostname,
-    const base::FilePath& file,
-    const scoped_refptr<base::SequencedWorkerPool>& worker_pool) {
-  net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
-  filter->AddHostnameInterceptor(
-      "http", hostname, CreateInterceptorForSingleFile(file, worker_pool));
-}
-
-// static
 GURL URLRequestMockHTTPJob::GetMockUrl(const base::FilePath& path) {
   return GetMockUrlForScheme(path, "http");
 }
diff --git a/net/test/url_request/url_request_mock_http_job.h b/net/test/url_request/url_request_mock_http_job.h
index 6e454f4..61d5069 100644
--- a/net/test/url_request/url_request_mock_http_job.h
+++ b/net/test/url_request/url_request_mock_http_job.h
@@ -54,13 +54,6 @@
       const base::FilePath& base_path,
       const scoped_refptr<base::SequencedWorkerPool>& worker_pool);
 
-  // Respond to all HTTP requests of |hostname| with contents of the file
-  // located at |file_path|.
-  static void AddHostnameToFileHandler(
-      const std::string& hostname,
-      const base::FilePath& file,
-      const scoped_refptr<base::SequencedWorkerPool>& worker_pool);
-
   // Given the path to a file relative to the path passed to AddUrlHandler(),
   // construct a mock URL.
   static GURL GetMockUrl(const base::FilePath& path);
diff --git a/net/tools/net_watcher/net_watcher.cc b/net/tools/net_watcher/net_watcher.cc
index b6cf393..fb5c8e4 100644
--- a/net/tools/net_watcher/net_watcher.cc
+++ b/net/tools/net_watcher/net_watcher.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "net/base/network_change_notifier.h"
@@ -114,6 +115,11 @@
   void OnProxyConfigChanged(
       const net::ProxyConfig& config,
       net::ProxyConfigService::ConfigAvailability availability) override {
+    // TODO(pkasting): Remove ScopedTracker below once crbug.com/455942 is
+    // fixed.
+    tracked_objects::ScopedTracker tracking_profile(
+        FROM_HERE_WITH_EXPLICIT_FUNCTION(
+            "455942 NetWatcher::OnProxyConfigChanged"));
     LOG(INFO) << "OnProxyConfigChanged("
               << ProxyConfigToString(config) << ", "
               << ConfigAvailabilityToString(availability) << ")";
diff --git a/net/udp/udp_client_socket.cc b/net/udp/udp_client_socket.cc
index 9cdaace..8ea024d 100644
--- a/net/udp/udp_client_socket.cc
+++ b/net/udp/udp_client_socket.cc
@@ -62,4 +62,10 @@
   return socket_.NetLog();
 }
 
+#if defined(OS_WIN)
+void UDPClientSocket::UseNonBlockingIO() {
+  socket_.UseNonBlockingIO();
+}
+#endif
+
 }  // namespace net
diff --git a/net/udp/udp_client_socket.h b/net/udp/udp_client_socket.h
index 427db7e..7b4e1a6 100644
--- a/net/udp/udp_client_socket.h
+++ b/net/udp/udp_client_socket.h
@@ -38,6 +38,12 @@
   int SetSendBufferSize(int32 size) override;
   const BoundNetLog& NetLog() const override;
 
+#if defined(OS_WIN)
+  // Switch to use non-blocking IO. Must be called right after construction and
+  // before other calls.
+  void UseNonBlockingIO();
+#endif
+
  private:
   UDPSocket socket_;
   DISALLOW_COPY_AND_ASSIGN(UDPClientSocket);
diff --git a/net/udp/udp_server_socket.cc b/net/udp/udp_server_socket.cc
index 4653f71..9fc92df 100644
--- a/net/udp/udp_server_socket.cc
+++ b/net/udp/udp_server_socket.cc
@@ -120,4 +120,10 @@
   socket_.DetachFromThread();
 }
 
+#if defined(OS_WIN)
+void UDPServerSocket::UseNonBlockingIO() {
+  socket_.UseNonBlockingIO();
+}
+#endif
+
 }  // namespace net
diff --git a/net/udp/udp_server_socket.h b/net/udp/udp_server_socket.h
index 0799105..dabb8f0 100644
--- a/net/udp/udp_server_socket.h
+++ b/net/udp/udp_server_socket.h
@@ -47,6 +47,12 @@
   int SetDiffServCodePoint(DiffServCodePoint dscp) override;
   void DetachFromThread() override;
 
+#if defined(OS_WIN)
+  // Switch to use non-blocking IO. Must be called right after construction and
+  // before other calls.
+  void UseNonBlockingIO();
+#endif
+
  private:
   UDPSocket socket_;
   bool allow_address_reuse_;
diff --git a/net/udp/udp_socket_perftest.cc b/net/udp/udp_socket_perftest.cc
new file mode 100644
index 0000000..86f0729
--- /dev/null
+++ b/net/udp/udp_socket_perftest.cc
@@ -0,0 +1,141 @@
+// 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/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/perf_time_logger.h"
+#include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log_unittest.h"
+#include "net/base/net_util.h"
+#include "net/base/test_completion_callback.h"
+#include "net/test/net_test_suite.h"
+#include "net/udp/udp_client_socket.h"
+#include "net/udp/udp_server_socket.h"
+#include "net/udp/udp_socket.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class UDPSocketPerfTest : public PlatformTest {
+ public:
+  UDPSocketPerfTest()
+      : buffer_(new net::IOBufferWithSize(kPacketSize)), weak_factory_(this) {}
+
+  void DoneWritePacketsToSocket(net::UDPClientSocket* socket,
+                                int num_of_packets,
+                                base::Closure done_callback,
+                                int error) {
+    WritePacketsToSocket(socket, num_of_packets, done_callback);
+  }
+
+  // Send |num_of_packets| to |socket|. Invoke |done_callback| when done.
+  void WritePacketsToSocket(net::UDPClientSocket* socket,
+                            int num_of_packets,
+                            base::Closure done_callback);
+
+  // Use non-blocking IO if |use_nonblocking_io| is true. This variable only
+  // has effect on Windows.
+  void WriteBenchmark(bool use_nonblocking_io);
+
+ protected:
+  static const int kPacketSize = 1024;
+  scoped_refptr<net::IOBufferWithSize> buffer_;
+  base::WeakPtrFactory<UDPSocketPerfTest> weak_factory_;
+};
+
+// Creates and address from an ip/port and returns it in |address|.
+void CreateUDPAddress(std::string ip_str,
+                      uint16 port,
+                      net::IPEndPoint* address) {
+  net::IPAddressNumber ip_number;
+  bool rv = net::ParseIPLiteralToNumber(ip_str, &ip_number);
+  if (!rv)
+    return;
+  *address = net::IPEndPoint(ip_number, port);
+}
+
+void UDPSocketPerfTest::WritePacketsToSocket(net::UDPClientSocket* socket,
+                                             int num_of_packets,
+                                             base::Closure done_callback) {
+  scoped_refptr<net::IOBufferWithSize> io_buffer(
+      new net::IOBufferWithSize(kPacketSize));
+  memset(io_buffer->data(), 'G', kPacketSize);
+
+  while (num_of_packets) {
+    int rv =
+        socket->Write(io_buffer.get(), io_buffer->size(),
+                      base::Bind(&UDPSocketPerfTest::DoneWritePacketsToSocket,
+                                 weak_factory_.GetWeakPtr(), socket,
+                                 num_of_packets - 1, done_callback));
+    if (rv == net::ERR_IO_PENDING)
+      break;
+    --num_of_packets;
+  }
+  if (!num_of_packets) {
+    done_callback.Run();
+    return;
+  }
+}
+
+void UDPSocketPerfTest::WriteBenchmark(bool use_nonblocking_io) {
+  base::MessageLoopForIO message_loop;
+  const uint16 kPort = 9999;
+
+  // Setup the server to listen.
+  net::IPEndPoint bind_address;
+  CreateUDPAddress("127.0.0.1", kPort, &bind_address);
+  net::CapturingNetLog server_log;
+  scoped_ptr<net::UDPServerSocket> server(
+      new net::UDPServerSocket(&server_log, net::NetLog::Source()));
+#if defined(OS_WIN)
+  if (use_nonblocking_io)
+    server->UseNonBlockingIO();
+#endif
+  int rv = server->Listen(bind_address);
+  ASSERT_EQ(net::OK, rv);
+
+  // Setup the client.
+  net::IPEndPoint server_address;
+  CreateUDPAddress("127.0.0.1", kPort, &server_address);
+  net::CapturingNetLog client_log;
+  scoped_ptr<net::UDPClientSocket> client(new net::UDPClientSocket(
+      net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(), &client_log,
+      net::NetLog::Source()));
+#if defined(OS_WIN)
+  if (use_nonblocking_io)
+    client->UseNonBlockingIO();
+#endif
+  rv = client->Connect(server_address);
+  EXPECT_EQ(net::OK, rv);
+
+  base::RunLoop run_loop;
+  base::TimeTicks start_ticks = base::TimeTicks::Now();
+  int packets = 100000;
+  client->SetSendBufferSize(1024);
+  WritePacketsToSocket(client.get(), packets, run_loop.QuitClosure());
+  run_loop.Run();
+
+  double elapsed = (base::TimeTicks::Now() - start_ticks).InSecondsF();
+  LOG(INFO) << "Write speed: " << packets / 1024 / elapsed << " MB/s";
+}
+
+TEST_F(UDPSocketPerfTest, Write) {
+  base::PerfTimeLogger timer("UDP_socket_write");
+  WriteBenchmark(false);
+}
+
+#if defined(OS_WIN)
+TEST_F(UDPSocketPerfTest, WriteNonBlocking) {
+  base::PerfTimeLogger timer("UDP_socket_write_nonblocking");
+  WriteBenchmark(true);
+}
+#endif
+
+}  // namespace
diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc
index 221be01..4f902a3 100644
--- a/net/udp/udp_socket_unittest.cc
+++ b/net/udp/udp_socket_unittest.cc
@@ -9,7 +9,10 @@
 
 #include "base/basictypes.h"
 #include "base/bind.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
@@ -27,9 +30,7 @@
 
 class UDPSocketTest : public PlatformTest {
  public:
-  UDPSocketTest()
-      : buffer_(new IOBufferWithSize(kMaxRead)) {
-  }
+  UDPSocketTest() : buffer_(new IOBufferWithSize(kMaxRead)) {}
 
   // Blocks until data is read from the socket.
   std::string RecvFromSocket(UDPServerSocket* socket) {
@@ -112,22 +113,36 @@
     return bytes_sent;
   }
 
+  void WriteSocketIgnoreResult(UDPClientSocket* socket, std::string msg) {
+    WriteSocket(socket, msg);
+  }
+
+  // Creates an address from ip address and port and writes it to |*address|.
+  void CreateUDPAddress(std::string ip_str, uint16 port, IPEndPoint* address) {
+    IPAddressNumber ip_number;
+    bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
+    if (!rv)
+      return;
+    *address = IPEndPoint(ip_number, port);
+  }
+
+  // Run unit test for a connection test.
+  // |use_nonblocking_io| is used to switch between overlapped and non-blocking
+  // IO on Windows. It has no effect in other ports.
+  void ConnectTest(bool use_nonblocking_io);
+
  protected:
   static const int kMaxRead = 1024;
   scoped_refptr<IOBufferWithSize> buffer_;
   IPEndPoint recv_from_address_;
 };
 
-// Creates and address from an ip/port and returns it in |address|.
-void CreateUDPAddress(std::string ip_str, uint16 port, IPEndPoint* address) {
-  IPAddressNumber ip_number;
-  bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
-  if (!rv)
-    return;
-  *address = IPEndPoint(ip_number, port);
+void ReadCompleteCallback(int* result_out, base::Closure callback, int result) {
+  *result_out = result;
+  callback.Run();
 }
 
-TEST_F(UDPSocketTest, Connect) {
+void UDPSocketTest::ConnectTest(bool use_nonblocking_io) {
   const uint16 kPort = 9999;
   std::string simple_message("hello world!");
 
@@ -137,6 +152,10 @@
   CapturingNetLog server_log;
   scoped_ptr<UDPServerSocket> server(
       new UDPServerSocket(&server_log, NetLog::Source()));
+#if defined(OS_WIN)
+  if (use_nonblocking_io)
+    server->UseNonBlockingIO();
+#endif
   server->AllowAddressReuse();
   int rv = server->Listen(bind_address);
   ASSERT_EQ(OK, rv);
@@ -146,10 +165,13 @@
   CreateUDPAddress("127.0.0.1", kPort, &server_address);
   CapturingNetLog client_log;
   scoped_ptr<UDPClientSocket> client(
-      new UDPClientSocket(DatagramSocket::DEFAULT_BIND,
-                          RandIntCallback(),
-                          &client_log,
-                          NetLog::Source()));
+      new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
+                          &client_log, NetLog::Source()));
+#if defined(OS_WIN)
+  if (use_nonblocking_io)
+    client->UseNonBlockingIO();
+#endif
+
   rv = client->Connect(server_address);
   EXPECT_EQ(OK, rv);
 
@@ -169,6 +191,23 @@
   str = ReadSocket(client.get());
   DCHECK(simple_message == str);
 
+  // Test asynchronous read. Server waits for message.
+  base::RunLoop run_loop;
+  int read_result = 0;
+  rv = server->RecvFrom(
+      buffer_.get(), kMaxRead, &recv_from_address_,
+      base::Bind(&ReadCompleteCallback, &read_result, run_loop.QuitClosure()));
+  EXPECT_EQ(ERR_IO_PENDING, rv);
+
+  // Client sends to the server.
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&UDPSocketTest::WriteSocketIgnoreResult,
+                 base::Unretained(this), client.get(), simple_message));
+  run_loop.Run();
+  EXPECT_EQ(simple_message.length(), static_cast<size_t>(read_result));
+  EXPECT_EQ(simple_message, std::string(buffer_->data(), read_result));
+
   // Delete sockets so they log their final events.
   server.reset();
   client.reset();
@@ -176,34 +215,48 @@
   // Check the server's log.
   CapturingNetLog::CapturedEntryList server_entries;
   server_log.GetEntries(&server_entries);
-  EXPECT_EQ(4u, server_entries.size());
-  EXPECT_TRUE(LogContainsBeginEvent(
-      server_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
+  EXPECT_EQ(5u, server_entries.size());
+  EXPECT_TRUE(
+      LogContainsBeginEvent(server_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
   EXPECT_TRUE(LogContainsEvent(
       server_entries, 1, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
+  EXPECT_TRUE(LogContainsEvent(server_entries, 2, NetLog::TYPE_UDP_BYTES_SENT,
+                               NetLog::PHASE_NONE));
   EXPECT_TRUE(LogContainsEvent(
-      server_entries, 2, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE));
-  EXPECT_TRUE(LogContainsEndEvent(
-      server_entries, 3, NetLog::TYPE_SOCKET_ALIVE));
+      server_entries, 3, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
+  EXPECT_TRUE(
+      LogContainsEndEvent(server_entries, 4, NetLog::TYPE_SOCKET_ALIVE));
 
   // Check the client's log.
   CapturingNetLog::CapturedEntryList client_entries;
   client_log.GetEntries(&client_entries);
-  EXPECT_EQ(6u, client_entries.size());
-  EXPECT_TRUE(LogContainsBeginEvent(
-      client_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
-  EXPECT_TRUE(LogContainsBeginEvent(
-      client_entries, 1, NetLog::TYPE_UDP_CONNECT));
-  EXPECT_TRUE(LogContainsEndEvent(
-      client_entries, 2, NetLog::TYPE_UDP_CONNECT));
-  EXPECT_TRUE(LogContainsEvent(
-      client_entries, 3, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE));
+  EXPECT_EQ(7u, client_entries.size());
+  EXPECT_TRUE(
+      LogContainsBeginEvent(client_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
+  EXPECT_TRUE(
+      LogContainsBeginEvent(client_entries, 1, NetLog::TYPE_UDP_CONNECT));
+  EXPECT_TRUE(LogContainsEndEvent(client_entries, 2, NetLog::TYPE_UDP_CONNECT));
+  EXPECT_TRUE(LogContainsEvent(client_entries, 3, NetLog::TYPE_UDP_BYTES_SENT,
+                               NetLog::PHASE_NONE));
   EXPECT_TRUE(LogContainsEvent(
       client_entries, 4, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
-  EXPECT_TRUE(LogContainsEndEvent(
-      client_entries, 5, NetLog::TYPE_SOCKET_ALIVE));
+  EXPECT_TRUE(LogContainsEvent(client_entries, 5, NetLog::TYPE_UDP_BYTES_SENT,
+                               NetLog::PHASE_NONE));
+  EXPECT_TRUE(
+      LogContainsEndEvent(client_entries, 6, NetLog::TYPE_SOCKET_ALIVE));
 }
 
+TEST_F(UDPSocketTest, Connect) {
+  // The variable |use_nonblocking_io| has no effect in non-Windows ports.
+  ConnectTest(false);
+}
+
+#if defined(OS_WIN)
+TEST_F(UDPSocketTest, ConnectNonBlocking) {
+  ConnectTest(true);
+}
+#endif
+
 #if defined(OS_MACOSX)
 // UDPSocketPrivate_Broadcast is disabled for OSX because it requires
 // root permissions on OSX 10.7+.
diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc
index 3c121b2..90ce661 100644
--- a/net/udp/udp_socket_win.cc
+++ b/net/udp/udp_socket_win.cc
@@ -149,7 +149,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "UDPSocketWin_Core_ReadDelegate_OnObjectSignaled"));
+          "418183 UDPSocketWin::Core::ReadDelegate::OnObjectSignaled"));
 
   DCHECK_EQ(object, core_->read_overlapped_.hEvent);
   if (core_->socket_)
@@ -162,7 +162,7 @@
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "UDPSocketWin_Core_WriteDelegate_OnObjectSignaled"));
+          "418183 UDPSocketWin::Core::WriteDelegate::OnObjectSignaled"));
 
   DCHECK_EQ(object, core_->write_overlapped_.hEvent);
   if (core_->socket_)
@@ -261,6 +261,9 @@
       multicast_time_to_live_(1),
       bind_type_(bind_type),
       rand_int_cb_(rand_int_cb),
+      use_non_blocking_io_(false),
+      read_iobuffer_len_(0),
+      write_iobuffer_len_(0),
       recv_from_address_(NULL),
       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)),
       qos_handle_(NULL),
@@ -285,7 +288,12 @@
   socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
   if (socket_ == INVALID_SOCKET)
     return MapSystemError(WSAGetLastError());
-  core_ = new Core(this);
+  if (!use_non_blocking_io_) {
+    core_ = new Core(this);
+  } else {
+    read_write_event_.Set(WSACreateEvent());
+    WSAEventSelect(socket_, read_write_event_.Get(), FD_READ | FD_WRITE);
+  }
   return OK;
 }
 
@@ -312,8 +320,13 @@
   addr_family_ = 0;
   is_connected_ = false;
 
-  core_->Detach();
-  core_ = NULL;
+  read_write_watcher_.StopWatching();
+  read_write_event_.Close();
+
+  if (core_) {
+    core_->Detach();
+    core_ = NULL;
+  }
 }
 
 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
@@ -377,7 +390,8 @@
   DCHECK(!callback.is_null());  // Synchronous operation not supported.
   DCHECK_GT(buf_len, 0);
 
-  int nread = InternalRecvFrom(buf, buf_len, address);
+  int nread = core_ ? InternalRecvFromOverlapped(buf, buf_len, address)
+                    : InternalRecvFromNonBlocking(buf, buf_len, address);
   if (nread != ERR_IO_PENDING)
     return nread;
 
@@ -410,7 +424,8 @@
   DCHECK_GT(buf_len, 0);
   DCHECK(!send_to_address_.get());
 
-  int nwrite = InternalSendTo(buf, buf_len, address);
+  int nwrite = core_ ? InternalSendToOverlapped(buf, buf_len, address)
+                     : InternalSendToNonBlocking(buf, buf_len, address);
   if (nwrite != ERR_IO_PENDING)
     return nwrite;
 
@@ -573,38 +588,24 @@
   WSAResetEvent(core_->read_overlapped_.hEvent);
   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
   // Convert address.
-  if (recv_from_address_ && result >= 0) {
-    if (!ReceiveAddressToIPEndpoint(recv_from_address_))
+  IPEndPoint address;
+  IPEndPoint* address_to_log = NULL;
+  if (result >= 0) {
+    if (address.FromSockAddr(core_->recv_addr_storage_.addr,
+                             core_->recv_addr_storage_.addr_len)) {
+      if (recv_from_address_)
+        *recv_from_address_ = address;
+      address_to_log = &address;
+    } else {
       result = ERR_ADDRESS_INVALID;
+    }
   }
-  LogRead(result, core_->read_iobuffer_->data());
+  LogRead(result, core_->read_iobuffer_->data(), address_to_log);
   core_->read_iobuffer_ = NULL;
   recv_from_address_ = NULL;
   DoReadCallback(result);
 }
 
-void UDPSocketWin::LogRead(int result, const char* bytes) const {
-  if (result < 0) {
-    net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
-    return;
-  }
-
-  if (net_log_.IsLogging()) {
-    // Get address for logging, if |address| is NULL.
-    IPEndPoint address;
-    bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
-    net_log_.AddEvent(
-        NetLog::TYPE_UDP_BYTES_RECEIVED,
-        CreateNetLogUDPDataTranferCallback(
-            result, bytes,
-            is_address_valid ? &address : NULL));
-  }
-
-  base::StatsCounter read_bytes("udp.read_bytes");
-  read_bytes.Add(result);
-  NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
-}
-
 void UDPSocketWin::DidCompleteWrite() {
   DWORD num_bytes, flags;
   BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
@@ -618,6 +619,91 @@
   DoWriteCallback(result);
 }
 
+void UDPSocketWin::OnObjectSignaled(HANDLE object) {
+  DCHECK(object == read_write_event_.Get());
+  WSANETWORKEVENTS network_events;
+  int os_error = 0;
+  int rv =
+      WSAEnumNetworkEvents(socket_, read_write_event_.Get(), &network_events);
+  if (rv == SOCKET_ERROR) {
+    os_error = WSAGetLastError();
+    rv = MapSystemError(os_error);
+    if (read_iobuffer_) {
+      read_iobuffer_ = NULL;
+      read_iobuffer_len_ = 0;
+      recv_from_address_ = NULL;
+      DoReadCallback(rv);
+    }
+    if (write_iobuffer_) {
+      write_iobuffer_ = NULL;
+      write_iobuffer_len_ = 0;
+      send_to_address_.reset();
+      DoWriteCallback(rv);
+    }
+    return;
+  }
+  if ((network_events.lNetworkEvents & FD_READ) && read_iobuffer_) {
+    OnReadSignaled();
+  }
+  if ((network_events.lNetworkEvents & FD_WRITE) && write_iobuffer_) {
+    OnWriteSignaled();
+  }
+
+  // There's still pending read / write. Watch for further events.
+  if (read_iobuffer_ || write_iobuffer_) {
+    WatchForReadWrite();
+  }
+}
+
+void UDPSocketWin::OnReadSignaled() {
+  int rv = InternalRecvFromNonBlocking(read_iobuffer_.get(), read_iobuffer_len_,
+                                       recv_from_address_);
+  if (rv == ERR_IO_PENDING)
+    return;
+  read_iobuffer_ = NULL;
+  read_iobuffer_len_ = 0;
+  recv_from_address_ = NULL;
+  DoReadCallback(rv);
+}
+
+void UDPSocketWin::OnWriteSignaled() {
+  int rv = InternalSendToNonBlocking(write_iobuffer_.get(), write_iobuffer_len_,
+                                     send_to_address_.get());
+  if (rv == ERR_IO_PENDING)
+    return;
+  write_iobuffer_ = NULL;
+  write_iobuffer_len_ = 0;
+  send_to_address_.reset();
+  DoWriteCallback(rv);
+}
+
+void UDPSocketWin::WatchForReadWrite() {
+  if (read_write_watcher_.IsWatching())
+    return;
+  bool watched =
+      read_write_watcher_.StartWatching(read_write_event_.Get(), this);
+  DCHECK(watched);
+}
+
+void UDPSocketWin::LogRead(int result,
+                           const char* bytes,
+                           const IPEndPoint* address) const {
+  if (result < 0) {
+    net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
+    return;
+  }
+
+  if (net_log_.IsLogging()) {
+    net_log_.AddEvent(
+        NetLog::TYPE_UDP_BYTES_RECEIVED,
+        CreateNetLogUDPDataTranferCallback(result, bytes, address));
+  }
+
+  base::StatsCounter read_bytes("udp.read_bytes");
+  read_bytes.Add(result);
+  NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
+}
+
 void UDPSocketWin::LogWrite(int result,
                             const char* bytes,
                             const IPEndPoint* address) const {
@@ -637,8 +723,9 @@
   NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result);
 }
 
-int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
-                                   IPEndPoint* address) {
+int UDPSocketWin::InternalRecvFromOverlapped(IOBuffer* buf,
+                                             int buf_len,
+                                             IPEndPoint* address) {
   DCHECK(!core_->read_iobuffer_.get());
   SockaddrStorage& storage = core_->recv_addr_storage_;
   storage.addr_len = sizeof(storage.addr_storage);
@@ -657,18 +744,26 @@
     if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
       int result = num;
       // Convert address.
-      if (address && result >= 0) {
-        if (!ReceiveAddressToIPEndpoint(address))
+      IPEndPoint address_storage;
+      IPEndPoint* address_to_log = NULL;
+      if (result >= 0) {
+        if (address_storage.FromSockAddr(core_->recv_addr_storage_.addr,
+                                         core_->recv_addr_storage_.addr_len)) {
+          if (address)
+            *address = address_storage;
+          address_to_log = &address_storage;
+        } else {
           result = ERR_ADDRESS_INVALID;
+        }
       }
-      LogRead(result, buf->data());
+      LogRead(result, buf->data(), address_to_log);
       return result;
     }
   } else {
     int os_error = WSAGetLastError();
     if (os_error != WSA_IO_PENDING) {
       int result = MapSystemError(os_error);
-      LogRead(result, NULL);
+      LogRead(result, NULL, NULL);
       return result;
     }
   }
@@ -677,8 +772,9 @@
   return ERR_IO_PENDING;
 }
 
-int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
-                                 const IPEndPoint* address) {
+int UDPSocketWin::InternalSendToOverlapped(IOBuffer* buf,
+                                           int buf_len,
+                                           const IPEndPoint* address) {
   DCHECK(!core_->write_iobuffer_.get());
   SockaddrStorage storage;
   struct sockaddr* addr = storage.addr;
@@ -723,6 +819,78 @@
   return ERR_IO_PENDING;
 }
 
+int UDPSocketWin::InternalRecvFromNonBlocking(IOBuffer* buf,
+                                              int buf_len,
+                                              IPEndPoint* address) {
+  DCHECK(!read_iobuffer_ || read_iobuffer_.get() == buf);
+  SockaddrStorage storage;
+  storage.addr_len = sizeof(storage.addr_storage);
+
+  CHECK_NE(INVALID_SOCKET, socket_);
+  int rv = recvfrom(socket_, buf->data(), buf_len, 0, storage.addr,
+                    &storage.addr_len);
+  if (rv == SOCKET_ERROR) {
+    int os_error = WSAGetLastError();
+    if (os_error == WSAEWOULDBLOCK) {
+      read_iobuffer_ = buf;
+      read_iobuffer_len_ = buf_len;
+      WatchForReadWrite();
+      return ERR_IO_PENDING;
+    }
+    rv = MapSystemError(os_error);
+    LogRead(rv, NULL, NULL);
+    return rv;
+  }
+  IPEndPoint address_storage;
+  IPEndPoint* address_to_log = NULL;
+  if (rv >= 0) {
+    if (address_storage.FromSockAddr(storage.addr, storage.addr_len)) {
+      if (address)
+        *address = address_storage;
+      address_to_log = &address_storage;
+    } else {
+      rv = ERR_ADDRESS_INVALID;
+    }
+  }
+  LogRead(rv, buf->data(), address_to_log);
+  return rv;
+}
+
+int UDPSocketWin::InternalSendToNonBlocking(IOBuffer* buf,
+                                            int buf_len,
+                                            const IPEndPoint* address) {
+  DCHECK(!write_iobuffer_ || write_iobuffer_.get() == buf);
+  SockaddrStorage storage;
+  struct sockaddr* addr = storage.addr;
+  // Convert address.
+  if (address) {
+    if (!address->ToSockAddr(addr, &storage.addr_len)) {
+      int result = ERR_ADDRESS_INVALID;
+      LogWrite(result, NULL, NULL);
+      return result;
+    }
+  } else {
+    addr = NULL;
+    storage.addr_len = 0;
+  }
+
+  int rv = sendto(socket_, buf->data(), buf_len, 0, addr, storage.addr_len);
+  if (rv == SOCKET_ERROR) {
+    int os_error = WSAGetLastError();
+    if (os_error == WSAEWOULDBLOCK) {
+      write_iobuffer_ = buf;
+      write_iobuffer_len_ = buf_len;
+      WatchForReadWrite();
+      return ERR_IO_PENDING;
+    }
+    rv = MapSystemError(os_error);
+    LogWrite(rv, NULL, NULL);
+    return rv;
+  }
+  LogWrite(rv, buf->data(), address);
+  return rv;
+}
+
 int UDPSocketWin::SetMulticastOptions() {
   if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
     DWORD loop = 0;
@@ -807,11 +975,6 @@
   return DoBind(IPEndPoint(address, 0));
 }
 
-bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
-  SockaddrStorage& storage = core_->recv_addr_storage_;
-  return address->FromSockAddr(storage.addr, storage.addr_len);
-}
-
 int UDPSocketWin::JoinGroup(
     const IPAddressNumber& group_address) const {
   DCHECK(CalledOnValidThread());
@@ -1016,4 +1179,9 @@
   base::NonThreadSafe::DetachFromThread();
 }
 
+void UDPSocketWin::UseNonBlockingIO() {
+  DCHECK(!core_);
+  use_non_blocking_io_ = true;
+}
+
 }  // namespace net
diff --git a/net/udp/udp_socket_win.h b/net/udp/udp_socket_win.h
index 6f0ec2c..d994eec 100644
--- a/net/udp/udp_socket_win.h
+++ b/net/udp/udp_socket_win.h
@@ -12,6 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
 #include "base/win/object_watcher.h"
+#include "base/win/scoped_handle.h"
 #include "net/base/address_family.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
@@ -23,7 +24,9 @@
 
 namespace net {
 
-class NET_EXPORT UDPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe) {
+class NET_EXPORT UDPSocketWin
+    : NON_EXPORTED_BASE(public base::NonThreadSafe),
+      NON_EXPORTED_BASE(public base::win::ObjectWatcher::Delegate) {
  public:
   UDPSocketWin(DatagramSocket::BindType bind_type,
                const RandIntCallback& rand_int_cb,
@@ -174,6 +177,10 @@
   // Resets the thread to be used for thread-safety checks.
   void DetachFromThread();
 
+  // This class by default uses overlapped IO. Call this method before Open()
+  // to switch to non-blocking IO.
+  void UseNonBlockingIO();
+
  private:
   enum SocketOptions {
     SOCKET_OPTION_MULTICAST_LOOP = 1 << 0
@@ -183,13 +190,20 @@
 
   void DoReadCallback(int rv);
   void DoWriteCallback(int rv);
+
   void DidCompleteRead();
   void DidCompleteWrite();
 
+  // base::ObjectWatcher::Delegate implementation.
+  virtual void OnObjectSignaled(HANDLE object);
+  void OnReadSignaled();
+  void OnWriteSignaled();
+
+  void WatchForReadWrite();
+
   // Handles stats and logging. |result| is the number of bytes transferred, on
-  // success, or the net error code on failure. LogRead retrieves the address
-  // from |recv_addr_storage_|, while LogWrite takes it as an optional argument.
-  void LogRead(int result, const char* bytes) const;
+  // success, or the net error code on failure.
+  void LogRead(int result, const char* bytes, const IPEndPoint* address) const;
   void LogWrite(int result, const char* bytes, const IPEndPoint* address) const;
 
   // Same as SendTo(), except that address is passed by pointer
@@ -201,8 +215,22 @@
                     const CompletionCallback& callback);
 
   int InternalConnect(const IPEndPoint& address);
-  int InternalRecvFrom(IOBuffer* buf, int buf_len, IPEndPoint* address);
-  int InternalSendTo(IOBuffer* buf, int buf_len, const IPEndPoint* address);
+
+  // Version for using overlapped IO.
+  int InternalRecvFromOverlapped(IOBuffer* buf,
+                                 int buf_len,
+                                 IPEndPoint* address);
+  int InternalSendToOverlapped(IOBuffer* buf,
+                               int buf_len,
+                               const IPEndPoint* address);
+
+  // Version for using non-blocking IO.
+  int InternalRecvFromNonBlocking(IOBuffer* buf,
+                                  int buf_len,
+                                  IPEndPoint* address);
+  int InternalSendToNonBlocking(IOBuffer* buf,
+                                int buf_len,
+                                const IPEndPoint* address);
 
   // Applies |socket_options_| to |socket_|. Should be called before
   // Bind().
@@ -211,10 +239,6 @@
   // Binds to a random port on |address|.
   int RandomBind(const IPAddressNumber& address);
 
-  // Attempts to convert the data in |recv_addr_storage_| and |recv_addr_len_|
-  // to an IPEndPoint and writes it to |address|. Returns true on success.
-  bool ReceiveAddressToIPEndpoint(IPEndPoint* address) const;
-
   SOCKET socket_;
   int addr_family_;
   bool is_connected_;
@@ -247,6 +271,22 @@
   // they are not destroyed while the OS still references them.
   scoped_refptr<Core> core_;
 
+  // True if non-blocking IO is used.
+  bool use_non_blocking_io_;
+
+  // Watches |read_write_event_|.
+  base::win::ObjectWatcher read_write_watcher_;
+
+  // Events for read and write.
+  base::win::ScopedHandle read_write_event_;
+
+  // The buffers used in Read() and Write().
+  scoped_refptr<IOBuffer> read_iobuffer_;
+  scoped_refptr<IOBuffer> write_iobuffer_;
+
+  int read_iobuffer_len_;
+  int write_iobuffer_len_;
+
   IPEndPoint* recv_from_address_;
 
   // Cached copy of the current address we're sending to, if any.  Used for
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 132a67d..d7203a4 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -227,12 +227,6 @@
   return upload_data_stream_.get() != NULL;
 }
 
-void URLRequest::SetExtraRequestHeaderById(int id, const string& value,
-                                           bool overwrite) {
-  DCHECK(!is_pending_ || is_redirecting_);
-  NOTREACHED() << "implement me!";
-}
-
 void URLRequest::SetExtraRequestHeaderByName(const string& name,
                                              const string& value,
                                              bool overwrite) {
@@ -273,6 +267,10 @@
 }
 
 LoadStateWithParam URLRequest::GetLoadState() const {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455952 is
+  // fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION("455952 URLRequest::GetLoadState"));
   // The !blocked_by_.empty() check allows |this| to report it's blocked on a
   // delegate before it has been started.
   if (calling_delegate_ || !blocked_by_.empty()) {
@@ -378,11 +376,6 @@
   return job_->GetUploadProgress();
 }
 
-void URLRequest::GetResponseHeaderById(int id, string* value) {
-  DCHECK(job_.get());
-  NOTREACHED() << "implement me!";
-}
-
 void URLRequest::GetResponseHeaderByName(const string& name, string* value) {
   DCHECK(value);
   if (response_info_.headers.get()) {
@@ -392,15 +385,6 @@
   }
 }
 
-void URLRequest::GetAllResponseHeaders(string* headers) {
-  DCHECK(headers);
-  if (response_info_.headers.get()) {
-    response_info_.headers->GetNormalizedHeaders(headers);
-  } else {
-    headers->clear();
-  }
-}
-
 HostPortPair URLRequest::GetSocketAddress() const {
   DCHECK(job_.get());
   return job_->GetSocketAddress();
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index af972bd..20aab60 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -82,14 +82,6 @@
                                            NetworkDelegate* network_delegate,
                                            const std::string& scheme);
 
-  // HTTP request/response header IDs (via some preprocessor fun) for use with
-  // SetRequestHeaderById and GetResponseHeaderById.
-  enum {
-#define HTTP_ATOM(x) HTTP_ ## x,
-#include "net/http/http_atom_list.h"
-#undef HTTP_ATOM
-  };
-
   // Referrer policies (see set_referrer_policy): During server redirects, the
   // referrer header might be cleared, if the protocol changes from HTTPS to
   // HTTP. This is the default behavior of URLRequest, corresponding to
@@ -334,11 +326,9 @@
   // Returns true if the request has a non-empty message body to upload.
   bool has_upload() const;
 
-  // Set an extra request header by ID or name, or remove one by name.  These
-  // methods may only be called before Start() is called, or before a new
-  // redirect in the request chain.
-  void SetExtraRequestHeaderById(int header_id, const std::string& value,
-                                 bool overwrite);
+  // Set or remove a extra request header.  These methods may only be called
+  // before Start() is called, or between receiving a redirect and trying to
+  // follow it.
   void SetExtraRequestHeaderByName(const std::string& name,
                                    const std::string& value, bool overwrite);
   void RemoveRequestHeaderByName(const std::string& name);
@@ -401,19 +391,13 @@
   // chunked, size is set to zero, but position will not be.
   UploadProgress GetUploadProgress() const;
 
-  // Get response header(s) by ID or name.  These methods may only be called
+  // Get response header(s) by name.  This method may only be called
   // once the delegate's OnResponseStarted method has been called.  Headers
   // that appear more than once in the response are coalesced, with values
   // separated by commas (per RFC 2616). This will not work with cookies since
   // comma can be used in cookie values.
-  // TODO(darin): add API to enumerate response headers.
-  void GetResponseHeaderById(int header_id, std::string* value);
   void GetResponseHeaderByName(const std::string& name, std::string* value);
 
-  // Get all response headers, \n-delimited and \n\0-terminated.  This includes
-  // the response status line.  Restrictions on GetResponseHeaders apply.
-  void GetAllResponseHeaders(std::string* headers);
-
   // The time when |this| was constructed.
   base::TimeTicks creation_time() const { return creation_time_; }
 
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index d774714..d1050e3 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -285,6 +285,11 @@
 }
 
 LoadState URLRequestFtpJob::GetLoadState() const {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455952 is
+  // fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "455952 URLRequestFtpJob::GetLoadState"));
   if (proxy_info_.is_direct()) {
     return ftp_transaction_ ?
         ftp_transaction_->GetLoadState() : LOAD_STATE_IDLE;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 68858c1..4247d83 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/debug/alias.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/file_version_info.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
@@ -289,6 +290,12 @@
 }
 
 void URLRequestHttpJob::Kill() {
+  if (awaiting_callback_) {
+    // TODO(battre) crbug.com/289715
+    // Simulate a crash to see who kills the job while it is waiting for a
+    // callback. This should not happen, see URLRequest::OrphanJob().
+    base::debug::DumpWithoutCrashing();
+  }
   if (!transaction_.get())
     return;
 
@@ -1020,6 +1027,11 @@
 }
 
 LoadState URLRequestHttpJob::GetLoadState() const {
+  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455952 is
+  // fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "455952 URLRequestHttpJob::GetLoadState"));
   return transaction_.get() ?
       transaction_->GetLoadState() : LOAD_STATE_IDLE;
 }
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 2be8a74..3fae14f 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -503,7 +503,8 @@
 void URLRequestJob::NotifyReadComplete(int bytes_read) {
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
   tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("URLRequestJob::NotifyReadComplete"));
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "423948 URLRequestJob::NotifyReadComplete"));
 
   if (!request_ || !request_->has_delegate())
     return;  // The request was destroyed, so there is no more work to do.
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index c3bc166..5937464 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -5989,10 +5989,8 @@
     TestDelegate d;
 
     GURL::Replacements replacements;
-    std::string username("user2");
-    std::string password("secret");
-    replacements.SetUsernameStr(username);
-    replacements.SetPasswordStr(password);
+    replacements.SetUsernameStr("user2");
+    replacements.SetPasswordStr("secret");
     GURL url_with_identity = url_requiring_auth.ReplaceComponents(replacements);
 
     scoped_ptr<URLRequest> r(context.CreateRequest(
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index 4aa2f1c..1a3df04 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -338,9 +338,8 @@
   // The test server doesn't have an unauthenticated proxy mode. WebSockets
   // cannot provide auth information that isn't already cached, so it's
   // necessary to preflight an HTTP request to authenticate against the proxy.
-  std::string scheme("http");
   GURL::Replacements replacements;
-  replacements.SetSchemeStr(scheme);
+  replacements.SetSchemeStr("http");
   // It doesn't matter what the URL is, as long as it is an HTTP navigation.
   GURL http_page =
       ws_server.GetURL("connect_check.html").ReplaceComponents(replacements);
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index 96df5fd..64940f1 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -94,20 +94,23 @@
   }
 
   if (compile_suid_client) {
-    sources += [ "suid/client/setuid_sandbox_client_unittest.cc" ]
+    sources += [
+      "suid/client/setuid_sandbox_client_unittest.cc",
+      "suid/client/setuid_sandbox_host_unittest.cc",
+    ]
   }
   if (use_seccomp_bpf) {
     sources += [
       "bpf_dsl/bpf_dsl_more_unittest.cc",
       "bpf_dsl/bpf_dsl_unittest.cc",
+      "bpf_dsl/codegen_unittest.cc",
       "bpf_dsl/cons_unittest.cc",
+      "bpf_dsl/syscall_set_unittest.cc",
       "seccomp-bpf-helpers/baseline_policy_unittest.cc",
       "seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc",
       "seccomp-bpf/bpf_tests_unittest.cc",
-      "seccomp-bpf/codegen_unittest.cc",
       "seccomp-bpf/errorcode_unittest.cc",
       "seccomp-bpf/sandbox_bpf_unittest.cc",
-      "seccomp-bpf/syscall_iterator_unittest.cc",
       "seccomp-bpf/syscall_unittest.cc",
     ]
   }
@@ -146,6 +149,8 @@
     "bpf_dsl/bpf_dsl.h",
     "bpf_dsl/bpf_dsl_forward.h",
     "bpf_dsl/bpf_dsl_impl.h",
+    "bpf_dsl/codegen.cc",
+    "bpf_dsl/codegen.h",
     "bpf_dsl/cons.h",
     "bpf_dsl/dump_bpf.cc",
     "bpf_dsl/dump_bpf.h",
@@ -153,9 +158,9 @@
     "bpf_dsl/policy.h",
     "bpf_dsl/policy_compiler.cc",
     "bpf_dsl/policy_compiler.h",
+    "bpf_dsl/syscall_set.cc",
+    "bpf_dsl/syscall_set.h",
     "bpf_dsl/trap_registry.h",
-    "seccomp-bpf/codegen.cc",
-    "seccomp-bpf/codegen.h",
     "seccomp-bpf/die.cc",
     "seccomp-bpf/die.h",
     "seccomp-bpf/errorcode.cc",
@@ -165,8 +170,6 @@
     "seccomp-bpf/sandbox_bpf.h",
     "seccomp-bpf/syscall.cc",
     "seccomp-bpf/syscall.h",
-    "seccomp-bpf/syscall_iterator.cc",
-    "seccomp-bpf/syscall_iterator.h",
     "seccomp-bpf/trap.cc",
     "seccomp-bpf/trap.h",
     "seccomp-bpf/verifier.cc",
@@ -306,6 +309,8 @@
       "suid/common/suid_unsafe_environment_variables.h",
       "suid/client/setuid_sandbox_client.cc",
       "suid/client/setuid_sandbox_client.h",
+      "suid/client/setuid_sandbox_host.cc",
+      "suid/client/setuid_sandbox_host.h",
     ]
     defines = [ "SANDBOX_IMPLEMENTATION" ]
 
diff --git a/sandbox/linux/seccomp-bpf/codegen.cc b/sandbox/linux/bpf_dsl/codegen.cc
similarity index 98%
rename from sandbox/linux/seccomp-bpf/codegen.cc
rename to sandbox/linux/bpf_dsl/codegen.cc
index 055aa71..793d95d 100644
--- a/sandbox/linux/seccomp-bpf/codegen.cc
+++ b/sandbox/linux/bpf_dsl/codegen.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 "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 
 #include <linux/filter.h>
 
diff --git a/sandbox/linux/seccomp-bpf/codegen.h b/sandbox/linux/bpf_dsl/codegen.h
similarity index 96%
rename from sandbox/linux/seccomp-bpf/codegen.h
rename to sandbox/linux/bpf_dsl/codegen.h
index ef04a5d..c2e1f93 100644
--- a/sandbox/linux/seccomp-bpf/codegen.h
+++ b/sandbox/linux/bpf_dsl/codegen.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_SECCOMP_BPF_CODEGEN_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
+#ifndef SANDBOX_LINUX_BPF_DSL_CODEGEN_H__
+#define SANDBOX_LINUX_BPF_DSL_CODEGEN_H__
 
 #include <stddef.h>
 #include <stdint.h>
@@ -120,4 +120,4 @@
 
 }  // namespace sandbox
 
-#endif  // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
+#endif  // SANDBOX_LINUX_BPF_DSL_CODEGEN_H__
diff --git a/sandbox/linux/seccomp-bpf/codegen_unittest.cc b/sandbox/linux/bpf_dsl/codegen_unittest.cc
similarity index 99%
rename from sandbox/linux/seccomp-bpf/codegen_unittest.cc
rename to sandbox/linux/bpf_dsl/codegen_unittest.cc
index 8d4bf5d..3abfc85 100644
--- a/sandbox/linux/seccomp-bpf/codegen_unittest.cc
+++ b/sandbox/linux/bpf_dsl/codegen_unittest.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 "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 
 #include <linux/filter.h>
 
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.cc b/sandbox/linux/bpf_dsl/dump_bpf.cc
index ddbcd0e..5cf53ff 100644
--- a/sandbox/linux/bpf_dsl/dump_bpf.cc
+++ b/sandbox/linux/bpf_dsl/dump_bpf.cc
@@ -6,8 +6,8 @@
 
 #include <stdio.h>
 
+#include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/linux/bpf_dsl/trap_registry.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.h b/sandbox/linux/bpf_dsl/dump_bpf.h
index ce260f8..cd12be7 100644
--- a/sandbox/linux/bpf_dsl/dump_bpf.h
+++ b/sandbox/linux/bpf_dsl/dump_bpf.h
@@ -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 "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/sandbox_export.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index f91f70c..2b72f3b 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -14,13 +14,13 @@
 #include "base/macros.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
 #include "sandbox/linux/seccomp-bpf/die.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
 #include "sandbox/linux/seccomp-bpf/syscall.h"
-#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
 
 namespace sandbox {
 namespace bpf_dsl {
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.h b/sandbox/linux/bpf_dsl/policy_compiler.h
index 8737c42..faf6be5 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.h
+++ b/sandbox/linux/bpf_dsl/policy_compiler.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
 #include "sandbox/sandbox_export.h"
 
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator.cc b/sandbox/linux/bpf_dsl/syscall_set.cc
similarity index 97%
rename from sandbox/linux/seccomp-bpf/syscall_iterator.cc
rename to sandbox/linux/bpf_dsl/syscall_set.cc
index 195a8b0..22d6046 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator.cc
+++ b/sandbox/linux/bpf_dsl/syscall_set.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 "sandbox/linux/seccomp-bpf/syscall_iterator.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
 
 #include "base/logging.h"
 #include "base/macros.h"
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator.h b/sandbox/linux/bpf_dsl/syscall_set.h
similarity index 92%
rename from sandbox/linux/seccomp-bpf/syscall_iterator.h
rename to sandbox/linux/bpf_dsl/syscall_set.h
index 5080fcc..b9f076d 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator.h
+++ b/sandbox/linux/bpf_dsl/syscall_set.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_SECCOMP_BPF_SYSCALL_ITERATOR_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_ITERATOR_H__
+#ifndef SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__
+#define SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__
 
 #include <stdint.h>
 
@@ -14,8 +14,6 @@
 
 namespace sandbox {
 
-// TODO(mdempsky): Rename this header to syscall_set.h.
-
 // Iterates over the entire system call range from 0..0xFFFFFFFFu. This
 // iterator is aware of how system calls look like and will skip quickly
 // over ranges that can't contain system calls. It iterates more slowly
@@ -102,4 +100,4 @@
 
 }  // namespace sandbox
 
-#endif  // SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_ITERATOR_H__
+#endif  // SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc b/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
similarity index 87%
rename from sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc
rename to sandbox/linux/bpf_dsl/syscall_set_unittest.cc
index 3bc1eaa..5730dc4 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc
+++ b/sandbox/linux/bpf_dsl/syscall_set_unittest.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 "sandbox/linux/seccomp-bpf/syscall_iterator.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
 
 #include <stdint.h>
 
@@ -18,7 +18,7 @@
     SyscallSet::InvalidOnly(),
 };
 
-SANDBOX_TEST(SyscallIterator, Monotonous) {
+SANDBOX_TEST(SyscallSet, Monotonous) {
   for (const SyscallSet& set : kSyscallSets) {
     uint32_t prev = 0;
     bool have_prev = false;
@@ -54,7 +54,7 @@
   SANDBOX_ASSERT(prev == max);
 }
 
-SANDBOX_TEST(SyscallIterator, ValidSyscallRanges) {
+SANDBOX_TEST(SyscallSet, ValidSyscallRanges) {
   AssertRange(MIN_SYSCALL, MAX_PUBLIC_SYSCALL);
 #if defined(__arm__)
   AssertRange(MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL);
@@ -62,7 +62,7 @@
 #endif
 }
 
-SANDBOX_TEST(SyscallIterator, InvalidSyscalls) {
+SANDBOX_TEST(SyscallSet, InvalidSyscalls) {
   static const uint32_t kExpected[] = {
 #if defined(__mips__)
     0,
@@ -93,19 +93,19 @@
   }
 }
 
-SANDBOX_TEST(SyscallIterator, ValidOnlyIsOnlyValid) {
+SANDBOX_TEST(SyscallSet, ValidOnlyIsOnlyValid) {
   for (uint32_t sysnum : SyscallSet::ValidOnly()) {
     SANDBOX_ASSERT(SyscallSet::IsValid(sysnum));
   }
 }
 
-SANDBOX_TEST(SyscallIterator, InvalidOnlyIsOnlyInvalid) {
+SANDBOX_TEST(SyscallSet, InvalidOnlyIsOnlyInvalid) {
   for (uint32_t sysnum : SyscallSet::InvalidOnly()) {
     SANDBOX_ASSERT(!SyscallSet::IsValid(sysnum));
   }
 }
 
-SANDBOX_TEST(SyscallIterator, AllIsValidOnlyPlusInvalidOnly) {
+SANDBOX_TEST(SyscallSet, AllIsValidOnlyPlusInvalidOnly) {
   std::vector<uint32_t> merged;
   const SyscallSet valid_only = SyscallSet::ValidOnly();
   const SyscallSet invalid_only = SyscallSet::InvalidOnly();
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 15bd71c..c03b024 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -122,6 +122,8 @@
         'bpf_dsl/bpf_dsl.h',
         'bpf_dsl/bpf_dsl_forward.h',
         'bpf_dsl/bpf_dsl_impl.h',
+        'bpf_dsl/codegen.cc',
+        'bpf_dsl/codegen.h',
         'bpf_dsl/cons.h',
         'bpf_dsl/dump_bpf.cc',
         'bpf_dsl/dump_bpf.h',
@@ -129,9 +131,9 @@
         'bpf_dsl/policy.h',
         'bpf_dsl/policy_compiler.cc',
         'bpf_dsl/policy_compiler.h',
+        'bpf_dsl/syscall_set.cc',
+        'bpf_dsl/syscall_set.h',
         'bpf_dsl/trap_registry.h',
-        'seccomp-bpf/codegen.cc',
-        'seccomp-bpf/codegen.h',
         'seccomp-bpf/die.cc',
         'seccomp-bpf/die.h',
         'seccomp-bpf/errorcode.cc',
@@ -141,8 +143,6 @@
         'seccomp-bpf/sandbox_bpf.h',
         'seccomp-bpf/syscall.cc',
         'seccomp-bpf/syscall.h',
-        'seccomp-bpf/syscall_iterator.cc',
-        'seccomp-bpf/syscall_iterator.h',
         'seccomp-bpf/trap.cc',
         'seccomp-bpf/trap.h',
         'seccomp-bpf/verifier.cc',
@@ -315,6 +315,8 @@
         'suid/common/suid_unsafe_environment_variables.h',
         'suid/client/setuid_sandbox_client.cc',
         'suid/client/setuid_sandbox_client.h',
+        'suid/client/setuid_sandbox_host.cc',
+        'suid/client/setuid_sandbox_host.h',
       ],
       'defines': [
         'SANDBOX_IMPLEMENTATION',
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index 61517cc..eef29db 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -34,20 +34,21 @@
     [ 'compile_suid_client==1', {
       'sources': [
         'suid/client/setuid_sandbox_client_unittest.cc',
+        'suid/client/setuid_sandbox_host_unittest.cc',
       ],
     }],
     [ 'use_seccomp_bpf==1', {
       'sources': [
         'bpf_dsl/bpf_dsl_more_unittest.cc',
         'bpf_dsl/bpf_dsl_unittest.cc',
+        'bpf_dsl/codegen_unittest.cc',
         'bpf_dsl/cons_unittest.cc',
+        'bpf_dsl/syscall_set_unittest.cc',
         'seccomp-bpf-helpers/baseline_policy_unittest.cc',
         'seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc',
         'seccomp-bpf/bpf_tests_unittest.cc',
-        'seccomp-bpf/codegen_unittest.cc',
         'seccomp-bpf/errorcode_unittest.cc',
         'seccomp-bpf/sandbox_bpf_unittest.cc',
-        'seccomp-bpf/syscall_iterator_unittest.cc',
         'seccomp-bpf/syscall_unittest.cc',
       ],
     }],
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index 555f672..d51fa78 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -23,15 +23,15 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/third_party/valgrind/valgrind.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/linux/bpf_dsl/dump_bpf.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
 #include "sandbox/linux/seccomp-bpf/die.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
 #include "sandbox/linux/seccomp-bpf/syscall.h"
-#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
 #include "sandbox/linux/seccomp-bpf/trap.h"
 #include "sandbox/linux/seccomp-bpf/verifier.h"
 #include "sandbox/linux/services/linux_syscalls.h"
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
index 1a9c1f8..e46889b 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.h
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
@@ -10,7 +10,7 @@
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/sandbox_export.h"
 
 namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/seccomp-bpf/verifier.cc
index 548df25..68fca88 100644
--- a/sandbox/linux/seccomp-bpf/verifier.cc
+++ b/sandbox/linux/seccomp-bpf/verifier.cc
@@ -12,10 +12,10 @@
 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
 
 namespace sandbox {
 
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc
index 1209fdf..40a2bc4 100644
--- a/sandbox/linux/services/credentials_unittest.cc
+++ b/sandbox/linux/services/credentials_unittest.cc
@@ -123,11 +123,11 @@
 }
 
 // Test the WorkingDirectoryIsRoot() helper.
-TEST(Credentials, CanDetectRoot) {
-  ASSERT_EQ(0, chdir("/proc/"));
-  ASSERT_FALSE(WorkingDirectoryIsRoot());
-  ASSERT_EQ(0, chdir("/"));
-  ASSERT_TRUE(WorkingDirectoryIsRoot());
+SANDBOX_TEST(Credentials, CanDetectRoot) {
+  PCHECK(0 == chdir("/proc/"));
+  CHECK(!WorkingDirectoryIsRoot());
+  PCHECK(0 == chdir("/"));
+  CHECK(WorkingDirectoryIsRoot());
 }
 
 // Disabled on ASAN because of crbug.com/451603.
diff --git a/sandbox/linux/services/namespace_sandbox_unittest.cc b/sandbox/linux/services/namespace_sandbox_unittest.cc
index ace1f92..91e1db9 100644
--- a/sandbox/linux/services/namespace_sandbox_unittest.cc
+++ b/sandbox/linux/services/namespace_sandbox_unittest.cc
@@ -90,7 +90,8 @@
   return 0;
 }
 
-TEST_F(NamespaceSandboxTest, ChrootAndDropCapabilities) {
+// Temporarily disabled on ASAN due to crbug.com/451603.
+TEST_F(NamespaceSandboxTest, DISABLE_ON_ASAN(ChrootAndDropCapabilities)) {
   TestProc("ChrootMe");
 }
 
diff --git a/sandbox/linux/services/unix_domain_socket_unittest.cc b/sandbox/linux/services/unix_domain_socket_unittest.cc
index 4d57c0d..dafa91d 100644
--- a/sandbox/linux/services/unix_domain_socket_unittest.cc
+++ b/sandbox/linux/services/unix_domain_socket_unittest.cc
@@ -17,7 +17,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/posix/unix_domain_socket_linux.h"
-#include "base/process/process_handle.h"
+#include "base/process/process.h"
 #include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/tests/unit_tests.h"
 
@@ -57,10 +57,9 @@
   // base::GetParentProcessId() is defined as taking a ProcessHandle instead of
   // a ProcessId, even though it's a POSIX-only function and IDs and Handles
   // are both simply pid_t on POSIX... :/
-  base::ProcessHandle handle;
-  CHECK(base::OpenProcessHandle(pid, &handle));
-  base::ProcessId ret = base::GetParentProcessId(pid);
-  base::CloseProcessHandle(handle);
+  base::Process process = base::Process::Open(pid);
+  CHECK(process.IsValid());
+  base::ProcessId ret = base::GetParentProcessId(process.Handle());
   return ret;
 }
 
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.cc b/sandbox/linux/suid/client/setuid_sandbox_client.cc
index f0b5cef..12ef7f9 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.cc
@@ -5,95 +5,24 @@
 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
 
 #include <fcntl.h>
-#include <stdlib.h>
-#include <sys/socket.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include "base/command_line.h"
+#include <string>
+
 #include "base/environment.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
-#include "base/process/launch.h"
-#include "base/process/process_metrics.h"
 #include "base/strings/string_number_conversions.h"
-#include "sandbox/linux/services/init_process_reaper.h"
 #include "sandbox/linux/suid/common/sandbox.h"
-#include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h"
 
 namespace {
 
 bool IsFileSystemAccessDenied() {
-  base::ScopedFD self_exe(HANDLE_EINTR(open(base::kProcSelfExe, O_RDONLY)));
-  return !self_exe.is_valid();
-}
-
-// Set an environment variable that reflects the API version we expect from the
-// setuid sandbox. Old versions of the sandbox will ignore this.
-void SetSandboxAPIEnvironmentVariable(base::Environment* env) {
-  env->SetVar(sandbox::kSandboxEnvironmentApiRequest,
-              base::IntToString(sandbox::kSUIDSandboxApiNumber));
-}
-
-// Unset environment variables that are expected to be set by the setuid
-// sandbox. This is to allow nesting of one instance of the SUID sandbox
-// inside another.
-void UnsetExpectedEnvironmentVariables(base::EnvironmentMap* env_map) {
-  DCHECK(env_map);
-  const base::NativeEnvironmentString environment_vars[] = {
-      sandbox::kSandboxDescriptorEnvironmentVarName,
-      sandbox::kSandboxHelperPidEnvironmentVarName,
-      sandbox::kSandboxEnvironmentApiProvides,
-      sandbox::kSandboxPIDNSEnvironmentVarName,
-      sandbox::kSandboxNETNSEnvironmentVarName,
-  };
-
-  for (size_t i = 0; i < arraysize(environment_vars); ++i) {
-    // Setting values in EnvironmentMap to an empty-string will make
-    // sure that they get unset from the environment via AlterEnvironment().
-    (*env_map)[environment_vars[i]] = base::NativeEnvironmentString();
-  }
-}
-
-// Wrapper around a shared C function.
-// Returns the "saved" environment variable name corresponding to |envvar|
-// in a new string or NULL.
-std::string* CreateSavedVariableName(const char* env_var) {
-  char* const saved_env_var = SandboxSavedEnvironmentVariable(env_var);
-  if (!saved_env_var)
-    return NULL;
-  std::string* saved_env_var_copy = new std::string(saved_env_var);
-  // SandboxSavedEnvironmentVariable is the C function that we wrap and uses
-  // malloc() to allocate memory.
-  free(saved_env_var);
-  return saved_env_var_copy;
-}
-
-// The ELF loader will clear many environment variables so we save them to
-// different names here so that the SUID sandbox can resolve them for the
-// renderer.
-void SaveSUIDUnsafeEnvironmentVariables(base::Environment* env) {
-  for (unsigned i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) {
-    const char* env_var = kSUIDUnsafeEnvironmentVariables[i];
-    // Get the saved environment variable corresponding to envvar.
-    scoped_ptr<std::string> saved_env_var(CreateSavedVariableName(env_var));
-    if (saved_env_var == NULL)
-      continue;
-
-    std::string value;
-    if (env->GetVar(env_var, &value))
-      env->SetVar(saved_env_var->c_str(), value);
-    else
-      env->UnSetVar(saved_env_var->c_str());
-  }
+  base::ScopedFD root_dir(HANDLE_EINTR(open("/", O_RDONLY)));
+  return !root_dir.is_valid();
 }
 
 int GetHelperApi(base::Environment* env) {
@@ -128,30 +57,21 @@
   return EnvToInt(env, sandbox::kSandboxDescriptorEnvironmentVarName);
 }
 
-const char* GetDevelSandboxPath() {
-  return getenv("CHROME_DEVEL_SANDBOX");
-}
-
 }  // namespace
 
 namespace sandbox {
 
 SetuidSandboxClient* SetuidSandboxClient::Create() {
   base::Environment* environment(base::Environment::Create());
-  SetuidSandboxClient* sandbox_client(new SetuidSandboxClient);
-
   CHECK(environment);
-  sandbox_client->env_ = environment;
-  return sandbox_client;
+  return new SetuidSandboxClient(environment);
 }
 
-SetuidSandboxClient::SetuidSandboxClient()
-    : env_(NULL),
-      sandboxed_(false) {
+SetuidSandboxClient::SetuidSandboxClient(base::Environment* env)
+    : env_(env), sandboxed_(false) {
 }
 
 SetuidSandboxClient::~SetuidSandboxClient() {
-  delete env_;
 }
 
 void SetuidSandboxClient::CloseDummyFile() {
@@ -170,7 +90,7 @@
 }
 
 bool SetuidSandboxClient::ChrootMe() {
-  int ipc_fd = GetIPCDescriptor(env_);
+  int ipc_fd = GetIPCDescriptor(env_.get());
 
   if (ipc_fd < 0) {
     LOG(ERROR) << "Failed to obtain the sandbox IPC descriptor";
@@ -183,7 +103,7 @@
   }
 
   // We need to reap the chroot helper process in any event.
-  pid_t helper_pid = GetHelperPID(env_);
+  pid_t helper_pid = GetHelperPID(env_.get());
   // If helper_pid is -1 we wait for any child.
   if (HANDLE_EINTR(waitpid(helper_pid, NULL, 0)) < 0) {
     PLOG(ERROR) << "Failed to wait for setuid helper to die";
@@ -208,17 +128,12 @@
   return true;
 }
 
-bool SetuidSandboxClient::CreateInitProcessReaper(
-    base::Closure* post_fork_parent_callback) {
-  return sandbox::CreateInitProcessReaper(post_fork_parent_callback);
-}
-
 bool SetuidSandboxClient::IsSuidSandboxUpToDate() const {
-  return GetHelperApi(env_) == kSUIDSandboxApiNumber;
+  return GetHelperApi(env_.get()) == kSUIDSandboxApiNumber;
 }
 
 bool SetuidSandboxClient::IsSuidSandboxChild() const {
-  return GetIPCDescriptor(env_) >= 0;
+  return GetIPCDescriptor(env_.get()) >= 0;
 }
 
 bool SetuidSandboxClient::IsInNewPIDNamespace() const {
@@ -233,87 +148,4 @@
   return sandboxed_;
 }
 
-// Check if CHROME_DEVEL_SANDBOX is set but empty. This currently disables
-// the setuid sandbox. TODO(jln): fix this (crbug.com/245376).
-bool SetuidSandboxClient::IsDisabledViaEnvironment() {
-  const char* devel_sandbox_path = GetDevelSandboxPath();
-  if (devel_sandbox_path && '\0' == *devel_sandbox_path) {
-    return true;
-  }
-  return false;
-}
-
-base::FilePath SetuidSandboxClient::GetSandboxBinaryPath() {
-  base::FilePath sandbox_binary;
-  base::FilePath exe_dir;
-  if (PathService::Get(base::DIR_EXE, &exe_dir)) {
-    base::FilePath sandbox_candidate = exe_dir.AppendASCII("chrome-sandbox");
-    if (base::PathExists(sandbox_candidate))
-      sandbox_binary = sandbox_candidate;
-  }
-
-  // In user-managed builds, including development builds, an environment
-  // variable is required to enable the sandbox. See
-  // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
-  struct stat st;
-  if (sandbox_binary.empty() && stat(base::kProcSelfExe, &st) == 0 &&
-      st.st_uid == getuid()) {
-    const char* devel_sandbox_path = GetDevelSandboxPath();
-    if (devel_sandbox_path) {
-      sandbox_binary = base::FilePath(devel_sandbox_path);
-    }
-  }
-
-  return sandbox_binary;
-}
-
-void SetuidSandboxClient::PrependWrapper(base::CommandLine* cmd_line) {
-  std::string sandbox_binary(GetSandboxBinaryPath().value());
-  struct stat st;
-  if (sandbox_binary.empty() || stat(sandbox_binary.c_str(), &st) != 0) {
-    LOG(FATAL) << "The SUID sandbox helper binary is missing: "
-               << sandbox_binary << " Aborting now. See "
-                                    "https://code.google.com/p/chromium/wiki/"
-                                    "LinuxSUIDSandboxDevelopment.";
-  }
-
-  if (access(sandbox_binary.c_str(), X_OK) != 0 || (st.st_uid != 0) ||
-      ((st.st_mode & S_ISUID) == 0) || ((st.st_mode & S_IXOTH)) == 0) {
-    LOG(FATAL) << "The SUID sandbox helper binary was found, but is not "
-                  "configured correctly. Rather than run without sandboxing "
-                  "I'm aborting now. You need to make sure that "
-               << sandbox_binary << " is owned by root and has mode 4755.";
-  }
-
-  cmd_line->PrependWrapper(sandbox_binary);
-}
-
-void SetuidSandboxClient::SetupLaunchOptions(
-    base::LaunchOptions* options,
-    base::FileHandleMappingVector* fds_to_remap,
-    base::ScopedFD* dummy_fd) {
-  DCHECK(options);
-  DCHECK(fds_to_remap);
-
-  // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
-  options->allow_new_privs = true;
-  UnsetExpectedEnvironmentVariables(&options->environ);
-
-  // Set dummy_fd to the reading end of a closed pipe.
-  int pipe_fds[2];
-  PCHECK(0 == pipe(pipe_fds));
-  PCHECK(0 == IGNORE_EINTR(close(pipe_fds[1])));
-  dummy_fd->reset(pipe_fds[0]);
-
-  // We no longer need a dummy socket for discovering the child's PID,
-  // but the sandbox is still hard-coded to expect a file descriptor at
-  // kZygoteIdFd. Fixing this requires a sandbox API change. :(
-  fds_to_remap->push_back(std::make_pair(dummy_fd->get(), kZygoteIdFd));
-}
-
-void SetuidSandboxClient::SetupLaunchEnvironment() {
-  SaveSUIDUnsafeEnvironmentVariables(env_);
-  SetSandboxAPIEnvironmentVariable(env_);
-}
-
 }  // namespace sandbox
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.h b/sandbox/linux/suid/client/setuid_sandbox_client.h
index e6a3e4c..026894f 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.h
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.h
@@ -5,28 +5,20 @@
 #ifndef SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
 #define SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
 
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_file.h"
-#include "base/process/launch.h"
+#include "base/environment.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
 #include "sandbox/sandbox_export.h"
 
 namespace sandbox {
 
-// Helper class to use the setuid sandbox. This class is to be used both
-// before launching the setuid helper and after being executed through the
-// setuid helper.
+// Helper class to use the setuid sandbox. This class is to be used
+// after being executed through the setuid helper.
 // This class is difficult to use. It has been created by refactoring very old
 // code scathered through the Chromium code base.
 //
 // A typical use for "A" launching a sandboxed process "B" would be:
-// 1. A calls SetupLaunchEnvironment()
-// 2. A sets up a CommandLine and then amends it with
-//    PrependWrapper() (or manually, by relying on GetSandboxBinaryPath()).
-// 3. A uses SetupLaunchOptions() to arrange for a dummy descriptor for the
-//    setuid sandbox ABI.
-// 4. A launches B with base::LaunchProcess, using the amended CommandLine.
+// (Steps 1 through 4 are described in setuid_sandbox_host.h.)
 // 5. B uses CloseDummyFile() to close the dummy file descriptor.
 // 6. B performs various initializations that require access to the file
 //    system.
@@ -37,13 +29,13 @@
 //    cannot receive any signal from any other process, excluding SIGKILL.
 //    If B dies, all the processes in the namespace will die.
 //    B can fork() and the parent can assume the role of init(1), by using
-//    CreateInitProcessReaper().
+//    sandbox::CreateInitProcessReaper().
 // 8. B requests being chroot-ed through ChrootMe() and
 //    requests other sandboxing status via the status functions.
 class SANDBOX_EXPORT SetuidSandboxClient {
  public:
   // All instantation should go through this factory method.
-  static class SetuidSandboxClient* Create();
+  static SetuidSandboxClient* Create();
   ~SetuidSandboxClient();
 
   // Close the dummy file descriptor leftover from the sandbox ABI.
@@ -52,11 +44,6 @@
   // to an empty directory.
   // Will only work if we have been launched through the setuid helper.
   bool ChrootMe();
-  // When a new PID namespace is created, the process with pid == 1 should
-  // assume the role of init.
-  // See sandbox/linux/services/init_process_reaper.h for more information
-  // on this API.
-  bool CreateInitProcessReaper(base::Closure* post_fork_parent_callback);
 
   // Did we get launched through an up to date setuid binary ?
   bool IsSuidSandboxUpToDate() const;
@@ -69,33 +56,11 @@
   // Are we done and fully sandboxed ?
   bool IsSandboxed() const;
 
-  // The setuid sandbox may still be disabled via the environment.
-  // This is tracked in crbug.com/245376.
-  bool IsDisabledViaEnvironment();
-  // Get the sandbox binary path. This method knows about the
-  // CHROME_DEVEL_SANDBOX environment variable used for user-managed builds. If
-  // the sandbox binary cannot be found, it will return an empty FilePath.
-  base::FilePath GetSandboxBinaryPath();
-  // Modify |cmd_line| to launch via the setuid sandbox. Crash if the setuid
-  // sandbox binary cannot be found.  |cmd_line| must not be NULL.
-  void PrependWrapper(base::CommandLine* cmd_line);
-  // Set-up the launch options for launching via the setuid sandbox.  Caller is
-  // responsible for keeping |dummy_fd| alive until LaunchProcess() completes.
-  // |options| and |fds_to_remap| must not be NULL.
-  // (Keeping |dummy_fd| alive is an unfortunate historical artifact of the
-  // chrome-sandbox ABI.)
-  void SetupLaunchOptions(base::LaunchOptions* options,
-                          base::FileHandleMappingVector* fds_to_remap,
-                          base::ScopedFD* dummy_fd);
-  // Set-up the environment. This should be done prior to launching the setuid
-  // helper.
-  void SetupLaunchEnvironment();
-
  private:
-  SetuidSandboxClient();
+  explicit SetuidSandboxClient(base::Environment* env);
 
   // Holds the environment. Will never be NULL.
-  base::Environment* env_;
+  scoped_ptr<base::Environment> env_;
   bool sandboxed_;
 
   DISALLOW_COPY_AND_ASSIGN(SetuidSandboxClient);
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
index d4f7dfe..2acd8fb 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
@@ -2,63 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
+
 #include "base/environment.h"
-#include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
 #include "sandbox/linux/suid/common/sandbox.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace sandbox {
 
-TEST(SetuidSandboxClient, SetupLaunchEnvironment) {
-  const char kTestValue[] = "This is a test";
-  scoped_ptr<base::Environment> env(base::Environment::Create());
-  EXPECT_TRUE(env != NULL);
-
-  std::string saved_ld_preload;
-  bool environment_had_ld_preload;
-  // First, back-up the real LD_PRELOAD if any.
-  environment_had_ld_preload = env->GetVar("LD_PRELOAD", &saved_ld_preload);
-  // Setup environment variables to save or not save.
-  EXPECT_TRUE(env->SetVar("LD_PRELOAD", kTestValue));
-  EXPECT_TRUE(env->UnSetVar("LD_ORIGIN_PATH"));
-
-  scoped_ptr<SetuidSandboxClient>
-      sandbox_client(SetuidSandboxClient::Create());
-  EXPECT_TRUE(sandbox_client != NULL);
-
-  // Make sure the environment is clean.
-  EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiRequest));
-  EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiProvides));
-
-  sandbox_client->SetupLaunchEnvironment();
-
-  // Check if the requested API environment was set.
-  std::string api_request;
-  EXPECT_TRUE(env->GetVar(kSandboxEnvironmentApiRequest, &api_request));
-  int api_request_num;
-  EXPECT_TRUE(base::StringToInt(api_request, &api_request_num));
-  EXPECT_EQ(api_request_num, kSUIDSandboxApiNumber);
-
-  // Now check if LD_PRELOAD was saved to SANDBOX_LD_PRELOAD.
-  std::string sandbox_ld_preload;
-  EXPECT_TRUE(env->GetVar("SANDBOX_LD_PRELOAD", &sandbox_ld_preload));
-  EXPECT_EQ(sandbox_ld_preload, kTestValue);
-
-  // Check that LD_ORIGIN_PATH was not saved.
-  EXPECT_FALSE(env->HasVar("SANDBOX_LD_ORIGIN_PATH"));
-
-  // We should not forget to restore LD_PRELOAD at the end, or this environment
-  // variable will affect the next running tests!
-  if (environment_had_ld_preload) {
-    EXPECT_TRUE(env->SetVar("LD_PRELOAD", saved_ld_preload));
-  } else {
-    EXPECT_TRUE(env->UnSetVar("LD_PRELOAD"));
-  }
-}
-
 TEST(SetuidSandboxClient, SandboxedClientAPI) {
   scoped_ptr<base::Environment> env(base::Environment::Create());
   EXPECT_TRUE(env != NULL);
@@ -89,13 +42,5 @@
   EXPECT_FALSE(sandbox_client->IsSandboxed());
 }
 
-// This test doesn't accomplish much, but will make sure that analysis tools
-// will run this codepath.
-TEST(SetuidSandboxClient, GetSandboxBinaryPath) {
-  scoped_ptr<SetuidSandboxClient> setuid_sandbox_client(
-      SetuidSandboxClient::Create());
-  ignore_result(setuid_sandbox_client->GetSandboxBinaryPath());
-}
-
 }  // namespace sandbox
 
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host.cc b/sandbox/linux/suid/client/setuid_sandbox_host.cc
new file mode 100644
index 0000000..71171eb
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_host.cc
@@ -0,0 +1,195 @@
+// 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/suid/client/setuid_sandbox_host.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <string>
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/process/launch.h"
+#include "base/process/process_metrics.h"
+#include "base/strings/string_number_conversions.h"
+#include "sandbox/linux/suid/common/sandbox.h"
+#include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h"
+
+namespace {
+
+// Set an environment variable that reflects the API version we expect from the
+// setuid sandbox. Old versions of the sandbox will ignore this.
+void SetSandboxAPIEnvironmentVariable(base::Environment* env) {
+  env->SetVar(sandbox::kSandboxEnvironmentApiRequest,
+              base::IntToString(sandbox::kSUIDSandboxApiNumber));
+}
+
+// Unset environment variables that are expected to be set by the setuid
+// sandbox. This is to allow nesting of one instance of the SUID sandbox
+// inside another.
+void UnsetExpectedEnvironmentVariables(base::EnvironmentMap* env_map) {
+  DCHECK(env_map);
+  const base::NativeEnvironmentString environment_vars[] = {
+      sandbox::kSandboxDescriptorEnvironmentVarName,
+      sandbox::kSandboxHelperPidEnvironmentVarName,
+      sandbox::kSandboxEnvironmentApiProvides,
+      sandbox::kSandboxPIDNSEnvironmentVarName,
+      sandbox::kSandboxNETNSEnvironmentVarName,
+  };
+
+  for (size_t i = 0; i < arraysize(environment_vars); ++i) {
+    // Setting values in EnvironmentMap to an empty-string will make
+    // sure that they get unset from the environment via AlterEnvironment().
+    (*env_map)[environment_vars[i]] = base::NativeEnvironmentString();
+  }
+}
+
+// Wrapper around a shared C function.
+// Returns the "saved" environment variable name corresponding to |envvar|
+// in a new string or NULL.
+std::string* CreateSavedVariableName(const char* env_var) {
+  char* const saved_env_var = SandboxSavedEnvironmentVariable(env_var);
+  if (!saved_env_var)
+    return NULL;
+  std::string* saved_env_var_copy = new std::string(saved_env_var);
+  // SandboxSavedEnvironmentVariable is the C function that we wrap and uses
+  // malloc() to allocate memory.
+  free(saved_env_var);
+  return saved_env_var_copy;
+}
+
+// The ELF loader will clear many environment variables so we save them to
+// different names here so that the SUID sandbox can resolve them for the
+// renderer.
+void SaveSUIDUnsafeEnvironmentVariables(base::Environment* env) {
+  for (unsigned i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) {
+    const char* env_var = kSUIDUnsafeEnvironmentVariables[i];
+    // Get the saved environment variable corresponding to envvar.
+    scoped_ptr<std::string> saved_env_var(CreateSavedVariableName(env_var));
+    if (saved_env_var == NULL)
+      continue;
+
+    std::string value;
+    if (env->GetVar(env_var, &value))
+      env->SetVar(saved_env_var->c_str(), value);
+    else
+      env->UnSetVar(saved_env_var->c_str());
+  }
+}
+
+const char* GetDevelSandboxPath() {
+  return getenv("CHROME_DEVEL_SANDBOX");
+}
+
+}  // namespace
+
+namespace sandbox {
+
+SetuidSandboxHost* SetuidSandboxHost::Create() {
+  base::Environment* environment(base::Environment::Create());
+  CHECK(environment);
+  return new SetuidSandboxHost(environment);
+}
+
+SetuidSandboxHost::SetuidSandboxHost(base::Environment* env) : env_(env) {
+}
+
+SetuidSandboxHost::~SetuidSandboxHost() {
+}
+
+// Check if CHROME_DEVEL_SANDBOX is set but empty. This currently disables
+// the setuid sandbox. TODO(jln): fix this (crbug.com/245376).
+bool SetuidSandboxHost::IsDisabledViaEnvironment() {
+  const char* devel_sandbox_path = GetDevelSandboxPath();
+  if (devel_sandbox_path && '\0' == *devel_sandbox_path) {
+    return true;
+  }
+  return false;
+}
+
+base::FilePath SetuidSandboxHost::GetSandboxBinaryPath() {
+  base::FilePath sandbox_binary;
+  base::FilePath exe_dir;
+  if (PathService::Get(base::DIR_EXE, &exe_dir)) {
+    base::FilePath sandbox_candidate = exe_dir.AppendASCII("chrome-sandbox");
+    if (base::PathExists(sandbox_candidate))
+      sandbox_binary = sandbox_candidate;
+  }
+
+  // In user-managed builds, including development builds, an environment
+  // variable is required to enable the sandbox. See
+  // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
+  struct stat st;
+  if (sandbox_binary.empty() && stat(base::kProcSelfExe, &st) == 0 &&
+      st.st_uid == getuid()) {
+    const char* devel_sandbox_path = GetDevelSandboxPath();
+    if (devel_sandbox_path) {
+      sandbox_binary = base::FilePath(devel_sandbox_path);
+    }
+  }
+
+  return sandbox_binary;
+}
+
+void SetuidSandboxHost::PrependWrapper(base::CommandLine* cmd_line) {
+  std::string sandbox_binary(GetSandboxBinaryPath().value());
+  struct stat st;
+  if (sandbox_binary.empty() || stat(sandbox_binary.c_str(), &st) != 0) {
+    LOG(FATAL) << "The SUID sandbox helper binary is missing: "
+               << sandbox_binary << " Aborting now. See "
+                                    "https://code.google.com/p/chromium/wiki/"
+                                    "LinuxSUIDSandboxDevelopment.";
+  }
+
+  if (access(sandbox_binary.c_str(), X_OK) != 0 || (st.st_uid != 0) ||
+      ((st.st_mode & S_ISUID) == 0) || ((st.st_mode & S_IXOTH)) == 0) {
+    LOG(FATAL) << "The SUID sandbox helper binary was found, but is not "
+                  "configured correctly. Rather than run without sandboxing "
+                  "I'm aborting now. You need to make sure that "
+               << sandbox_binary << " is owned by root and has mode 4755.";
+  }
+
+  cmd_line->PrependWrapper(sandbox_binary);
+}
+
+void SetuidSandboxHost::SetupLaunchOptions(
+    base::LaunchOptions* options,
+    base::FileHandleMappingVector* fds_to_remap,
+    base::ScopedFD* dummy_fd) {
+  DCHECK(options);
+  DCHECK(fds_to_remap);
+
+  // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
+  options->allow_new_privs = true;
+  UnsetExpectedEnvironmentVariables(&options->environ);
+
+  // Set dummy_fd to the reading end of a closed pipe.
+  int pipe_fds[2];
+  PCHECK(0 == pipe(pipe_fds));
+  PCHECK(0 == IGNORE_EINTR(close(pipe_fds[1])));
+  dummy_fd->reset(pipe_fds[0]);
+
+  // We no longer need a dummy socket for discovering the child's PID,
+  // but the sandbox is still hard-coded to expect a file descriptor at
+  // kZygoteIdFd. Fixing this requires a sandbox API change. :(
+  fds_to_remap->push_back(std::make_pair(dummy_fd->get(), kZygoteIdFd));
+}
+
+void SetuidSandboxHost::SetupLaunchEnvironment() {
+  SaveSUIDUnsafeEnvironmentVariables(env_.get());
+  SetSandboxAPIEnvironmentVariable(env_.get());
+}
+
+}  // namespace sandbox
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host.h b/sandbox/linux/suid/client/setuid_sandbox_host.h
new file mode 100644
index 0000000..6788892
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_host.h
@@ -0,0 +1,70 @@
+// 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_SUID_SETUID_SANDBOX_HOST_H_
+#define SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process/launch.h"
+#include "sandbox/sandbox_export.h"
+
+namespace sandbox {
+
+// Helper class to use the setuid sandbox. This class is to be used
+// before launching the setuid helper.
+// This class is difficult to use. It has been created by refactoring very old
+// code scathered through the Chromium code base.
+//
+// A typical use for "A" launching a sandboxed process "B" would be:
+// 1. A calls SetupLaunchEnvironment()
+// 2. A sets up a base::CommandLine and then amends it with
+//    PrependWrapper() (or manually, by relying on GetSandboxBinaryPath()).
+// 3. A uses SetupLaunchOptions() to arrange for a dummy descriptor for the
+//    setuid sandbox ABI.
+// 4. A launches B with base::LaunchProcess, using the amended
+// base::CommandLine.
+// (The remaining steps are described within setuid_sandbox_client.h.)
+class SANDBOX_EXPORT SetuidSandboxHost {
+ public:
+  // All instantation should go through this factory method.
+  static SetuidSandboxHost* Create();
+  ~SetuidSandboxHost();
+
+  // The setuid sandbox may still be disabled via the environment.
+  // This is tracked in crbug.com/245376.
+  bool IsDisabledViaEnvironment();
+  // Get the sandbox binary path. This method knows about the
+  // CHROME_DEVEL_SANDBOX environment variable used for user-managed builds. If
+  // the sandbox binary cannot be found, it will return an empty FilePath.
+  base::FilePath GetSandboxBinaryPath();
+  // Modify |cmd_line| to launch via the setuid sandbox. Crash if the setuid
+  // sandbox binary cannot be found.  |cmd_line| must not be NULL.
+  void PrependWrapper(base::CommandLine* cmd_line);
+  // Set-up the launch options for launching via the setuid sandbox.  Caller is
+  // responsible for keeping |dummy_fd| alive until LaunchProcess() completes.
+  // |options| and |fds_to_remap| must not be NULL.
+  // (Keeping |dummy_fd| alive is an unfortunate historical artifact of the
+  // chrome-sandbox ABI.)
+  void SetupLaunchOptions(base::LaunchOptions* options,
+                          base::FileHandleMappingVector* fds_to_remap,
+                          base::ScopedFD* dummy_fd);
+  // Set-up the environment. This should be done prior to launching the setuid
+  // helper.
+  void SetupLaunchEnvironment();
+
+ private:
+  explicit SetuidSandboxHost(base::Environment* env);
+
+  // Holds the environment. Will never be NULL.
+  scoped_ptr<base::Environment> env_;
+
+  DISALLOW_COPY_AND_ASSIGN(SetuidSandboxHost);
+};
+
+}  // namespace sandbox
+
+#endif  // SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc b/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc
new file mode 100644
index 0000000..8415abb
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc
@@ -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.
+
+#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
+
+#include <string>
+
+#include "base/environment.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "sandbox/linux/suid/common/sandbox.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+TEST(SetuidSandboxHost, SetupLaunchEnvironment) {
+  const char kTestValue[] = "This is a test";
+  scoped_ptr<base::Environment> env(base::Environment::Create());
+  EXPECT_TRUE(env != NULL);
+
+  std::string saved_ld_preload;
+  bool environment_had_ld_preload;
+  // First, back-up the real LD_PRELOAD if any.
+  environment_had_ld_preload = env->GetVar("LD_PRELOAD", &saved_ld_preload);
+  // Setup environment variables to save or not save.
+  EXPECT_TRUE(env->SetVar("LD_PRELOAD", kTestValue));
+  EXPECT_TRUE(env->UnSetVar("LD_ORIGIN_PATH"));
+
+  scoped_ptr<SetuidSandboxHost> sandbox_host(SetuidSandboxHost::Create());
+  EXPECT_TRUE(sandbox_host != NULL);
+
+  // Make sure the environment is clean.
+  EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiRequest));
+  EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiProvides));
+
+  sandbox_host->SetupLaunchEnvironment();
+
+  // Check if the requested API environment was set.
+  std::string api_request;
+  EXPECT_TRUE(env->GetVar(kSandboxEnvironmentApiRequest, &api_request));
+  int api_request_num;
+  EXPECT_TRUE(base::StringToInt(api_request, &api_request_num));
+  EXPECT_EQ(api_request_num, kSUIDSandboxApiNumber);
+
+  // Now check if LD_PRELOAD was saved to SANDBOX_LD_PRELOAD.
+  std::string sandbox_ld_preload;
+  EXPECT_TRUE(env->GetVar("SANDBOX_LD_PRELOAD", &sandbox_ld_preload));
+  EXPECT_EQ(sandbox_ld_preload, kTestValue);
+
+  // Check that LD_ORIGIN_PATH was not saved.
+  EXPECT_FALSE(env->HasVar("SANDBOX_LD_ORIGIN_PATH"));
+
+  // We should not forget to restore LD_PRELOAD at the end, or this environment
+  // variable will affect the next running tests!
+  if (environment_had_ld_preload) {
+    EXPECT_TRUE(env->SetVar("LD_PRELOAD", saved_ld_preload));
+  } else {
+    EXPECT_TRUE(env->UnSetVar("LD_PRELOAD"));
+  }
+}
+
+// This test doesn't accomplish much, but will make sure that analysis tools
+// will run this codepath.
+TEST(SetuidSandboxHost, GetSandboxBinaryPath) {
+  scoped_ptr<SetuidSandboxHost> setuid_sandbox_host(
+      SetuidSandboxHost::Create());
+  ignore_result(setuid_sandbox_host->GetSandboxBinaryPath());
+}
+
+}  // namespace sandbox
diff --git a/services/surfaces/surfaces_impl.cc b/services/surfaces/surfaces_impl.cc
index 083b6a4..1119985 100644
--- a/services/surfaces/surfaces_impl.cc
+++ b/services/surfaces/surfaces_impl.cc
@@ -4,7 +4,7 @@
 
 #include "services/surfaces/surfaces_impl.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/resources/returned_resource.h"
 #include "cc/surfaces/display.h"
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index a7d2296..fb7da07 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -319,9 +319,6 @@
     "ext/skia_utils_mac.h",
     "ext/skia_utils_win.cc",
     "ext/skia_utils_win.h",
-    "ext/vector_canvas.h",
-    "ext/vector_platform_device_emf_win.cc",
-    "ext/vector_platform_device_emf_win.h",
   ]
 
   # The skia gypi values are relative to the skia_dir, so we need to rebase.
@@ -633,13 +630,8 @@
     "ext/refptr_unittest.cc",
     "ext/skia_utils_ios_unittest.mm",
     "ext/skia_utils_mac_unittest.mm",
-    "ext/vector_canvas_unittest.cc",
   ]
 
-  if (!is_win) {
-    sources -= [ "ext/vector_canvas_unittest.cc" ]
-  }
-
   if (!is_win && !is_mac) {
     sources -= [ "ext/platform_canvas_unittest.cc" ]
   }
diff --git a/skia/ext/vector_canvas.h b/skia/ext/vector_canvas.h
deleted file mode 100644
index 673becc..0000000
--- a/skia/ext/vector_canvas.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-#ifndef SKIA_EXT_VECTOR_CANVAS_H_
-#define SKIA_EXT_VECTOR_CANVAS_H_
-
-#include "base/compiler_specific.h"
-#include "skia/ext/platform_canvas.h"
-
-// This was a specialization of PlatformCanvas, but all necessary functionality
-// has been subsumed by just SkCanvas and a specialized device (PDF or EMF).
-// Future evolution goal is to replace this notion (canvas+device) with
-// an updated version of SkDocument, which will have explicit APIs for margins.
-// At that point, this class (and header) will be removed entirely.
-
-namespace skia {
-    typedef PlatformCanvas VectorCanvas;
-}  // namespace skia
-
-#endif  // SKIA_EXT_VECTOR_CANVAS_H_
-
diff --git a/skia/ext/vector_canvas_unittest.cc b/skia/ext/vector_canvas_unittest.cc
deleted file mode 100644
index d3ad9a0..0000000
--- a/skia/ext/vector_canvas_unittest.cc
+++ /dev/null
@@ -1,970 +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.
-
-#include "build/build_config.h"
-
-#if !defined(OS_WIN)
-#include <unistd.h>
-#endif
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "skia/ext/vector_canvas.h"
-#include "skia/ext/vector_platform_device_emf_win.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/effects/SkDashPathEffect.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace skia {
-
-namespace {
-
-const char kGenerateSwitch[] = "vector-canvas-generate";
-
-// Lightweight HDC management.
-class Context {
- public:
-  Context() : context_(CreateCompatibleDC(NULL)) {
-    EXPECT_TRUE(context_);
-  }
-  ~Context() {
-    DeleteDC(context_);
-  }
-
-  HDC context() const { return context_; }
-
- private:
-  HDC context_;
-
-  DISALLOW_COPY_AND_ASSIGN(Context);
-};
-
-// Lightweight HBITMAP management.
-class Bitmap {
- public:
-  Bitmap(const Context& context, int x, int y) {
-    BITMAPINFOHEADER hdr;
-    hdr.biSize = sizeof(BITMAPINFOHEADER);
-    hdr.biWidth = x;
-    hdr.biHeight = -y;  // Minus means top-down bitmap.
-    hdr.biPlanes = 1;
-    hdr.biBitCount = 32;
-    hdr.biCompression = BI_RGB;  // No compression.
-    hdr.biSizeImage = 0;
-    hdr.biXPelsPerMeter = 1;
-    hdr.biYPelsPerMeter = 1;
-    hdr.biClrUsed = 0;
-    hdr.biClrImportant = 0;
-    bitmap_ = CreateDIBSection(context.context(),
-                               reinterpret_cast<BITMAPINFO*>(&hdr), 0,
-                               &data_, NULL, 0);
-    EXPECT_TRUE(bitmap_);
-    EXPECT_TRUE(SelectObject(context.context(), bitmap_));
-  }
-  ~Bitmap() {
-    EXPECT_TRUE(DeleteObject(bitmap_));
-  }
-
- private:
-  HBITMAP bitmap_;
-
-  void* data_;
-
-  DISALLOW_COPY_AND_ASSIGN(Bitmap);
-};
-
-// Lightweight raw-bitmap management. The image, once initialized, is immuable.
-// It is mainly used for comparison.
-class Image {
- public:
-  // Creates the image from the given filename on disk.
-  explicit Image(const base::FilePath& filename) : ignore_alpha_(true) {
-    std::string compressed;
-    base::ReadFileToString(filename, &compressed);
-    EXPECT_TRUE(compressed.size());
-
-    SkBitmap bitmap;
-    EXPECT_TRUE(gfx::PNGCodec::Decode(
-        reinterpret_cast<const unsigned char*>(compressed.data()),
-        compressed.size(), &bitmap));
-    SetSkBitmap(bitmap);
-  }
-
-  // Loads the image from a canvas.
-  Image(skia::PlatformCanvas& canvas) : ignore_alpha_(true) {
-    // Use a different way to access the bitmap. The normal way would be to
-    // query the SkBitmap.
-    skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
-    HDC context = scoped_platform_paint.GetPlatformSurface();
-    HGDIOBJ bitmap = GetCurrentObject(context, OBJ_BITMAP);
-    EXPECT_TRUE(bitmap != NULL);
-    // Initialize the clip region to the entire bitmap.
-    BITMAP bitmap_data;
-    EXPECT_EQ(GetObject(bitmap, sizeof(BITMAP), &bitmap_data), sizeof(BITMAP));
-    width_ = bitmap_data.bmWidth;
-    height_ = bitmap_data.bmHeight;
-    row_length_ = bitmap_data.bmWidthBytes;
-    size_t size = row_length_ * height_;
-    data_.resize(size);
-    memcpy(&*data_.begin(), bitmap_data.bmBits, size);
-  }
-
-  // Loads the image from a canvas.
-  Image(const SkBitmap& bitmap) : ignore_alpha_(true) {
-    SetSkBitmap(bitmap);
-  }
-
-  int width() const { return width_; }
-  int height() const { return height_; }
-  int row_length() const { return row_length_; }
-
-  // Save the image to a png file. Used to create the initial test files.
-  void SaveToFile(const base::FilePath& filename) {
-    std::vector<unsigned char> compressed;
-    ASSERT_TRUE(gfx::PNGCodec::Encode(&*data_.begin(),
-                                      gfx::PNGCodec::FORMAT_BGRA,
-                                      gfx::Size(width_, height_),
-                                      row_length_,
-                                      true,
-                                      std::vector<gfx::PNGCodec::Comment>(),
-                                      &compressed));
-    ASSERT_TRUE(compressed.size());
-    FILE* f = base::OpenFile(filename, "wb");
-    ASSERT_TRUE(f);
-    ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
-              compressed.size());
-    base::CloseFile(f);
-  }
-
-  // Returns the percentage of the image that is different from the other,
-  // between 0 and 100.
-  double PercentageDifferent(const Image& rhs) const {
-    if (width_ != rhs.width_ ||
-        height_ != rhs.height_ ||
-        row_length_ != rhs.row_length_ ||
-        width_ == 0 ||
-        height_ == 0) {
-      return 100.;  // When of different size or empty, they are 100% different.
-    }
-    // Compute pixels different in the overlap
-    int pixels_different = 0;
-    for (int y = 0; y < height_; ++y) {
-      for (int x = 0; x < width_; ++x) {
-        uint32_t lhs_pixel = pixel_at(x, y);
-        uint32_t rhs_pixel = rhs.pixel_at(x, y);
-        if (lhs_pixel != rhs_pixel)
-          ++pixels_different;
-      }
-    }
-
-    // Like the WebKit ImageDiff tool, we define percentage different in terms
-    // of the size of the 'actual' bitmap.
-    double total_pixels = static_cast<double>(width_) *
-                          static_cast<double>(height_);
-    return static_cast<double>(pixels_different) / total_pixels * 100.;
-  }
-
-  // Returns the 0x0RGB or 0xARGB value of the pixel at the given location,
-  // depending on ignore_alpha_.
-  uint32 pixel_at(int x, int y) const {
-    EXPECT_TRUE(x >= 0 && x < width_);
-    EXPECT_TRUE(y >= 0 && y < height_);
-    const uint32* data = reinterpret_cast<const uint32*>(&*data_.begin());
-    const uint32* data_row = data + y * row_length_ / sizeof(uint32);
-    if (ignore_alpha_)
-      return data_row[x] & 0xFFFFFF;  // Strip out A.
-    else
-      return data_row[x];
-  }
-
- protected:
-  void SetSkBitmap(const SkBitmap& bitmap) {
-    SkAutoLockPixels lock(bitmap);
-    width_ = bitmap.width();
-    height_ = bitmap.height();
-    row_length_ = static_cast<int>(bitmap.rowBytes());
-    size_t size = row_length_ * height_;
-    data_.resize(size);
-    memcpy(&*data_.begin(), bitmap.getAddr(0, 0), size);
-  }
-
- private:
-  // Pixel dimensions of the image.
-  int width_;
-  int height_;
-
-  // Length of a line in bytes.
-  int row_length_;
-
-  // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's
-  // 0xABGR).
-  std::vector<unsigned char> data_;
-
-  // Flag to signal if the comparison functions should ignore the alpha channel.
-  const bool ignore_alpha_;
-
-  DISALLOW_COPY_AND_ASSIGN(Image);
-};
-
-// Base for tests. Capability to process an image.
-class ImageTest : public testing::Test {
- public:
-  // In what state is the test running.
-  enum ProcessAction {
-    GENERATE,
-    COMPARE,
-    NOOP,
-  };
-
-  ImageTest(ProcessAction default_action)
-      : action_(default_action) {
-  }
-
- protected:
-  virtual void SetUp() {
-    const testing::TestInfo& test_info =
-        *testing::UnitTest::GetInstance()->current_test_info();
-    PathService::Get(base::DIR_SOURCE_ROOT, &test_dir_);
-    test_dir_ = test_dir_.AppendASCII("skia").
-                          AppendASCII("ext").
-                          AppendASCII("data").
-                          AppendASCII(test_info.test_case_name()).
-                          AppendASCII(test_info.name());
-
-    // Hack for a quick lowercase. We assume all the tests names are ASCII.
-    base::FilePath::StringType tmp(test_dir_.value());
-    for (size_t i = 0; i < tmp.size(); ++i)
-      tmp[i] = base::ToLowerASCII(tmp[i]);
-    test_dir_ = base::FilePath(tmp);
-
-    if (action_ == GENERATE) {
-      // Make sure the directory exist.
-      base::CreateDirectory(test_dir_);
-    }
-  }
-
-  // Returns the fully qualified path of a data file.
-  base::FilePath test_file(const base::FilePath::StringType& filename) const {
-    // Hack for a quick lowercase. We assume all the test data file names are
-    // ASCII.
-#if defined(OS_WIN)
-    std::string tmp = base::UTF16ToASCII(filename);
-#else
-    std::string tmp(filename);
-#endif
-    for (size_t i = 0; i < tmp.size(); ++i)
-      tmp[i] = base::ToLowerASCII(tmp[i]);
-
-    return test_dir_.AppendASCII(tmp);
-  }
-
-  // Compares or saves the bitmap currently loaded in the context, depending on
-  // kGenerating value. Returns 0 on success or any positive value between ]0,
-  // 100] on failure. The return value is the percentage of difference between
-  // the image in the file and the image in the canvas.
-  double ProcessCanvas(skia::PlatformCanvas& canvas,
-                       base::FilePath::StringType filename) const {
-    filename = filename + FILE_PATH_LITERAL(".png");
-    switch (action_) {
-      case GENERATE:
-        SaveImage(canvas, filename);
-        return 0.;
-      case COMPARE:
-        return CompareImage(canvas, filename);
-      case NOOP:
-        return 0;
-      default:
-        // Invalid state, returns that the image is 100 different.
-        return 100.;
-    }
-  }
-
-  // Compares the bitmap currently loaded in the context with the file. Returns
-  // the percentage of pixel difference between both images, between 0 and 100.
-  double CompareImage(skia::PlatformCanvas& canvas,
-                      const base::FilePath::StringType& filename) const {
-    Image image1(canvas);
-    Image image2(test_file(filename));
-    double diff = image1.PercentageDifferent(image2);
-    return diff;
-  }
-
-  // Saves the bitmap currently loaded in the context into the file.
-  void SaveImage(skia::PlatformCanvas& canvas,
-                 const base::FilePath::StringType& filename) const {
-    Image(canvas).SaveToFile(test_file(filename));
-  }
-
-  ProcessAction action_;
-
-  // Path to directory used to contain the test data.
-  base::FilePath test_dir_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageTest);
-};
-
-// Premultiply the Alpha channel on the R, B and G channels.
-void Premultiply(SkBitmap bitmap) {
-  SkAutoLockPixels lock(bitmap);
-  for (int x = 0; x < bitmap.width(); ++x) {
-    for (int y = 0; y < bitmap.height(); ++y) {
-      uint32_t* pixel_addr = bitmap.getAddr32(x, y);
-      uint32_t color = *pixel_addr;
-      BYTE alpha = SkColorGetA(color);
-      if (!alpha) {
-        *pixel_addr = 0;
-      } else {
-        BYTE alpha_offset = alpha / 2;
-        *pixel_addr = SkColorSetARGB(
-            SkColorGetA(color),
-            (SkColorGetR(color) * 255 + alpha_offset) / alpha,
-            (SkColorGetG(color) * 255 + alpha_offset) / alpha,
-            (SkColorGetB(color) * 255 + alpha_offset) / alpha);
-      }
-    }
-  }
-}
-
-void LoadPngFileToSkBitmap(const base::FilePath& filename,
-                           SkBitmap* bitmap,
-                           bool is_opaque) {
-  std::string compressed;
-  base::ReadFileToString(base::MakeAbsoluteFilePath(filename), &compressed);
-  ASSERT_TRUE(compressed.size());
-
-  ASSERT_TRUE(gfx::PNGCodec::Decode(
-      reinterpret_cast<const unsigned char*>(compressed.data()),
-      compressed.size(), bitmap));
-
-  EXPECT_EQ(is_opaque, bitmap->isOpaque());
-  Premultiply(*bitmap);
-}
-
-}  // namespace
-
-// Streams an image.
-inline std::ostream& operator<<(std::ostream& out, const Image& image) {
-  return out << "Image(" << image.width() << ", "
-             << image.height() << ", " << image.row_length() << ")";
-}
-
-// Runs simultaneously the same drawing commands on VectorCanvas and
-// PlatformCanvas and compare the results.
-class VectorCanvasTest : public ImageTest {
- public:
-  typedef ImageTest parent;
-
-  VectorCanvasTest() : parent(CurrentMode()), compare_canvas_(true) {
-  }
-
- protected:
-  virtual void SetUp() {
-    parent::SetUp();
-    Init(100);
-    number_ = 0;
-  }
-
-  virtual void TearDown() {
-    delete pcanvas_;
-    pcanvas_ = NULL;
-
-    delete vcanvas_;
-    vcanvas_ = NULL;
-
-    delete bitmap_;
-    bitmap_ = NULL;
-
-    delete context_;
-    context_ = NULL;
-
-    parent::TearDown();
-  }
-
-  void Init(int size) {
-    size_ = size;
-    context_ = new Context();
-    bitmap_ = new Bitmap(*context_, size_, size_);
-    vcanvas_ = new VectorCanvas(
-        VectorPlatformDeviceEmf::CreateDevice(
-            size_, size_, true, context_->context()));
-    pcanvas_ = CreatePlatformCanvas(size_, size_, false);
-
-    // Clear white.
-    vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
-    pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
-  }
-
-  // Compares both canvas and returns the pixel difference in percentage between
-  // both images. 0 on success and ]0, 100] on failure.
-  double ProcessImage(const base::FilePath::StringType& filename) {
-    std::wstring number(base::StringPrintf(L"%02d_", number_++));
-    double diff1 = parent::ProcessCanvas(*vcanvas_, number + L"vc_" + filename);
-    double diff2 = parent::ProcessCanvas(*pcanvas_, number + L"pc_" + filename);
-    if (!compare_canvas_)
-      return std::max(diff1, diff2);
-
-    Image image1(*vcanvas_);
-    Image image2(*pcanvas_);
-    double diff = image1.PercentageDifferent(image2);
-    return std::max(std::max(diff1, diff2), diff);
-  }
-
-  // Returns COMPARE, which is the default. If kGenerateSwitch command
-  // line argument is used to start this process, GENERATE is returned instead.
-  static ProcessAction CurrentMode() {
-    return base::CommandLine::ForCurrentProcess()->HasSwitch(kGenerateSwitch)
-               ? GENERATE
-               : COMPARE;
-  }
-
-  // Length in x and y of the square canvas.
-  int size_;
-
-  // Current image number in the current test. Used to number of test files.
-  int number_;
-
-  // A temporary HDC to draw into.
-  Context* context_;
-
-  // Bitmap created inside context_.
-  Bitmap* bitmap_;
-
-  // Vector based canvas.
-  VectorCanvas* vcanvas_;
-
-  // Pixel based canvas.
-  PlatformCanvas* pcanvas_;
-
-  // When true (default), vcanvas_ and pcanvas_ contents are compared and
-  // verified to be identical.
-  bool compare_canvas_;
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Actual tests
-
-#if !defined(USE_AURA)  // http://crbug.com/154358
-
-TEST_F(VectorCanvasTest, BasicDrawing) {
-  EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.)
-      << L"clean";
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clean")));
-
-  // Clear white.
-  {
-    vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
-    pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawARGB")));
-
-  // Diagonal line top-left to bottom-right.
-  {
-    SkPaint paint;
-    // Default color is black.
-    vcanvas_->drawLine(10, 10, 90, 90, paint);
-    pcanvas_->drawLine(10, 10, 90, 90, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_black")));
-
-  // Rect.
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorGREEN);
-    vcanvas_->drawRectCoords(25, 25, 75, 75, paint);
-    pcanvas_->drawRectCoords(25, 25, 75, 75, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_green")));
-
-  // A single-point rect doesn't leave any mark.
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorBLUE);
-    vcanvas_->drawRectCoords(5, 5, 5, 5, paint);
-    pcanvas_->drawRectCoords(5, 5, 5, 5, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
-
-  // Rect.
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorBLUE);
-    vcanvas_->drawRectCoords(75, 50, 80, 55, paint);
-    pcanvas_->drawRectCoords(75, 50, 80, 55, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
-
-  // Empty again
-  {
-    vcanvas_->drawPaint(SkPaint());
-    pcanvas_->drawPaint(SkPaint());
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
-
-  // Horizontal line left to right.
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorRED);
-    vcanvas_->drawLine(10, 20, 90, 20, paint);
-    pcanvas_->drawLine(10, 20, 90, 20, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_left_to_right")));
-
-  // Vertical line downward.
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorRED);
-    vcanvas_->drawLine(30, 10, 30, 90, paint);
-    pcanvas_->drawLine(30, 10, 30, 90, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_red")));
-}
-
-TEST_F(VectorCanvasTest, Circles) {
-  // There is NO WAY to make them agree. At least verify that the output doesn't
-  // change across versions. This test is disabled. See bug 1060231.
-  compare_canvas_ = false;
-
-  // Stroked Circle.
-  {
-    SkPaint paint;
-    SkPath path;
-    path.addCircle(50, 75, 10);
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setColor(SK_ColorMAGENTA);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke")));
-
-  // Filled Circle.
-  {
-    SkPaint paint;
-    SkPath path;
-    path.addCircle(50, 25, 10);
-    paint.setStyle(SkPaint::kFill_Style);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_fill")));
-
-  // Stroked Circle over.
-  {
-    SkPaint paint;
-    SkPath path;
-    path.addCircle(50, 25, 10);
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setColor(SK_ColorBLUE);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_over_strike")));
-
-  // Stroke and Fill Circle.
-  {
-    SkPaint paint;
-    SkPath path;
-    path.addCircle(12, 50, 10);
-    paint.setStyle(SkPaint::kStrokeAndFill_Style);
-    paint.setColor(SK_ColorRED);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke_and_fill")));
-
-  // Line + Quad + Cubic.
-  {
-    SkPaint paint;
-    SkPath path;
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setColor(SK_ColorGREEN);
-    path.moveTo(1, 1);
-    path.lineTo(60, 40);
-    path.lineTo(80, 80);
-    path.quadTo(20, 50, 10, 90);
-    path.quadTo(50, 20, 90, 10);
-    path.cubicTo(20, 40, 50, 50, 10, 10);
-    path.cubicTo(30, 20, 50, 50, 90, 10);
-    path.addRect(90, 90, 95, 96);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("mixed_stroke")));
-}
-
-TEST_F(VectorCanvasTest, LineOrientation) {
-  // There is NO WAY to make them agree. At least verify that the output doesn't
-  // change across versions. This test is disabled. See bug 1060231.
-  compare_canvas_ = false;
-
-  // Horizontal lines.
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorRED);
-    // Left to right.
-    vcanvas_->drawLine(10, 20, 90, 20, paint);
-    pcanvas_->drawLine(10, 20, 90, 20, paint);
-    // Right to left.
-    vcanvas_->drawLine(90, 30, 10, 30, paint);
-    pcanvas_->drawLine(90, 30, 10, 30, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal")));
-
-  // Vertical lines.
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorRED);
-    // Top down.
-    vcanvas_->drawLine(20, 10, 20, 90, paint);
-    pcanvas_->drawLine(20, 10, 20, 90, paint);
-    // Bottom up.
-    vcanvas_->drawLine(30, 90, 30, 10, paint);
-    pcanvas_->drawLine(30, 90, 30, 10, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical")));
-
-  // Try again with a 180 degres rotation.
-  vcanvas_->rotate(180);
-  pcanvas_->rotate(180);
-
-  // Horizontal lines (rotated).
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorRED);
-    vcanvas_->drawLine(-10, -25, -90, -25, paint);
-    pcanvas_->drawLine(-10, -25, -90, -25, paint);
-    vcanvas_->drawLine(-90, -35, -10, -35, paint);
-    pcanvas_->drawLine(-90, -35, -10, -35, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal_180")));
-
-  // Vertical lines (rotated).
-  {
-    SkPaint paint;
-    paint.setColor(SK_ColorRED);
-    vcanvas_->drawLine(-25, -10, -25, -90, paint);
-    pcanvas_->drawLine(-25, -10, -25, -90, paint);
-    vcanvas_->drawLine(-35, -90, -35, -10, paint);
-    pcanvas_->drawLine(-35, -90, -35, -10, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical_180")));
-}
-
-TEST_F(VectorCanvasTest, PathOrientation) {
-  // There is NO WAY to make them agree. At least verify that the output doesn't
-  // change across versions. This test is disabled. See bug 1060231.
-  compare_canvas_ = false;
-
-  // Horizontal lines.
-  {
-    SkPaint paint;
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setColor(SK_ColorRED);
-    SkPath path;
-    SkPoint start;
-    start.set(10, 20);
-    SkPoint end;
-    end.set(90, 20);
-    path.moveTo(start);
-    path.lineTo(end);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_ltr")));
-
-  // Horizontal lines.
-  {
-    SkPaint paint;
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setColor(SK_ColorRED);
-    SkPath path;
-    SkPoint start;
-    start.set(90, 30);
-    SkPoint end;
-    end.set(10, 30);
-    path.moveTo(start);
-    path.lineTo(end);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_rtl")));
-}
-
-TEST_F(VectorCanvasTest, DiagonalLines) {
-  SkPaint paint;
-  paint.setColor(SK_ColorRED);
-
-  vcanvas_->drawLine(10, 10, 90, 90, paint);
-  pcanvas_->drawLine(10, 10, 90, 90, paint);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("nw-se")));
-
-  // Starting here, there is NO WAY to make them agree. At least verify that the
-  // output doesn't change across versions. This test is disabled. See bug
-  // 1060231.
-  compare_canvas_ = false;
-
-  vcanvas_->drawLine(10, 95, 90, 15, paint);
-  pcanvas_->drawLine(10, 95, 90, 15, paint);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("sw-ne")));
-
-  vcanvas_->drawLine(90, 10, 10, 90, paint);
-  pcanvas_->drawLine(90, 10, 10, 90, paint);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("ne-sw")));
-
-  vcanvas_->drawLine(95, 90, 15, 10, paint);
-  pcanvas_->drawLine(95, 90, 15, 10, paint);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("se-nw")));
-}
-
-#if defined(OS_WIN)
-#define MAYBE_PathEffects DISABLED_PathEffects
-#else
-#define MAYBE_PathEffects PathEffects
-#endif
-TEST_F(VectorCanvasTest, MAYBE_PathEffects) {
-  {
-    SkPaint paint;
-    SkScalar intervals[] = { 1, 1 };
-    skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
-        new SkDashPathEffect(intervals, arraysize(intervals), 0));
-    paint.setPathEffect(effect.get());
-    paint.setColor(SK_ColorMAGENTA);
-    paint.setStyle(SkPaint::kStroke_Style);
-
-    vcanvas_->drawLine(10, 10, 90, 10, paint);
-    pcanvas_->drawLine(10, 10, 90, 10, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_line")));
-
-
-  // Starting here, there is NO WAY to make them agree. At least verify that the
-  // output doesn't change across versions. This test is disabled. See bug
-  // 1060231.
-  compare_canvas_ = false;
-
-  {
-    SkPaint paint;
-    SkScalar intervals[] = { 3, 5 };
-    skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
-        new SkDashPathEffect(intervals, arraysize(intervals), 0));
-    paint.setPathEffect(effect.get());
-    paint.setColor(SK_ColorMAGENTA);
-    paint.setStyle(SkPaint::kStroke_Style);
-
-    SkPath path;
-    path.moveTo(10, 15);
-    path.lineTo(90, 15);
-    path.lineTo(90, 90);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
-
-  {
-    SkPaint paint;
-    SkScalar intervals[] = { 2, 1 };
-    skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
-        new SkDashPathEffect(intervals, arraysize(intervals), 0));
-    paint.setPathEffect(effect.get());
-    paint.setColor(SK_ColorMAGENTA);
-    paint.setStyle(SkPaint::kStroke_Style);
-
-    vcanvas_->drawRectCoords(20, 20, 30, 30, paint);
-    pcanvas_->drawRectCoords(20, 20, 30, 30, paint);
-  }
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_rect")));
-
-  // This thing looks like it has been drawn by a 3 years old kid. I haven't
-  // filed a bug on this since I guess nobody is expecting this to look nice.
-  {
-    SkPaint paint;
-    SkScalar intervals[] = { 1, 1 };
-    skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
-        new SkDashPathEffect(intervals, arraysize(intervals), 0));
-    paint.setPathEffect(effect.get());
-    paint.setColor(SK_ColorMAGENTA);
-    paint.setStyle(SkPaint::kStroke_Style);
-
-    SkPath path;
-    path.addCircle(50, 75, 10);
-    vcanvas_->drawPath(path, paint);
-    pcanvas_->drawPath(path, paint);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle")));
-  }
-}
-
-TEST_F(VectorCanvasTest, Bitmaps) {
-  {
-    SkBitmap bitmap;
-    LoadPngFileToSkBitmap(test_file(L"bitmap_opaque.png"), &bitmap, true);
-    vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
-    pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("opaque")));
-  }
-
-  {
-    SkBitmap bitmap;
-    LoadPngFileToSkBitmap(test_file(L"bitmap_alpha.png"), &bitmap, false);
-    vcanvas_->drawBitmap(bitmap, 5, 15, NULL);
-    pcanvas_->drawBitmap(bitmap, 5, 15, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("alpha")));
-  }
-}
-
-TEST_F(VectorCanvasTest, ClippingRect) {
-  SkBitmap bitmap;
-  LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
-                        true);
-  SkRect rect;
-  rect.fLeft = 2;
-  rect.fTop = 2;
-  rect.fRight = 30.5f;
-  rect.fBottom = 30.5f;
-  vcanvas_->clipRect(rect);
-  pcanvas_->clipRect(rect);
-
-  vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
-  pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rect")));
-}
-
-TEST_F(VectorCanvasTest, ClippingPath) {
-  SkBitmap bitmap;
-  LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
-                        true);
-  SkPath path;
-  path.addCircle(20, 20, 10);
-  vcanvas_->clipPath(path);
-  pcanvas_->clipPath(path);
-
-  vcanvas_->drawBitmap(bitmap, 14, 3, NULL);
-  pcanvas_->drawBitmap(bitmap, 14, 3, NULL);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("path")));
-}
-
-TEST_F(VectorCanvasTest, ClippingCombined) {
-  SkBitmap bitmap;
-  LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
-                        true);
-
-  SkRect rect;
-  rect.fLeft = 2;
-  rect.fTop = 2;
-  rect.fRight = 30.5f;
-  rect.fBottom = 30.5f;
-  vcanvas_->clipRect(rect);
-  pcanvas_->clipRect(rect);
-  SkPath path;
-  path.addCircle(20, 20, 10);
-  vcanvas_->clipPath(path, SkRegion::kUnion_Op);
-  pcanvas_->clipPath(path, SkRegion::kUnion_Op);
-
-  vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
-  pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("combined")));
-}
-
-TEST_F(VectorCanvasTest, ClippingIntersect) {
-  SkBitmap bitmap;
-  LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
-                        true);
-
-  SkRect rect;
-  rect.fLeft = 2;
-  rect.fTop = 2;
-  rect.fRight = 30.5f;
-  rect.fBottom = 30.5f;
-  vcanvas_->clipRect(rect);
-  pcanvas_->clipRect(rect);
-  SkPath path;
-  path.addCircle(23, 23, 15);
-  vcanvas_->clipPath(path);
-  pcanvas_->clipPath(path);
-
-  vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
-  pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
-  EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("intersect")));
-}
-
-TEST_F(VectorCanvasTest, ClippingClean) {
-  SkBitmap bitmap;
-  LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
-                        true);
-  {
-    SkAutoCanvasRestore acrv(vcanvas_, true);
-    SkAutoCanvasRestore acrp(pcanvas_, true);
-    SkRect rect;
-    rect.fLeft = 2;
-    rect.fTop = 2;
-    rect.fRight = 30.5f;
-    rect.fBottom = 30.5f;
-    vcanvas_->clipRect(rect);
-    pcanvas_->clipRect(rect);
-
-    vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
-    pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clipped")));
-  }
-  {
-    // Verify that the clipping region has been fixed back.
-    vcanvas_->drawBitmap(bitmap, 55, 3, NULL);
-    pcanvas_->drawBitmap(bitmap, 55, 3, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("unclipped")));
-  }
-}
-
-// See http://crbug.com/26938
-TEST_F(VectorCanvasTest, DISABLED_Matrix) {
-  SkBitmap bitmap;
-  LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
-                        true);
-  {
-    vcanvas_->translate(15, 3);
-    pcanvas_->translate(15, 3);
-    vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
-    pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate1")));
-  }
-  {
-    vcanvas_->translate(-30, -23);
-    pcanvas_->translate(-30, -23);
-    vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
-    pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate2")));
-  }
-  vcanvas_->resetMatrix();
-  pcanvas_->resetMatrix();
-
-  // For scaling and rotation, they use a different algorithm (nearest
-  // neighborhood vs smoothing). At least verify that the output doesn't change
-  // across versions.
-  compare_canvas_ = false;
-
-  {
-    vcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
-    pcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
-    vcanvas_->drawBitmap(bitmap, 1, 1, NULL);
-    pcanvas_->drawBitmap(bitmap, 1, 1, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("scale")));
-  }
-  vcanvas_->resetMatrix();
-  pcanvas_->resetMatrix();
-
-  {
-    vcanvas_->rotate(67);
-    pcanvas_->rotate(67);
-    vcanvas_->drawBitmap(bitmap, 20, -50, NULL);
-    pcanvas_->drawBitmap(bitmap, 20, -50, NULL);
-    EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rotate")));
-  }
-}
-
-#endif  // !defined(USE_AURA)
-
-}  // namespace skia
diff --git a/skia/ext/vector_platform_device_emf_win.cc b/skia/ext/vector_platform_device_emf_win.cc
deleted file mode 100644
index 90e4a20..0000000
--- a/skia/ext/vector_platform_device_emf_win.cc
+++ /dev/null
@@ -1,982 +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.
-
-#include "skia/ext/vector_platform_device_emf_win.h"
-
-#include <windows.h>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "skia/ext/bitmap_platform_device.h"
-#include "skia/ext/skia_utils_win.h"
-#include "third_party/skia/include/core/SkPathEffect.h"
-#include "third_party/skia/include/core/SkTemplates.h"
-#include "third_party/skia/include/core/SkUtils.h"
-#include "third_party/skia/include/ports/SkTypeface_win.h"
-
-namespace skia {
-
-#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
-    do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
-
-// static
-SkBaseDevice* VectorPlatformDeviceEmf::CreateDevice(
-    int width, int height, bool is_opaque, HANDLE shared_section) {
-  if (!is_opaque) {
-    // TODO(maruel):  http://crbug.com/18382 When restoring a semi-transparent
-    // layer, i.e. merging it, we need to rasterize it because GDI doesn't
-    // support transparency except for AlphaBlend(). Right now, a
-    // BitmapPlatformDevice is created when VectorCanvas think a saveLayers()
-    // call is being done. The way to save a layer would be to create an
-    // EMF-based VectorDevice and have this device registers the drawing. When
-    // playing back the device into a bitmap, do it at the printer's dpi instead
-    // of the layout's dpi (which is much lower).
-    return BitmapPlatformDevice::Create(width, height, is_opaque,
-                                        shared_section);
-  }
-
-  // TODO(maruel):  http://crbug.com/18383 Look if it would be worth to
-  // increase the resolution by ~10x (any worthy factor) to increase the
-  // rendering precision (think about printing) while using a relatively
-  // low dpi. This happens because we receive float as input but the GDI
-  // functions works with integers. The idea is to premultiply the matrix
-  // with this factor and multiply each SkScalar that are passed to
-  // SkScalarRound(value) as SkScalarRound(value * 10). Safari is already
-  // doing the same for text rendering.
-  SkASSERT(shared_section);
-  SkBaseDevice* device = VectorPlatformDeviceEmf::create(
-      reinterpret_cast<HDC>(shared_section), width, height);
-  return device;
-}
-
-static void FillBitmapInfoHeader(int width, int height, BITMAPINFOHEADER* hdr) {
-  hdr->biSize = sizeof(BITMAPINFOHEADER);
-  hdr->biWidth = width;
-  hdr->biHeight = -height;  // Minus means top-down bitmap.
-  hdr->biPlanes = 1;
-  hdr->biBitCount = 32;
-  hdr->biCompression = BI_RGB;  // no compression
-  hdr->biSizeImage = 0;
-  hdr->biXPelsPerMeter = 1;
-  hdr->biYPelsPerMeter = 1;
-  hdr->biClrUsed = 0;
-  hdr->biClrImportant = 0;
-}
-
-SkBaseDevice* VectorPlatformDeviceEmf::create(HDC dc, int width, int height) {
-  InitializeDC(dc);
-
-  // Link the SkBitmap to the current selected bitmap in the device context.
-  SkBitmap bitmap;
-  HGDIOBJ selected_bitmap = GetCurrentObject(dc, OBJ_BITMAP);
-  bool succeeded = false;
-  if (selected_bitmap != NULL) {
-    BITMAP bitmap_data = {0};
-    if (GetObject(selected_bitmap, sizeof(BITMAP), &bitmap_data) ==
-        sizeof(BITMAP)) {
-      // The context has a bitmap attached. Attach our SkBitmap to it.
-      // Warning: If the bitmap gets unselected from the HDC,
-      // VectorPlatformDeviceEmf has no way to detect this, so the HBITMAP
-      // could be released while SkBitmap still has a reference to it. Be
-      // cautious.
-      if (width == bitmap_data.bmWidth && height == bitmap_data.bmHeight) {
-        SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
-        succeeded = bitmap.installPixels(info, bitmap_data.bmBits,
-                                         bitmap_data.bmWidthBytes);
-      }
-    }
-  }
-
-  if (!succeeded)
-    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
-
-  return new VectorPlatformDeviceEmf(dc, bitmap);
-}
-
-VectorPlatformDeviceEmf::VectorPlatformDeviceEmf(HDC dc, const SkBitmap& bitmap)
-    : SkBitmapDevice(bitmap),
-      hdc_(dc),
-      previous_brush_(NULL),
-      previous_pen_(NULL) {
-  transform_.reset();
-  SetPlatformDevice(this, this);
-}
-
-VectorPlatformDeviceEmf::~VectorPlatformDeviceEmf() {
-  SkASSERT(previous_brush_ == NULL);
-  SkASSERT(previous_pen_ == NULL);
-}
-
-HDC VectorPlatformDeviceEmf::BeginPlatformPaint() {
-  return hdc_;
-}
-
-void VectorPlatformDeviceEmf::drawPaint(const SkDraw& draw,
-                                        const SkPaint& paint) {
-  // TODO(maruel):  Bypass the current transformation matrix.
-  SkRect rect;
-  rect.fLeft = 0;
-  rect.fTop = 0;
-  rect.fRight = SkIntToScalar(width() + 1);
-  rect.fBottom = SkIntToScalar(height() + 1);
-  drawRect(draw, rect, paint);
-}
-
-void VectorPlatformDeviceEmf::drawPoints(const SkDraw& draw,
-                                         SkCanvas::PointMode mode,
-                                         size_t count,
-                                         const SkPoint pts[],
-                                         const SkPaint& paint) {
-  if (!count)
-    return;
-
-  if (mode == SkCanvas::kPoints_PointMode) {
-    SkASSERT(false);
-    return;
-  }
-
-  SkPaint tmp_paint(paint);
-  tmp_paint.setStyle(SkPaint::kStroke_Style);
-
-  // Draw a path instead.
-  SkPath path;
-  switch (mode) {
-    case SkCanvas::kLines_PointMode:
-      if (count % 2) {
-        SkASSERT(false);
-        return;
-      }
-      for (size_t i = 0; i < count / 2; ++i) {
-        path.moveTo(pts[2 * i]);
-        path.lineTo(pts[2 * i + 1]);
-      }
-      break;
-    case SkCanvas::kPolygon_PointMode:
-      path.moveTo(pts[0]);
-      for (size_t i = 1; i < count; ++i) {
-        path.lineTo(pts[i]);
-      }
-      break;
-    default:
-      SkASSERT(false);
-      return;
-  }
-  // Draw the calculated path.
-  drawPath(draw, path, tmp_paint);
-}
-
-void VectorPlatformDeviceEmf::drawRect(const SkDraw& draw,
-                                       const SkRect& rect,
-                                       const SkPaint& paint) {
-  CHECK_FOR_NODRAW_ANNOTATION(paint);
-  if (paint.getPathEffect()) {
-    // Draw a path instead.
-    SkPath path_orginal;
-    path_orginal.addRect(rect);
-
-    // Apply the path effect to the rect.
-    SkPath path_modified;
-    paint.getFillPath(path_orginal, &path_modified);
-
-    // Removes the path effect from the temporary SkPaint object.
-    SkPaint paint_no_effet(paint);
-    paint_no_effet.setPathEffect(NULL);
-
-    // Draw the calculated path.
-    drawPath(draw, path_modified, paint_no_effet);
-    return;
-  }
-
-  if (!ApplyPaint(paint)) {
-    return;
-  }
-  HDC dc = BeginPlatformPaint();
-  if (!Rectangle(dc, SkScalarRoundToInt(rect.fLeft),
-                 SkScalarRoundToInt(rect.fTop),
-                 SkScalarRoundToInt(rect.fRight),
-                 SkScalarRoundToInt(rect.fBottom))) {
-    SkASSERT(false);
-  }
-  EndPlatformPaint();
-  Cleanup();
-}
-
-void VectorPlatformDeviceEmf::drawRRect(const SkDraw& draw, const SkRRect& rr,
-                                        const SkPaint& paint) {
-  SkPath path;
-  path.addRRect(rr);
-  this->drawPath(draw, path, paint, NULL, true);
-}
-
-void VectorPlatformDeviceEmf::drawPath(const SkDraw& draw,
-                                       const SkPath& path,
-                                       const SkPaint& paint,
-                                       const SkMatrix* prePathMatrix,
-                                       bool pathIsMutable) {
-  CHECK_FOR_NODRAW_ANNOTATION(paint);
-  if (paint.getPathEffect()) {
-    // Apply the path effect forehand.
-    SkPath path_modified;
-    paint.getFillPath(path, &path_modified);
-
-    // Removes the path effect from the temporary SkPaint object.
-    SkPaint paint_no_effet(paint);
-    paint_no_effet.setPathEffect(NULL);
-
-    // Draw the calculated path.
-    drawPath(draw, path_modified, paint_no_effet);
-    return;
-  }
-
-  if (!ApplyPaint(paint)) {
-    return;
-  }
-  HDC dc = BeginPlatformPaint();
-  if (PlatformDevice::LoadPathToDC(dc, path)) {
-    switch (paint.getStyle()) {
-      case SkPaint::kFill_Style: {
-        BOOL res = StrokeAndFillPath(dc);
-        SkASSERT(res != 0);
-        break;
-      }
-      case SkPaint::kStroke_Style: {
-        BOOL res = StrokePath(dc);
-        SkASSERT(res != 0);
-        break;
-      }
-      case SkPaint::kStrokeAndFill_Style: {
-        BOOL res = StrokeAndFillPath(dc);
-        SkASSERT(res != 0);
-        break;
-      }
-      default:
-        SkASSERT(false);
-        break;
-    }
-  }
-  EndPlatformPaint();
-  Cleanup();
-}
-
-void VectorPlatformDeviceEmf::drawBitmapRect(const SkDraw& draw,
-                                             const SkBitmap& bitmap,
-                                             const SkRect* src,
-                                             const SkRect& dst,
-                                             const SkPaint& paint,
-                                             SkCanvas::DrawBitmapRectFlags flags) {
-    SkMatrix    matrix;
-    SkRect      bitmapBounds, tmpSrc, tmpDst;
-    SkBitmap    tmpBitmap;
-
-    bitmapBounds.isetWH(bitmap.width(), bitmap.height());
-
-    // Compute matrix from the two rectangles
-    if (src) {
-        tmpSrc = *src;
-    } else {
-        tmpSrc = bitmapBounds;
-    }
-    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
-
-    const SkBitmap* bitmapPtr = &bitmap;
-
-    // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
-    // needed (if the src was clipped). No check needed if src==null.
-    if (src) {
-        if (!bitmapBounds.contains(*src)) {
-            if (!tmpSrc.intersect(bitmapBounds)) {
-                return; // nothing to draw
-            }
-            // recompute dst, based on the smaller tmpSrc
-            matrix.mapRect(&tmpDst, tmpSrc);
-        }
-
-        // since we may need to clamp to the borders of the src rect within
-        // the bitmap, we extract a subset.
-        // TODO: make sure this is handled in drawrect and remove it from here.
-        SkIRect srcIR;
-        tmpSrc.roundOut(&srcIR);
-        if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
-            return;
-        }
-        bitmapPtr = &tmpBitmap;
-
-        // Since we did an extract, we need to adjust the matrix accordingly
-        SkScalar dx = 0, dy = 0;
-        if (srcIR.fLeft > 0) {
-            dx = SkIntToScalar(srcIR.fLeft);
-        }
-        if (srcIR.fTop > 0) {
-            dy = SkIntToScalar(srcIR.fTop);
-        }
-        if (dx || dy) {
-            matrix.preTranslate(dx, dy);
-        }
-    }
-    this->drawBitmap(draw, *bitmapPtr, matrix, paint);
-}
-
-void VectorPlatformDeviceEmf::drawBitmap(const SkDraw& draw,
-                                         const SkBitmap& bitmap,
-                                         const SkMatrix& matrix,
-                                         const SkPaint& paint) {
-  // Load the temporary matrix. This is what will translate, rotate and resize
-  // the bitmap.
-  SkMatrix actual_transform(transform_);
-  actual_transform.preConcat(matrix);
-  LoadTransformToDC(hdc_, actual_transform);
-
-  InternalDrawBitmap(bitmap, 0, 0, paint);
-
-  // Restore the original matrix.
-  LoadTransformToDC(hdc_, transform_);
-}
-
-void VectorPlatformDeviceEmf::drawSprite(const SkDraw& draw,
-                                         const SkBitmap& bitmap,
-                                         int x, int y,
-                                         const SkPaint& paint) {
-  SkMatrix identity;
-  identity.reset();
-  LoadTransformToDC(hdc_, identity);
-
-  InternalDrawBitmap(bitmap, x, y, paint);
-
-  // Restore the original matrix.
-  LoadTransformToDC(hdc_, transform_);
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-static bool gdiCanHandleText(const SkPaint& paint) {
-  return !paint.getShader() &&
-         !paint.getPathEffect() &&
-         (SkPaint::kFill_Style == paint.getStyle()) &&
-         (255 == paint.getAlpha());
-}
-
-class SkGDIFontSetup {
- public:
-  SkGDIFontSetup() :
-      fHDC(NULL),
-      fNewFont(NULL),
-      fSavedFont(NULL),
-      fSavedTextColor(0),
-      fUseGDI(false) {
-    SkDEBUGCODE(fUseGDIHasBeenCalled = false;)
-  }
-  ~SkGDIFontSetup();
-
-  // can only be called once
-  bool useGDI(HDC hdc, const SkPaint&);
-
- private:
-  HDC      fHDC;
-  HFONT    fNewFont;
-  HFONT    fSavedFont;
-  COLORREF fSavedTextColor;
-  bool     fUseGDI;
-  SkDEBUGCODE(bool fUseGDIHasBeenCalled;)
-};
-
-bool SkGDIFontSetup::useGDI(HDC hdc, const SkPaint& paint) {
-  SkASSERT(!fUseGDIHasBeenCalled);
-  SkDEBUGCODE(fUseGDIHasBeenCalled = true;)
-
-  fUseGDI = gdiCanHandleText(paint);
-  if (fUseGDI) {
-    fSavedTextColor = GetTextColor(hdc);
-    SetTextColor(hdc, skia::SkColorToCOLORREF(paint.getColor()));
-
-    LOGFONT lf = {0};
-    SkLOGFONTFromTypeface(paint.getTypeface(), &lf);
-    lf.lfHeight = -SkScalarRoundToInt(paint.getTextSize());
-    fNewFont = CreateFontIndirect(&lf);
-    fSavedFont = (HFONT)::SelectObject(hdc, fNewFont);
-    fHDC = hdc;
-  }
-  return fUseGDI;
-}
-
-SkGDIFontSetup::~SkGDIFontSetup() {
-  if (fUseGDI) {
-    ::SelectObject(fHDC, fSavedFont);
-    ::DeleteObject(fNewFont);
-    SetTextColor(fHDC, fSavedTextColor);
-  }
-}
-
-static SkScalar getAscent(const SkPaint& paint) {
-  SkPaint::FontMetrics fm;
-  paint.getFontMetrics(&fm);
-  return fm.fAscent;
-}
-
-// return the options int for ExtTextOut. Only valid if the paint's text
-// encoding is not UTF8 (in which case ExtTextOut can't be used).
-static UINT getTextOutOptions(const SkPaint& paint) {
-  if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
-    return ETO_GLYPH_INDEX;
-  } else {
-    SkASSERT(SkPaint::kUTF16_TextEncoding == paint.getTextEncoding());
-    return 0;
-  }
-}
-
-static SkiaEnsureTypefaceCharactersAccessible
-    g_skia_ensure_typeface_characters_accessible = NULL;
-
-SK_API void SetSkiaEnsureTypefaceCharactersAccessible(
-    SkiaEnsureTypefaceCharactersAccessible func) {
-  // This function is supposed to be called once in process life time.
-  SkASSERT(g_skia_ensure_typeface_characters_accessible == NULL);
-  g_skia_ensure_typeface_characters_accessible = func;
-}
-
-void EnsureTypefaceCharactersAccessible(
-    const SkTypeface& typeface, const wchar_t* text, unsigned int text_length) {
-  LOGFONT lf = {0};
-  SkLOGFONTFromTypeface(&typeface, &lf);
-  g_skia_ensure_typeface_characters_accessible(lf, text, text_length);
-}
-
-bool EnsureExtTextOut(HDC hdc, int x, int y, UINT options, const RECT * lprect,
-                      LPCWSTR text, unsigned int characters, const int * lpDx,
-                      SkTypeface* const typeface) {
-  bool success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx);
-  if (!success) {
-    if (typeface) {
-      EnsureTypefaceCharactersAccessible(*typeface,
-                                         text,
-                                         characters);
-      success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx);
-      if (!success) {
-        LOGFONT lf = {0};
-        SkLOGFONTFromTypeface(typeface, &lf);
-        VLOG(1) << "SkFontHost::EnsureTypefaceCharactersAccessible FAILED for "
-                << " FaceName = " << lf.lfFaceName
-                << " and characters: " << base::string16(text, characters);
-      }
-    } else {
-      VLOG(1) << "ExtTextOut FAILED for default FaceName "
-              << " and characters: " << base::string16(text, characters);
-    }
-  }
-  return success;
-}
-
-void VectorPlatformDeviceEmf::drawText(const SkDraw& draw,
-                                       const void* text,
-                                       size_t byteLength,
-                                       SkScalar x,
-                                       SkScalar y,
-                                       const SkPaint& paint) {
-  SkGDIFontSetup setup;
-  bool useDrawPath = true;
-
-  if (SkPaint::kUTF8_TextEncoding != paint.getTextEncoding()
-      && setup.useGDI(hdc_, paint)) {
-    UINT options = getTextOutOptions(paint);
-    UINT count = byteLength >> 1;
-    useDrawPath = !EnsureExtTextOut(hdc_, SkScalarRoundToInt(x),
-        SkScalarRoundToInt(y + getAscent(paint)), options, 0,
-        reinterpret_cast<const wchar_t*>(text), count, NULL,
-        paint.getTypeface());
-  }
-
-  if (useDrawPath) {
-    SkPath path;
-    paint.getTextPath(text, byteLength, x, y, &path);
-    drawPath(draw, path, paint);
-  }
-}
-
-static size_t size_utf8(const char* text) {
-  return SkUTF8_CountUTF8Bytes(text);
-}
-
-static size_t size_utf16(const char* text) {
-  uint16_t c = *reinterpret_cast<const uint16_t*>(text);
-  return SkUTF16_IsHighSurrogate(c) ? 4 : 2;
-}
-
-static size_t size_glyphid(const char* text) {
-  return 2;
-}
-
-void VectorPlatformDeviceEmf::drawPosText(const SkDraw& draw,
-                                          const void* text,
-                                          size_t len,
-                                          const SkScalar pos[],
-                                          int scalarsPerPos,
-                                          const SkPoint& offset,
-                                          const SkPaint& paint) {
-  SkGDIFontSetup setup;
-  bool useDrawText = true;
-
-  if (scalarsPerPos == 2 && len >= 2 &&
-      SkPaint::kUTF8_TextEncoding != paint.getTextEncoding() &&
-      setup.useGDI(hdc_, paint)) {
-    int startX = SkScalarRoundToInt(pos[0] + offset.x());
-    int startY = SkScalarRoundToInt(pos[1] + offset.y() + getAscent(paint));
-    const int count = len >> 1;
-    SkAutoSTMalloc<64, INT> storage(count);
-    INT* advances = storage.get();
-    for (int i = 0; i < count - 1; ++i) {
-      advances[i] = SkScalarRoundToInt(pos[2] - pos[0]);
-      pos += 2;
-    }
-    advances[count - 1] = 0;
-    useDrawText = !EnsureExtTextOut(hdc_, startX, startY,
-        getTextOutOptions(paint), 0, reinterpret_cast<const wchar_t*>(text),
-        count, advances, paint.getTypeface());
-  }
-
-  if (useDrawText) {
-    size_t (*bytesPerCodePoint)(const char*);
-    switch (paint.getTextEncoding()) {
-    case SkPaint::kUTF8_TextEncoding:
-      bytesPerCodePoint = size_utf8;
-      break;
-    case SkPaint::kUTF16_TextEncoding:
-      bytesPerCodePoint = size_utf16;
-      break;
-    default:
-      SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
-      bytesPerCodePoint = size_glyphid;
-      break;
-    }
-
-    const char* curr = reinterpret_cast<const char*>(text);
-    const char* stop = curr + len;
-    while (curr < stop) {
-      SkScalar x = offset.x() + pos[0];
-      SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[1] : 0);
-
-      size_t bytes = bytesPerCodePoint(curr);
-      drawText(draw, curr, bytes, x, y, paint);
-      curr += bytes;
-      pos += scalarsPerPos;
-    }
-  }
-}
-
-void VectorPlatformDeviceEmf::drawTextOnPath(const SkDraw& draw,
-                                             const void* text,
-                                             size_t len,
-                                             const SkPath& path,
-                                             const SkMatrix* matrix,
-                                             const SkPaint& paint) {
-  // This function isn't used in the code. Verify this assumption.
-  SkASSERT(false);
-}
-
-void VectorPlatformDeviceEmf::drawVertices(const SkDraw& draw,
-                                           SkCanvas::VertexMode vmode,
-                                           int vertexCount,
-                                           const SkPoint vertices[],
-                                           const SkPoint texs[],
-                                           const SkColor colors[],
-                                           SkXfermode* xmode,
-                                           const uint16_t indices[],
-                                           int indexCount,
-                                           const SkPaint& paint) {
-  // This function isn't used in the code. Verify this assumption.
-  SkASSERT(false);
-}
-
-void VectorPlatformDeviceEmf::drawDevice(const SkDraw& draw,
-                                         SkBaseDevice* device,
-                                         int x,
-                                         int y,
-                                         const SkPaint& paint) {
-  // TODO(maruel):  http://b/1183870 Playback the EMF buffer at printer's dpi if
-  // it is a vectorial device.
-  drawSprite(draw, device->accessBitmap(false), x, y, paint);
-}
-
-bool VectorPlatformDeviceEmf::ApplyPaint(const SkPaint& paint) {
-  // Note: The goal here is to transfert the SkPaint's state to the HDC's state.
-  // This function does not execute the SkPaint drawing commands. These should
-  // be executed in drawPaint().
-
-  SkPaint::Style style = paint.getStyle();
-  if (!paint.getAlpha())
-      style = (SkPaint::Style) SkPaint::kStyleCount;
-
-  switch (style) {
-    case SkPaint::kFill_Style:
-      if (!CreateBrush(true, paint) ||
-          !CreatePen(false, paint))
-        return false;
-      break;
-    case SkPaint::kStroke_Style:
-      if (!CreateBrush(false, paint) ||
-          !CreatePen(true, paint))
-        return false;
-      break;
-    case SkPaint::kStrokeAndFill_Style:
-      if (!CreateBrush(true, paint) ||
-          !CreatePen(true, paint))
-        return false;
-      break;
-    default:
-      if (!CreateBrush(false, paint) ||
-          !CreatePen(false, paint))
-        return false;
-      break;
-  }
-
-  /*
-  getFlags();
-    isAntiAlias();
-    isDither()
-    isLinearText()
-    isSubpixelText()
-    isUnderlineText()
-    isStrikeThruText()
-    isFakeBoldText()
-    isDevKernText()
-    isFilterBitmap()
-
-  // Skia's text is not used. This should be fixed.
-  getTextAlign()
-  getTextScaleX()
-  getTextSkewX()
-  getTextEncoding()
-  getFontMetrics()
-  getFontSpacing()
-  */
-
-  // BUG 1094907: Implement shaders. Shaders currently in use:
-  //  SkShader::CreateBitmapShader
-  //  SkGradientShader::CreateRadial
-  //  SkGradientShader::CreateLinear
-  // SkASSERT(!paint.getShader());
-
-  // http://b/1106647 Implement loopers and mask filter. Looper currently in
-  // use:
-  //   SkBlurDrawLooper is used for shadows.
-  // SkASSERT(!paint.getLooper());
-  // SkASSERT(!paint.getMaskFilter());
-
-  // http://b/1165900 Implement xfermode.
-  // SkASSERT(!paint.getXfermode());
-
-  // The path effect should be processed before arriving here.
-  SkASSERT(!paint.getPathEffect());
-
-  // This isn't used in the code. Verify this assumption.
-  SkASSERT(!paint.getRasterizer());
-  // Reuse code to load Win32 Fonts.
-  return true;
-}
-
-void VectorPlatformDeviceEmf::setMatrixClip(const SkMatrix& transform,
-                                            const SkRegion& region,
-                                            const SkClipStack&) {
-  transform_ = transform;
-  LoadTransformToDC(hdc_, transform_);
-  clip_region_ = region;
-  if (!clip_region_.isEmpty())
-    LoadClipRegion();
-}
-
-void VectorPlatformDeviceEmf::LoadClipRegion() {
-  SkMatrix t;
-  t.reset();
-  LoadClippingRegionToDC(hdc_, clip_region_, t);
-}
-
-SkBaseDevice* VectorPlatformDeviceEmf::onCreateCompatibleDevice(
-                                                    const CreateInfo& info) {
-  SkASSERT(info.fInfo.colorType() == kN32_SkColorType);
-  return VectorPlatformDeviceEmf::CreateDevice(
-      info.fInfo.width(), info.fInfo.height(), info.fInfo.isOpaque(), NULL);
-}
-
-bool VectorPlatformDeviceEmf::CreateBrush(bool use_brush, COLORREF color) {
-  SkASSERT(previous_brush_ == NULL);
-  // We can't use SetDCBrushColor() or DC_BRUSH when drawing to a EMF buffer.
-  // SetDCBrushColor() calls are not recorded at all and DC_BRUSH will use
-  // WHITE_BRUSH instead.
-
-  if (!use_brush) {
-    // Set the transparency.
-    if (0 == SetBkMode(hdc_, TRANSPARENT)) {
-      SkASSERT(false);
-      return false;
-    }
-
-    // Select the NULL brush.
-    previous_brush_ = SelectObject(GetStockObject(NULL_BRUSH));
-    return previous_brush_ != NULL;
-  }
-
-  // Set the opacity.
-  if (0 == SetBkMode(hdc_, OPAQUE)) {
-    SkASSERT(false);
-    return false;
-  }
-
-  // Create and select the brush.
-  previous_brush_ = SelectObject(CreateSolidBrush(color));
-  return previous_brush_ != NULL;
-}
-
-bool VectorPlatformDeviceEmf::CreatePen(bool use_pen,
-                                        COLORREF color,
-                                        int stroke_width,
-                                        float stroke_miter,
-                                        DWORD pen_style) {
-  SkASSERT(previous_pen_ == NULL);
-  // We can't use SetDCPenColor() or DC_PEN when drawing to a EMF buffer.
-  // SetDCPenColor() calls are not recorded at all and DC_PEN will use BLACK_PEN
-  // instead.
-
-  // No pen case
-  if (!use_pen) {
-    previous_pen_ = SelectObject(GetStockObject(NULL_PEN));
-    return previous_pen_ != NULL;
-  }
-
-  // Use the stock pen if the stroke width is 0.
-  if (stroke_width == 0) {
-    // Create a pen with the right color.
-    previous_pen_ = SelectObject(::CreatePen(PS_SOLID, 0, color));
-    return previous_pen_ != NULL;
-  }
-
-  // Load a custom pen.
-  LOGBRUSH brush = {0};
-  brush.lbStyle = BS_SOLID;
-  brush.lbColor = color;
-  brush.lbHatch = 0;
-  HPEN pen = ExtCreatePen(pen_style, stroke_width, &brush, 0, NULL);
-  SkASSERT(pen != NULL);
-  previous_pen_ = SelectObject(pen);
-  if (previous_pen_ == NULL)
-    return false;
-
-  if (!SetMiterLimit(hdc_, stroke_miter, NULL)) {
-    SkASSERT(false);
-    return false;
-  }
-  return true;
-}
-
-void VectorPlatformDeviceEmf::Cleanup() {
-  if (previous_brush_) {
-    HGDIOBJ result = SelectObject(previous_brush_);
-    previous_brush_ = NULL;
-    if (result) {
-      BOOL res = DeleteObject(result);
-      SkASSERT(res != 0);
-    }
-  }
-  if (previous_pen_) {
-    HGDIOBJ result = SelectObject(previous_pen_);
-    previous_pen_ = NULL;
-    if (result) {
-      BOOL res = DeleteObject(result);
-      SkASSERT(res != 0);
-    }
-  }
-  // Remove any loaded path from the context.
-  AbortPath(hdc_);
-}
-
-HGDIOBJ VectorPlatformDeviceEmf::SelectObject(HGDIOBJ object) {
-  HGDIOBJ result = ::SelectObject(hdc_, object);
-  SkASSERT(result != HGDI_ERROR);
-  if (result == HGDI_ERROR)
-    return NULL;
-  return result;
-}
-
-bool VectorPlatformDeviceEmf::CreateBrush(bool use_brush,
-                                          const SkPaint& paint) {
-  // Make sure that for transparent color, no brush is used.
-  if (paint.getAlpha() == 0) {
-    use_brush = false;
-  }
-
-  return CreateBrush(use_brush, SkColorToCOLORREF(paint.getColor()));
-}
-
-bool VectorPlatformDeviceEmf::CreatePen(bool use_pen, const SkPaint& paint) {
-  // Make sure that for transparent color, no pen is used.
-  if (paint.getAlpha() == 0) {
-    use_pen = false;
-  }
-
-  DWORD pen_style = PS_GEOMETRIC | PS_SOLID;
-  switch (paint.getStrokeJoin()) {
-    case SkPaint::kMiter_Join:
-      // Connects path segments with a sharp join.
-      pen_style |= PS_JOIN_MITER;
-      break;
-    case SkPaint::kRound_Join:
-      // Connects path segments with a round join.
-      pen_style |= PS_JOIN_ROUND;
-      break;
-    case SkPaint::kBevel_Join:
-      // Connects path segments with a flat bevel join.
-      pen_style |= PS_JOIN_BEVEL;
-      break;
-    default:
-      SkASSERT(false);
-      break;
-  }
-  switch (paint.getStrokeCap()) {
-    case SkPaint::kButt_Cap:
-      // Begin/end contours with no extension.
-      pen_style |= PS_ENDCAP_FLAT;
-      break;
-    case SkPaint::kRound_Cap:
-      // Begin/end contours with a semi-circle extension.
-      pen_style |= PS_ENDCAP_ROUND;
-      break;
-    case SkPaint::kSquare_Cap:
-      // Begin/end contours with a half square extension.
-      pen_style |= PS_ENDCAP_SQUARE;
-      break;
-    default:
-      SkASSERT(false);
-      break;
-  }
-
-  return CreatePen(use_pen,
-                   SkColorToCOLORREF(paint.getColor()),
-                   SkScalarRoundToInt(paint.getStrokeWidth()),
-                   paint.getStrokeMiter(),
-                   pen_style);
-}
-
-void VectorPlatformDeviceEmf::InternalDrawBitmap(const SkBitmap& bitmap,
-                                                 int x, int y,
-                                                 const SkPaint& paint) {
-  unsigned char alpha = paint.getAlpha();
-  if (alpha == 0)
-    return;
-
-  bool is_translucent;
-  if (alpha != 255) {
-    // ApplyPaint expect an opaque color.
-    SkPaint tmp_paint(paint);
-    tmp_paint.setAlpha(255);
-    if (!ApplyPaint(tmp_paint))
-      return;
-    is_translucent = true;
-  } else {
-    if (!ApplyPaint(paint))
-      return;
-    is_translucent = false;
-  }
-  int src_size_x = bitmap.width();
-  int src_size_y = bitmap.height();
-  if (!src_size_x || !src_size_y)
-    return;
-
-  // Create a BMP v4 header that we can serialize. We use the shared "V3"
-  // fillter to fill the stardard items, then add in the "V4" stuff we want.
-  BITMAPV4HEADER bitmap_header = {0};
-  FillBitmapInfoHeader(src_size_x, src_size_y,
-                       reinterpret_cast<BITMAPINFOHEADER*>(&bitmap_header));
-  bitmap_header.bV4Size = sizeof(BITMAPV4HEADER);
-  bitmap_header.bV4RedMask   = 0x00ff0000;
-  bitmap_header.bV4GreenMask = 0x0000ff00;
-  bitmap_header.bV4BlueMask  = 0x000000ff;
-  bitmap_header.bV4AlphaMask = 0xff000000;
-
-  SkAutoLockPixels lock(bitmap);
-  SkASSERT(bitmap.colorType() == kN32_SkColorType);
-  const uint32_t* pixels = static_cast<const uint32_t*>(bitmap.getPixels());
-  if (pixels == NULL) {
-    SkASSERT(false);
-    return;
-  }
-
-  if (!is_translucent) {
-    int row_length = bitmap.rowBytesAsPixels();
-    // There is no quick way to determine if an image is opaque.
-    for (int y2 = 0; y2 < src_size_y; ++y2) {
-      for (int x2 = 0; x2 < src_size_x; ++x2) {
-        if (SkColorGetA(pixels[(y2 * row_length) + x2]) != 255) {
-          is_translucent = true;
-          y2 = src_size_y;
-          break;
-        }
-      }
-    }
-  }
-
-  HDC dc = BeginPlatformPaint();
-  BITMAPINFOHEADER hdr = {0};
-  FillBitmapInfoHeader(src_size_x, src_size_y, &hdr);
-  if (is_translucent) {
-    // The image must be loaded as a bitmap inside a device context.
-    HDC bitmap_dc = ::CreateCompatibleDC(dc);
-    void* bits = NULL;
-    HBITMAP hbitmap = ::CreateDIBSection(
-        bitmap_dc, reinterpret_cast<const BITMAPINFO*>(&hdr),
-        DIB_RGB_COLORS, &bits, NULL, 0);
-
-    // static cast to a char so we can do byte ptr arithmatic to
-    // get the offset.
-    unsigned char* dest_buffer = static_cast<unsigned char *>(bits);
-
-    // We will copy row by row to avoid having to worry about
-    // the row strides being different.
-    const int dest_row_size = hdr.biBitCount / 8 * hdr.biWidth;
-    for (int row = 0; row < bitmap.height(); ++row) {
-      int dest_offset = row * dest_row_size;
-      // pixels_offset in terms of pixel count.
-      int src_offset = row * bitmap.rowBytesAsPixels();
-      memcpy(dest_buffer + dest_offset, pixels + src_offset, dest_row_size);
-    }
-    SkASSERT(hbitmap);
-    HGDIOBJ old_bitmap = ::SelectObject(bitmap_dc, hbitmap);
-
-    // After some analysis of IE7's behavior, this is the thing to do. I was
-    // sure IE7 was doing so kind of bitmasking due to the way translucent image
-    // where renderered but after some windbg tracing, it is being done by the
-    // printer driver after all (mostly HP printers). IE7 always use AlphaBlend
-    // for bitmasked images. The trick seems to switch the stretching mode in
-    // what the driver expects.
-    DWORD previous_mode = GetStretchBltMode(dc);
-    BOOL result = SetStretchBltMode(dc, COLORONCOLOR);
-    SkASSERT(result);
-    // Note that this function expect premultiplied colors (!)
-    BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
-    result = GdiAlphaBlend(dc,
-                           x, y,  // Destination origin.
-                           src_size_x, src_size_y,  // Destination size.
-                           bitmap_dc,
-                           0, 0,  // Source origin.
-                           src_size_x, src_size_y,  // Source size.
-                           blend_function);
-    SkASSERT(result);
-    result = SetStretchBltMode(dc, previous_mode);
-    SkASSERT(result);
-
-    ::SelectObject(bitmap_dc, static_cast<HBITMAP>(old_bitmap));
-    DeleteObject(hbitmap);
-    DeleteDC(bitmap_dc);
-  } else {
-    int nCopied = StretchDIBits(dc,
-                                x, y,  // Destination origin.
-                                src_size_x, src_size_y,
-                                0, 0,  // Source origin.
-                                src_size_x, src_size_y,  // Source size.
-                                pixels,
-                                reinterpret_cast<const BITMAPINFO*>(&hdr),
-                                DIB_RGB_COLORS,
-                                SRCCOPY);
-  }
-  EndPlatformPaint();
-  Cleanup();
-}
-
-}  // namespace skia
diff --git a/skia/ext/vector_platform_device_emf_win.h b/skia/ext/vector_platform_device_emf_win.h
deleted file mode 100644
index 81b92af..0000000
--- a/skia/ext/vector_platform_device_emf_win.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// 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.
-
-#ifndef SKIA_EXT_VECTOR_PLATFORM_DEVICE_EMF_WIN_H_
-#define SKIA_EXT_VECTOR_PLATFORM_DEVICE_EMF_WIN_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "skia/ext/platform_device.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-#include "third_party/skia/include/core/SkRegion.h"
-
-namespace skia {
-
-// A device is basically a wrapper around SkBitmap that provides a surface for
-// SkCanvas to draw into. This specific device is not not backed by a surface
-// and is thus unreadable. This is because the backend is completely vectorial.
-// This device is a simple wrapper over a Windows device context (HDC) handle.
-// TODO(robertphillips): Once Skia's SkBaseDevice is refactored to remove
-// the bitmap-specific entry points, this class should derive from it.
-class VectorPlatformDeviceEmf : public SkBitmapDevice, public PlatformDevice {
- public:
-  SK_API static SkBaseDevice* CreateDevice(int width, int height, bool isOpaque,
-                                           HANDLE shared_section);
-
-  // Factory function. The DC is kept as the output context.
-  static SkBaseDevice* create(HDC dc, int width, int height);
-
-  VectorPlatformDeviceEmf(HDC dc, const SkBitmap& bitmap);
-  virtual ~VectorPlatformDeviceEmf();
-
-  // PlatformDevice methods
-  virtual PlatformSurface BeginPlatformPaint() override;
-
-  // SkBaseDevice methods.
-  virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) override;
-  virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
-                          size_t count, const SkPoint[],
-                          const SkPaint& paint) override;
-  virtual void drawRect(const SkDraw& draw, const SkRect& r,
-                        const SkPaint& paint) override;
-  virtual void drawRRect(const SkDraw&, const SkRRect& rr,
-                         const SkPaint& paint) override;
-  virtual void drawPath(const SkDraw& draw, const SkPath& path,
-                        const SkPaint& paint,
-                        const SkMatrix* prePathMatrix = NULL,
-                        bool pathIsMutable = false) override;
-  virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
-                              const SkRect* src, const SkRect& dst,
-                              const SkPaint& paint,
-                              SkCanvas::DrawBitmapRectFlags flags) override;
-  virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
-                          const SkMatrix& matrix,
-                          const SkPaint& paint) override;
-  virtual void drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
-                          int x, int y, const SkPaint& paint) override;
-  virtual void drawText(const SkDraw& draw, const void* text, size_t len,
-                        SkScalar x, SkScalar y, const SkPaint& paint) override;
-  virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
-                           const SkScalar pos[], int scalarsPerPos,
-                           const SkPoint& offset, const SkPaint& paint) override;
-  virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
-                              const SkPath& path, const SkMatrix* matrix,
-                              const SkPaint& paint) override;
-  virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode,
-                            int vertexCount,
-                            const SkPoint verts[], const SkPoint texs[],
-                            const SkColor colors[], SkXfermode* xmode,
-                            const uint16_t indices[], int indexCount,
-                            const SkPaint& paint) override;
-  virtual void drawDevice(const SkDraw& draw, SkBaseDevice*, int x, int y,
-                          const SkPaint&) override;
-
-  virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region,
-                             const SkClipStack&) override;
-
-  void LoadClipRegion();
-
- protected:
-  virtual SkBaseDevice* onCreateCompatibleDevice(const CreateInfo& info) override;
-
- private:
-  // Applies the SkPaint's painting properties in the current GDI context, if
-  // possible. If GDI can't support all paint's properties, returns false. It
-  // doesn't execute the "commands" in SkPaint.
-  bool ApplyPaint(const SkPaint& paint);
-
-  // Selects a new object in the device context. It can be a pen, a brush, a
-  // clipping region, a bitmap or a font. Returns the old selected object.
-  HGDIOBJ SelectObject(HGDIOBJ object);
-
-  // Creates a brush according to SkPaint's properties.
-  bool CreateBrush(bool use_brush, const SkPaint& paint);
-
-  // Creates a pen according to SkPaint's properties.
-  bool CreatePen(bool use_pen, const SkPaint& paint);
-
-  // Restores back the previous objects (pen, brush, etc) after a paint command.
-  void Cleanup();
-
-  // Creates a brush according to SkPaint's properties.
-  bool CreateBrush(bool use_brush, COLORREF color);
-
-  // Creates a pen according to SkPaint's properties.
-  bool CreatePen(bool use_pen, COLORREF color, int stroke_width,
-                 float stroke_miter, DWORD pen_style);
-
-  // Draws a bitmap in the the device, using the currently loaded matrix.
-  void InternalDrawBitmap(const SkBitmap& bitmap, int x, int y,
-                          const SkPaint& paint);
-
-  // The Windows Device Context handle. It is the backend used with GDI drawing.
-  // This backend is write-only and vectorial.
-  HDC hdc_;
-
-  // Translation assigned to the DC: we need to keep track of this separately
-  // so it can be updated even if the DC isn't created yet.
-  SkMatrix transform_;
-
-  // The current clipping
-  SkRegion clip_region_;
-
-  // Previously selected brush before the current drawing.
-  HGDIOBJ previous_brush_;
-
-  // Previously selected pen before the current drawing.
-  HGDIOBJ previous_pen_;
-
-  DISALLOW_COPY_AND_ASSIGN(VectorPlatformDeviceEmf);
-};
-
-typedef void (*SkiaEnsureTypefaceCharactersAccessible)
-    (const LOGFONT& font, const wchar_t* text, unsigned int text_length);
-
-SK_API void SetSkiaEnsureTypefaceCharactersAccessible(
-    SkiaEnsureTypefaceCharactersAccessible func);
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_VECTOR_PLATFORM_DEVICE_EMF_WIN_H_
diff --git a/skia/skia_chrome.gypi b/skia/skia_chrome.gypi
index 6a24635..d689a92 100644
--- a/skia/skia_chrome.gypi
+++ b/skia/skia_chrome.gypi
@@ -77,9 +77,6 @@
     'ext/skia_utils_mac.h',
     'ext/skia_utils_win.cc',
     'ext/skia_utils_win.h',
-    'ext/vector_canvas.h',
-    'ext/vector_platform_device_emf_win.cc',
-    'ext/vector_platform_device_emf_win.h',
   ],
   'conditions': [
     [ 'OS == "android" and '
diff --git a/skia/skia_tests.gyp b/skia/skia_tests.gyp
index fcc7347..698493d 100644
--- a/skia/skia_tests.gyp
+++ b/skia/skia_tests.gyp
@@ -29,14 +29,8 @@
         'ext/refptr_unittest.cc',
         'ext/skia_utils_ios_unittest.mm',
         'ext/skia_utils_mac_unittest.mm',
-        'ext/vector_canvas_unittest.cc',
       ],
       'conditions': [
-        ['OS != "win"', {
-          'sources!': [
-            'ext/vector_canvas_unittest.cc',
-          ],
-        }],
         ['OS != "win" and OS != "mac"', {
           'sources!': [
             'ext/platform_canvas_unittest.cc',
diff --git a/sky/compositor/layer.cc b/sky/compositor/layer.cc
index 006206d..5c05fdf 100644
--- a/sky/compositor/layer.cc
+++ b/sky/compositor/layer.cc
@@ -4,7 +4,7 @@
 
 #include "sky/compositor/layer.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "sky/compositor/layer_host.h"
 #include "sky/compositor/picture_serializer.h"
 #include "sky/compositor/rasterizer.h"
diff --git a/sky/compositor/layer_host.cc b/sky/compositor/layer_host.cc
index 697ed26..bf46618 100644
--- a/sky/compositor/layer_host.cc
+++ b/sky/compositor/layer_host.cc
@@ -4,8 +4,8 @@
 
 #include "sky/compositor/layer_host.h"
 
-#include "base/debug/trace_event.h"
 #include "base/message_loop/message_loop.h"
+#include "base/trace_event/trace_event.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "mojo/gpu/gl_context.h"
 #include "mojo/services/surfaces/public/cpp/surfaces_utils.h"
diff --git a/sky/compositor/rasterizer_ganesh.cc b/sky/compositor/rasterizer_ganesh.cc
index d91749e..46ac59b 100644
--- a/sky/compositor/rasterizer_ganesh.cc
+++ b/sky/compositor/rasterizer_ganesh.cc
@@ -4,7 +4,7 @@
 
 #include "sky/compositor/rasterizer_ganesh.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "mojo/skia/ganesh_surface.h"
 #include "sky/compositor/layer_host.h"
 #include "third_party/skia/include/core/SkCanvas.h"
diff --git a/sky/engine/platform/SharedTimer.cpp b/sky/engine/platform/SharedTimer.cpp
index 90312a1..8debac0 100644
--- a/sky/engine/platform/SharedTimer.cpp
+++ b/sky/engine/platform/SharedTimer.cpp
@@ -5,6 +5,7 @@
 #include "sky/engine/config.h"
 #include "sky/engine/platform/SharedTimer.h"
 
+#include <cmath>
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "sky/engine/wtf/CurrentTime.h"
diff --git a/sky/engine/platform/TraceEvent.h b/sky/engine/platform/TraceEvent.h
index bd0c344..d0d23a5 100644
--- a/sky/engine/platform/TraceEvent.h
+++ b/sky/engine/platform/TraceEvent.h
@@ -2,4 +2,4 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
diff --git a/sky/engine/platform/network/ResourceResponse.cpp b/sky/engine/platform/network/ResourceResponse.cpp
index 200e583..2614e1d 100644
--- a/sky/engine/platform/network/ResourceResponse.cpp
+++ b/sky/engine/platform/network/ResourceResponse.cpp
@@ -27,6 +27,7 @@
 #include "sky/engine/config.h"
 #include "sky/engine/platform/network/ResourceResponse.h"
 
+#include <cmath>
 #include "sky/engine/wtf/CurrentTime.h"
 #include "sky/engine/wtf/StdLibExtras.h"
 
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 01d893f..b5fc002 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -743,6 +743,9 @@
       "ppapi_unittests",
       "printing_unittests",
       "remoting_unittests",
+      "sbox_unittests",
+      "sbox_integration_tests",
+      "sbox_validation_tests",
       "ipc_tests",
       "sync_unit_tests",
       "skia_unittests",
@@ -791,6 +794,9 @@
       "ppapi_unittests",
       "printing_unittests",
       "remoting_unittests",
+      "sbox_unittests",
+      "sbox_integration_tests",
+      "sbox_validation_tests",
       "ipc_tests",
       "sync_unit_tests",
       "skia_unittests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index c9059e7..55e5481 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -101,6 +101,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
@@ -245,6 +246,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
@@ -389,6 +391,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
@@ -534,6 +537,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json
index 7244be8..3d5b728 100644
--- a/testing/buildbot/chromium.memory.fyi.json
+++ b/testing/buildbot/chromium.memory.fyi.json
@@ -4,7 +4,12 @@
       "accessibility_unittests",
       "app_list_unittests",
       "aura_unittests",
-      "base_unittests",
+      {
+        "test": "base_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
       "cacheinvalidation_unittests",
       "cast_unittests",
       "cc_unittests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 452fc51..c462aaf 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -92,6 +92,7 @@
           "can_use_on_swarming_builders": true
         }
       },
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
@@ -233,6 +234,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
@@ -382,6 +384,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
@@ -535,6 +538,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
@@ -681,6 +685,7 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
+      "nacl_loader_unittests",
       {
         "test": "net_unittests",
         "swarming": {
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json
index c5e51b6..c2d7e72 100644
--- a/testing/buildbot/chromium_trybot.json
+++ b/testing/buildbot/chromium_trybot.json
@@ -174,10 +174,7 @@
     "mojo_public_system_unittests",
     "mojo_public_utility_unittests",
     "mojo_system_unittests",
-    {
-      "test": "nacl_loader_unittests",
-      "platforms": ["linux"]
-    },
+    "nacl_loader_unittests",
     {
       "test": "net_unittests",
       "swarming": {
diff --git a/testing/gtest.gyp b/testing/gtest.gyp
index c4510f6..d61772e 100644
--- a/testing/gtest.gyp
+++ b/testing/gtest.gyp
@@ -39,6 +39,7 @@
           'sources': [
             'gtest_mac.h',
             'gtest_mac.mm',
+            'platform_test_mac.mm',
           ],
           'link_settings': {
             'libraries': [
@@ -46,11 +47,6 @@
             ],
           },
         }],
-        ['OS == "mac"', {
-          'sources': [
-            'platform_test_mac.mm',
-          ],
-        }],
         ['OS == "ios"', {
           'dependencies' : [
             '<(DEPTH)/testing/iossim/iossim.gyp:iossim#host',
@@ -85,7 +81,6 @@
           'sources': [
             'coverage_util_ios.cc',
             'coverage_util_ios.h',
-            'platform_test_ios.mm',
           ],
         }],
         ['OS=="ios" and asan==1', {
diff --git a/testing/legion/__init__.py b/testing/legion/__init__.py
new file mode 100644
index 0000000..50b23df
--- /dev/null
+++ b/testing/legion/__init__.py
@@ -0,0 +1,3 @@
+# 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.
diff --git a/testing/legion/client_controller.py b/testing/legion/client_controller.py
new file mode 100755
index 0000000..dd80c29
--- /dev/null
+++ b/testing/legion/client_controller.py
@@ -0,0 +1,51 @@
+#!/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.
+
+"""The main client_controller code.
+
+This code is the main entry point for the client machines and handles
+registering with the host server and running the local RPC server.
+"""
+
+import argparse
+import logging
+import socket
+import sys
+import time
+
+#pylint: disable=relative-import
+import client_rpc_server
+import common_lib
+
+
+def main():
+  print ' '.join(sys.argv)
+  common_lib.InitLogging()
+  logging.info('Client controller starting')
+
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--otp',
+                      help='One time token used to authenticate with the host')
+  parser.add_argument('--host',
+                      help='The ip address of the host')
+  parser.add_argument('--idle-timeout', type=int,
+                      default=common_lib.DEFAULT_TIMEOUT_SECS,
+                      help='The idle timeout for the rpc server in seconds')
+  args, _ = parser.parse_known_args()
+
+  logging.info(
+      'Registering with discovery server at %s using OTP %s', args.host,
+      args.otp)
+  server = common_lib.ConnectToServer(args.host).RegisterClient(
+      args.otp, common_lib.MY_IP)
+
+  server = client_rpc_server.RPCServer(args.host, args.idle_timeout)
+
+  server.serve_forever()
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/testing/legion/client_lib.py b/testing/legion/client_lib.py
new file mode 100644
index 0000000..4d6a633
--- /dev/null
+++ b/testing/legion/client_lib.py
@@ -0,0 +1,214 @@
+# 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 the client library."""
+
+import argparse
+import datetime
+import logging
+import os
+import socket
+import subprocess
+import sys
+import tempfile
+import threading
+import xmlrpclib
+
+#pylint: disable=relative-import
+import common_lib
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+SWARMING_DIR = os.path.join(THIS_DIR, '..', '..', 'tools/swarming_client')
+ISOLATE_PY = os.path.join(SWARMING_DIR, 'isolate.py')
+SWARMING_PY = os.path.join(SWARMING_DIR, 'swarming.py')
+
+
+class Error(Exception):
+  pass
+
+
+class ConnectionTimeoutError(Error):
+  pass
+
+
+class ClientController(object):
+  """Creates, configures, and controls a client machine."""
+
+  _client_count = 0
+  _controllers = []
+
+  def __init__(self, isolate_file, config_vars, dimensions, priority=100,
+               idle_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS,
+               connection_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS,
+               verbosity='ERROR', name=None):
+    assert isinstance(config_vars, dict)
+    assert isinstance(dimensions, dict)
+    type(self)._controllers.append(self)
+    type(self)._client_count += 1
+    self.verbosity = verbosity
+    self._name = name or 'Client%d' % type(self)._client_count
+    self._priority = priority
+    self._isolate_file = isolate_file
+    self._isolated_file = isolate_file + 'd'
+    self._idle_timeout_secs = idle_timeout_secs
+    self._config_vars = config_vars
+    self._dimensions = dimensions
+    self._connect_event = threading.Event()
+    self._connected = False
+    self._ip_address = None
+    self._otp = self._CreateOTP()
+    self._rpc = None
+
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--isolate-server')
+    parser.add_argument('--swarming-server')
+    parser.add_argument('--client-connection-timeout-secs',
+                        default=common_lib.DEFAULT_TIMEOUT_SECS)
+    args, _ = parser.parse_known_args()
+
+    self._isolate_server = args.isolate_server
+    self._swarming_server = args.swarming_server
+    self._connection_timeout_secs = (connection_timeout_secs or
+                                    args.client_connection_timeout_secs)
+
+  @property
+  def name(self):
+    return self._name
+
+  @property
+  def otp(self):
+    return self._otp
+
+  @property
+  def connected(self):
+    return self._connected
+
+  @property
+  def connect_event(self):
+    return self._connect_event
+
+  @property
+  def rpc(self):
+    return self._rpc
+
+  @property
+  def verbosity(self):
+    return self._verbosity
+
+  @verbosity.setter
+  def verbosity(self, level):
+    """Sets the verbosity level as a string.
+
+    Either a string ('INFO', 'DEBUG', etc) or a logging level (logging.INFO,
+    logging.DEBUG, etc) is allowed.
+    """
+    assert isinstance(level, (str, int))
+    if isinstance(level, int):
+      level = logging.getLevelName(level)
+    self._verbosity = level  #pylint: disable=attribute-defined-outside-init
+
+  @classmethod
+  def ReleaseAllControllers(cls):
+    for controller in cls._controllers:
+      controller.Release()
+
+  def _CreateOTP(self):
+    """Creates the OTP."""
+    host_name = socket.gethostname()
+    test_name = os.path.basename(sys.argv[0])
+    creation_time = datetime.datetime.utcnow()
+    otp = 'client:%s-host:%s-test:%s-creation:%s' % (
+        self._name, host_name, test_name, creation_time)
+    return otp
+
+  def Create(self):
+    """Creates the client machine."""
+    logging.info('Creating %s', self.name)
+    self._connect_event.clear()
+    self._ExecuteIsolate()
+    self._ExecuteSwarming()
+
+  def WaitForConnection(self):
+    """Waits for the client machine to connect.
+
+    Raises:
+      ConnectionTimeoutError if the client doesn't connect in time.
+    """
+    logging.info('Waiting for %s to connect with a timeout of %d seconds',
+                 self._name, self._connection_timeout_secs)
+    self._connect_event.wait(self._connection_timeout_secs)
+    if not self._connect_event.is_set():
+      raise ConnectionTimeoutError('%s failed to connect' % self.name)
+
+  def Release(self):
+    """Quits the client's RPC server so it can release the machine."""
+    if self._rpc is not None and self._connected:
+      logging.info('Releasing %s', self._name)
+      try:
+        self._rpc.Quit()
+      except (socket.error, xmlrpclib.Fault):
+        logging.error('Unable to connect to %s to call Quit', self.name)
+      self._rpc = None
+      self._connected = False
+
+  def _ExecuteIsolate(self):
+    """Executes isolate.py."""
+    cmd = [
+        'python',
+        ISOLATE_PY,
+        'archive',
+        '--isolate', self._isolate_file,
+        '--isolated', self._isolated_file,
+        ]
+
+    if self._isolate_server:
+      cmd.extend(['--isolate-server', self._isolate_server])
+    for key, value in self._config_vars.iteritems():
+      cmd.extend(['--config-var', key, value])
+
+    self._ExecuteProcess(cmd)
+
+  def _ExecuteSwarming(self):
+    """Executes swarming.py."""
+    cmd = [
+        'python',
+        SWARMING_PY,
+        'trigger',
+        self._isolated_file,
+        '--priority', str(self._priority),
+        ]
+
+    if self._isolate_server:
+      cmd.extend(['--isolate-server', self._isolate_server])
+    if self._swarming_server:
+      cmd.extend(['--swarming', self._swarming_server])
+    for key, value in self._dimensions.iteritems():
+      cmd.extend(['--dimension', key, value])
+
+    cmd.extend([
+        '--',
+        '--host', common_lib.MY_IP,
+        '--otp', self._otp,
+        '--verbosity', self._verbosity,
+        '--idle-timeout', str(self._idle_timeout_secs),
+        ])
+
+    self._ExecuteProcess(cmd)
+
+  def _ExecuteProcess(self, cmd):
+    """Executes a process, waits for it to complete, and checks for success."""
+    logging.debug('Running %s', ' '.join(cmd))
+    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    _, stderr = p.communicate()
+    if p.returncode != 0:
+      stderr.seek(0)
+      raise Error(stderr)
+
+  def OnConnect(self, ip_address):
+    """Receives client ip address on connection."""
+    self._ip_address = ip_address
+    self._connected = True
+    self._rpc = common_lib.ConnectToServer(self._ip_address)
+    logging.info('%s connected from %s', self._name, ip_address)
+    self._connect_event.set()
diff --git a/testing/legion/client_rpc_methods.py b/testing/legion/client_rpc_methods.py
new file mode 100644
index 0000000..24a552e
--- /dev/null
+++ b/testing/legion/client_rpc_methods.py
@@ -0,0 +1,42 @@
+# 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 the client RPC methods."""
+
+import logging
+import subprocess
+import threading
+
+
+class RPCMethods(object):
+  """Class exposing RPC methods."""
+
+  def __init__(self, server):
+    self.server = server
+
+  def Echo(self, message):
+    """Simple RPC method to print and return a message."""
+    logging.info('Echoing %s', message)
+    return 'echo %s' % str(message)
+
+  def Subprocess(self, cmd):
+    """Run the commands in a subprocess.
+
+    Returns:
+      (returncode, stdout, stderr).
+    """
+    p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE)
+    stdout, stderr = p.communicate()
+    return (p.returncode, stdout, stderr)
+
+  def Quit(self):
+    """Call server.shutdown in another thread.
+
+    This is needed because server.shutdown waits for the server to actually
+    quit. However the server cannot shutdown until it completes handling this
+    call. Calling this in the same thread results in a deadlock.
+    """
+    t = threading.Thread(target=self.server.shutdown)
+    t.start()
diff --git a/testing/legion/client_rpc_server.py b/testing/legion/client_rpc_server.py
new file mode 100644
index 0000000..7a5f565
--- /dev/null
+++ b/testing/legion/client_rpc_server.py
@@ -0,0 +1,128 @@
+# 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.
+
+"""The client RPC server code.
+
+This server is an XML-RPC server which serves code from
+client_rpc_methods.RPCMethods.
+
+This server will run until shutdown is called on the server object. This can
+be achieved in 2 ways:
+
+- Calling the Quit RPC method defined in RPCMethods
+- Not receiving any calls within the idle_timeout_secs time.
+"""
+
+import logging
+import threading
+import time
+import xmlrpclib
+import SimpleXMLRPCServer
+import SocketServer
+
+#pylint: disable=relative-import
+import client_rpc_methods
+import common_lib
+
+
+class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+  """Restricts access to only specified IP address.
+
+  This call assumes the server is RPCServer.
+  """
+
+  def do_POST(self):
+    """Verifies the client is authorized to perform RPCs."""
+    if self.client_address[0] != self.server.authorized_address:
+      logging.error('Received unauthorized RPC request from %s',
+                    self.client_address[0])
+      self.send_response(403)
+      response = 'Forbidden'
+      self.send_header('Content-type', 'text/plain')
+      self.send_header('Content-length', str(len(response)))
+      self.end_headers()
+      self.wfile.write(response)
+    else:
+      return SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self)
+
+
+class RPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer,
+                SocketServer.ThreadingMixIn):
+  """Restricts all endpoints to only specified IP addresses."""
+
+  def __init__(self, authorized_address,
+               idle_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS):
+    SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(
+        self, (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT),
+        allow_none=True, logRequests=False,
+        requestHandler=RequestHandler)
+
+    self.authorized_address = authorized_address
+    self.idle_timeout_secs = idle_timeout_secs
+    self.register_instance(client_rpc_methods.RPCMethods(self))
+
+    self._shutdown_requested_event = threading.Event()
+    self._rpc_received_event = threading.Event()
+    self._idle_thread = threading.Thread(target=self._CheckForIdleQuit)
+
+  def shutdown(self):
+    """Shutdown the server.
+
+    This overloaded method sets the _shutdown_requested_event to allow the
+    idle timeout thread to quit.
+    """
+    self._shutdown_requested_event.set()
+    SimpleXMLRPCServer.SimpleXMLRPCServer.shutdown(self)
+    logging.info('Server shutdown complete')
+
+  def serve_forever(self, poll_interval=0.5):
+    """Serve forever.
+
+    This overloaded method starts the idle timeout thread before calling
+    serve_forever. This ensures the idle timer thread doesn't get started
+    without the server running.
+
+    Args:
+      poll_interval: The interval to poll for shutdown.
+    """
+    logging.info('RPC server starting')
+    self._idle_thread.start()
+    SimpleXMLRPCServer.SimpleXMLRPCServer.serve_forever(self, poll_interval)
+
+  def _dispatch(self, method, params):
+    """Dispatch the call to the correct method with the provided params.
+
+    This overloaded method adds logging to help trace connection and
+    call problems.
+
+    Args:
+      method: The method name to call.
+      params: A tuple of parameters to pass.
+
+    Returns:
+      The result of the parent class' _dispatch method.
+    """
+    logging.debug('Calling %s%s', method, params)
+    self._rpc_received_event.set()
+    return SimpleXMLRPCServer.SimpleXMLRPCServer._dispatch(self, method, params)
+
+  def _CheckForIdleQuit(self):
+    """Check for, and exit, if the server is idle for too long.
+
+    This method must be run in a separate thread to avoid a deadlock when
+    calling server.shutdown.
+    """
+    timeout = time.time() + self.idle_timeout_secs
+    while time.time() < timeout:
+      if self._shutdown_requested_event.is_set():
+        # An external source called shutdown()
+        return
+      elif self._rpc_received_event.is_set():
+        logging.debug('Resetting the idle timeout')
+        timeout = time.time() + self.idle_timeout_secs
+        self._rpc_received_event.clear()
+      time.sleep(1)
+    # We timed out, kill the server
+    logging.warning('Shutting down the server due to the idle timeout')
+    self.shutdown()
diff --git a/testing/legion/common_lib.py b/testing/legion/common_lib.py
new file mode 100644
index 0000000..b66481e
--- /dev/null
+++ b/testing/legion/common_lib.py
@@ -0,0 +1,40 @@
+# 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.
+
+"""Common library methods used by both host and client controllers."""
+
+import argparse
+import logging
+import socket
+import xmlrpclib
+
+LOGGING_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'WARN', 'ERROR']
+MY_IP = socket.gethostbyname(socket.gethostname())
+SERVER_ADDRESS = ''
+SERVER_PORT = 31710
+DEFAULT_TIMEOUT_SECS = 20 * 60  # 30 minutes
+
+
+def InitLogging():
+  """Initialize the logging module.
+
+  Raises:
+    argparse.ArgumentError if the --verbosity arg is incorrect.
+  """
+  parser = argparse.ArgumentParser()
+  logging_action = parser.add_argument('--verbosity', default='ERROR')
+  args, _ = parser.parse_known_args()
+  if args.verbosity not in LOGGING_LEVELS:
+    raise argparse.ArgumentError(
+        logging_action, 'Only levels %s supported' % str(LOGGING_LEVELS))
+  logging.basicConfig(
+      format='%(asctime)s %(filename)s:%(lineno)s %(levelname)s] %(message)s',
+      datefmt='%H:%M:%S', level=args.verbosity)
+
+
+def ConnectToServer(server):
+  """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)
diff --git a/testing/legion/discovery_server.py b/testing/legion/discovery_server.py
new file mode 100644
index 0000000..94786ce
--- /dev/null
+++ b/testing/legion/discovery_server.py
@@ -0,0 +1,55 @@
+# 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.
+
+"""The discovery server used to register clients.
+
+The discovery server is started by the host controller and allows the clients
+to register themselves when they start. Authentication of the client controllers
+is based on an OTP passed to the client controller binary on startup.
+"""
+
+import logging
+import threading
+import xmlrpclib
+import SimpleXMLRPCServer
+
+#pylint: disable=relative-import
+import common_lib
+
+
+class DiscoveryServer(object):
+  """Discovery server run on the host."""
+
+  def __init__(self):
+    self._expected_clients = {}
+    self._rpc_server = None
+    self._thread = None
+
+  def _RegisterClientRPC(self, otp, ip):
+    """The RPC used by a client to register with the discovery server."""
+    assert otp in self._expected_clients
+    cb = self._expected_clients.pop(otp)
+    cb(ip)
+
+  def RegisterClientCallback(self, otp, callback):
+    """Registers a callback associated with an OTP."""
+    assert callable(callback)
+    self._expected_clients[otp] = callback
+
+  def Start(self):
+    """Starts the discovery server."""
+    logging.debug('Starting discovery server')
+    self._rpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer(
+        (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT),
+        allow_none=True, logRequests=False)
+    self._rpc_server.register_function(
+        self._RegisterClientRPC, 'RegisterClient')
+    self._thread = threading.Thread(target=self._rpc_server.serve_forever)
+    self._thread.start()
+
+  def Shutdown(self):
+    """Shuts the discovery server down."""
+    if self._thread and self._thread.is_alive():
+      logging.debug('Shutting down discovery server')
+      self._rpc_server.shutdown()
diff --git a/testing/legion/examples/hello_world/client_test.isolate b/testing/legion/examples/hello_world/client_test.isolate
new file mode 100644
index 0000000..7135ef2
--- /dev/null
+++ b/testing/legion/examples/hello_world/client_test.isolate
@@ -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.
+
+{
+  'includes': [
+    '../../legion.isolate'
+  ],
+  'conditions': [
+    ['multi_machine == 1', {
+      'variables': {
+        'command': [
+          'python',
+          '../../client_controller.py',
+        ],
+        'files': [
+          'client_test.py',
+          'client_test.isolate'
+        ],
+      },
+    }],
+  ],
+}
diff --git a/testing/legion/examples/hello_world/client_test.py b/testing/legion/examples/hello_world/client_test.py
new file mode 100755
index 0000000..0333f7b
--- /dev/null
+++ b/testing/legion/examples/hello_world/client_test.py
@@ -0,0 +1,27 @@
+#!/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.
+
+"""A simple client test module.
+
+This module is invoked by the host by calling the client controller's
+Subprocess RPC method. The name is passed in as a required argument on the
+command line.
+"""
+
+import argparse
+import os
+import sys
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('name')
+  args = parser.parse_args()
+  print 'Hello world from', args.name
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/testing/legion/examples/hello_world/host_test.isolate b/testing/legion/examples/hello_world/host_test.isolate
new file mode 100644
index 0000000..da4ee4e
--- /dev/null
+++ b/testing/legion/examples/hello_world/host_test.isolate
@@ -0,0 +1,22 @@
+# 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.
+
+{
+  'includes': [
+    '../../legion.isolate',
+    'client_test.isolate'
+  ],
+  'conditions': [
+    ['multi_machine == 1', {
+      'variables': {
+        'command': [
+          'host_test.py',
+        ],
+        'files': [
+          'host_test.py',
+        ],
+      },
+    }],
+  ]
+}
diff --git a/testing/legion/examples/hello_world/host_test.py b/testing/legion/examples/hello_world/host_test.py
new file mode 100755
index 0000000..77eca06
--- /dev/null
+++ b/testing/legion/examples/hello_world/host_test.py
@@ -0,0 +1,74 @@
+#!/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.
+
+"""A simple host test module.
+
+This module runs on the host machine and is responsible for creating 2
+client 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 logging
+import time
+
+import host_controller
+
+
+class ExampleController(host_controller.HostController):
+  """A simple example controller for a test."""
+
+  def __init__(self):
+    super(ExampleController, self).__init__()
+    self.client1 = None
+    self.client2 = None
+
+  def CreateClient(self):
+    """Create a client object and set the proper values."""
+    client = self.NewClient(
+        isolate_file='client_test.isolate',
+        config_vars={'multi_machine': '1'},
+        dimensions={'os': 'Linux', 'pool': 'legion'}, priority=200,
+        idle_timeout_secs=90, connection_timeout_secs=90,
+        verbosity=logging.INFO)
+    client.Create()
+    return client
+
+  def SetUp(self):
+    """Create the client machines and wait until they connect.
+
+    In this call the actual creation of the client machines is done in parallel
+    by the system. The WaitForConnect calls are performed in series but will
+    return as soon as the clients connect.
+    """
+    self.client1 = self.CreateClient()
+    self.client2 = self.CreateClient()
+    self.client1.WaitForConnection()
+    self.client2.WaitForConnection()
+
+  def Task(self):
+    """Main method to run the task code."""
+    self.CallEcho(self.client1)
+    self.CallEcho(self.client2)
+    self.CallClientTest(self.client1)
+    self.CallClientTest(self.client2)
+
+  def CallEcho(self, client):
+    """Call rpc.Echo on a client."""
+    logging.info('Calling Echo on %s', client.name)
+    logging.info(self.client1.rpc.Echo(client.name))
+
+  def CallClientTest(self, client):
+    """Call client_test.py name on a client."""
+    logging.info('Calling Subprocess to run "./client_test.py %s"', client.name)
+    retcode, stdout, stderr = client.rpc.Subprocess(
+        ['./client_test.py', client.name])
+    logging.info('retcode: %s, stdout: %s, stderr: %s', retcode, stdout, stderr)
+
+
+if __name__ == '__main__':
+  ExampleController().RunController()
diff --git a/testing/legion/host_controller.py b/testing/legion/host_controller.py
new file mode 100644
index 0000000..dadcba4
--- /dev/null
+++ b/testing/legion/host_controller.py
@@ -0,0 +1,70 @@
+# 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 the host controller base library.
+
+This module is the basis on which host controllers are built and executed.
+"""
+
+import logging
+import sys
+
+#pylint: disable=relative-import
+import client_lib
+import common_lib
+import discovery_server
+
+
+class HostController(object):
+  """The base host controller class."""
+
+  def __init__(self):
+    self._discovery_server = discovery_server.DiscoveryServer()
+
+  def SetUp(self):
+    """Setup method used by the subclass."""
+    pass
+
+  def Task(self):
+    """Main task method used by the subclass."""
+    pass
+
+  def TearDown(self):
+    """Teardown method used by the subclass."""
+    pass
+
+  def NewClient(self, *args, **kwargs):
+    controller = client_lib.ClientController(*args, **kwargs)
+    self._discovery_server.RegisterClientCallback(
+        controller.otp, controller.OnConnect)
+    return controller
+
+  def RunController(self):
+    """Main entry point for the controller."""
+    print ' '.join(sys.argv)
+    common_lib.InitLogging()
+    self._discovery_server.Start()
+
+    error = None
+    tb = None
+    try:
+      self.SetUp()
+      self.Task()
+    except Exception as e:
+      # Defer raising exceptions until after TearDown and _TearDown are called.
+      error = e
+      tb = sys.exc_info()[-1]
+    try:
+      self.TearDown()
+    except Exception as e:
+      # Defer raising exceptions until after _TearDown is called.
+      # Note that an error raised here will obscure any errors raised
+      # previously.
+      error = e
+      tb = sys.exc_info()[-1]
+
+    self._discovery_server.Shutdown()
+    client_lib.ClientController.ReleaseAllControllers()
+    if error:
+      raise error, None, tb  #pylint: disable=raising-bad-type
diff --git a/testing/legion/legion.isolate b/testing/legion/legion.isolate
new file mode 100644
index 0000000..463764d
--- /dev/null
+++ b/testing/legion/legion.isolate
@@ -0,0 +1,20 @@
+# 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.
+
+{
+  'variables': {
+    'files': [
+      '__init__.py',
+      'client_controller.py',
+      'client_lib.py',
+      'client_rpc_methods.py',
+      'client_rpc_server.py',
+      'common_lib.py',
+      'discovery_server.py',
+      'host_controller.py',
+      'legion.isolate',
+      '../../tools/swarming_client/',
+    ],
+  },
+}
diff --git a/testing/platform_test_ios.mm b/testing/platform_test_ios.mm
deleted file mode 100644
index 5162c1d..0000000
--- a/testing/platform_test_ios.mm
+++ /dev/null
@@ -1,18 +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 "platform_test.h"
-
-#import <Foundation/Foundation.h>
-
-#include "coverage_util_ios.h"
-
-PlatformTest::PlatformTest()
-    : pool_([[NSAutoreleasePool alloc] init]) {
-}
-
-PlatformTest::~PlatformTest() {
-  [pool_ release];
-  coverage_util::FlushCoverageDataIfNecessary();
-}
diff --git a/testing/test_env.py b/testing/test_env.py
index 0743f34..66a3721 100755
--- a/testing/test_env.py
+++ b/testing/test_env.py
@@ -35,7 +35,10 @@
 def trim_cmd(cmd):
   """Removes internal flags from cmd since they're just used to communicate from
   the host machine to this script running on the swarm slaves."""
-  internal_flags = frozenset(['--asan=0', '--asan=1', '--lsan=0', '--lsan=1'])
+  sanitizers = ['asan', 'lsan', 'msan', 'tsan']
+  internal_flags = frozenset('--%s=%d' % (name, value)
+                             for name in sanitizers
+                             for value in [0, 1])
   return [i for i in cmd if i not in internal_flags]
 
 
@@ -49,12 +52,12 @@
   return out
 
 
-def get_asan_env(cmd, lsan):
-  """Returns the envirnoment flags needed for ASan and LSan."""
+def get_sanitizer_env(cmd, asan, lsan, msan, tsan):
+  """Returns the envirnoment flags needed for sanitizer tools."""
 
   extra_env = {}
 
-  # Instruct GTK to use malloc while running ASan or LSan tests.
+  # Instruct GTK to use malloc while running sanitizer-instrumented tests.
   extra_env['G_SLICE'] = 'always-malloc'
 
   extra_env['NSS_DISABLE_ARENA_FREE_LIST'] = '1'
@@ -65,25 +68,12 @@
   symbolizer_path = os.path.abspath(os.path.join(ROOT_DIR, 'third_party',
       'llvm-build', 'Release+Asserts', 'bin', 'llvm-symbolizer'))
 
-  asan_options = []
-  if lsan:
-    asan_options.append('detect_leaks=1')
-    if sys.platform == 'linux2':
-      # Use the debug version of libstdc++ under LSan. If we don't, there will
-      # be a lot of incomplete stack traces in the reports.
-      extra_env['LD_LIBRARY_PATH'] = '/usr/lib/x86_64-linux-gnu/debug:'
-
+  if lsan or tsan:
     # LSan is not sandbox-compatible, so we can use online symbolization. In
     # fact, it needs symbolization to be able to apply suppressions.
     symbolization_options = ['symbolize=1',
                              'external_symbolizer_path=%s' % symbolizer_path]
-
-    suppressions_file = os.path.join(ROOT_DIR, 'tools', 'lsan',
-        'suppressions.txt')
-    lsan_options = ['suppressions=%s' % suppressions_file,
-                    'print_suppressions=1']
-    extra_env['LSAN_OPTIONS'] = ' '.join(lsan_options)
-  else:
+  elif asan or msan:
     # ASan uses a script for offline symbolization.
     # Important note: when running ASan with leak detection enabled, we must use
     # the LSan symbolization options above.
@@ -91,26 +81,57 @@
     # Set the path to llvm-symbolizer to be used by asan_symbolize.py
     extra_env['LLVM_SYMBOLIZER_PATH'] = symbolizer_path
 
-  asan_options.extend(symbolization_options)
+  if asan:
+    asan_options = symbolization_options[:]
+    if lsan:
+      asan_options.append('detect_leaks=1')
 
-  extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
+    extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
 
-  if sys.platform == 'darwin':
-    isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
-    # This is needed because the test binary has @executable_path embedded in it
-    # it that the OS tries to resolve to the cache directory and not the mapped
-    #  directory.
-    extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir)
+    if sys.platform == 'darwin':
+      isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
+      # This is needed because the test binary has @executable_path embedded in
+      # it that the OS tries to resolve to the cache directory and not the
+      # mapped directory.
+      extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir)
+
+  if lsan:
+    if asan or msan:
+      lsan_options = []
+    else:
+      lsan_options = symbolization_options[:]
+    if sys.platform == 'linux2':
+      # Use the debug version of libstdc++ under LSan. If we don't, there will
+      # be a lot of incomplete stack traces in the reports.
+      extra_env['LD_LIBRARY_PATH'] = '/usr/lib/x86_64-linux-gnu/debug:'
+
+    suppressions_file = os.path.join(ROOT_DIR, 'tools', 'lsan',
+        'suppressions.txt')
+    lsan_options += ['suppressions=%s' % suppressions_file,
+                     'print_suppressions=1']
+    extra_env['LSAN_OPTIONS'] = ' '.join(lsan_options)
+
+  if msan:
+    msan_options = symbolization_options[:]
+    if lsan:
+      msan_options.append('detect_leaks=1')
+    extra_env['MSAN_OPTIONS'] = ' '.join(msan_options)
+
+  if tsan:
+    tsan_options = symbolization_options[:]
+    extra_env['TSAN_OPTIONS'] = ' '.join(tsan_options)
 
   return extra_env
 
 
-def get_sanitizer_symbolize_command(json_path=None):
+def get_sanitizer_symbolize_command(json_path=None, executable_path=None):
   """Construct the command to invoke offline symbolization script."""
   script_path = '../tools/valgrind/asan/asan_symbolize.py'
   cmd = [sys.executable, script_path]
   if json_path is not None:
     cmd.append('--test-summary-json-file=%s' % json_path)
+  if executable_path is not None:
+    cmd.append('--executable-path=%s' % executable_path)
   return cmd
 
 
@@ -130,7 +151,8 @@
     return
 
   try:
-    symbolize_command = get_sanitizer_symbolize_command(json_path=json_path)
+    symbolize_command = get_sanitizer_symbolize_command(
+        json_path=json_path, executable_path=cmd[0])
     p = subprocess.Popen(symbolize_command, stderr=subprocess.PIPE, env=env)
     (_, stderr) = p.communicate()
   except OSError as e:
@@ -159,14 +181,15 @@
   # Copy logic from  tools/build/scripts/slave/runtest.py.
   asan = '--asan=1' in cmd
   lsan = '--lsan=1' in cmd
-  use_symbolization_script = asan and not lsan
+  msan = '--msan=1' in cmd
+  tsan = '--tsan=1' in cmd
+  use_symbolization_script = (asan or msan) and not lsan
 
-  if asan:
-    extra_env.update(get_asan_env(cmd, lsan))
-    # ASan is not yet sandbox-friendly on Windows (http://crbug.com/382867).
-    if sys.platform == 'win32':
-      cmd.append('--no-sandbox')
-  if lsan:
+  if asan or lsan or msan or tsan:
+    extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan))
+
+  if lsan or tsan:
+    # LSan and TSan are not sandbox-friendly.
     cmd.append('--no-sandbox')
 
   cmd = trim_cmd(cmd)
@@ -187,8 +210,9 @@
       # Need to pipe to the symbolizer script.
       p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE,
                             stderr=sys.stdout)
-      p2 = subprocess.Popen(get_sanitizer_symbolize_command(),
-                            env=env, stdin=p1.stdout)
+      p2 = subprocess.Popen(
+          get_sanitizer_symbolize_command(executable_path=cmd[0]),
+          env=env, stdin=p1.stdout)
       p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
       p1.wait()
       p2.wait()
diff --git a/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1 b/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
index e15eeb1..94c02d2 100644
--- a/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
+++ b/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
@@ -1 +1 @@
-fd80d8d02666517d0781d3039499b4131e5d3e4e
\ No newline at end of file
+e73c227c9cfacfc5fecaa22ee3555b90925f96c2
\ No newline at end of file
diff --git a/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1 b/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
index e2d07aa..b415234 100644
--- a/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
+++ b/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
@@ -1 +1 @@
-905e9e6eb9b0e11f0587177cfbaf9f7822736f34
\ No newline at end of file
+05497e34b29c01dd82df76d2fbdf017d4a2c4214
\ No newline at end of file
diff --git a/third_party/binutils/README.chromium b/third_party/binutils/README.chromium
index 5daa8d7..d20934b 100644
--- a/third_party/binutils/README.chromium
+++ b/third_party/binutils/README.chromium
@@ -19,5 +19,11 @@
  * ehframe-race.patch for http://crbug.com/161942 from upstream change
    https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=635aa30e3ae9735e362cfd1cda2be9f7b65b32a2
 
+ * unlock-thin.patch for http://crbug.com/453195 from upstream change
+   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=2cfbf2fece582c29df348104b28677c38a8301f4
+
+ * plugin-dso-fix.patch for http://crbug.com/453195 from upstream change
+   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
+
  * (build-all.sh|build-one.sh|upload.sh) scripts for building the binutils
    binaries and uploading them to Google storage.
diff --git a/third_party/binutils/build-all.sh b/third_party/binutils/build-all.sh
index fc00db1..a39984c 100755
--- a/third_party/binutils/build-all.sh
+++ b/third_party/binutils/build-all.sh
@@ -44,6 +44,8 @@
   (
     cd binutils-$VERSION
     patch -p1 < ../ehframe-race.patch
+    patch -p1 < ../unlock-thin.patch
+    patch -p1 < ../plugin-dso-fix.patch
   )
 fi
 
@@ -106,6 +108,10 @@
   # Copy them out of the chroot
   cp -a "$BUILDDIR/output/$ARCHNAME" "$OUTPUTDIR"
 
+  # Copy plugin header out of the chroot
+  mkdir "$OUTPUTDIR/$ARCHNAME/include"
+  cp "$BUILDDIR/binutils-$VERSION/include/plugin-api.h" "$OUTPUTDIR/$ARCHNAME/include/"
+
   # Clean up chroot
   sudo rm -rf "$BUILDDIR"
 done
diff --git a/third_party/binutils/plugin-dso-fix.patch b/third_party/binutils/plugin-dso-fix.patch
new file mode 100644
index 0000000..5589756
--- /dev/null
+++ b/third_party/binutils/plugin-dso-fix.patch
@@ -0,0 +1,97 @@
+commit 3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
+Author: Peter Collingbourne <pcc@google.com>
+Date:   Wed Feb 4 09:47:28 2015 -0800
+
+    Resolve forwarding symbols in plugins.
+    
+    2015-02-04  Peter Collingbourne  <pcc@google.com>
+    
+    	* plugin.cc (Pluginobj::get_symbol_resolution_info): Resolve
+    	forwarding symbols when computing symbol resolution info for plugins.
+
+diff --git a/gold/plugin.cc b/gold/plugin.cc
+index bde8c78..68da8e3 100644
+--- a/gold/plugin.cc
++++ b/gold/plugin.cc
+@@ -914,7 +914,8 @@ is_visible_from_outside(Symbol* lsym)
+ // Get symbol resolution info.
+ 
+ ld_plugin_status
+-Pluginobj::get_symbol_resolution_info(int nsyms,
++Pluginobj::get_symbol_resolution_info(Symbol_table* symtab,
++				      int nsyms,
+ 				      ld_plugin_symbol* syms,
+ 				      int version) const
+ {
+@@ -943,6 +944,8 @@ Pluginobj::get_symbol_resolution_info(int nsyms,
+     {
+       ld_plugin_symbol* isym = &syms[i];
+       Symbol* lsym = this->symbols_[i];
++      if (lsym->is_forwarder())
++        lsym = symtab->resolve_forwards(lsym);
+       ld_plugin_symbol_resolution res = LDPR_UNKNOWN;
+ 
+       if (lsym->is_undefined())
+@@ -1511,14 +1514,16 @@ static enum ld_plugin_status
+ get_symbols(const void* handle, int nsyms, ld_plugin_symbol* syms)
+ {
+   gold_assert(parameters->options().has_plugins());
+-  Object* obj = parameters->options().plugins()->object(
++  Plugin_manager* plugins = parameters->options().plugins();
++  Object* obj = plugins->object(
+     static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+   if (obj == NULL)
+     return LDPS_ERR;
+   Pluginobj* plugin_obj = obj->pluginobj();
+   if (plugin_obj == NULL)
+     return LDPS_ERR;
+-  return plugin_obj->get_symbol_resolution_info(nsyms, syms, 1);
++  Symbol_table* symtab = plugins->symtab();
++  return plugin_obj->get_symbol_resolution_info(symtab, nsyms, syms, 1);
+ }
+ 
+ // Version 2 of the above.  The only difference is that this version
+@@ -1528,14 +1533,16 @@ static enum ld_plugin_status
+ get_symbols_v2(const void* handle, int nsyms, ld_plugin_symbol* syms)
+ {
+   gold_assert(parameters->options().has_plugins());
+-  Object* obj = parameters->options().plugins()->object(
++  Plugin_manager* plugins = parameters->options().plugins();
++  Object* obj = plugins->object(
+     static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+   if (obj == NULL)
+     return LDPS_ERR;
+   Pluginobj* plugin_obj = obj->pluginobj();
+   if (plugin_obj == NULL)
+     return LDPS_ERR;
+-  return plugin_obj->get_symbol_resolution_info(nsyms, syms, 2);
++  Symbol_table* symtab = plugins->symtab();
++  return plugin_obj->get_symbol_resolution_info(symtab, nsyms, syms, 2);
+ }
+ 
+ // Add a new (real) input file generated by a plugin.
+diff --git a/gold/plugin.h b/gold/plugin.h
+index ef78b84..f926879 100644
+--- a/gold/plugin.h
++++ b/gold/plugin.h
+@@ -282,6 +282,10 @@ class Plugin_manager
+   input_objects() const
+   { return this->input_objects_; }
+ 
++  Symbol_table*
++  symtab()
++  { return this->symtab_; }
++
+   Layout*
+   layout()
+   { return this->layout_; }
+@@ -396,7 +400,8 @@ class Pluginobj : public Object
+ 
+   // Fill in the symbol resolution status for the given plugin symbols.
+   ld_plugin_status
+-  get_symbol_resolution_info(int nsyms,
++  get_symbol_resolution_info(Symbol_table* symtab,
++			     int nsyms,
+ 			     ld_plugin_symbol* syms,
+ 			     int version) const;
+ 
diff --git a/third_party/binutils/unlock-thin.patch b/third_party/binutils/unlock-thin.patch
new file mode 100644
index 0000000..6a4b6a7
--- /dev/null
+++ b/third_party/binutils/unlock-thin.patch
@@ -0,0 +1,129 @@
+commit 2cfbf2fece582c29df348104b28677c38a8301f4
+Author: Cary Coutant <ccoutant@google.com>
+Date:   Tue Feb 3 19:54:57 2015 -0800
+
+    Fix a file descriptor leak in gold.
+    
+    When an LTO linker plugin claims an external member of a thin archive, gold
+    does not properly unlock the file and make its file descriptor available for
+    reuse. This patch fixes the problem by modifying Archive::include_member to
+    unlock the object file via an RAII class instance, ensuring that it will be
+    unlocked no matter what path is taken through the function.
+    
+    gold/
+    	PR gold/15660
+    	* archive.cc (Thin_archive_object_unlocker): New class.
+    	(Archive::include_member): Unlock external members of thin archives.
+    	* testsuite/Makefile.am (plugin_test_1): Rename .syms files.
+    	(plugin_test_2): Likewise.
+    	(plugin_test_3): Likewise.
+    	(plugin_test_4): Likewise.
+    	(plugin_test_5): Likewise.
+    	(plugin_test_6): Likewise.
+    	(plugin_test_7): Likewise.
+    	(plugin_test_8): Likewise.
+    	(plugin_test_9): Likewise.
+    	(plugin_test_10): Likewise.
+    	(plugin_test_11): New test case.
+    	* testsuite/Makefile.in: Regenerate.
+    	* testsuite/plugin_test.c (claim_file_hook): Check for parallel .syms
+    	file to decide whether to claim file.
+    	(all_symbols_read_hook): Likewise.
+    	* testsuite/plugin_test_1.sh: Adjust expected output.
+    	* testsuite/plugin_test_2.sh: Likewise.
+    	* testsuite/plugin_test_3.sh: Likewise.
+    	* testsuite/plugin_test_6.sh: Likewise.
+    	* testsuite/plugin_test_tls.sh: Likewise.
+    	* testsuite/plugin_test_11.sh: New testcase.
+
+diff --git a/gold/archive.cc b/gold/archive.cc
+index 69107f5..6d25980 100644
+--- a/gold/archive.cc
++++ b/gold/archive.cc
+@@ -930,6 +930,32 @@ Archive::count_members()
+   return ret;
+ }
+ 
++// RAII class to ensure we unlock the object if it's a member of a
++// thin archive. We can't use Task_lock_obj in Archive::include_member
++// because the object file is already locked when it's opened by
++// get_elf_object_for_member.
++
++class Thin_archive_object_unlocker
++{
++ public:
++  Thin_archive_object_unlocker(const Task *task, Object* obj)
++    : task_(task), obj_(obj)
++  { }
++
++  ~Thin_archive_object_unlocker()
++  {
++    if (this->obj_->offset() == 0)
++      this->obj_->unlock(this->task_);
++  }
++
++ private:
++  Thin_archive_object_unlocker(const Thin_archive_object_unlocker&);
++  Thin_archive_object_unlocker& operator=(const Thin_archive_object_unlocker&);
++
++  const Task* task_;
++  Object* obj_;
++};
++
+ // Include an archive member in the link.  OFF is the file offset of
+ // the member header.  WHY is the reason we are including this member.
+ // Return true if we added the member or if we had an error, return
+@@ -978,6 +1004,10 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
+       return unconfigured ? false : true;
+     }
+ 
++  // If the object is an external member of a thin archive,
++  // unlock it when we're done here.
++  Thin_archive_object_unlocker unlocker(this->task_, obj);
++
+   if (mapfile != NULL)
+     mapfile->report_include_archive_member(obj->name(), sym, why);
+ 
+@@ -991,31 +1021,21 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
+ 
+   if (!input_objects->add_object(obj))
+     {
+-      // If this is an external member of a thin archive, unlock the
+-      // file.
+-      if (obj->offset() == 0)
+-	obj->unlock(this->task_);
+       delete obj;
++      return true;
+     }
+-  else
+-    {
+-      {
+-	if (layout->incremental_inputs() != NULL)
+-	  layout->incremental_inputs()->report_object(obj, 0, this, NULL);
+-	Read_symbols_data sd;
+-	obj->read_symbols(&sd);
+-	obj->layout(symtab, layout, &sd);
+-	obj->add_symbols(symtab, &sd, layout);
+-      }
+-
+-      // If this is an external member of a thin archive, unlock the file
+-      // for the next task.
+-      if (obj->offset() == 0)
+-        obj->unlock(this->task_);
+ 
+-      this->included_member_ = true;
+-    }
++  if (layout->incremental_inputs() != NULL)
++    layout->incremental_inputs()->report_object(obj, 0, this, NULL);
++
++  {
++    Read_symbols_data sd;
++    obj->read_symbols(&sd);
++    obj->layout(symtab, layout, &sd);
++    obj->add_symbols(symtab, &sd, layout);
++  }
+ 
++  this->included_member_ = true;
+   return true;
+ }
+ 
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi
index 2691ef8..0750678 100644
--- a/third_party/boringssl/boringssl.gypi
+++ b/third_party/boringssl/boringssl.gypi
@@ -331,6 +331,7 @@
       'linux-arm/crypto/sha/sha256-armv4.S',
       'linux-arm/crypto/sha/sha512-armv4.S',
       'src/crypto/chacha/chacha_vec_arm.S',
+      'src/crypto/cpu-arm-asm.S',
       'src/crypto/poly1305/poly1305_arm_asm.S',
     ],
     'boringssl_linux_x86_sources': [
diff --git a/third_party/boringssl/update_gypi_and_asm.py b/third_party/boringssl/update_gypi_and_asm.py
index 476e42f..db11e64 100644
--- a/third_party/boringssl/update_gypi_and_asm.py
+++ b/third_party/boringssl/update_gypi_and_asm.py
@@ -29,6 +29,7 @@
     ('linux', 'arm'): [
         'src/crypto/poly1305/poly1305_arm_asm.S',
         'src/crypto/chacha/chacha_vec_arm.S',
+        'src/crypto/cpu-arm-asm.S',
     ],
 }
 
diff --git a/third_party/libevent/README.chromium b/third_party/libevent/README.chromium
index be4fee3..a3e5c6e 100644
--- a/third_party/libevent/README.chromium
+++ b/third_party/libevent/README.chromium
@@ -23,3 +23,4 @@
    nacl_nonsfi/event-config.h are derived from linux/ counterparts.
    nacl_nonsfi/random.c is also added to provide the random() function,
    which is missing in the newlib-based PNaCl toolchain.
+8) Apply https://github.com/libevent/libevent/commit/ea6b1df
diff --git a/third_party/libevent/evdns.c b/third_party/libevent/evdns.c
index da6ea19..6fa971c 100644
--- a/third_party/libevent/evdns.c
+++ b/third_party/libevent/evdns.c
@@ -55,7 +55,9 @@
 #endif
 
 /* #define _POSIX_C_SOURCE 200507 */
+#if !defined(_GNU_SOURCE)
 #define _GNU_SOURCE
+#endif
 
 #ifdef DNS_USE_CPU_CLOCK_FOR_ID
 #ifdef DNS_USE_OPENSSL_FOR_ID
diff --git a/third_party/libxml/libxml.gyp b/third_party/libxml/libxml.gyp
index dcc75b9..1decbe9 100644
--- a/third_party/libxml/libxml.gyp
+++ b/third_party/libxml/libxml.gyp
@@ -237,6 +237,7 @@
                 'libraries': [
                   # We need dl for dlopen() and friends.
                   '-ldl',
+                  '-lm',
                 ],
               },
             }],
diff --git a/third_party/mesa/mesa.gyp b/third_party/mesa/mesa.gyp
index bf2afcd..220bc17 100644
--- a/third_party/mesa/mesa.gyp
+++ b/third_party/mesa/mesa.gyp
@@ -46,13 +46,7 @@
       "_GLAPI_NO_EXPORTS",
     ],
     'conditions': [
-      ['OS=="android"', {
-        'defines': [
-          '__GLIBC__',
-          '_GNU_SOURCE',
-        ],
-      }],
-      ['OS=="linux"', {
+      ['OS == "linux" or OS == "android"', {
         'defines': [
           '_GNU_SOURCE',
         ],
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index 973672b..1367d8a 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -30,10 +30,13 @@
   }
 }
 
-# This condif should be applied to targets using generated code from the proto
+# This config should be applied to targets using generated code from the proto
 # compiler. It sets up the include directories properly.
 config("using_proto") {
-  include_dirs = [ "$root_gen_dir/protoc_out" ]
+  include_dirs = [
+    "src",
+    "$root_gen_dir/protoc_out",
+  ]
 }
 
 protobuf_lite_sources = [
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium
index 8e51806..c6bb5c2 100644
--- a/third_party/protobuf/README.chromium
+++ b/third_party/protobuf/README.chromium
@@ -38,3 +38,5 @@
 
 GetEmptyString() and GoogleOnceInit() have been uninlined, for a large savings
 in binary size.
+
+A BUILD.gn file has been added for building with GN.
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium
index fdf3394..8fb3768 100644
--- a/third_party/qcms/README.chromium
+++ b/third_party/qcms/README.chromium
@@ -51,5 +51,7 @@
    - https://code.google.com/p/chromium/issues/detail?id=401971
  - Minor variable name change: description -> description_offset
    - https://code.google.com/p/chromium/issues/detail?id=401971
+ - Avoid divisions creating sample points in the float cube LUT builder
+   - https://code.google.com/p/chromium/issues/detail?id=443863
 To regenerate google.patch:
   git diff b8456f38 src > google.patch
diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
index 08db142..9fd8238 100644
--- a/third_party/qcms/src/transform.c
+++ b/third_party/qcms/src/transform.c
@@ -1118,28 +1118,31 @@
 	float* src = NULL;
 	float* dest = NULL;
 	float* lut = NULL;
+	float inverse;
 
 	src = malloc(lutSize*sizeof(float));
 	dest = malloc(lutSize*sizeof(float));
 
 	if (src && dest) {
-		/* Prepare a list of points we want to sample */
+		/* Prepare a list of points we want to sample: x, y, z order */
 		l = 0;
+		inverse = 1 / (float)(samples-1);
 		for (x = 0; x < samples; x++) {
 			for (y = 0; y < samples; y++) {
 				for (z = 0; z < samples; z++) {
-					src[l++] = x / (float)(samples-1);
-					src[l++] = y / (float)(samples-1);
-					src[l++] = z / (float)(samples-1);
+					src[l++] = x * inverse; // r
+					src[l++] = y * inverse; // g
+					src[l++] = z * inverse; // b
 				}
 			}
 		}
 
 		lut = qcms_chain_transform(in, out, src, dest, lutSize);
+
 		if (lut) {
-			transform->r_clut = &lut[0];
-			transform->g_clut = &lut[1];
-			transform->b_clut = &lut[2];
+			transform->r_clut = &lut[0]; // r
+			transform->g_clut = &lut[1]; // g
+			transform->b_clut = &lut[2]; // b
 			transform->grid_size = samples;
 			if (in_type == QCMS_DATA_RGBA_8) {
 				transform->transform_fn = qcms_transform_data_tetra_clut_rgba;
@@ -1149,8 +1152,8 @@
 		}
 	}
 
-
-	//XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed
+	// XXX: qcms_modular_transform_data may return the lut in either the src or the
+	// dest buffer. If so, it must not be free-ed.
 	if (src && lut != src) {
 		free(src);
 	}
diff --git a/third_party/re2/patches/re2-libcxx.patch b/third_party/re2/patches/re2-libcxx.patch
index fc4dd1c..3ef6eb5 100644
--- a/third_party/re2/patches/re2-libcxx.patch
+++ b/third_party/re2/patches/re2-libcxx.patch
@@ -12,3 +12,12 @@
  
  #include <tr1/unordered_set>
  using std::tr1::unordered_set;
+@@ -54,7 +55,7 @@ using std::tr1::unordered_set;
+ #else
+
+ #include <unordered_set>
+-#if defined(WIN32) || defined(OS_ANDROID)
++#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
+ using std::tr1::unordered_set;
+ #else
+ using std::unordered_set;
diff --git a/third_party/re2/util/util.h b/third_party/re2/util/util.h
index 8350445..4f0fdb8 100644
--- a/third_party/re2/util/util.h
+++ b/third_party/re2/util/util.h
@@ -55,7 +55,7 @@
 #else
 
 #include <unordered_set>
-#if defined(WIN32) || defined(OS_ANDROID)
+#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
 using std::tr1::unordered_set;
 #else
 using std::unordered_set;
diff --git a/tools/android/forwarder2/device_forwarder_main.cc b/tools/android/forwarder2/device_forwarder_main.cc
index c215efa..8b5df26 100644
--- a/tools/android/forwarder2/device_forwarder_main.cc
+++ b/tools/android/forwarder2/device_forwarder_main.cc
@@ -48,7 +48,7 @@
  public:
   ServerDelegate() : initialized_(false) {}
 
-  virtual ~ServerDelegate() {
+  ~ServerDelegate() override {
     if (!controller_thread_.get())
       return;
     // The DeviceController instance, if any, is constructed on the controller
@@ -68,7 +68,7 @@
   }
 
   // Daemon::ServerDelegate:
-  virtual void Init() override {
+  void Init() override {
     DCHECK(!g_notifier);
     g_notifier = new forwarder2::PipeNotifier();
     signal(SIGTERM, KillHandler);
@@ -77,7 +77,7 @@
     controller_thread_->Start();
   }
 
-  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
+  void OnClientConnected(scoped_ptr<Socket> client_socket) override {
     if (initialized_) {
       client_socket->WriteString("OK");
       return;
@@ -119,7 +119,7 @@
   bool has_failed() const { return has_failed_; }
 
   // Daemon::ClientDelegate:
-  virtual void OnDaemonReady(Socket* daemon_socket) override {
+  void OnDaemonReady(Socket* daemon_socket) override {
     char buf[kBufSize];
     const int bytes_read = daemon_socket->Read(
         buf, sizeof(buf) - 1 /* leave space for null terminator */);
diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc
index a94a97b..f5d8e2f 100644
--- a/tools/android/forwarder2/host_forwarder_main.cc
+++ b/tools/android/forwarder2/host_forwarder_main.cc
@@ -314,7 +314,7 @@
   }
 
   // Daemon::ServerDelegate:
-  virtual void Init() override {
+  void Init() override {
     LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
     DCHECK(!g_notifier);
     g_notifier = new PipeNotifier();
@@ -322,7 +322,7 @@
     signal(SIGINT, KillHandler);
   }
 
-  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
+  void OnClientConnected(scoped_ptr<Socket> client_socket) override {
     char buf[kBufSize];
     const int bytes_read = client_socket->Read(buf, sizeof(buf));
     if (bytes_read <= 0) {
@@ -366,7 +366,7 @@
   bool has_failed() const { return has_failed_; }
 
   // Daemon::ClientDelegate:
-  virtual void OnDaemonReady(Socket* daemon_socket) override {
+  void OnDaemonReady(Socket* daemon_socket) override {
     // Send the forward command to the daemon.
     CHECK_EQ(static_cast<long>(command_pickle_.size()),
              daemon_socket->WriteNumBytes(command_pickle_.data(),
diff --git a/tools/android/heap_profiler/heap_profiler_unittest.cc b/tools/android/heap_profiler/heap_profiler_unittest.cc
index d69af5f..1771a88 100644
--- a/tools/android/heap_profiler/heap_profiler_unittest.cc
+++ b/tools/android/heap_profiler/heap_profiler_unittest.cc
@@ -14,9 +14,9 @@
 
 class HeapProfilerTest : public testing::Test {
  public:
-  virtual void SetUp() override { heap_profiler_init(&stats_); }
+  void SetUp() override { heap_profiler_init(&stats_); }
 
-  virtual void TearDown() override {
+  void TearDown() override {
     CheckAllocVsStacktaceConsistency();
     heap_profiler_cleanup();
   }
diff --git a/tools/android/run_pie/run_pie.gyp b/tools/android/run_pie/run_pie.gyp
index b713dc4..75850f4 100644
--- a/tools/android/run_pie/run_pie.gyp
+++ b/tools/android/run_pie/run_pie.gyp
@@ -18,10 +18,10 @@
       'ldflags!': [
         '-pie',
       ],
-      # Don't inherit unneeded dependencies on stlport.so, so the binary remains
+      # Don't inherit unneeded dependencies on libc++, so the binary remains
       # self-contained also in component=shared_library builds.
       'libraries!': [
-        '-l<(android_stlport_library)',
+        '-l<(android_libcpp_library)',
       ],
     },
     {
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index 7b964cc..a2b7b19 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -904,7 +904,7 @@
       --platform=android-14 \
       --install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
       --system=linux-x86_64 \
-      --stl=stlport \
+      --stl=libcxx \
       --toolchain=arm-linux-androideabi-4.9
 
   # Android NDK r9d copies a broken unwind.h into the toolchain, see
diff --git a/tools/git/move_source_file.py b/tools/git/move_source_file.py
index 117b3eb..b5496fd 100755
--- a/tools/git/move_source_file.py
+++ b/tools/git/move_source_file.py
@@ -119,6 +119,48 @@
       r'\1%s\2' % PathMinusFirstComponent(to_path),
       ['*.gyp*'])
 
+  # Update references in BUILD.gn files.
+  #
+  # Unlike .gyp(i) files, BUILD.gn files can be placed in any directories,
+  # and paths in a BUILD.gn file are relative to the directory where the
+  # BUILD.gn file is placed.
+  #
+  # For instance, "chrome/browser/chromeos/device_uma.h" is listed as
+  # "browser/chromeos/device_uma.h" in "chrome/chrome_browser_chromeos.gypi",
+  # but it's listed as "device_uma.h" in "chrome/browser/chromeos/BUILD.gn".
+  #
+  # To handle this, the code here will visit directories from the top level
+  # src directory to the directory of |from_path| and try to update BUILD.gn
+  # in each directory.
+  #
+  # The code only handles files moved/renamed within the same BUILD.gn
+  # file. If files are moved beyond the same BUILD.gn file, the affected
+  # BUILD.gn files should be fixed manually.
+  def SplitByFirstComponent(path):
+    """'foo/bar/baz' -> ('foo', 'bar/baz')
+       'bar' -> ('bar', '')
+       '' -> ('', '')
+    """
+    parts = re.split(r"[/\\]", path, 1)
+    if len(parts) == 2:
+      return (parts[0], parts[1])
+    else:
+      return (parts[0], '')
+
+  visiting_directory = ''
+  from_rest = from_path
+  to_rest = to_path
+  while True:
+    mffr.MultiFileFindReplace(
+        r'([\'"])%s([\'"])' % from_rest,
+        r'\1%s\2' % to_rest,
+        [os.path.join(visiting_directory, 'BUILD.gn')])
+    from_first, from_rest = SplitByFirstComponent(from_rest)
+    to_first, to_rest = SplitByFirstComponent(to_rest)
+    visiting_directory = os.path.join(visiting_directory, from_first)
+    if not from_rest or not to_rest:
+        break
+
 
 def MakeIncludeGuardName(path_from_root):
   """Returns an include guard name given a path from root."""
diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py
index cd61dae..9280d7a 100755
--- a/tools/valgrind/asan/asan_symbolize.py
+++ b/tools/valgrind/asan/asan_symbolize.py
@@ -10,6 +10,8 @@
 import base64
 import json
 import os
+import re
+import subprocess
 import sys
 
 class LineBuffered(object):
@@ -48,6 +50,73 @@
     os.environ['LLVM_SYMBOLIZER_PATH'] = os.path.abspath(symbolizer_path)
 
 
+def is_hash_name(name):
+  match = re.match('[0-9a-f]+$', name)
+  return bool(match)
+
+
+def split_path(path):
+  ret = []
+  while True:
+    head, tail = os.path.split(path)
+    if head == path:
+      return [head] + ret
+    ret, path = [tail] + ret, head
+
+
+def chrome_product_dir_path(exe_path):
+  if exe_path is None:
+    return None
+  path_parts = split_path(exe_path)
+  # Make sure the product dir path isn't empty if |exe_path| consists of
+  # a single component.
+  if len(path_parts) == 1:
+    path_parts = ['.'] + path_parts
+  for index, part in enumerate(path_parts):
+    if part.endswith('.app'):
+      return os.path.join(*path_parts[:index])
+  # If the executable isn't an .app bundle, it's a commandline binary that
+  # resides right in the product dir.
+  return os.path.join(*path_parts[:-1])
+
+
+inode_path_cache = {}
+
+
+def find_inode_at_path(inode, path):
+  if inode in inode_path_cache:
+    return inode_path_cache[inode]
+  cmd = ['find', path, '-inum', str(inode)]
+  find_line = subprocess.check_output(cmd).rstrip()
+  lines = find_line.split('\n')
+  ret = None
+  if lines:
+    # `find` may give us several paths (e.g. 'Chromium Framework' in the
+    # product dir and 'Chromium Framework' inside 'Chromium.app',
+    # chrome_dsym_hints() will produce correct .dSYM path for any of them.
+    ret = lines[0]
+  inode_path_cache[inode] = ret
+  return ret
+
+
+# Create a binary name filter that works around https://crbug.com/444835.
+# When running tests on OSX swarming servers, ASan sometimes prints paths to
+# files in cache (ending with SHA1 filenames) instead of paths to hardlinks to
+# those files in the product dir.
+# For a given |binary_path| chrome_osx_binary_name_filter() returns one of the
+# hardlinks to the same inode in |product_dir_path|.
+def make_chrome_osx_binary_name_filter(product_dir_path=''):
+  def chrome_osx_binary_name_filter(binary_path):
+    basename = os.path.basename(binary_path)
+    if is_hash_name(basename) and product_dir_path:
+      inode = os.stat(binary_path).st_ino
+      new_binary_path = find_inode_at_path(inode, product_dir_path)
+      if new_binary_path:
+        return new_binary_path
+    return binary_path
+  return chrome_osx_binary_name_filter
+
+
 # Construct a path to the .dSYM bundle for the given binary.
 # There are three possible cases for binary location in Chromium:
 # 1. The binary is a standalone executable or dynamic library in the product
@@ -63,7 +132,7 @@
 # path. Only one of these bundles may be a framework and frameworks cannot
 # contain other bundles.
 def chrome_dsym_hints(binary):
-  path_parts = binary.split(os.path.sep)
+  path_parts = split_path(binary)
   app_positions = []
   framework_positions = []
   for index, part in enumerate(path_parts):
@@ -89,7 +158,7 @@
   # In case 2 this is the same as |outermost_bundle|.
   innermost_bundle = bundle_positions[-1]
   dsym_path = product_dir + [path_parts[innermost_bundle]]
-  result = '%s.dSYM' % os.path.sep.join(dsym_path)
+  result = '%s.dSYM' % os.path.join(*dsym_path)
   return [result]
 
 
@@ -169,13 +238,22 @@
   parser.add_argument('strip_path_prefix', nargs='*',
       help='When printing source file names, the longest prefix ending in one '
            'of these substrings will be stripped. E.g.: "Release/../../".')
+  parser.add_argument('--executable-path',
+      help='Path to program executable. Used on OSX swarming bots to locate '
+           'dSYM bundles for associated frameworks and bundles.')
   args = parser.parse_args()
 
   disable_buffering()
   set_symbolizer_path()
   asan_symbolize.demangle = True
   asan_symbolize.fix_filename_patterns = args.strip_path_prefix
-  loop = asan_symbolize.SymbolizationLoop(dsym_hint_producer=chrome_dsym_hints)
+  binary_name_filter = None
+  if os.uname()[0] == 'Darwin':
+    binary_name_filter = make_chrome_osx_binary_name_filter(
+        chrome_product_dir_path(args.executable_path))
+  loop = asan_symbolize.SymbolizationLoop(
+      binary_name_filter=binary_name_filter,
+      dsym_hint_producer=chrome_dsym_hints)
 
   if args.test_summary_json_file:
     symbolize_snippets_in_json(args.test_summary_json_file, loop)
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 51ebeda..554beb3 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -567,7 +567,8 @@
                   "--no-retry-failures",  # retrying takes too much time
                   # http://crbug.com/176908: Don't launch a browser when done.
                   "--no-show-results",
-                  "--nocheck-sys-deps"]
+                  "--nocheck-sys-deps",
+                  "--additional-drt-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 876d6f7..1a9b9ee 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -461,11 +461,12 @@
 name=http://crbug.com/371348
 system call NtCreateSection
 KERNELBASE.dll!CreateFileMappingW
-base.dll!base::SharedMemory::Create
-base.dll!base::SharedMemory::CreateAnonymous
-content.dll!content::ChildThread::AllocateSharedMemory
-content.dll!content::ChildSharedBitmapManager::AllocateSharedBitmap
-cc.dll!cc::ResourceProvider::CreateBitmap
+*!base::SharedMemory::Create
+*!base::SharedMemory::CreateAnonymous
+*!content::ChildThreadImpl::AllocateSharedMemory
+...
+*!content::ChildSharedBitmapManager::AllocateSharedBitmap
+*!cc::ResourceProvider::CreateBitmap
 
 HANDLE LEAK
 name=http://crbug.com/371357
@@ -711,3 +712,62 @@
 KERNELBASE.dll!OpenProcess
 base.dll!base::Process::OpenWithExtraPriviles
 content.dll!content::BrowserMessageFilter::Internal::OnChannelConnected
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/455060
+*!content::FrameAccessibility::GetParent
+*!content::RenderFrameHostImpl::AccessibilityGetParentFrame
+*!content::BrowserAccessibilityManager::GetDelegateFromRootManager
+*!content::BrowserAccessibilityManager::OnWindowBlurred
+...
+*!content::RenderWidgetHostViewAura::Destroy
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/455066
+system call NtReadFile parameter #4
+KERNELBASE.dll!ReadFile
+KERNEL32.dll!ReadFile
+*!net::FileStream::Context::ReadAsync
+*!base::internal::RunnableAdapter<>::Run
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/455994
+drmemorylib.dll!replace_operator_delete
+*!IPC::Listener::`vector deleting destructor'
+*!content::RenderFrameImpl::~RenderFrameImpl
+*!content::RenderFrameImpl::`vector deleting destructor'
+*!content::RenderViewImpl::~RenderViewImpl
+*!content::RenderViewImpl::`vector deleting destructor'
+*!scoped_refptr<>::Release
+*!base::internal::BindState<>::`scalar deleting destructor'
+*!scoped_refptr<>::Release
+*!base::internal::CallbackBase::~CallbackBase
+*!base::MessagePumpDefault::Run
+*!base::MessageLoop::RunHandler
+*!base::MessageLoop::Run
+*!content::RendererMain
+*!content::RunNamedProcessTypeMain
+*!content::ContentMainRunnerImpl::Run
+*!content::ContentMain
+*!content::LaunchTests
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/456131
+...
+*!content::NavigateToURL
+*!content::BrowserSideNavigationBrowserTest_BrowserInitiatedNavigations_Test::RunTestOnMainThread
+*!content::ContentBrowserTest::RunTestOnMainThreadLoop
+*!content::BrowserTestBase::ProxyRunTestOnMainThreadLoop
+*!content::ShellBrowserMainParts::PreMainMessageLoopRun
+*!content::BrowserMainLoop::PreMainMessageLoopRun
+*!base::internal::Invoker<>::Run
+*!content::StartupTaskRunner::RunAllTasksNow
+*!content::BrowserMainLoop::CreateStartupTasks
+*!content::BrowserMainRunnerImpl::Initialize
+*!ShellBrowserMain
+*!content::ShellMainDelegate::RunProcess
+*!content::RunNamedProcessTypeMain
+*!content::ContentMainRunnerImpl::Run
+*!content::ContentMain
+*!content::BrowserTestBase::SetUp
+*!content::ContentBrowserTest::SetUp
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index 2036d21..d823d49 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1890,10 +1890,11 @@
 *!testing::internal::HandleExceptionsInMethodIfSupported<>
 
 UNINITIALIZED READ
-name=bug_446256
-*!`anonymous namespace'::GraphicsContextTest_trackDisplayListRecording_Test::TestBody
-*!testing::internal::HandleExceptionsInMethodIfSupported<>
-
-UNINITIALIZED READ
 name=bug_399842
 skia.dll!S32A_Opaque_BlitRow32_SSE4
+
+UNINITIALIZED READ
+name=bug_455417
+*!std::char_traits<>::compare
+...
+*!*::*URLRequest*::TestBody
diff --git a/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 0000000..f1382da
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,2 @@
+# crbug.com/455536
+ChromeWatcherCommandLineTest.BasicTest
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
index 5a8f1bc..a43a673 100644
--- a/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
+++ b/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
@@ -32,6 +32,3 @@
 
 # http://crbug.com/403533
 ExtensionPathUtilTest.BasicPrettifyPathTest
-
-# http://crbug.com/452071
-SupervisedUserServiceExtensionTest.InstallContentPacks
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 579b481..10849ae 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -3401,10 +3401,10 @@
    bug_431213
    Memcheck:Leak
    fun:_Znw*
-   fun:_ZN3gin22CreateFunctionTemplateIFSsPN4mojo2js13HandleWrapperEEEEN2v85LocalINS6_16FunctionTemplateEEEPNS6_7IsolateEN4base8CallbackIT_EEi
-   fun:_ZN3gin12_GLOBAL__N_114CallbackTraitsIMN4mojo2js13HandleWrapperEFSsvEvE14CreateTemplateEPN2v87IsolateES6_
-   fun:_ZN3gin21ObjectTemplateBuilder9SetMethodIMN4mojo2js13HandleWrapperEFSsvEEERS0_RKN4base16BasicStringPieceISsEERKT_
-   fun:_ZN4mojo2js13HandleWrapper24GetObjectTemplateBuilderEPN2v87IsolateE
+   fun:_ZN3gin22CreateFunctionTemplateIF*LocalINS6_16FunctionTemplateEEEPNS6_7IsolateEN4base8CallbackIT_EEi
+   fun:_ZN3gin12_GLOBAL__N_114CallbackTraitsIMN*CreateTemplateEPN2v87IsolateES6_
+   fun:_ZN3gin21ObjectTemplateBuilder9SetMethodIMN*0_RKN4base16BasicStringPieceISsEERKT_
+   fun:_ZN*24GetObjectTemplateBuilderEPN2v87IsolateE
 }
 {
    bug_436110
@@ -3596,3 +3596,23 @@
    fun:_ZN4base12SimpleThread10ThreadMainEv
    fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
 }
+{
+   bug_455732
+   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
+   fun:_ZN4mojo8internal6Router26HandleIncomingMessageThunk6AcceptEPNS_7MessageE
+   fun:_ZN7content32ApplicationSetupRequestValidator6AcceptEPN4mojo7MessageE
+   fun:_ZN4mojo8internal22MessageHeaderValidator6AcceptEPNS_7MessageE
+   fun:_ZN4mojo22ReadAndDispatchMessageENS_17MessagePipeHandleEPNS_15MessageReceiverEPb
+   fun:_ZN4mojo8internal9Connector17ReadSingleMessageEPi
+   fun:_ZN4mojo8internal9Connector24ReadAllAvailableMessagesEv
+   fun:_ZN4mojo8internal9Connector13OnHandleReadyEi
+   fun:_ZN4mojo8internal9Connector17CallOnHandleReadyEPvi
+   fun:_ZN4mojo8internal12_GLOBAL__N_113OnHandleReadyEPNS_6common13HandleWatcherEPFvPviES5_i
+}
diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc
index 116b744..a7a43ee 100644
--- a/ui/events/gesture_detection/gesture_provider.cc
+++ b/ui/events/gesture_detection/gesture_provider.cc
@@ -7,7 +7,7 @@
 #include <cmath>
 
 #include "base/auto_reset.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/gesture_detection/gesture_event_data.h"
 #include "ui/events/gesture_detection/gesture_listeners.h"
diff --git a/ui/events/gesture_detection/motion_event_buffer.cc b/ui/events/gesture_detection/motion_event_buffer.cc
index 89690d6..2b3d2c3 100644
--- a/ui/events/gesture_detection/motion_event_buffer.cc
+++ b/ui/events/gesture_detection/motion_event_buffer.cc
@@ -4,7 +4,7 @@
 
 #include "ui/events/gesture_detection/motion_event_buffer.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "ui/events/gesture_detection/motion_event.h"
 #include "ui/events/gesture_detection/motion_event_generic.h"
 
diff --git a/ui/events/latency_info.cc b/ui/events/latency_info.cc
index 248acb9..145b77a 100644
--- a/ui/events/latency_info.cc
+++ b/ui/events/latency_info.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/debug/trace_event.h"
 #include "base/json/json_writer.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/stringprintf.h"
+#include "base/trace_event/trace_event.h"
 #include "ui/events/latency_info.h"
 
 #include <algorithm>
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 5943bb6..52daf1c 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -817,18 +817,6 @@
 { 'return_type': 'void',
   'names': ['glReleaseShaderCompiler'],
   'arguments': 'void', },
-# Multisampling API is different in different GL versions, some require an
-# explicit resolve step for renderbuffers and/or FBO texture attachments and
-# some do not. Multiple alternatives might be present in a single
-# implementation, which require different use of the API and may have
-# different performance (explicit resolve performing worse, for example).
-# So even though the function signature is the same across versions, we split
-# their definitions so that the function to use can be chosen correctly at a
-# higher level.
-# TODO(oetuaho@nvidia.com): Some of these might still be possible to combine.
-# This could also fix weirdness in the mock bindings that's caused by the same
-# function name appearing multiple times.
-# This is the ES3 function, which requires explicit resolve:
 { 'return_type': 'void',
   'names': ['glRenderbufferStorageEXT', 'glRenderbufferStorage'],
   'arguments':
@@ -838,18 +826,11 @@
   'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
                'GLsizei width, GLsizei height', },
 { 'return_type': 'void',
-  'names': ['glRenderbufferStorageMultisampleANGLE',
-            'glRenderbufferStorageMultisample'],
+  'names': ['glRenderbufferStorageMultisampleANGLE'],
   'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
                'GLsizei width, GLsizei height', },
-# In desktop GL, EXT and core versions both have an explicit resolve step,
-# though desktop core GL implicitly resolves when drawing to a window.
-# TODO(oetuaho@nvidia.com): Right now this function also doubles as ES2 EXT
-# function, which has implicit resolve, and for which the fallback is wrong.
-# Fix this.
 { 'return_type': 'void',
-  'names': ['glRenderbufferStorageMultisampleEXT',
-            'glRenderbufferStorageMultisample'],
+  'names': ['glRenderbufferStorageMultisampleEXT'],
   'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
                'GLsizei width, GLsizei height', },
 { 'return_type': 'void',
@@ -1379,7 +1360,7 @@
   'arguments': 'EGLint engine', },
 { 'return_type': 'EGLint',
   'versions': [{ 'name': 'eglWaitSyncKHR',
-                 'extensions': ['EGL_KHR_fence_sync', 'EGL_KHR_wait_sync'] }],
+                 'extensions': ['EGL_KHR_wait_sync'] }],
   'arguments': 'EGLDisplay dpy, EGLSyncKHR sync, EGLint flags' },
 ]
 
diff --git a/ui/gl/gl_bindings_autogen_egl.cc b/ui/gl/gl_bindings_autogen_egl.cc
index e0de7f2..003b545 100644
--- a/ui/gl/gl_bindings_autogen_egl.cc
+++ b/ui/gl/gl_bindings_autogen_egl.cc
@@ -209,7 +209,7 @@
   }
 
   debug_fn.eglWaitSyncKHRFn = 0;
-  if (ext.b_EGL_KHR_fence_sync || ext.b_EGL_KHR_wait_sync) {
+  if (ext.b_EGL_KHR_wait_sync) {
     fn.eglWaitSyncKHRFn = reinterpret_cast<eglWaitSyncKHRProc>(
         GetGLProcAddress("eglWaitSyncKHR"));
     DCHECK(fn.eglWaitSyncKHRFn);
diff --git a/ui/gl/gl_bindings_autogen_gl.cc b/ui/gl/gl_bindings_autogen_gl.cc
index 642190c..11383b1 100644
--- a/ui/gl/gl_bindings_autogen_gl.cc
+++ b/ui/gl/gl_bindings_autogen_gl.cc
@@ -1692,12 +1692,7 @@
   }
 
   debug_fn.glRenderbufferStorageMultisampleANGLEFn = 0;
-  if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) {
-    fn.glRenderbufferStorageMultisampleANGLEFn =
-        reinterpret_cast<glRenderbufferStorageMultisampleANGLEProc>(
-            GetGLProcAddress("glRenderbufferStorageMultisample"));
-    DCHECK(fn.glRenderbufferStorageMultisampleANGLEFn);
-  } else if (ext.b_GL_ANGLE_framebuffer_multisample) {
+  if (ext.b_GL_ANGLE_framebuffer_multisample) {
     fn.glRenderbufferStorageMultisampleANGLEFn =
         reinterpret_cast<glRenderbufferStorageMultisampleANGLEProc>(
             GetGLProcAddress("glRenderbufferStorageMultisampleANGLE"));
@@ -1705,13 +1700,8 @@
   }
 
   debug_fn.glRenderbufferStorageMultisampleEXTFn = 0;
-  if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) {
-    fn.glRenderbufferStorageMultisampleEXTFn =
-        reinterpret_cast<glRenderbufferStorageMultisampleEXTProc>(
-            GetGLProcAddress("glRenderbufferStorageMultisample"));
-    DCHECK(fn.glRenderbufferStorageMultisampleEXTFn);
-  } else if (ext.b_GL_EXT_multisampled_render_to_texture ||
-             ext.b_GL_EXT_framebuffer_multisample) {
+  if (ext.b_GL_EXT_multisampled_render_to_texture ||
+      ext.b_GL_EXT_framebuffer_multisample) {
     fn.glRenderbufferStorageMultisampleEXTFn =
         reinterpret_cast<glRenderbufferStorageMultisampleEXTProc>(
             GetGLProcAddress("glRenderbufferStorageMultisampleEXT"));
diff --git a/ui/gl/gl_bindings_autogen_mock.cc b/ui/gl/gl_bindings_autogen_mock.cc
index 185d809..8e84aa3 100644
--- a/ui/gl/gl_bindings_autogen_mock.cc
+++ b/ui/gl/gl_bindings_autogen_mock.cc
@@ -1829,8 +1829,8 @@
                                                        GLsizei width,
                                                        GLsizei height) {
   MakeFunctionUnique("glRenderbufferStorageMultisample");
-  interface_->RenderbufferStorageMultisampleEXT(target, samples, internalformat,
-                                                width, height);
+  interface_->RenderbufferStorageMultisample(target, samples, internalformat,
+                                             width, height);
 }
 
 void GL_BINDING_CALL
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index 4cfcf73..f89f1d2 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -38,20 +38,6 @@
   canceled_ = true;
 }
 
-GLContext::FlushEvent::FlushEvent() {
-}
-
-GLContext::FlushEvent::~FlushEvent() {
-}
-
-void GLContext::FlushEvent::Signal() {
-  flag_.Set();
-}
-
-bool GLContext::FlushEvent::IsSignaled() {
-  return flag_.IsSet();
-}
-
 GLContext::GLContext(GLShareGroup* share_group) :
     share_group_(share_group),
     swap_interval_(1),
@@ -69,13 +55,6 @@
   }
 }
 
-scoped_refptr<GLContext::FlushEvent> GLContext::SignalFlush() {
-  DCHECK(IsCurrent(NULL));
-  scoped_refptr<FlushEvent> flush_event = new FlushEvent();
-  flush_events_.push_back(flush_event);
-  return flush_event;
-}
-
 bool GLContext::GetTotalGpuMemory(size_t* bytes) {
   DCHECK(bytes);
   *bytes = 0;
@@ -230,12 +209,6 @@
   SetGLToRealGLApi();
 }
 
-void GLContext::OnFlush() {
-  for (size_t n = 0; n < flush_events_.size(); n++)
-    flush_events_[n]->Signal();
-  flush_events_.clear();
-}
-
 GLContextReal::GLContextReal(GLShareGroup* share_group)
     : GLContext(share_group) {}
 
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index 62cabcd..5eac838 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -34,25 +34,6 @@
   virtual bool Initialize(
       GLSurface* compatible_surface, GpuPreference gpu_preference) = 0;
 
-  class FlushEvent : public base::RefCountedThreadSafe<FlushEvent> {
-    public:
-      bool IsSignaled();
-
-    private:
-      friend class base::RefCountedThreadSafe<FlushEvent>;
-      friend class GLContext;
-      FlushEvent();
-      virtual ~FlushEvent();
-      void Signal();
-
-      base::CancellationFlag flag_;
-  };
-
-  // Needs to be called with this context current. It will return a FlushEvent
-  // that is initially unsignaled, but will transition to signaled after the
-  // next glFlush() or glFinish() occurs in this context.
-  scoped_refptr<FlushEvent> SignalFlush();
-
   // Destroys the GL context.
   virtual void Destroy() = 0;
 
@@ -143,9 +124,6 @@
   // Returns the GL renderer string. The context must be current.
   virtual std::string GetGLRenderer();
 
-  // Called when glFlush()/glFinish() is called with this context current.
-  void OnFlush();
-
  protected:
   virtual ~GLContext();
 
@@ -186,8 +164,6 @@
   scoped_ptr<GLStateRestorer> state_restorer_;
   scoped_ptr<GLVersionInfo> version_info_;
 
-  std::vector<scoped_refptr<FlushEvent> > flush_events_;
-
   int swap_interval_;
   bool force_swap_interval_zero_;
 
diff --git a/ui/gl/gl_context_android.cc b/ui/gl/gl_context_android.cc
index 76b9238..9d3c86c 100644
--- a/ui/gl/gl_context_android.cc
+++ b/ui/gl/gl_context_android.cc
@@ -26,18 +26,18 @@
   GLNonOwnedContext(GLShareGroup* share_group);
 
   // Implement GLContext.
-  virtual bool Initialize(GLSurface* compatible_surface,
-                          GpuPreference gpu_preference) override;
-  virtual void Destroy() override {}
-  virtual bool MakeCurrent(GLSurface* surface) override;
-  virtual void ReleaseCurrent(GLSurface* surface) override {}
-  virtual bool IsCurrent(GLSurface* surface) override { return true; }
-  virtual void* GetHandle() override { return NULL; }
-  virtual void OnSetSwapInterval(int interval) override {}
-  virtual std::string GetExtensions() override;
+  bool Initialize(GLSurface* compatible_surface,
+                  GpuPreference gpu_preference) override;
+  void Destroy() override {}
+  bool MakeCurrent(GLSurface* surface) override;
+  void ReleaseCurrent(GLSurface* surface) override {}
+  bool IsCurrent(GLSurface* surface) override { return true; }
+  void* GetHandle() override { return NULL; }
+  void OnSetSwapInterval(int interval) override {}
+  std::string GetExtensions() override;
 
  protected:
-  virtual ~GLNonOwnedContext() {}
+  ~GLNonOwnedContext() override {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(GLNonOwnedContext);
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index c254411..0fb3a74 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -19,35 +19,6 @@
 
 namespace gfx {
 
-namespace {
-
-// static
-GLFence* CreateFence(bool flush) {
-  DCHECK(GLContext::GetCurrent())
-      << "Trying to create fence with no context";
-
-  scoped_ptr<GLFence> fence;
-  // Prefer ARB_sync which supports server-side wait.
-  if (g_driver_gl.ext.b_GL_ARB_sync ||
-      GetGLVersionInfo()->is_es3) {
-    fence.reset(new GLFenceARB(flush));
-#if defined(OS_MACOSX)
-  } else if (g_driver_gl.ext.b_GL_APPLE_fence) {
-    fence.reset(new GLFenceAPPLE(flush));
-#else
-  } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
-    fence.reset(new GLFenceEGL(flush));
-#endif
-  } else if (g_driver_gl.ext.b_GL_NV_fence) {
-    fence.reset(new GLFenceNV(flush));
-  }
-
-  DCHECK_EQ(!!fence.get(), GLFence::IsSupported());
-  return fence.release();
-}
-
-}  // namespace
-
 GLFence::GLFence() {
 }
 
@@ -66,11 +37,27 @@
 }
 
 GLFence* GLFence::Create() {
-  return CreateFence(true);
-}
+  DCHECK(GLContext::GetCurrent())
+      << "Trying to create fence with no context";
 
-GLFence* GLFence::CreateWithoutFlush() {
-  return CreateFence(false);
+  scoped_ptr<GLFence> fence;
+  // Prefer ARB_sync which supports server-side wait.
+  if (g_driver_gl.ext.b_GL_ARB_sync ||
+      GetGLVersionInfo()->is_es3) {
+    fence.reset(new GLFenceARB);
+#if defined(OS_MACOSX)
+  } else if (g_driver_gl.ext.b_GL_APPLE_fence) {
+    fence.reset(new GLFenceAPPLE);
+#else
+  } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
+    fence.reset(new GLFenceEGL);
+#endif
+  } else if (g_driver_gl.ext.b_GL_NV_fence) {
+    fence.reset(new GLFenceNV);
+  }
+
+  DCHECK_EQ(!!fence.get(), GLFence::IsSupported());
+  return fence.release();
 }
 
 }  // namespace gfx
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
index 5af253d..76511f4 100644
--- a/ui/gl/gl_fence.h
+++ b/ui/gl/gl_fence.h
@@ -18,12 +18,6 @@
   static bool IsSupported();
   static GLFence* Create();
 
-  // Creates a fence that is not guaranteed to signal until the current context
-  // is flushed. It is illegal to call Client/ServerWait() on a fence without
-  // having explicitly called glFlush() or glFinish() in the originating
-  // context.
-  static GLFence* CreateWithoutFlush();
-
   virtual bool HasCompleted() = 0;
   virtual void ClientWait() = 0;
 
diff --git a/ui/gl/gl_fence_apple.cc b/ui/gl/gl_fence_apple.cc
index 9df0cad..3b5f697 100644
--- a/ui/gl/gl_fence_apple.cc
+++ b/ui/gl/gl_fence_apple.cc
@@ -5,19 +5,14 @@
 #include "ui/gl/gl_fence_apple.h"
 
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 
 namespace gfx {
 
-GLFenceAPPLE::GLFenceAPPLE(bool flush) {
+GLFenceAPPLE::GLFenceAPPLE() {
   glGenFencesAPPLE(1, &fence_);
   glSetFenceAPPLE(fence_);
   DCHECK(glIsFenceAPPLE(fence_));
-  if (flush) {
-    glFlush();
-  } else {
-    flush_event_ = GLContext::GetCurrent()->SignalFlush();
-  }
+  glFlush();
 }
 
 bool GLFenceAPPLE::HasCompleted() {
@@ -27,11 +22,7 @@
 
 void GLFenceAPPLE::ClientWait() {
   DCHECK(glIsFenceAPPLE(fence_));
-  if (!flush_event_.get() || flush_event_->IsSignaled()) {
-    glFinishFenceAPPLE(fence_);
-  } else {
-    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-  }
+  glFinishFenceAPPLE(fence_);
 }
 
 void GLFenceAPPLE::ServerWait() {
diff --git a/ui/gl/gl_fence_apple.h b/ui/gl/gl_fence_apple.h
index 6c8633d..5458e0d 100644
--- a/ui/gl/gl_fence_apple.h
+++ b/ui/gl/gl_fence_apple.h
@@ -7,14 +7,13 @@
 
 #include "base/macros.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence.h"
 
 namespace gfx {
 
 class GL_EXPORT GLFenceAPPLE : public GLFence {
  public:
-  GLFenceAPPLE(bool flush);
+  GLFenceAPPLE();
   ~GLFenceAPPLE() override;
 
   // GLFence implementation:
@@ -24,7 +23,6 @@
 
  private:
   GLuint fence_;
-  scoped_refptr<GLContext::FlushEvent> flush_event_;
 
   DISALLOW_COPY_AND_ASSIGN(GLFenceAPPLE);
 };
diff --git a/ui/gl/gl_fence_arb.cc b/ui/gl/gl_fence_arb.cc
index 05bda6b..5c6b337 100644
--- a/ui/gl/gl_fence_arb.cc
+++ b/ui/gl/gl_fence_arb.cc
@@ -6,7 +6,6 @@
 
 #include "base/strings/stringprintf.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 
 namespace gfx {
 
@@ -24,14 +23,10 @@
 
 }  // namespace
 
-GLFenceARB::GLFenceARB(bool flush) {
+GLFenceARB::GLFenceARB() {
   sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
   DCHECK_EQ(GL_TRUE, glIsSync(sync_));
-  if (flush) {
-    glFlush();
-  } else {
-    flush_event_ = GLContext::GetCurrent()->SignalFlush();
-  }
+  glFlush();
 }
 
 bool GLFenceARB::HasCompleted() {
@@ -52,25 +47,17 @@
 
 void GLFenceARB::ClientWait() {
   DCHECK_EQ(GL_TRUE, glIsSync(sync_));
-  if (!flush_event_.get() || flush_event_->IsSignaled()) {
-    GLenum result =
-        glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
-    DCHECK_NE(static_cast<GLenum>(GL_TIMEOUT_EXPIRED), result);
-    if (result == GL_WAIT_FAILED) {
-      LOG(FATAL) << "Failed to wait for GLFence. error code:" << GetGLErrors();
-    }
-  } else {
-    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  GLenum result =
+      glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+  DCHECK_NE(static_cast<GLenum>(GL_TIMEOUT_EXPIRED), result);
+  if (result == GL_WAIT_FAILED) {
+    LOG(FATAL) << "Failed to wait for GLFence. error code:" << GetGLErrors();
   }
 }
 
 void GLFenceARB::ServerWait() {
   DCHECK_EQ(GL_TRUE, glIsSync(sync_));
-  if (!flush_event_.get() || flush_event_->IsSignaled()) {
-    glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
-  } else {
-    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-  }
+  glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
 }
 
 GLFenceARB::~GLFenceARB() {
diff --git a/ui/gl/gl_fence_arb.h b/ui/gl/gl_fence_arb.h
index ef43948..3975efe 100644
--- a/ui/gl/gl_fence_arb.h
+++ b/ui/gl/gl_fence_arb.h
@@ -7,14 +7,13 @@
 
 #include "base/macros.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence.h"
 
 namespace gfx {
 
 class GL_EXPORT GLFenceARB : public GLFence {
  public:
-  GLFenceARB(bool flush);
+  GLFenceARB();
   ~GLFenceARB() override;
 
   // GLFence implementation:
@@ -24,7 +23,6 @@
 
  private:
   GLsync sync_;
-  scoped_refptr<GLContext::FlushEvent> flush_event_;
 
   DISALLOW_COPY_AND_ASSIGN(GLFenceARB);
 };
diff --git a/ui/gl/gl_fence_egl.cc b/ui/gl/gl_fence_egl.cc
index c96d6d8..74f0a01 100644
--- a/ui/gl/gl_fence_egl.cc
+++ b/ui/gl/gl_fence_egl.cc
@@ -6,19 +6,25 @@
 
 #include "ui/gl/egl_util.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 
 namespace gfx {
 
-GLFenceEGL::GLFenceEGL(bool flush) {
+namespace {
+
+bool g_ignore_egl_sync_failures = false;
+
+}  // namespace
+
+// static
+void GLFenceEGL::SetIgnoreFailures() {
+  g_ignore_egl_sync_failures = true;
+}
+
+GLFenceEGL::GLFenceEGL() {
   display_ = eglGetCurrentDisplay();
   sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
   DCHECK(sync_ != EGL_NO_SYNC_KHR);
-  if (flush) {
-    glFlush();
-  } else {
-    flush_event_ = GLContext::GetCurrent()->SignalFlush();
-  }
+  glFlush();
 }
 
 bool GLFenceEGL::HasCompleted() {
@@ -35,17 +41,15 @@
 }
 
 void GLFenceEGL::ClientWait() {
-  if (!flush_event_.get() || flush_event_->IsSignaled()) {
-    EGLint flags = 0;
-    EGLTimeKHR time = EGL_FOREVER_KHR;
-    EGLint result = eglClientWaitSyncKHR(display_, sync_, flags, time);
-    DCHECK_NE(EGL_TIMEOUT_EXPIRED_KHR, result);
-    if (result == EGL_FALSE) {
-      LOG(FATAL) << "Failed to wait for EGLSync. error:"
-                 << ui::GetLastEGLErrorString();
-    }
-  } else {
-    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  EGLint flags = 0;
+  EGLTimeKHR time = EGL_FOREVER_KHR;
+  EGLint result = eglClientWaitSyncKHR(display_, sync_, flags, time);
+  DCHECK_IMPLIES(!g_ignore_egl_sync_failures,
+                 EGL_TIMEOUT_EXPIRED_KHR == result);
+  if (result == EGL_FALSE) {
+    LOG(ERROR) << "Failed to wait for EGLSync. error:"
+               << ui::GetLastEGLErrorString();
+    CHECK(g_ignore_egl_sync_failures);
   }
 }
 
@@ -54,14 +58,11 @@
     ClientWait();
     return;
   }
-  if (!flush_event_.get() || flush_event_->IsSignaled()) {
-    EGLint flags = 0;
-    if (eglWaitSyncKHR(display_, sync_, flags) == EGL_FALSE) {
-      LOG(FATAL) << "Failed to wait for EGLSync. error:"
-                 << ui::GetLastEGLErrorString();
-    }
-  } else {
-    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  EGLint flags = 0;
+  if (eglWaitSyncKHR(display_, sync_, flags) == EGL_FALSE) {
+    LOG(ERROR) << "Failed to wait for EGLSync. error:"
+               << ui::GetLastEGLErrorString();
+    CHECK(g_ignore_egl_sync_failures);
   }
 }
 
diff --git a/ui/gl/gl_fence_egl.h b/ui/gl/gl_fence_egl.h
index 75a0444..5b6006c 100644
--- a/ui/gl/gl_fence_egl.h
+++ b/ui/gl/gl_fence_egl.h
@@ -7,14 +7,15 @@
 
 #include "base/macros.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence.h"
 
 namespace gfx {
 
 class GL_EXPORT GLFenceEGL : public GLFence {
  public:
-  GLFenceEGL(bool flush);
+  static void SetIgnoreFailures();
+
+  GLFenceEGL();
   ~GLFenceEGL() override;
 
   // GLFence implementation:
@@ -25,7 +26,6 @@
  private:
   EGLSyncKHR sync_;
   EGLDisplay display_;
-  scoped_refptr<GLContext::FlushEvent> flush_event_;
 
   DISALLOW_COPY_AND_ASSIGN(GLFenceEGL);
 };
diff --git a/ui/gl/gl_fence_nv.cc b/ui/gl/gl_fence_nv.cc
index 46dadd5..0e23b28 100644
--- a/ui/gl/gl_fence_nv.cc
+++ b/ui/gl/gl_fence_nv.cc
@@ -5,11 +5,10 @@
 #include "ui/gl/gl_fence_nv.h"
 
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 
 namespace gfx {
 
-GLFenceNV::GLFenceNV(bool flush) {
+GLFenceNV::GLFenceNV() {
   // What if either of these GL calls fails? TestFenceNV will return true.
   // See spec:
   // http://www.opengl.org/registry/specs/NV/fence.txt
@@ -23,11 +22,7 @@
   glGenFencesNV(1, &fence_);
   glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
   DCHECK(glIsFenceNV(fence_));
-  if (flush) {
-    glFlush();
-  } else {
-    flush_event_ = GLContext::GetCurrent()->SignalFlush();
-  }
+  glFlush();
 }
 
 bool GLFenceNV::HasCompleted() {
@@ -37,11 +32,7 @@
 
 void GLFenceNV::ClientWait() {
   DCHECK(glIsFenceNV(fence_));
-  if (!flush_event_.get() || flush_event_->IsSignaled()) {
-    glFinishFenceNV(fence_);
-  } else {
-    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-  }
+  glFinishFenceNV(fence_);
 }
 
 void GLFenceNV::ServerWait() {
diff --git a/ui/gl/gl_fence_nv.h b/ui/gl/gl_fence_nv.h
index 0bac11c..b1dc88f 100644
--- a/ui/gl/gl_fence_nv.h
+++ b/ui/gl/gl_fence_nv.h
@@ -7,14 +7,13 @@
 
 #include "base/macros.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence.h"
 
 namespace gfx {
 
 class GL_EXPORT GLFenceNV : public GLFence {
  public:
-  GLFenceNV(bool flush);
+  GLFenceNV();
   ~GLFenceNV() override;
 
   // GLFence implementation:
@@ -24,7 +23,6 @@
 
  private:
   GLuint fence_;
-  scoped_refptr<GLContext::FlushEvent> flush_event_;
 
   DISALLOW_COPY_AND_ASSIGN(GLFenceNV);
 };
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index fada5e3..81a1b72 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -395,11 +395,6 @@
   driver_ = driver;
 }
 
-void GLApiBase::SignalFlush() {
-  DCHECK(GLContext::GetCurrent());
-  GLContext::GetCurrent()->OnFlush();
-}
-
 RealGLApi::RealGLApi() {
 }
 
@@ -412,12 +407,10 @@
 
 void RealGLApi::glFlushFn() {
   GLApiBase::glFlushFn();
-  GLApiBase::SignalFlush();
 }
 
 void RealGLApi::glFinishFn() {
   GLApiBase::glFinishFn();
-  GLApiBase::SignalFlush();
 }
 
 TraceGLApi::~TraceGLApi() {
@@ -525,12 +518,10 @@
 
 void VirtualGLApi::glFlushFn() {
   GLApiBase::glFlushFn();
-  GLApiBase::SignalFlush();
 }
 
 void VirtualGLApi::glFinishFn() {
   GLApiBase::glFinishFn();
-  GLApiBase::SignalFlush();
 }
 
 ScopedSetGLToRealGLApi::ScopedSetGLToRealGLApi()
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h
index 1b23097..d408600 100644
--- a/ui/gl/gl_gl_api_implementation.h
+++ b/ui/gl/gl_gl_api_implementation.h
@@ -44,7 +44,6 @@
   GLApiBase();
   ~GLApiBase() override;
   void InitializeBase(DriverGL* driver);
-  void SignalFlush();
 
   DriverGL* driver_;
 };
diff --git a/ui/gl/gl_image_surface_texture.h b/ui/gl/gl_image_surface_texture.h
index eaf4363..d2ff5b7 100644
--- a/ui/gl/gl_image_surface_texture.h
+++ b/ui/gl/gl_image_surface_texture.h
@@ -19,23 +19,23 @@
   bool Initialize(SurfaceTexture* surface_texture);
 
   // Overridden from GLImage:
-  virtual void Destroy(bool have_context) override;
-  virtual gfx::Size GetSize() override;
-  virtual bool BindTexImage(unsigned target) override;
-  virtual void ReleaseTexImage(unsigned target) override {}
-  virtual bool CopyTexImage(unsigned target) override;
-  virtual void WillUseTexImage() override {}
-  virtual void DidUseTexImage() override {}
-  virtual void WillModifyTexImage() override {}
-  virtual void DidModifyTexImage() override {}
-  virtual bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
-                                    int z_order,
-                                    OverlayTransform transform,
-                                    const Rect& bounds_rect,
-                                    const RectF& crop_rect) override;
+  void Destroy(bool have_context) override;
+  gfx::Size GetSize() override;
+  bool BindTexImage(unsigned target) override;
+  void ReleaseTexImage(unsigned target) override {}
+  bool CopyTexImage(unsigned target) override;
+  void WillUseTexImage() override {}
+  void DidUseTexImage() override {}
+  void WillModifyTexImage() override {}
+  void DidModifyTexImage() override {}
+  bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+                            int z_order,
+                            OverlayTransform transform,
+                            const Rect& bounds_rect,
+                            const RectF& crop_rect) override;
 
  protected:
-  virtual ~GLImageSurfaceTexture();
+  ~GLImageSurfaceTexture() override;
 
  private:
   scoped_refptr<SurfaceTexture> surface_texture_;
diff --git a/url/gurl.h b/url/gurl.h
index ef1e529..566fc5e 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -18,8 +18,8 @@
 
 class URL_EXPORT GURL {
  public:
-  typedef url::StdStringReplacements<std::string> Replacements;
-  typedef url::StdStringReplacements<base::string16> ReplacementsW;
+  typedef url::StringPieceReplacements<std::string> Replacements;
+  typedef url::StringPieceReplacements<base::string16> ReplacementsW;
 
   // Creates an empty, invalid URL.
   GURL();
diff --git a/url/url_canon_stdstring.h b/url/url_canon_stdstring.h
index c3d8ba1..662cac7 100644
--- a/url/url_canon_stdstring.h
+++ b/url/url_canon_stdstring.h
@@ -12,6 +12,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
+#include "base/strings/string_piece.h"
 #include "url/url_canon.h"
 #include "url/url_export.h"
 
@@ -48,35 +49,35 @@
 };
 
 // An extension of the Replacements class that allows the setters to use
-// standard strings.
+// StringPieces (implicitly allowing strings or char*s).
 //
-// The strings passed as arguments are not copied and must remain valid until
-// this class goes out of scope.
+// The contents of the StringPieces are not copied and must remain valid until
+// the StringPieceReplacements object goes out of scope.
 template<typename STR>
-class StdStringReplacements : public Replacements<typename STR::value_type> {
+class StringPieceReplacements : public Replacements<typename STR::value_type> {
  public:
-  void SetSchemeStr(const STR& s) {
+  void SetSchemeStr(const base::BasicStringPiece<STR>& s) {
     this->SetScheme(s.data(), Component(0, static_cast<int>(s.length())));
   }
-  void SetUsernameStr(const STR& s) {
+  void SetUsernameStr(const base::BasicStringPiece<STR>& s) {
     this->SetUsername(s.data(), Component(0, static_cast<int>(s.length())));
   }
-  void SetPasswordStr(const STR& s) {
+  void SetPasswordStr(const base::BasicStringPiece<STR>& s) {
     this->SetPassword(s.data(), Component(0, static_cast<int>(s.length())));
   }
-  void SetHostStr(const STR& s) {
+  void SetHostStr(const base::BasicStringPiece<STR>& s) {
     this->SetHost(s.data(), Component(0, static_cast<int>(s.length())));
   }
-  void SetPortStr(const STR& s) {
+  void SetPortStr(const base::BasicStringPiece<STR>& s) {
     this->SetPort(s.data(), Component(0, static_cast<int>(s.length())));
   }
-  void SetPathStr(const STR& s) {
+  void SetPathStr(const base::BasicStringPiece<STR>& s) {
     this->SetPath(s.data(), Component(0, static_cast<int>(s.length())));
   }
-  void SetQueryStr(const STR& s) {
+  void SetQueryStr(const base::BasicStringPiece<STR>& s) {
     this->SetQuery(s.data(), Component(0, static_cast<int>(s.length())));
   }
-  void SetRefStr(const STR& s) {
+  void SetRefStr(const base::BasicStringPiece<STR>& s) {
     this->SetRef(s.data(), Component(0, static_cast<int>(s.length())));
   }
 };