Update from https://crrev.com/319330
- New chromium clang rules require explicit external destructors so
  system/lib added for MessagePipe, DataPipe and SharedBuffer
- New chromium clang rules require override and no virtual in
  declarations, so many files updated.
- cc_strip_video patch updated.

BUG=
R=jamesr@chromium.org

Review URL: https://codereview.chromium.org/988693005
diff --git a/DEPS b/DEPS
index b0da0d6..bc8e552 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': 'f47e70712b964b5360a3fec9e5e84bb594fc1f02',
+  'skia_revision': 'a9baa652bb329b5a286e1638938f63433701efca',
   # 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': 'f63eb3696b36b47be841f52711176985e93b655c',
+  'v8_revision': 'a1d36b4b6b1a3bb35d3bc5b64fbd5de9f55fed26',
   # 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': '7825f6199ce25dffe5fec5addb2fafe37f187034',
+  'angle_revision': '019304886ad8b985d67202edec431407bb1b5c53',
   # 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': '93b3d0af1b30db55ee42bd2e983f7753153217db',
+  'buildtools_revision': 'd4dd4f79f60bf019625b3a1436979b0a42c892df',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Dart
   # and whatever else without interference from each other.
@@ -79,10 +79,10 @@
    Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
 
   'src/third_party/icu':
-   Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '2081ee6abfa118003fd559cb72393f5df561dba7',
+   Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'eda9e75b1fa17f57ffa369ee3543a2301b68d0a9',
 
   'src/tools/grit':
-    Var('chromium_git') + '/external/grit-i18n.git' + '@' + 'a5890a8118c0c80cc0560e6d8d5cf65e5d725509', # from svn revision 185
+    Var('chromium_git') + '/external/grit-i18n.git' + '@' + '0287c187b11ed53590254e4d817e836a44a7a1a7', # from svn revision 186
 
   'src/v8':
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
@@ -124,7 +124,7 @@
    'https://boringssl.googlesource.com/boringssl.git' + '@' +  Var('boringssl_revision'),
 
   'src/tools/gyp':
-    Var('chromium_git') + '/external/gyp.git' + '@' + '34640080d08ab2a37665512e52142947def3056d', # from svn revision 2028
+    Var('chromium_git') + '/external/gyp.git' + '@' + '4a9b712d5cb4a5ba7a9950128a7219569caf7263',
 }
 
 
diff --git a/DEPS.nacl b/DEPS.nacl
index cd06226..92386bb 100644
--- a/DEPS.nacl
+++ b/DEPS.nacl
@@ -7,7 +7,7 @@
 # Now we need to add in NaCl.
 
 vars.update({
-  'nacl_revision': '62b6f76d587ef1f7e9231815fd31fef0a1dca6ff',
+  'nacl_revision': '19f11aa481261f38f2a1e9a04e41a7e12aa70e32',
 })
 
 deps.update({
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 9dbc41c..402b19a 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -15,6 +15,8 @@
     "allocator/allocator_extension.h",
     "allocator/type_profiler_control.cc",
     "allocator/type_profiler_control.h",
+    "android/animation_frame_time_histogram.cc",
+    "android/animation_frame_time_histogram.h",
     "android/application_status_listener.cc",
     "android/application_status_listener.h",
     "android/base_jni_onload.cc",
@@ -386,18 +388,18 @@
     "metrics/histogram.h",
     "metrics/histogram_base.cc",
     "metrics/histogram_base.h",
-    "metrics/histogram_delta_serialization.cc",
-    "metrics/sample_map.cc",
-    "metrics/sample_map.h",
-    "metrics/sample_vector.cc",
-    "metrics/sample_vector.h",
     "metrics/histogram_delta_serialization.",
+    "metrics/histogram_delta_serialization.cc",
     "metrics/histogram_flattener.h",
     "metrics/histogram_macros.h",
     "metrics/histogram_samples.cc",
     "metrics/histogram_samples.h",
     "metrics/histogram_snapshot_manager.cc",
     "metrics/histogram_snapshot_manager.h",
+    "metrics/sample_map.cc",
+    "metrics/sample_map.h",
+    "metrics/sample_vector.cc",
+    "metrics/sample_vector.h",
     "metrics/sparse_histogram.cc",
     "metrics/sparse_histogram.h",
     "metrics/statistics_recorder.cc",
@@ -783,9 +785,9 @@
       "files/file_proxy.cc",
       "files/file_util.cc",
       "files/file_util_proxy.cc",
+      "files/scoped_temp_dir.cc",
       "path_service.cc",
       "scoped_native_library.cc",
-      "files/scoped_temp_dir.cc",
     ]
   }
 
@@ -1066,6 +1068,8 @@
 source_set("prefs") {
   sources = [
     "prefs/base_prefs_export.h",
+    "prefs/base_prefs_switches.cc",
+    "prefs/base_prefs_switches.h",
     "prefs/default_pref_store.cc",
     "prefs/default_pref_store.h",
     "prefs/json_pref_store.cc",
@@ -1163,6 +1167,8 @@
 }
 
 if (is_win) {
+  # Target to manually rebuild pe_image_test.dll which is checked into
+  # base/test/data/pe_image.
   shared_library("pe_image_test") {
     sources = [
       "win/pe_image_test.cc",
@@ -1487,10 +1493,6 @@
     set_sources_assignment_filter(sources_assignment_filter)
   }
 
-  if (is_win) {
-    deps += [ ":pe_image_test" ]
-  }
-
   # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 }
@@ -1500,6 +1502,7 @@
   generate_jni("base_jni_headers") {
     sources = [
       "android/java/src/org/chromium/base/ApplicationStatus.java",
+      "android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java",
       "android/java/src/org/chromium/base/BuildInfo.java",
       "android/java/src/org/chromium/base/CommandLine.java",
       "android/java/src/org/chromium/base/ContentUriUtils.java",
diff --git a/base/android/animation_frame_time_histogram.cc b/base/android/animation_frame_time_histogram.cc
new file mode 100644
index 0000000..0d79619
--- /dev/null
+++ b/base/android/animation_frame_time_histogram.cc
@@ -0,0 +1,36 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/animation_frame_time_histogram.h"
+
+#include "base/android/jni_string.h"
+#include "base/metrics/histogram_macros.h"
+#include "jni/AnimationFrameTimeHistogram_jni.h"
+
+// static
+void SaveHistogram(JNIEnv* env,
+                   jobject jcaller,
+                   jstring j_histogram_name,
+                   jlongArray j_frame_times_ms,
+                   jint j_count) {
+  jlong *frame_times_ms = env->GetLongArrayElements(j_frame_times_ms, NULL);
+  std::string histogram_name = base::android::ConvertJavaStringToUTF8(
+      env, j_histogram_name);
+
+  for (int i = 0; i < j_count; ++i) {
+    UMA_HISTOGRAM_TIMES(histogram_name.c_str(),
+                        base::TimeDelta::FromMilliseconds(frame_times_ms[i]));
+  }
+}
+
+namespace base {
+namespace android {
+
+// static
+bool RegisterAnimationFrameTimeHistogram(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/base/android/animation_frame_time_histogram.h b/base/android/animation_frame_time_histogram.h
new file mode 100644
index 0000000..63f938b
--- /dev/null
+++ b/base/android/animation_frame_time_histogram.h
@@ -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.
+
+#ifndef BASE_ANDROID_ANIMATION_FRAME_TIME_HISTOGRAM_H_
+#define BASE_ANDROID_ANIMATION_FRAME_TIME_HISTOGRAM_H_
+
+#include <jni.h>
+
+namespace base {
+namespace android {
+
+bool RegisterAnimationFrameTimeHistogram(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_ANIMATION_FRAME_TIME_HISTOGRAM_H_
diff --git a/base/android/base_jni_registrar.cc b/base/android/base_jni_registrar.cc
index 4dda482..7439d3c 100644
--- a/base/android/base_jni_registrar.cc
+++ b/base/android/base_jni_registrar.cc
@@ -4,6 +4,7 @@
 
 #include "base/android/base_jni_registrar.h"
 
+#include "base/android/animation_frame_time_histogram.h"
 #include "base/android/application_status_listener.h"
 #include "base/android/build_info.h"
 #include "base/android/command_line_android.h"
@@ -33,6 +34,8 @@
 namespace android {
 
 static RegistrationMethod kBaseRegisteredMethods[] = {
+    {"AnimationFrameTimeHistogram",
+     base::android::RegisterAnimationFrameTimeHistogram},
     {"ApplicationStatusListener",
      base::android::ApplicationStatusListener::RegisterBindings},
     {"BuildInfo", base::android::BuildInfo::RegisterBindings},
diff --git a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
new file mode 100644
index 0000000..ad5cdd8
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
@@ -0,0 +1,145 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.TimeAnimator;
+import android.animation.TimeAnimator.TimeListener;
+import android.util.Log;
+
+/**
+ * Record Android animation frame rate and save it to UMA histogram. This is mainly for monitoring
+ * any jankiness of short Chrome Android animations. It is limited to few seconds of recording.
+ */
+public class AnimationFrameTimeHistogram {
+    private static final String TAG = "AnimationFrameTimeHistogram";
+    private static final int MAX_FRAME_TIME_NUM = 600; // 10 sec on 60 fps.
+
+    private final Recorder mRecorder = new Recorder();
+    private final String mHistogramName;
+
+    /**
+     * @param histogramName The histogram name that the recorded frame times will be saved.
+     *                      This must be also defined in histograms.xml
+     * @return An AnimatorListener instance that records frame time histogram on start and end
+     *         automatically.
+     */
+    public static AnimatorListener getAnimatorRecorder(final String histogramName) {
+        return new AnimatorListenerAdapter() {
+            private final AnimationFrameTimeHistogram mAnimationFrameTimeHistogram =
+                    new AnimationFrameTimeHistogram(histogramName);
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mAnimationFrameTimeHistogram.startRecording();
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimationFrameTimeHistogram.endRecording();
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mAnimationFrameTimeHistogram.endRecording();
+            }
+        };
+    }
+
+    /**
+     * @param histogramName The histogram name that the recorded frame times will be saved.
+     *                      This must be also defined in histograms.xml
+     */
+    public AnimationFrameTimeHistogram(String histogramName) {
+        mHistogramName = histogramName;
+    }
+
+    /**
+     * Start recording frame times. The recording can fail if it exceeds a few seconds.
+     */
+    public void startRecording() {
+        mRecorder.startRecording();
+    }
+
+    /**
+     * End recording and save it to histogram. It won't save histogram if the recording wasn't
+     * successful.
+     */
+    public void endRecording() {
+        if (mRecorder.endRecording()) {
+            nativeSaveHistogram(mHistogramName,
+                    mRecorder.getFrameTimesMs(), mRecorder.getFrameTimesCount());
+        }
+        mRecorder.cleanUp();
+    }
+
+    /**
+     * Record Android animation frame rate and return the result.
+     */
+    private static class Recorder implements TimeListener {
+        // TODO(kkimlabs): If we can use in the future, migrate to Choreographer for minimal
+        //                 workload.
+        private final TimeAnimator mAnimator = new TimeAnimator();
+        private long[] mFrameTimesMs;
+        private int mFrameTimesCount;
+
+        private Recorder() {
+            mAnimator.setTimeListener(this);
+        }
+
+        private void startRecording() {
+            assert !mAnimator.isRunning();
+            mFrameTimesCount = 0;
+            mFrameTimesMs = new long[MAX_FRAME_TIME_NUM];
+            mAnimator.start();
+        }
+
+        /**
+         * @return Whether the recording was successful. If successful, the result is available via
+         *         getFrameTimesNs and getFrameTimesCount.
+         */
+        private boolean endRecording() {
+            boolean succeeded = mAnimator.isStarted();
+            mAnimator.end();
+            return succeeded;
+        }
+
+        private long[] getFrameTimesMs() {
+            return mFrameTimesMs;
+        }
+
+        private int getFrameTimesCount() {
+            return mFrameTimesCount;
+        }
+
+        /**
+         * Deallocates the temporary buffer to record frame times. Must be called after ending
+         * the recording and getting the result.
+         */
+        private void cleanUp() {
+            mFrameTimesMs = null;
+        }
+
+        @Override
+        public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+            if (mFrameTimesCount == mFrameTimesMs.length) {
+                mAnimator.end();
+                cleanUp();
+                Log.w(TAG, "Animation frame time recording reached the maximum number. It's either"
+                        + "the animation took too long or recording end is not called.");
+                return;
+            }
+
+            // deltaTime is 0 for the first frame.
+            if (deltaTime > 0) {
+                mFrameTimesMs[mFrameTimesCount++] = deltaTime;
+            }
+        }
+    }
+
+    private native void nativeSaveHistogram(String histogramName, long[] frameTimesMs, int count);
+}
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index c03cad2..4198853 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -72,13 +72,6 @@
     }
 
     /**
-     * @return True if the running version of the Android supports HTML clipboard.
-     */
-    public static boolean isHTMLClipboardSupported() {
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-    }
-
-    /**
      * @see android.view.View#setLayoutDirection(int)
      */
     public static void setLayoutDirection(View view, int layoutDirection) {
diff --git a/base/base.gyp b/base/base.gyp
index 30de275..3888ad9 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -338,6 +338,8 @@
       ],
       'sources': [
         'prefs/base_prefs_export.h',
+        'prefs/base_prefs_switches.cc',
+        'prefs/base_prefs_switches.h',
         'prefs/default_pref_store.cc',
         'prefs/default_pref_store.h',
         'prefs/json_pref_store.cc',
@@ -382,12 +384,18 @@
       # TODO(pasko): Remove this target when crbug.com/424562 is fixed.
       # GN: //base:protect_file_posix
       'target_name': 'protect_file_posix',
-      'type': 'static_library',
-      'dependencies': [
-        'base',
-      ],
-      'sources': [
-        'files/protect_file_posix.cc',
+      'conditions': [
+        ['os_posix == 1', {
+          'type': 'static_library',
+          'dependencies': [
+            'base',
+          ],
+          'sources': [
+            'files/protect_file_posix.cc',
+          ],
+        }, {
+          'type': 'none',
+        }],
       ],
     },
     {
@@ -778,9 +786,6 @@
             'message_loop/message_pump_libevent_unittest.cc',
             'threading/worker_pool_posix_unittest.cc',
           ],
-          'dependencies': [
-            'pe_image_test',
-          ],
           # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
           'msvs_disabled_warnings': [
             4267,
@@ -941,6 +946,8 @@
         'test/mock_chrome_application_mac.mm',
         'test/mock_devices_changed_observer.cc',
         'test/mock_devices_changed_observer.h',
+        'test/mock_log.cc',
+        'test/mock_log.h',
         'test/multiprocess_test.cc',
         'test/multiprocess_test.h',
         'test/multiprocess_test_android.cc',
@@ -1336,6 +1343,7 @@
           'type': 'none',
           'sources': [
             'android/java/src/org/chromium/base/ApplicationStatus.java',
+            'android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java',
             'android/java/src/org/chromium/base/BuildInfo.java',
             'android/java/src/org/chromium/base/CommandLine.java',
             'android/java/src/org/chromium/base/ContentUriUtils.java',
@@ -1551,6 +1559,8 @@
           },
         },
         {
+          # Target to manually rebuild pe_image_test.dll which is checked into
+          # base/test/data/pe_image.
           'target_name': 'pe_image_test',
           'type': 'shared_library',
           'sources': [
diff --git a/base/base.gypi b/base/base.gypi
index 148246f..0f8fff2 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -17,6 +17,8 @@
           'allocator/allocator_extension.h',
           'allocator/type_profiler_control.cc',
           'allocator/type_profiler_control.h',
+          'android/animation_frame_time_histogram.cc',
+          'android/animation_frame_time_histogram.h',
           'android/application_status_listener.cc',
           'android/application_status_listener.h',
           'android/base_jni_onload.cc',
diff --git a/base/base_nacl.gyp b/base/base_nacl.gyp
index 63e1ed4..90a2893 100644
--- a/base/base_nacl.gyp
+++ b/base/base_nacl.gyp
@@ -7,8 +7,12 @@
     'chromium_code': 1,
   },
   'includes': [
-    '../build/common_untrusted.gypi',
+    # base.gypi must be included before common_untrusted.gypi.
+    #
+    # TODO(sergeyu): Replace the target_defaults magic in base.gypi with a
+    # sources variables lists. That way order of includes will not matter.
     'base.gypi',
+    '../build/common_untrusted.gypi',
   ],
   'conditions': [
     ['disable_nacl==0 and disable_nacl_untrusted==0', {
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate
index e5495e3..5126fb3 100644
--- a/base/base_unittests.isolate
+++ b/base/base_unittests.isolate
@@ -19,7 +19,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
@@ -52,7 +51,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
@@ -72,13 +70,6 @@
         ],
       },
     }],
-    ['OS=="win"', {
-      'variables': {
-        'files': [
-          '<(PRODUCT_DIR)/pe_image_test.dll',
-        ],
-      },
-    }],
   ],
   'includes': [
     'base.isolate',
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
index 63e5480..f6d0029 100644
--- a/base/files/file_path_watcher_win.cc
+++ b/base/files/file_path_watcher_win.cc
@@ -11,7 +11,6 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop_proxy.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/time/time.h"
 #include "base/win/object_watcher.h"
 
@@ -147,11 +146,6 @@
 }
 
 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(
-          "418183 FilePathWatcherImpl::OnObjectSignaled"));
-
   DCHECK(object == handle_);
   // Make sure we stay alive through the body of this function.
   scoped_refptr<FilePathWatcherImpl> keep_alive(this);
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc
index d256236..47b0b09 100644
--- a/base/files/important_file_writer.cc
+++ b/base/files/important_file_writer.cc
@@ -10,12 +10,14 @@
 
 #include "base/bind.h"
 #include "base/critical_closure.h"
+#include "base/debug/alias.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/task_runner.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread.h"
@@ -54,6 +56,20 @@
 // static
 bool ImportantFileWriter::WriteFileAtomically(const FilePath& path,
                                               const std::string& data) {
+#if defined(OS_CHROMEOS)
+  // On Chrome OS, chrome gets killed when it cannot finish shutdown quickly,
+  // and this function seems to be one of the slowest shutdown steps.
+  // Include some info to the report for investigation. crbug.com/418627
+  // TODO(hashimoto): Remove this.
+  struct {
+    size_t data_size;
+    char path[128];
+  } file_info;
+  file_info.data_size = data.size();
+  base::strlcpy(file_info.path, path.value().c_str(),
+                arraysize(file_info.path));
+  base::debug::Alias(&file_info);
+#endif
   // Write the data to a temp file then rename to avoid data loss if we crash
   // while writing the file. Ensure that the temp file is on the same volume
   // as target file, so it can be moved in one step, and that the temp file
diff --git a/base/json/json_file_value_serializer.cc b/base/json/json_file_value_serializer.cc
index 71033f6..72a0970 100644
--- a/base/json/json_file_value_serializer.cc
+++ b/base/json/json_file_value_serializer.cc
@@ -10,16 +10,14 @@
 
 using base::FilePath;
 
-const char JSONFileValueSerializer::kAccessDenied[] = "Access denied.";
-const char JSONFileValueSerializer::kCannotReadFile[] = "Can't read file.";
-const char JSONFileValueSerializer::kFileLocked[] = "File locked.";
-const char JSONFileValueSerializer::kNoSuchFile[] = "File doesn't exist.";
+const char JSONFileValueDeserializer::kAccessDenied[] = "Access denied.";
+const char JSONFileValueDeserializer::kCannotReadFile[] = "Can't read file.";
+const char JSONFileValueDeserializer::kFileLocked[] = "File locked.";
+const char JSONFileValueDeserializer::kNoSuchFile[] = "File doesn't exist.";
 
 JSONFileValueSerializer::JSONFileValueSerializer(
     const base::FilePath& json_file_path)
-    : json_file_path_(json_file_path),
-      allow_trailing_comma_(false),
-      last_read_size_(0U) {
+    : json_file_path_(json_file_path) {
 }
 
 JSONFileValueSerializer::~JSONFileValueSerializer() {
@@ -53,7 +51,17 @@
   return true;
 }
 
-int JSONFileValueSerializer::ReadFileToString(std::string* json_string) {
+JSONFileValueDeserializer::JSONFileValueDeserializer(
+    const base::FilePath& json_file_path)
+    : json_file_path_(json_file_path),
+      allow_trailing_comma_(false),
+      last_read_size_(0U) {
+}
+
+JSONFileValueDeserializer::~JSONFileValueDeserializer() {
+}
+
+int JSONFileValueDeserializer::ReadFileToString(std::string* json_string) {
   DCHECK(json_string);
   if (!base::ReadFileToString(json_file_path_, json_string)) {
 #if defined(OS_WIN)
@@ -74,7 +82,7 @@
   return JSON_NO_ERROR;
 }
 
-const char* JSONFileValueSerializer::GetErrorMessageForCode(int error_code) {
+const char* JSONFileValueDeserializer::GetErrorMessageForCode(int error_code) {
   switch (error_code) {
     case JSON_NO_ERROR:
       return "";
@@ -92,8 +100,8 @@
   }
 }
 
-base::Value* JSONFileValueSerializer::Deserialize(int* error_code,
-                                                  std::string* error_str) {
+base::Value* JSONFileValueDeserializer::Deserialize(int* error_code,
+                                                    std::string* error_str) {
   std::string json_string;
   int error = ReadFileToString(&json_string);
   if (error != JSON_NO_ERROR) {
@@ -104,7 +112,7 @@
     return NULL;
   }
 
-  JSONStringValueSerializer serializer(json_string);
-  serializer.set_allow_trailing_comma(allow_trailing_comma_);
-  return serializer.Deserialize(error_code, error_str);
+  JSONStringValueDeserializer deserializer(json_string);
+  deserializer.set_allow_trailing_comma(allow_trailing_comma_);
+  return deserializer.Deserialize(error_code, error_str);
 }
diff --git a/base/json/json_file_value_serializer.h b/base/json/json_file_value_serializer.h
index 6cfcbe8..aab47ee 100644
--- a/base/json/json_file_value_serializer.h
+++ b/base/json/json_file_value_serializer.h
@@ -14,10 +14,9 @@
 
 class BASE_EXPORT JSONFileValueSerializer : public base::ValueSerializer {
  public:
-  // |json_file_path_| is the path of a file that will be source of the
-  // deserialization or the destination of the serialization.
-  // When deserializing, the file should exist, but when serializing, the
-  // serializer will attempt to create the file at the specified location.
+  // |json_file_path_| is the path of a file that will be destination of the
+  // serialization. The serializer will attempt to create the file at the
+  // specified location.
   explicit JSONFileValueSerializer(const base::FilePath& json_file_path);
 
   ~JSONFileValueSerializer() override;
@@ -36,6 +35,22 @@
   // output.
   bool SerializeAndOmitBinaryValues(const base::Value& root);
 
+ private:
+  bool SerializeInternal(const base::Value& root, bool omit_binary_values);
+
+  const base::FilePath json_file_path_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSONFileValueSerializer);
+};
+
+class BASE_EXPORT JSONFileValueDeserializer : public base::ValueDeserializer {
+ public:
+  // |json_file_path_| is the path of a file that will be source of the
+  // deserialization.
+  explicit JSONFileValueDeserializer(const base::FilePath& json_file_path);
+
+  ~JSONFileValueDeserializer() override;
+
   // Attempt to deserialize the data structure encoded in the file 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
@@ -69,22 +84,20 @@
     allow_trailing_comma_ = new_value;
   }
 
-  // Returns the syze (in bytes) of JSON string read from disk in the last
+  // Returns the size (in bytes) of JSON string read from disk in the last
   // successful |Deserialize()| call.
   size_t get_last_read_size() const { return last_read_size_; }
 
  private:
-  bool SerializeInternal(const base::Value& root, bool omit_binary_values);
+  // A wrapper for ReadFileToString which returns a non-zero JsonFileError if
+  // there were file errors.
+  int ReadFileToString(std::string* json_string);
 
   const base::FilePath json_file_path_;
   bool allow_trailing_comma_;
   size_t last_read_size_;
 
-  // A wrapper for ReadFileToString which returns a non-zero JsonFileError if
-  // there were file errors.
-  int ReadFileToString(std::string* json_string);
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(JSONFileValueSerializer);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSONFileValueDeserializer);
 };
 
 #endif  // BASE_JSON_JSON_FILE_VALUE_SERIALIZER_H_
diff --git a/base/json/json_string_value_serializer.cc b/base/json/json_string_value_serializer.cc
index b626640..debf9f0 100644
--- a/base/json/json_string_value_serializer.cc
+++ b/base/json/json_string_value_serializer.cc
@@ -12,17 +12,7 @@
 
 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) {
+      pretty_print_(false) {
 }
 
 JSONStringValueSerializer::~JSONStringValueSerializer() {}
@@ -50,9 +40,17 @@
   return base::JSONWriter::WriteWithOptions(&root, options, json_string_);
 }
 
-Value* JSONStringValueSerializer::Deserialize(int* error_code,
-                                              std::string* error_str) {
-  return base::JSONReader::ReadAndReturnError(json_string_readonly_,
+JSONStringValueDeserializer::JSONStringValueDeserializer(
+    const base::StringPiece& json_string)
+    : json_string_(json_string),
+      allow_trailing_comma_(false) {
+}
+
+JSONStringValueDeserializer::~JSONStringValueDeserializer() {}
+
+Value* JSONStringValueDeserializer::Deserialize(int* error_code,
+                                                std::string* error_str) {
+  return base::JSONReader::ReadAndReturnError(json_string_,
       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 7f99bc9..bc0e66d 100644
--- a/base/json/json_string_value_serializer.h
+++ b/base/json/json_string_value_serializer.h
@@ -15,16 +15,11 @@
 
 class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer {
  public:
-  // |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. |json_string| must not be null.
+  // |json_string| is the string that will be the destination of the
+  // serialization.  The caller of the constructor retains ownership of the
+  // string. |json_string| must not be null.
   explicit JSONStringValueSerializer(std::string* json_string);
 
-  // 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;
 
   // Attempt to serialize the data structure represented by Value into
@@ -36,6 +31,27 @@
   // output.
   bool SerializeAndOmitBinaryValues(const base::Value& root);
 
+  void set_pretty_print(bool new_value) { pretty_print_ = new_value; }
+  bool pretty_print() { return pretty_print_; }
+
+ private:
+  bool SerializeInternal(const base::Value& root, bool omit_binary_values);
+
+  // Owned by the caller of the constructor.
+  std::string* json_string_;
+  bool pretty_print_;  // If true, serialization will span multiple lines.
+
+  DISALLOW_COPY_AND_ASSIGN(JSONStringValueSerializer);
+};
+
+class BASE_EXPORT JSONStringValueDeserializer : public base::ValueDeserializer {
+ public:
+  // This retains a reference to the contents of |json_string|, so the data
+  // must outlive the JSONStringValueDeserializer.
+  explicit JSONStringValueDeserializer(const base::StringPiece& json_string);
+
+  ~JSONStringValueDeserializer() override;
+
   // 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
@@ -46,28 +62,17 @@
   base::Value* Deserialize(int* error_code,
                            std::string* error_message) override;
 
-  void set_pretty_print(bool new_value) { pretty_print_ = new_value; }
-  bool pretty_print() { return pretty_print_; }
-
   void set_allow_trailing_comma(bool new_value) {
     allow_trailing_comma_ = new_value;
   }
 
  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_;
-  // 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.
+  // Data is owned by the caller of the constructor.
+  base::StringPiece json_string_;
   // If true, deserialization will allow trailing commas.
   bool allow_trailing_comma_;
 
-  DISALLOW_COPY_AND_ASSIGN(JSONStringValueSerializer);
+  DISALLOW_COPY_AND_ASSIGN(JSONStringValueDeserializer);
 };
 
 #endif  // BASE_JSON_JSON_STRING_VALUE_SERIALIZER_H_
-
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc
index d2a84de..225ee67 100644
--- a/base/json/json_value_serializer_unittest.cc
+++ b/base/json/json_value_serializer_unittest.cc
@@ -86,28 +86,10 @@
   ASSERT_EQ(1, value);
 }
 
-// Test proper JSON [de]serialization from string is working.
-TEST(JSONValueSerializerTest, ReadProperJSONFromString) {
+// Test proper JSON deserialization from string is working.
+TEST(JSONValueDeserializerTest, 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);
+  JSONStringValueDeserializer str_deserializer(kProperJSON);
 
   int error_code = 0;
   std::string error_message;
@@ -121,12 +103,12 @@
 }
 
 // Test proper JSON deserialization from a StringPiece substring.
-TEST(JSONValueSerializerTest, ReadProperJSONFromStringPiece) {
+TEST(JSONValueDeserializerTest, 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);
+  JSONStringValueDeserializer str_deserializer(proper_json);
 
   int error_code = 0;
   std::string error_message;
@@ -141,9 +123,9 @@
 
 // Test that trialing commas are only properly deserialized from string when
 // the proper flag for that is set.
-TEST(JSONValueSerializerTest, ReadJSONWithTrailingCommasFromString) {
+TEST(JSONValueDeserializerTest, ReadJSONWithTrailingCommasFromString) {
   // Try to deserialize it through the serializer.
-  JSONStringValueSerializer str_deserializer(kProperJSONWithCommas);
+  JSONStringValueDeserializer str_deserializer(kProperJSONWithCommas);
 
   int error_code = 0;
   std::string error_message;
@@ -161,8 +143,8 @@
   CheckJSONIsStillTheSame(*value);
 }
 
-// Test proper JSON [de]serialization from file is working.
-TEST(JSONValueSerializerTest, ReadProperJSONFromFile) {
+// Test proper JSON deserialization from file is working.
+TEST(JSONValueDeserializerTest, ReadProperJSONFromFile) {
   ScopedTempDir tempdir;
   ASSERT_TRUE(tempdir.CreateUniqueTempDir());
   // Write it down in the file.
@@ -171,7 +153,7 @@
             WriteFile(temp_file, kProperJSON, strlen(kProperJSON)));
 
   // Try to deserialize it through the serializer.
-  JSONFileValueSerializer file_deserializer(temp_file);
+  JSONFileValueDeserializer file_deserializer(temp_file);
 
   int error_code = 0;
   std::string error_message;
@@ -186,7 +168,7 @@
 
 // Test that trialing commas are only properly deserialized from file when
 // the proper flag for that is set.
-TEST(JSONValueSerializerTest, ReadJSONWithCommasFromFile) {
+TEST(JSONValueDeserializerTest, ReadJSONWithCommasFromFile) {
   ScopedTempDir tempdir;
   ASSERT_TRUE(tempdir.CreateUniqueTempDir());
   // Write it down in the file.
@@ -196,7 +178,7 @@
                       strlen(kProperJSONWithCommas)));
 
   // Try to deserialize it through the serializer.
-  JSONFileValueSerializer file_deserializer(temp_file);
+  JSONFileValueDeserializer file_deserializer(temp_file);
   // This must fail without the proper flag.
   int error_code = 0;
   std::string error_message;
@@ -214,11 +196,27 @@
   CheckJSONIsStillTheSame(*value);
 }
 
+TEST(JSONValueDeserializerTest, AllowTrailingComma) {
+  scoped_ptr<Value> root;
+  scoped_ptr<Value> root_expected;
+  static const char kTestWithCommas[] = "{\"key\": [true,],}";
+  static const char kTestNoCommas[] = "{\"key\": [true]}";
+
+  JSONStringValueDeserializer deserializer(kTestWithCommas);
+  deserializer.set_allow_trailing_comma(true);
+  JSONStringValueDeserializer deserializer_expected(kTestNoCommas);
+  root.reset(deserializer.Deserialize(NULL, NULL));
+  ASSERT_TRUE(root.get());
+  root_expected.reset(deserializer_expected.Deserialize(NULL, NULL));
+  ASSERT_TRUE(root_expected.get());
+  ASSERT_TRUE(root->Equals(root_expected.get()));
+}
+
 TEST(JSONValueSerializerTest, Roundtrip) {
   static const char kOriginalSerialization[] =
     "{\"bool\":true,\"double\":3.14,\"int\":42,\"list\":[1,2],\"null\":null}";
-  JSONStringValueSerializer serializer(kOriginalSerialization);
-  scoped_ptr<Value> root(serializer.Deserialize(NULL, NULL));
+  JSONStringValueDeserializer deserializer(kOriginalSerialization);
+  scoped_ptr<Value> root(deserializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(root.get());
   ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
 
@@ -241,10 +239,6 @@
   ASSERT_TRUE(root_dict->GetDouble("double", &double_value));
   ASSERT_DOUBLE_EQ(3.14, double_value);
 
-  // We shouldn't be able to write using this serializer, since it was
-  // initialized with a const string.
-  ASSERT_FALSE(serializer.Serialize(*root_dict));
-
   std::string test_serialization;
   JSONStringValueSerializer mutable_serializer(&test_serialization);
   ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
@@ -331,7 +325,7 @@
   ASSERT_EQ(kExpected, actual);
 
   // escaped ascii text -> json
-  JSONStringValueSerializer deserializer(kExpected);
+  JSONStringValueDeserializer deserializer(kExpected);
   scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(deserial_root.get());
   DictionaryValue* dict_root =
@@ -355,7 +349,7 @@
   ASSERT_EQ(kExpected, actual);
 
   // escaped ascii text -> json
-  JSONStringValueSerializer deserializer(kExpected);
+  JSONStringValueDeserializer deserializer(kExpected);
   scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(deserial_root.get());
   DictionaryValue* dict_root =
@@ -366,7 +360,7 @@
 
   // Test converting escaped regular chars
   static const char kEscapedChars[] = "{\"test\":\"\\u0067\\u006f\"}";
-  JSONStringValueSerializer deserializer2(kEscapedChars);
+  JSONStringValueDeserializer deserializer2(kEscapedChars);
   deserial_root.reset(deserializer2.Deserialize(NULL, NULL));
   ASSERT_TRUE(deserial_root.get());
   dict_root = static_cast<DictionaryValue*>(deserial_root.get());
@@ -374,22 +368,6 @@
   ASSERT_EQ(ASCIIToUTF16("go"), test_value);
 }
 
-TEST(JSONValueSerializerTest, AllowTrailingComma) {
-  scoped_ptr<Value> root;
-  scoped_ptr<Value> root_expected;
-  static const char kTestWithCommas[] = "{\"key\": [true,],}";
-  static const char kTestNoCommas[] = "{\"key\": [true]}";
-
-  JSONStringValueSerializer serializer(kTestWithCommas);
-  serializer.set_allow_trailing_comma(true);
-  JSONStringValueSerializer serializer_expected(kTestNoCommas);
-  root.reset(serializer.Deserialize(NULL, NULL));
-  ASSERT_TRUE(root.get());
-  root_expected.reset(serializer_expected.Deserialize(NULL, NULL));
-  ASSERT_TRUE(root_expected.get());
-  ASSERT_TRUE(root->Equals(root_expected.get()));
-}
-
 TEST(JSONValueSerializerTest, JSONReaderComments) {
   ValidateJsonList("[ // 2, 3, ignore me ] \n1 ]");
   ValidateJsonList("[ /* 2, \n3, ignore me ]*/ \n1 ]");
@@ -435,7 +413,7 @@
 
   ASSERT_TRUE(PathExists(original_file_path));
 
-  JSONFileValueSerializer deserializer(original_file_path);
+  JSONFileValueDeserializer deserializer(original_file_path);
   scoped_ptr<Value> root;
   root.reset(deserializer.Deserialize(NULL, NULL));
 
@@ -483,7 +461,7 @@
 
   ASSERT_TRUE(PathExists(original_file_path));
 
-  JSONFileValueSerializer deserializer(original_file_path);
+  JSONFileValueDeserializer deserializer(original_file_path);
   scoped_ptr<Value> root;
   root.reset(deserializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(root.get());
@@ -508,9 +486,9 @@
   source_file_path = source_file_path.Append(
       FILE_PATH_LITERAL("serializer_test_nowhitespace.json"));
   ASSERT_TRUE(PathExists(source_file_path));
-  JSONFileValueSerializer serializer(source_file_path);
+  JSONFileValueDeserializer deserializer(source_file_path);
   scoped_ptr<Value> root;
-  root.reset(serializer.Deserialize(NULL, NULL));
+  root.reset(deserializer.Deserialize(NULL, NULL));
   ASSERT_TRUE(root.get());
 }
 
diff --git a/base/mac/foundation_util.h b/base/mac/foundation_util.h
index accc0d9..353ed7c 100644
--- a/base/mac/foundation_util.h
+++ b/base/mac/foundation_util.h
@@ -296,6 +296,7 @@
 CF_CAST_DECL(CGColor);
 
 CF_CAST_DECL(CTFont);
+CF_CAST_DECL(CTFontDescriptor);
 CF_CAST_DECL(CTRun);
 
 CF_CAST_DECL(SecACL);
diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm
index 2895b66..27d6e7c 100644
--- a/base/mac/foundation_util.mm
+++ b/base/mac/foundation_util.mm
@@ -362,6 +362,7 @@
 
 CF_CAST_DEFN(CGColor);
 
+CF_CAST_DEFN(CTFontDescriptor);
 CF_CAST_DEFN(CTRun);
 
 #if defined(OS_IOS)
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h
index 2795b19..25d937e 100644
--- a/base/mac/sdk_forward_declarations.h
+++ b/base/mac/sdk_forward_declarations.h
@@ -285,6 +285,10 @@
 - (NSString*)UUIDString;
 @end
 
+@interface NSControl (MountainLionSDK)
+@property BOOL allowsExpansionToolTips;
+@end
+
 #endif  // MAC_OS_X_VERSION_10_8
 
 
diff --git a/base/memory/discardable_memory_android.cc b/base/memory/discardable_memory_android.cc
index 5dcdfdc..2b35587 100644
--- a/base/memory/discardable_memory_android.cc
+++ b/base/memory/discardable_memory_android.cc
@@ -52,8 +52,8 @@
 void DiscardableMemory::GetSupportedTypes(
     std::vector<DiscardableMemoryType>* types) {
   const DiscardableMemoryType supported_types[] = {
-    DISCARDABLE_MEMORY_TYPE_ASHMEM,
     DISCARDABLE_MEMORY_TYPE_SHMEM,
+    DISCARDABLE_MEMORY_TYPE_ASHMEM,
     DISCARDABLE_MEMORY_TYPE_EMULATED
   };
   types->assign(supported_types, supported_types + arraysize(supported_types));
diff --git a/base/memory/discardable_memory_mac.cc b/base/memory/discardable_memory_mac.cc
index e0096e5..2881f5e 100644
--- a/base/memory/discardable_memory_mac.cc
+++ b/base/memory/discardable_memory_mac.cc
@@ -22,8 +22,8 @@
 void DiscardableMemory::GetSupportedTypes(
     std::vector<DiscardableMemoryType>* types) {
   const DiscardableMemoryType supported_types[] = {
-    DISCARDABLE_MEMORY_TYPE_MACH,
     DISCARDABLE_MEMORY_TYPE_SHMEM,
+    DISCARDABLE_MEMORY_TYPE_MACH,
     DISCARDABLE_MEMORY_TYPE_EMULATED
   };
   types->assign(supported_types, supported_types + arraysize(supported_types));
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h
index 59c5d5b..e3b437c 100644
--- a/base/memory/discardable_shared_memory.h
+++ b/base/memory/discardable_shared_memory.h
@@ -74,7 +74,7 @@
   // must have been mapped via Map().
   void* memory() const;
 
-  // Returns the last know usage time for DiscardableSharedMemory object. This
+  // Returns the last known usage time for DiscardableSharedMemory object. This
   // may be earlier than the "true" usage time when memory has been used by a
   // different process. Returns NULL time if purged.
   Time last_known_usage() const { return last_known_usage_; }
@@ -84,7 +84,7 @@
   // for two reasons; object might be locked or our last known usage timestamp
   // might be out of date. Last known usage time is updated to |current_time|
   // if locked or the actual last usage timestamp if unlocked. It is often
-  // neccesary to call this function twice for the object to successfully be
+  // necessary to call this function twice for the object to successfully be
   // purged. First call, updates |last_known_usage_|. Second call, successfully
   // purges the object using the updated |last_known_usage_|.
   // Note: there is no guarantee that multiple calls to this function will
diff --git a/base/prefs/base_prefs_switches.cc b/base/prefs/base_prefs_switches.cc
new file mode 100644
index 0000000..304248b
--- /dev/null
+++ b/base/prefs/base_prefs_switches.cc
@@ -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.
+
+#include "base/prefs/base_prefs_switches.h"
+
+namespace switches {
+
+// Pretty-prints pref JSON files.
+const char kPrettyPrintPrefs[] = "pretty-print-prefs";
+
+}  // namespace switches
diff --git a/base/prefs/base_prefs_switches.h b/base/prefs/base_prefs_switches.h
new file mode 100644
index 0000000..7a6b665
--- /dev/null
+++ b/base/prefs/base_prefs_switches.h
@@ -0,0 +1,14 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_PREFS_BASE_PREFS_SWITCHES_H_
+#define BASE_PREFS_BASE_PREFS_SWITCHES_H_
+
+namespace switches {
+
+extern const char kPrettyPrintPrefs[];
+
+}  // namespace switches
+
+#endif  // BASE_PREFS_BASE_PREFS_SWITCHES_H_
diff --git a/base/prefs/json_pref_store.cc b/base/prefs/json_pref_store.cc
index c52a95c..2e34b50 100644
--- a/base/prefs/json_pref_store.cc
+++ b/base/prefs/json_pref_store.cc
@@ -8,12 +8,14 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram.h"
+#include "base/prefs/base_prefs_switches.h"
 #include "base/prefs/pref_filter.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_util.h"
@@ -56,16 +58,16 @@
     DVLOG(1) << "Error while loading JSON file: " << error_msg
              << ", file: " << path.value();
     switch (error_code) {
-      case JSONFileValueSerializer::JSON_ACCESS_DENIED:
+      case JSONFileValueDeserializer::JSON_ACCESS_DENIED:
         return PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED;
         break;
-      case JSONFileValueSerializer::JSON_CANNOT_READ_FILE:
+      case JSONFileValueDeserializer::JSON_CANNOT_READ_FILE:
         return PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER;
         break;
-      case JSONFileValueSerializer::JSON_FILE_LOCKED:
+      case JSONFileValueDeserializer::JSON_FILE_LOCKED:
         return PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED;
         break;
-      case JSONFileValueSerializer::JSON_NO_SUCH_FILE:
+      case JSONFileValueDeserializer::JSON_NO_SUCH_FILE:
         return PersistentPrefStore::PREF_READ_ERROR_NO_FILE;
         break;
       default:
@@ -119,14 +121,14 @@
   std::string error_msg;
   scoped_ptr<JsonPrefStore::ReadResult> read_result(
       new JsonPrefStore::ReadResult);
-  JSONFileValueSerializer serializer(path);
-  read_result->value.reset(serializer.Deserialize(&error_code, &error_msg));
+  JSONFileValueDeserializer deserializer(path);
+  read_result->value.reset(deserializer.Deserialize(&error_code, &error_msg));
   read_result->error =
       HandleReadErrors(read_result->value.get(), path, error_code, error_msg);
   read_result->no_dir = !base::PathExists(path.DirName());
 
   if (read_result->error == PersistentPrefStore::PREF_READ_ERROR_NONE)
-    RecordJsonDataSizeHistogram(path, serializer.get_last_read_size());
+    RecordJsonDataSizeHistogram(path, deserializer.get_last_read_size());
 
   return read_result.Pass();
 }
@@ -398,7 +400,10 @@
     pref_filter_->FilterSerializeData(prefs_.get());
 
   JSONStringValueSerializer serializer(output);
-  serializer.set_pretty_print(true);
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kPrettyPrintPrefs)) {
+    serializer.set_pretty_print(true);
+  }
   return serializer.Serialize(*prefs_);
 }
 
diff --git a/base/process/kill.cc b/base/process/kill.cc
index caca348..a647d96 100644
--- a/base/process/kill.cc
+++ b/base/process/kill.cc
@@ -14,11 +14,8 @@
   bool result = true;
   NamedProcessIterator iter(executable_name, filter);
   while (const ProcessEntry* entry = iter.NextProcessEntry()) {
-#if defined(OS_WIN)
-    result &= KillProcessById(entry->pid(), exit_code, true);
-#else
-    result &= KillProcess(entry->pid(), exit_code, true);
-#endif
+    Process process = Process::Open(entry->pid());
+    result &= KillProcess(process.Handle(), exit_code, true);
   }
   return result;
 }
diff --git a/base/process/kill.h b/base/process/kill.h
index 8c0a213..df0d95e 100644
--- a/base/process/kill.h
+++ b/base/process/kill.h
@@ -57,12 +57,6 @@
 BASE_EXPORT bool KillProcessGroup(ProcessHandle process_group_id);
 #endif  // defined(OS_POSIX)
 
-#if defined(OS_WIN)
-BASE_EXPORT bool KillProcessById(ProcessId process_id,
-                                 int exit_code,
-                                 bool wait);
-#endif  // defined(OS_WIN)
-
 // Get the termination status of the process by interpreting the
 // circumstances of the child process' death. |exit_code| is set to
 // the status returned by waitpid() on POSIX, and from
@@ -94,22 +88,6 @@
     ProcessHandle handle, int* exit_code);
 #endif  // defined(OS_POSIX)
 
-// Waits for process to exit. On POSIX systems, if the process hasn't been
-// signaled then puts the exit code in |exit_code|; otherwise it's considered
-// a failure. On Windows |exit_code| is always filled. Returns true on success,
-// and closes |handle| in any case.
-BASE_EXPORT bool WaitForExitCode(ProcessHandle handle, int* exit_code);
-
-// Waits for process to exit. If it did exit within |timeout_milliseconds|,
-// then puts the exit code in |exit_code|, and returns true.
-// In POSIX systems, if the process has been signaled then |exit_code| is set
-// to -1. Returns false on failure (the caller is then responsible for closing
-// |handle|).
-// The caller is always responsible for closing the |handle|.
-BASE_EXPORT bool WaitForExitCodeWithTimeout(ProcessHandle handle,
-                                            int* exit_code,
-                                            base::TimeDelta timeout);
-
 // Wait for all the processes based on the named executable to exit.  If filter
 // is non-null, then only processes selected by the filter are waited on.
 // Returns after all processes have exited or wait_milliseconds have expired.
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc
index 77705ee..298486b 100644
--- a/base/process/kill_posix.cc
+++ b/base/process/kill_posix.cc
@@ -22,161 +22,6 @@
 
 namespace {
 
-#if !defined(OS_NACL_NONSFI)
-bool WaitpidWithTimeout(ProcessHandle handle,
-                        int* status,
-                        base::TimeDelta wait) {
-  // This POSIX version of this function only guarantees that we wait no less
-  // than |wait| for the process to exit.  The child process may
-  // exit sometime before the timeout has ended but we may still block for up
-  // to 256 milliseconds after the fact.
-  //
-  // waitpid() has no direct support on POSIX for specifying a timeout, you can
-  // either ask it to block indefinitely or return immediately (WNOHANG).
-  // When a child process terminates a SIGCHLD signal is sent to the parent.
-  // Catching this signal would involve installing a signal handler which may
-  // affect other parts of the application and would be difficult to debug.
-  //
-  // Our strategy is to call waitpid() once up front to check if the process
-  // has already exited, otherwise to loop for |wait|, sleeping for
-  // at most 256 milliseconds each time using usleep() and then calling
-  // waitpid().  The amount of time we sleep starts out at 1 milliseconds, and
-  // we double it every 4 sleep cycles.
-  //
-  // usleep() is speced to exit if a signal is received for which a handler
-  // has been installed.  This means that when a SIGCHLD is sent, it will exit
-  // depending on behavior external to this function.
-  //
-  // This function is used primarily for unit tests, if we want to use it in
-  // the application itself it would probably be best to examine other routes.
-
-  if (wait.InMilliseconds() == base::kNoTimeout) {
-    return HANDLE_EINTR(waitpid(handle, status, 0)) > 0;
-  }
-
-  pid_t ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
-  static const int64 kMaxSleepInMicroseconds = 1 << 18;  // ~256 milliseconds.
-  int64 max_sleep_time_usecs = 1 << 10;  // ~1 milliseconds.
-  int64 double_sleep_time = 0;
-
-  // If the process hasn't exited yet, then sleep and try again.
-  TimeTicks wakeup_time = TimeTicks::Now() + wait;
-  while (ret_pid == 0) {
-    TimeTicks now = TimeTicks::Now();
-    if (now > wakeup_time)
-      break;
-    // Guaranteed to be non-negative!
-    int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
-    // Sleep for a bit while we wait for the process to finish.
-    if (sleep_time_usecs > max_sleep_time_usecs)
-      sleep_time_usecs = max_sleep_time_usecs;
-
-    // usleep() will return 0 and set errno to EINTR on receipt of a signal
-    // such as SIGCHLD.
-    usleep(sleep_time_usecs);
-    ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
-
-    if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
-        (double_sleep_time++ % 4 == 0)) {
-      max_sleep_time_usecs *= 2;
-    }
-  }
-
-  return ret_pid > 0;
-}
-
-#if defined(OS_MACOSX)
-// Using kqueue on Mac so that we can wait on non-child processes.
-// We can't use kqueues on child processes because we need to reap
-// our own children using wait.
-static bool WaitForSingleNonChildProcess(ProcessHandle handle,
-                                         TimeDelta wait) {
-  DCHECK_GT(handle, 0);
-  DCHECK(wait.InMilliseconds() == kNoTimeout || wait > TimeDelta());
-
-  ScopedFD kq(kqueue());
-  if (!kq.is_valid()) {
-    DPLOG(ERROR) << "kqueue";
-    return false;
-  }
-
-  struct kevent change = {0};
-  EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
-  int result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
-  if (result == -1) {
-    if (errno == ESRCH) {
-      // If the process wasn't found, it must be dead.
-      return true;
-    }
-
-    DPLOG(ERROR) << "kevent (setup " << handle << ")";
-    return false;
-  }
-
-  // Keep track of the elapsed time to be able to restart kevent if it's
-  // interrupted.
-  bool wait_forever = wait.InMilliseconds() == kNoTimeout;
-  TimeDelta remaining_delta;
-  TimeTicks deadline;
-  if (!wait_forever) {
-    remaining_delta = wait;
-    deadline = TimeTicks::Now() + remaining_delta;
-  }
-
-  result = -1;
-  struct kevent event = {0};
-
-  while (wait_forever || remaining_delta > TimeDelta()) {
-    struct timespec remaining_timespec;
-    struct timespec* remaining_timespec_ptr;
-    if (wait_forever) {
-      remaining_timespec_ptr = NULL;
-    } else {
-      remaining_timespec = remaining_delta.ToTimeSpec();
-      remaining_timespec_ptr = &remaining_timespec;
-    }
-
-    result = kevent(kq.get(), NULL, 0, &event, 1, remaining_timespec_ptr);
-
-    if (result == -1 && errno == EINTR) {
-      if (!wait_forever) {
-        remaining_delta = deadline - TimeTicks::Now();
-      }
-      result = 0;
-    } else {
-      break;
-    }
-  }
-
-  if (result < 0) {
-    DPLOG(ERROR) << "kevent (wait " << handle << ")";
-    return false;
-  } else if (result > 1) {
-    DLOG(ERROR) << "kevent (wait " << handle << "): unexpected result "
-                << result;
-    return false;
-  } else if (result == 0) {
-    // Timed out.
-    return false;
-  }
-
-  DCHECK_EQ(result, 1);
-
-  if (event.filter != EVFILT_PROC ||
-      (event.fflags & NOTE_EXIT) == 0 ||
-      event.ident != static_cast<uintptr_t>(handle)) {
-    DLOG(ERROR) << "kevent (wait " << handle
-                << "): unexpected event: filter=" << event.filter
-                << ", fflags=" << event.fflags
-                << ", ident=" << event.ident;
-    return false;
-  }
-
-  return true;
-}
-#endif  // OS_MACOSX
-#endif  // !defined(OS_NACL_NONSFI)
-
 TerminationStatus GetTerminationStatusImpl(ProcessHandle handle,
                                            bool can_block,
                                            int* exit_code) {
@@ -302,52 +147,6 @@
 }
 
 #if !defined(OS_NACL_NONSFI)
-bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
-  int status;
-  if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
-    NOTREACHED();
-    return false;
-  }
-
-  if (WIFEXITED(status)) {
-    *exit_code = WEXITSTATUS(status);
-    return true;
-  }
-
-  // If it didn't exit cleanly, it must have been signaled.
-  DCHECK(WIFSIGNALED(status));
-  return false;
-}
-
-bool WaitForExitCodeWithTimeout(ProcessHandle handle,
-                                int* exit_code,
-                                TimeDelta timeout) {
-  ProcessHandle parent_pid = GetParentProcessId(handle);
-  ProcessHandle our_pid = GetCurrentProcessHandle();
-  if (parent_pid != our_pid) {
-#if defined(OS_MACOSX)
-    // On Mac we can wait on non child processes.
-    return WaitForSingleNonChildProcess(handle, timeout);
-#else
-    // Currently on Linux we can't handle non child processes.
-    NOTIMPLEMENTED();
-#endif  // OS_MACOSX
-  }
-
-  int status;
-  if (!WaitpidWithTimeout(handle, &status, timeout))
-    return false;
-  if (WIFSIGNALED(status)) {
-    *exit_code = -1;
-    return true;
-  }
-  if (WIFEXITED(status)) {
-    *exit_code = WEXITSTATUS(status);
-    return true;
-  }
-  return false;
-}
-
 bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
                             TimeDelta wait,
                             const ProcessFilter* filter) {
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index 7daf5f8..3c93047 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -12,7 +12,6 @@
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "base/process/process_iterator.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/win/object_watcher.h"
 
 namespace base {
@@ -71,11 +70,6 @@
 }
 
 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(
-          "418183 TimerExpiredTask::OnObjectSignaled"));
-
   process_.Close();
 }
 
@@ -107,22 +101,6 @@
   return result;
 }
 
-// Attempts to kill the process identified by the given process
-// entry structure, giving it the specified exit code.
-// Returns true if this is successful, false otherwise.
-bool KillProcessById(ProcessId process_id, int exit_code, bool wait) {
-  HANDLE process = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE,
-                               FALSE,  // Don't inherit handle
-                               process_id);
-  if (!process) {
-    DPLOG(ERROR) << "Unable to open process " << process_id;
-    return false;
-  }
-  bool ret = KillProcess(process, exit_code, wait);
-  CloseHandle(process);
-  return ret;
-}
-
 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
   DWORD tmp_exit_code = 0;
 
@@ -181,26 +159,6 @@
   }
 }
 
-bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
-  // TODO(rvargas) crbug.com/417532: Remove this function.
-  Process process(handle);
-  return process.WaitForExit(exit_code);
-}
-
-bool WaitForExitCodeWithTimeout(ProcessHandle handle,
-                                int* exit_code,
-                                TimeDelta timeout) {
-  if (::WaitForSingleObject(
-      handle, static_cast<DWORD>(timeout.InMilliseconds())) != WAIT_OBJECT_0)
-    return false;
-  DWORD temp_code;  // Don't clobber out-parameters in case of failure.
-  if (!::GetExitCodeProcess(handle, &temp_code))
-    return false;
-
-  *exit_code = temp_code;
-  return true;
-}
-
 bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
                             TimeDelta wait,
                             const ProcessFilter* filter) {
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc
index 203b7c8..f9963fa 100644
--- a/base/process/launch_posix.cc
+++ b/base/process/launch_posix.cc
@@ -33,7 +33,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/posix/eintr_wrapper.h"
-#include "base/process/kill.h"
+#include "base/process/process.h"
 #include "base/process/process_metrics.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
@@ -684,7 +684,8 @@
 
         // Always wait for exit code (even if we know we'll declare
         // GOT_MAX_OUTPUT).
-        bool success = WaitForExitCode(pid, exit_code);
+        Process process(pid);
+        bool success = process.WaitForExit(exit_code);
 
         // If we stopped because we read as much as we wanted, we return
         // GOT_MAX_OUTPUT (because the child may exit due to |SIGPIPE|).
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index bc2f3f8..a36bf77 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -5,12 +5,206 @@
 #include "base/process/process.h"
 
 #include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/types.h>
+#include <sys/wait.h>
 
+#include "base/files/scoped_file.h"
 #include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
 #include "base/process/kill.h"
 
+#if defined(OS_MACOSX)
+#include <sys/event.h>
+#endif
+
+namespace {
+
+#if !defined(OS_NACL_NONSFI)
+
+bool WaitpidWithTimeout(base::ProcessHandle handle,
+                        int* status,
+                        base::TimeDelta wait) {
+  // This POSIX version of this function only guarantees that we wait no less
+  // than |wait| for the process to exit.  The child process may
+  // exit sometime before the timeout has ended but we may still block for up
+  // to 256 milliseconds after the fact.
+  //
+  // waitpid() has no direct support on POSIX for specifying a timeout, you can
+  // either ask it to block indefinitely or return immediately (WNOHANG).
+  // When a child process terminates a SIGCHLD signal is sent to the parent.
+  // Catching this signal would involve installing a signal handler which may
+  // affect other parts of the application and would be difficult to debug.
+  //
+  // Our strategy is to call waitpid() once up front to check if the process
+  // has already exited, otherwise to loop for |wait|, sleeping for
+  // at most 256 milliseconds each time using usleep() and then calling
+  // waitpid().  The amount of time we sleep starts out at 1 milliseconds, and
+  // we double it every 4 sleep cycles.
+  //
+  // usleep() is speced to exit if a signal is received for which a handler
+  // has been installed.  This means that when a SIGCHLD is sent, it will exit
+  // depending on behavior external to this function.
+  //
+  // This function is used primarily for unit tests, if we want to use it in
+  // the application itself it would probably be best to examine other routes.
+
+  if (wait == base::TimeDelta::Max()) {
+    return HANDLE_EINTR(waitpid(handle, status, 0)) > 0;
+  }
+
+  pid_t ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
+  static const int64 kMaxSleepInMicroseconds = 1 << 18;  // ~256 milliseconds.
+  int64 max_sleep_time_usecs = 1 << 10;  // ~1 milliseconds.
+  int64 double_sleep_time = 0;
+
+  // If the process hasn't exited yet, then sleep and try again.
+  base::TimeTicks wakeup_time = base::TimeTicks::Now() + wait;
+  while (ret_pid == 0) {
+    base::TimeTicks now = base::TimeTicks::Now();
+    if (now > wakeup_time)
+      break;
+    // Guaranteed to be non-negative!
+    int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
+    // Sleep for a bit while we wait for the process to finish.
+    if (sleep_time_usecs > max_sleep_time_usecs)
+      sleep_time_usecs = max_sleep_time_usecs;
+
+    // usleep() will return 0 and set errno to EINTR on receipt of a signal
+    // such as SIGCHLD.
+    usleep(sleep_time_usecs);
+    ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
+
+    if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
+        (double_sleep_time++ % 4 == 0)) {
+      max_sleep_time_usecs *= 2;
+    }
+  }
+
+  return ret_pid > 0;
+}
+
+#if defined(OS_MACOSX)
+// Using kqueue on Mac so that we can wait on non-child processes.
+// We can't use kqueues on child processes because we need to reap
+// our own children using wait.
+static bool WaitForSingleNonChildProcess(base::ProcessHandle handle,
+                                         base::TimeDelta wait) {
+  DCHECK_GT(handle, 0);
+  DCHECK_GT(wait, base::TimeDelta());
+
+  base::ScopedFD kq(kqueue());
+  if (!kq.is_valid()) {
+    DPLOG(ERROR) << "kqueue";
+    return false;
+  }
+
+  struct kevent change = {0};
+  EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
+  int result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
+  if (result == -1) {
+    if (errno == ESRCH) {
+      // If the process wasn't found, it must be dead.
+      return true;
+    }
+
+    DPLOG(ERROR) << "kevent (setup " << handle << ")";
+    return false;
+  }
+
+  // Keep track of the elapsed time to be able to restart kevent if it's
+  // interrupted.
+  bool wait_forever = (wait == base::TimeDelta::Max());
+  base::TimeDelta remaining_delta;
+  base::TimeTicks deadline;
+  if (!wait_forever) {
+    remaining_delta = wait;
+    deadline = base::TimeTicks::Now() + remaining_delta;
+  }
+
+  result = -1;
+  struct kevent event = {0};
+
+  while (wait_forever || remaining_delta > base::TimeDelta()) {
+    struct timespec remaining_timespec;
+    struct timespec* remaining_timespec_ptr;
+    if (wait_forever) {
+      remaining_timespec_ptr = NULL;
+    } else {
+      remaining_timespec = remaining_delta.ToTimeSpec();
+      remaining_timespec_ptr = &remaining_timespec;
+    }
+
+    result = kevent(kq.get(), NULL, 0, &event, 1, remaining_timespec_ptr);
+
+    if (result == -1 && errno == EINTR) {
+      if (!wait_forever) {
+        remaining_delta = deadline - base::TimeTicks::Now();
+      }
+      result = 0;
+    } else {
+      break;
+    }
+  }
+
+  if (result < 0) {
+    DPLOG(ERROR) << "kevent (wait " << handle << ")";
+    return false;
+  } else if (result > 1) {
+    DLOG(ERROR) << "kevent (wait " << handle << "): unexpected result "
+                << result;
+    return false;
+  } else if (result == 0) {
+    // Timed out.
+    return false;
+  }
+
+  DCHECK_EQ(result, 1);
+
+  if (event.filter != EVFILT_PROC ||
+      (event.fflags & NOTE_EXIT) == 0 ||
+      event.ident != static_cast<uintptr_t>(handle)) {
+    DLOG(ERROR) << "kevent (wait " << handle
+                << "): unexpected event: filter=" << event.filter
+                << ", fflags=" << event.fflags
+                << ", ident=" << event.ident;
+    return false;
+  }
+
+  return true;
+}
+#endif  // OS_MACOSX
+
+bool WaitForExitWithTimeoutImpl(base::ProcessHandle handle,
+                                int* exit_code,
+                                base::TimeDelta timeout) {
+  base::ProcessHandle parent_pid = base::GetParentProcessId(handle);
+  base::ProcessHandle our_pid = base::GetCurrentProcessHandle();
+  if (parent_pid != our_pid) {
+#if defined(OS_MACOSX)
+    // On Mac we can wait on non child processes.
+    return WaitForSingleNonChildProcess(handle, timeout);
+#else
+    // Currently on Linux we can't handle non child processes.
+    NOTIMPLEMENTED();
+#endif  // OS_MACOSX
+  }
+
+  int status;
+  if (!WaitpidWithTimeout(handle, &status, timeout))
+    return false;
+  if (WIFSIGNALED(status)) {
+    *exit_code = -1;
+    return true;
+  }
+  if (WIFEXITED(status)) {
+    *exit_code = WEXITSTATUS(status);
+    return true;
+  }
+  return false;
+}
+#endif  // !defined(OS_NACL_NONSFI)
+
+}  // namespace
+
 namespace base {
 
 Process::Process(ProcessHandle handle) : process_(handle) {
@@ -102,15 +296,11 @@
 }
 
 bool Process::WaitForExit(int* exit_code) {
-  // TODO(rvargas) crbug.com/417532: Remove this constant.
-  const int kNoTimeout = -1;
-  return WaitForExitWithTimeout(TimeDelta::FromMilliseconds(kNoTimeout),
-                                exit_code);
+  return WaitForExitWithTimeout(TimeDelta::Max(), exit_code);
 }
 
 bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
-  // TODO(rvargas) crbug.com/417532: Move the implementation here.
-  return base::WaitForExitCodeWithTimeout(Handle(), exit_code, timeout);
+  return WaitForExitWithTimeoutImpl(Handle(), exit_code, timeout);
 }
 
 #if !defined(OS_LINUX)
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index 8e5360b..b62fdb4 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/field_trial.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/process/kill.h"
 #include "base/win/windows_version.h"
 
@@ -141,10 +142,17 @@
 }
 
 bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
-  // TODO(rvargas) crbug.com/417532: Move the implementation here.
-  if (timeout > TimeDelta::FromMilliseconds(INFINITE))
-    timeout = TimeDelta::FromMilliseconds(INFINITE);
-  return base::WaitForExitCodeWithTimeout(Handle(), exit_code, timeout);
+  // Limit timeout to INFINITE.
+  DWORD timeout_ms = saturated_cast<DWORD>(timeout.InMilliseconds());
+  if (::WaitForSingleObject(Handle(), timeout_ms) != WAIT_OBJECT_0)
+    return false;
+
+  DWORD temp_code;  // Don't clobber out-parameters in case of failure.
+  if (!::GetExitCodeProcess(Handle(), &temp_code))
+    return false;
+
+  *exit_code = temp_code;
+  return true;
 }
 
 bool Process::IsProcessBackgrounded() const {
diff --git a/base/synchronization/waitable_event.h b/base/synchronization/waitable_event.h
index 5adc1ec..c35af54 100644
--- a/base/synchronization/waitable_event.h
+++ b/base/synchronization/waitable_event.h
@@ -21,9 +21,6 @@
 
 namespace base {
 
-// This replaces INFINITE from Win32
-static const int kNoTimeout = -1;
-
 class TimeDelta;
 
 // A WaitableEvent can be a useful thread synchronization tool when you want to
diff --git a/base/synchronization/waitable_event_watcher_win.cc b/base/synchronization/waitable_event_watcher_win.cc
index a04a435..46d47ac 100644
--- a/base/synchronization/waitable_event_watcher_win.cc
+++ b/base/synchronization/waitable_event_watcher_win.cc
@@ -5,7 +5,6 @@
 #include "base/synchronization/waitable_event_watcher.h"
 
 #include "base/compiler_specific.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/win/object_watcher.h"
 
@@ -37,11 +36,6 @@
 }
 
 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(
-          "418183 WaitableEventWatcher::OnObjectSignaled"));
-
   WaitableEvent* event = event_;
   EventCallback callback = callback_;
   event_ = NULL;
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 05a3dc3..120159e 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -36,6 +36,8 @@
     "mock_chrome_application_mac.mm",
     "mock_devices_changed_observer.cc",
     "mock_devices_changed_observer.h",
+    "mock_log.cc",
+    "mock_log.h",
     "multiprocess_test.cc",
     "multiprocess_test.h",
     "multiprocess_test_android.cc",
diff --git a/base/test/data/pe_image/pe_image_test_32.dll b/base/test/data/pe_image/pe_image_test_32.dll
new file mode 100755
index 0000000..118ce11
--- /dev/null
+++ b/base/test/data/pe_image/pe_image_test_32.dll
Binary files differ
diff --git a/base/test/data/pe_image/pe_image_test_64.dll b/base/test/data/pe_image/pe_image_test_64.dll
new file mode 100755
index 0000000..70f8ea4
--- /dev/null
+++ b/base/test/data/pe_image/pe_image_test_64.dll
Binary files differ
diff --git a/base/test/data/prefs/write.golden.json b/base/test/data/prefs/write.golden.json
index 9a5523c..fb1fff1 100644
--- a/base/test/data/prefs/write.golden.json
+++ b/base/test/data/prefs/write.golden.json
@@ -1,11 +1 @@
-{
-   "homepage": "http://www.cnn.com",
-   "long_int": {
-      "pref": "214748364842"
-   },
-   "some_directory": "/usr/sbin/",
-   "tabs": {
-      "max_tabs": 10,
-      "new_windows_in_tabs": false
-   }
-}
+{"homepage":"http://www.cnn.com","long_int":{"pref":"214748364842"},"some_directory":"/usr/sbin/","tabs":{"max_tabs":10,"new_windows_in_tabs":false}}
\ No newline at end of file
diff --git a/base/test/gtest_util.cc b/base/test/gtest_util.cc
index c0bc04a..b811194 100644
--- a/base/test/gtest_util.cc
+++ b/base/test/gtest_util.cc
@@ -47,7 +47,7 @@
 
 bool ReadTestNamesFromFile(const FilePath& path,
                            std::vector<SplitTestName>* output) {
-  JSONFileValueSerializer deserializer(path);
+  JSONFileValueDeserializer deserializer(path);
   int error_code = 0;
   std::string error_message;
   scoped_ptr<base::Value> value(
@@ -80,4 +80,4 @@
   return true;
 }
 
-}  // namespace
+}  // namespace base
diff --git a/base/test/mock_log.cc b/base/test/mock_log.cc
new file mode 100644
index 0000000..fa511d4
--- /dev/null
+++ b/base/test/mock_log.cc
@@ -0,0 +1,68 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/mock_log.h"
+
+namespace base {
+namespace test {
+
+// static
+MockLog* MockLog::g_instance_ = nullptr;
+Lock MockLog::g_lock;
+
+MockLog::MockLog() : is_capturing_logs_(false) {
+}
+
+MockLog::~MockLog() {
+  if (is_capturing_logs_) {
+    StopCapturingLogs();
+  }
+}
+
+void MockLog::StartCapturingLogs() {
+  AutoLock scoped_lock(g_lock);
+
+  // We don't use CHECK(), which can generate a new LOG message, and
+  // thus can confuse MockLog objects or other registered
+  // LogSinks.
+  RAW_CHECK(!is_capturing_logs_);
+  RAW_CHECK(!g_instance_);
+
+  is_capturing_logs_ = true;
+  g_instance_ = this;
+  previous_handler_ = logging::GetLogMessageHandler();
+  logging::SetLogMessageHandler(LogMessageHandler);
+}
+
+void MockLog::StopCapturingLogs() {
+  AutoLock scoped_lock(g_lock);
+
+  // We don't use CHECK(), which can generate a new LOG message, and
+  // thus can confuse MockLog objects or other registered
+  // LogSinks.
+  RAW_CHECK(is_capturing_logs_);
+  RAW_CHECK(g_instance_ == this);
+
+  is_capturing_logs_ = false;
+  logging::SetLogMessageHandler(previous_handler_);
+  g_instance_ = nullptr;
+}
+
+// static
+bool MockLog::LogMessageHandler(int severity,
+                                const char* file,
+                                int line,
+                                size_t message_start,
+                                const std::string& str) {
+  // gMock guarantees thread-safety for calling a mocked method
+  // (https://code.google.com/p/googlemock/wiki/CookBook#Using_Google_Mock_and_Threads)
+  // but we also need to make sure that Start/StopCapturingLogs are synchronized
+  // with LogMessageHandler.
+  AutoLock scoped_lock(g_lock);
+
+  return g_instance_->Log(severity, file, line, message_start, str);
+}
+
+}  // namespace test
+}  // namespace base
diff --git a/base/test/mock_log.h b/base/test/mock_log.h
new file mode 100644
index 0000000..315ef1f
--- /dev/null
+++ b/base/test/mock_log.h
@@ -0,0 +1,98 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TEST_MOCK_LOG_H_
+#define BASE_TEST_MOCK_LOG_H_
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace base {
+namespace test {
+
+// A MockLog object intercepts LOG() messages issued during its lifespan.  Using
+// this together with gMock, it's very easy to test how a piece of code calls
+// LOG().  The typical usage:
+//
+//   TEST(FooTest, LogsCorrectly) {
+//     MockLog log;
+//
+//     // We expect the WARNING "Something bad!" exactly twice.
+//     EXPECT_CALL(log, Log(WARNING, _, "Something bad!"))
+//         .Times(2);
+//
+//     // We allow foo.cc to call LOG(INFO) any number of times.
+//     EXPECT_CALL(log, Log(INFO, HasSubstr("/foo.cc"), _))
+//         .Times(AnyNumber());
+//
+//     log.StartCapturingLogs();  // Call this after done setting expectations.
+//     Foo();  // Exercises the code under test.
+//   }
+//
+// CAVEAT: base/logging does not allow a thread to call LOG() again when it's
+// already inside a LOG() call.  Doing so will cause a deadlock.  Therefore,
+// it's the user's responsibility to not call LOG() in an action triggered by
+// MockLog::Log().  You may call RAW_LOG() instead.
+class MockLog {
+ public:
+  // Creates a MockLog object that is not capturing logs.  If it were to start
+  // to capture logs, it could be a problem if some other threads already exist
+  // and are logging, as the user hasn't had a chance to set up expectation on
+  // this object yet (calling a mock method before setting the expectation is
+  // UNDEFINED behavior).
+  MockLog();
+
+  // When the object is destructed, it stops intercepting logs.
+  ~MockLog();
+
+  // Starts log capturing if the object isn't already doing so.
+  // Otherwise crashes.
+  void StartCapturingLogs();
+
+  // Stops log capturing if the object is capturing logs.  Otherwise crashes.
+  void StopCapturingLogs();
+
+  // Log method is invoked for every log message before it's sent to other log
+  // destinations (if any).  The method should return true to signal that it
+  // handled the message and the message should not be sent to other log
+  // destinations.
+  MOCK_METHOD5(Log,
+               bool(int severity,
+                    const char* file,
+                    int line,
+                    size_t message_start,
+                    const std::string& str));
+
+ private:
+  // The currently active mock log.
+  static MockLog* g_instance_;
+
+  // Lock protecting access to g_instance_.
+  static Lock g_lock;
+
+  // Static function which is set as the logging message handler.
+  // Called once for each message.
+  static bool LogMessageHandler(int severity,
+                                const char* file,
+                                int line,
+                                size_t message_start,
+                                const std::string& str);
+
+  // True if this object is currently capturing logs.
+  bool is_capturing_logs_;
+
+  // The previous handler to restore when the MockLog is destroyed.
+  logging::LogMessageHandlerFunction previous_handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockLog);
+};
+
+}  // namespace test
+}  // namespace base
+
+#endif  // BASE_TEST_MOCK_LOG_H_
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc
index a878280..8e65ccf 100644
--- a/base/test/test_mock_time_task_runner.cc
+++ b/base/test/test_mock_time_task_runner.cc
@@ -154,8 +154,7 @@
     const tracked_objects::Location& from_here,
     const Closure& task,
     TimeDelta delay) {
-  NOTREACHED();
-  return false;
+  return PostDelayedTask(from_here, task, delay);
 }
 
 void TestMockTimeTaskRunner::OnBeforeSelectingTask() {
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index 1a651f6..5f06013 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -32,13 +32,12 @@
 //   - It allows for reentrancy, in that it handles the running of tasks that in
 //     turn call back into it (e.g., to post more tasks).
 //   - Tasks are stored in a priority queue, and executed in the increasing
-//     order of post time + delay.
+//     order of post time + delay, but ignoring nestability.
 //   - It does not check for overflow when doing time arithmetic. A sufficient
 //     condition for preventing overflows is to make sure that the sum of all
 //     posted task delays and fast-forward increments is still representable by
 //     a TimeDelta, and that adding this delta to the starting values of Time
 //     and TickTime is still within their respective range.
-//   - Non-nestable tasks are not supported.
 //   - Tasks aren't guaranteed to be destroyed immediately after they're run.
 //
 // This is a slightly more sophisticated version of TestSimpleTaskRunner, in
diff --git a/base/third_party/nspr/BUILD.gn b/base/third_party/nspr/BUILD.gn
index c0b2ec2..a67e168 100644
--- a/base/third_party/nspr/BUILD.gn
+++ b/base/third_party/nspr/BUILD.gn
@@ -3,9 +3,7 @@
 # found in the LICENSE file.
 
 source_set("nspr") {
-  visibility = [
-    "//base/*",
-  ]
+  visibility = [ "//base/*" ]
 
   sources = [
     "prtime.cc",
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 89224f7..19b81b7 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -798,9 +798,11 @@
         // to run them. Also, there may be some tasks stuck behind running
         // ones with the same sequence token, but additional threads won't
         // help this case.
-        if (shutdown_called_ &&
-            blocking_shutdown_pending_task_count_ == 0)
+        if (shutdown_called_ && blocking_shutdown_pending_task_count_ == 0) {
+          AutoUnlock unlock(lock_);
+          delete_these_outside_lock.clear();
           break;
+        }
         waiting_thread_count_++;
 
         switch (status) {
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc
index ed5f896..9d0f607 100644
--- a/base/threading/sequenced_worker_pool_unittest.cc
+++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -67,6 +67,23 @@
   size_t unblock_counter_;
 };
 
+class DestructionDeadlockChecker
+    : public base::RefCountedThreadSafe<DestructionDeadlockChecker> {
+ public:
+  DestructionDeadlockChecker(const scoped_refptr<SequencedWorkerPool>& pool)
+      : pool_(pool) {}
+
+ protected:
+  virtual ~DestructionDeadlockChecker() {
+    // This method should not deadlock.
+    pool_->RunsTasksOnCurrentThread();
+  }
+
+ private:
+  scoped_refptr<SequencedWorkerPool> pool_;
+  friend class base::RefCountedThreadSafe<DestructionDeadlockChecker>;
+};
+
 class TestTracker : public base::RefCountedThreadSafe<TestTracker> {
  public:
   TestTracker()
@@ -117,6 +134,20 @@
     SignalWorkerDone(id);
   }
 
+  // This task posts itself back onto the SequencedWorkerPool before it
+  // finishes running. Each instance of the task maintains a strong reference
+  // to a DestructionDeadlockChecker. The DestructionDeadlockChecker is only
+  // destroyed when the task is destroyed without being run, which only happens
+  // during destruction of the SequencedWorkerPool.
+  void PostRepostingTask(
+      const scoped_refptr<SequencedWorkerPool>& pool,
+      const scoped_refptr<DestructionDeadlockChecker>& checker) {
+    Closure reposting_task =
+        base::Bind(&TestTracker::PostRepostingTask, this, pool, checker);
+    pool->PostWorkerTaskWithShutdownBehavior(
+        FROM_HERE, reposting_task, SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+  }
+
   // Waits until the given number of tasks have started executing.
   void WaitUntilTasksBlocked(size_t count) {
     {
@@ -749,6 +780,21 @@
   unused_pool->Shutdown();
 }
 
+// Checks that tasks are destroyed in the right context during shutdown. If a
+// task is destroyed while SequencedWorkerPool's global lock is held,
+// SequencedWorkerPool might deadlock.
+TEST_F(SequencedWorkerPoolTest, AvoidsDeadlockOnShutdown) {
+  for (int i = 0; i < 4; ++i) {
+    scoped_refptr<DestructionDeadlockChecker> checker(
+        new DestructionDeadlockChecker(pool()));
+    tracker()->PostRepostingTask(pool(), checker);
+  }
+
+  // Shutting down the pool should destroy the DestructionDeadlockCheckers,
+  // which in turn should not deadlock in their destructors.
+  pool()->Shutdown();
+}
+
 // Verify that FlushForTesting works as intended.
 TEST_F(SequencedWorkerPoolTest, FlushForTesting) {
   // Should be fine to call on a new instance.
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 7c46fd2..1e5f510 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -22,6 +22,7 @@
 
 namespace cc {
 class CompletionEvent;
+class TaskGraphRunner;
 }
 namespace chromeos {
 class BlockingMethodCaller;
@@ -177,6 +178,7 @@
   friend class ::HistogramSynchronizer;
   friend class ::ScopedAllowWaitForLegacyWebViewApi;
   friend class cc::CompletionEvent;
+  friend class cc::TaskGraphRunner;
   friend class mojo::common::WatcherThreadManager;
   friend class remoting::AutoThread;
   friend class MessagePumpDefault;
diff --git a/base/timer/timer.cc b/base/timer/timer.cc
index 11f73ca..fa6b8cd 100644
--- a/base/timer/timer.cc
+++ b/base/timer/timer.cc
@@ -163,8 +163,10 @@
   }
   // Remember the thread ID that posts the first task -- this will be verified
   // later when the task is abandoned to detect misuse from multiple threads.
-  if (!thread_id_)
+  if (!thread_id_) {
+    DCHECK(GetTaskRunner()->BelongsToCurrentThread());
     thread_id_ = static_cast<int>(PlatformThread::CurrentId());
+  }
 }
 
 scoped_refptr<SingleThreadTaskRunner> Timer::GetTaskRunner() {
diff --git a/base/timer/timer.h b/base/timer/timer.h
index ea34a9f..1ef58a3 100644
--- a/base/timer/timer.h
+++ b/base/timer/timer.h
@@ -89,7 +89,8 @@
   virtual TimeDelta GetCurrentDelay() const;
 
   // Set the task runner on which the task should be scheduled. This method can
-  // only be called before any tasks have been scheduled.
+  // only be called before any tasks have been scheduled. The task runner must
+  // run tasks on the same thread the timer is used on.
   virtual void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner);
 
   // Start the timer to run at the given |delay| from now. If the timer is
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index c8be8f8..cbed238 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/atomic_sequence_num.h"
 #include "base/compiler_specific.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "base/trace_event/process_memory_dump.h"
@@ -15,7 +16,27 @@
 namespace trace_event {
 
 namespace {
+
 MemoryDumpManager* g_instance_for_testing = nullptr;
+const int kTraceEventNumArgs = 1;
+const char* kTraceEventArgNames[] = {"dumps"};
+const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
+StaticAtomicSequenceNumber g_next_guid;
+
+const char* DumpPointTypeToString(const DumpPointType& dump_point_type) {
+  switch (dump_point_type) {
+    case DumpPointType::TASK_BEGIN:
+      return "TASK_BEGIN";
+    case DumpPointType::TASK_END:
+      return "TASK_END";
+    case DumpPointType::PERIODIC_INTERVAL:
+      return "PERIODIC_INTERVAL";
+    case DumpPointType::EXPLICITLY_TRIGGERED:
+      return "EXPLICITLY_TRIGGERED";
+  }
+  NOTREACHED();
+  return "UNKNOWN";
+}
 }
 
 // TODO(primiano): this should be smarter and should do something similar to
@@ -76,13 +97,18 @@
     dump_providers_enabled_.erase(it);
 }
 
-void MemoryDumpManager::RequestDumpPoint(DumpPointType type) {
-  // TODO(primiano): this will have more logic, IPC broadcast & co.
+void MemoryDumpManager::RequestDumpPoint(DumpPointType dump_point_type) {
+  // TODO(primiano): this will have more logic to coordinate dump points across
+  // multiple processes via IPC. See crbug.com/462930.
+
   // Bail out immediately if tracing is not enabled at all.
   if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
     return;
 
-  CreateLocalDumpPoint();
+  // TODO(primiano): Make guid actually unique (cross-process) by hashing it
+  // with the PID. See crbug.com/462931 for details.
+  const uint64 guid = g_next_guid.GetNext();
+  CreateLocalDumpPoint(dump_point_type, guid);
 }
 
 void MemoryDumpManager::BroadcastDumpRequest() {
@@ -90,17 +116,44 @@
 }
 
 // Creates a dump point for the current process and appends it to the trace.
-void MemoryDumpManager::CreateLocalDumpPoint() {
-  AutoLock lock(lock_);
+void MemoryDumpManager::CreateLocalDumpPoint(DumpPointType dump_point_type,
+                                             uint64 guid) {
+  bool did_any_provider_dump = false;
   scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump());
 
-  for (MemoryDumpProvider* dump_provider : dump_providers_enabled_) {
-    dump_provider->DumpInto(pmd.get());
+  // Serialize dump point generation so that memory dump providers don't have to
+  // deal with thread safety.
+  {
+    AutoLock lock(lock_);
+    for (auto it = dump_providers_enabled_.begin();
+         it != dump_providers_enabled_.end();) {
+      MemoryDumpProvider* dump_provider = *it;
+      if (dump_provider->DumpInto(pmd.get())) {
+        did_any_provider_dump = true;
+        ++it;
+      } else {
+        LOG(ERROR) << "The memory dumper " << dump_provider->GetFriendlyName()
+                   << " failed, possibly due to sandboxing (crbug.com/461788), "
+                      "disabling it for current process. Try restarting chrome "
+                      "with the --no-sandbox switch.";
+        it = dump_providers_enabled_.erase(it);
+      }
+    }
   }
 
-  scoped_refptr<TracedValue> value(new TracedValue());
-  pmd->AsValueInto(value.get());
-  // TODO(primiano): add the dump point to the trace at this point.
+  // Don't create a dump point if all the dumpers failed.
+  if (!did_any_provider_dump)
+    return;
+
+  scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
+  pmd->AsValueInto(static_cast<TracedValue*>(event_value.get()));
+  const char* const event_name = DumpPointTypeToString(dump_point_type);
+
+  TRACE_EVENT_API_ADD_TRACE_EVENT(
+      TRACE_EVENT_PHASE_MEMORY_DUMP,
+      TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, guid,
+      kTraceEventNumArgs, kTraceEventArgNames, kTraceEventArgTypes,
+      NULL /* arg_values */, &event_value, TRACE_EVENT_FLAG_HAS_ID);
 }
 
 void MemoryDumpManager::OnTraceLogEnabled() {
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
index 1a22e61..8a9b3b7 100644
--- a/base/trace_event/memory_dump_manager.h
+++ b/base/trace_event/memory_dump_manager.h
@@ -43,7 +43,7 @@
 
   // Requests a memory dump. The dump might happen or not depending on the
   // filters and categories specified when enabling tracing.
-  void RequestDumpPoint(DumpPointType type);
+  void RequestDumpPoint(DumpPointType dump_point_type);
 
   // TraceLog::EnabledStateObserver implementation.
   void OnTraceLogEnabled() override;
@@ -65,7 +65,7 @@
   void BroadcastDumpRequest();
 
   // Creates a dump point for the current process and appends it to the trace.
-  void CreateLocalDumpPoint();
+  void CreateLocalDumpPoint(DumpPointType dump_point_type, uint64 guid);
 
   std::vector<MemoryDumpProvider*> dump_providers_registered_;  // Not owned.
   std::vector<MemoryDumpProvider*> dump_providers_enabled_;     // Not owned.
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 1ba73e6..78be377 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -10,6 +10,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
+using testing::Return;
 
 namespace base {
 namespace trace_event {
@@ -48,7 +49,9 @@
 
 class MockDumpProvider : public MemoryDumpProvider {
  public:
-  MOCK_METHOD1(DumpInto, void(ProcessMemoryDump* pmd));
+  MOCK_METHOD1(DumpInto, bool(ProcessMemoryDump* pmd));
+
+  const char* GetFriendlyName() const override { return "MockDumpProvider"; }
 };
 
 TEST_F(MemoryDumpManagerTest, SingleDumper) {
@@ -64,7 +67,7 @@
   // Now repeat enabling the memory category and check that the dumper is
   // invoked this time.
   EnableTracing(kTraceCategory);
-  EXPECT_CALL(mdp, DumpInto(_)).Times(3);
+  EXPECT_CALL(mdp, DumpInto(_)).Times(3).WillRepeatedly(Return(true));
   for (int i = 0; i < 3; ++i)
     mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
   DisableTracing();
@@ -83,7 +86,7 @@
   mdm_->RegisterDumpProvider(&mdp);
 
   EnableTracing(kTraceCategory);
-  EXPECT_CALL(mdp, DumpInto(_)).Times(1);
+  EXPECT_CALL(mdp, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
   mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
 
   mdm_->UnregisterDumpProvider(&mdp);
@@ -100,7 +103,7 @@
   // Enable only mdp1.
   mdm_->RegisterDumpProvider(&mdp1);
   EnableTracing(kTraceCategory);
-  EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
+  EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
   EXPECT_CALL(mdp2, DumpInto(_)).Times(0);
   mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
   DisableTracing();
@@ -110,18 +113,40 @@
   mdm_->RegisterDumpProvider(&mdp2);
   EnableTracing(kTraceCategory);
   EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
-  EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
+  EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
   mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
   DisableTracing();
 
   // Enable both mdp1 and mdp2.
   mdm_->RegisterDumpProvider(&mdp1);
   EnableTracing(kTraceCategory);
-  EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
-  EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
+  EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
+  EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
   mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
   DisableTracing();
 }
 
+// Enable both dump providers, make mdp1 fail and assert that only mdp2 is
+// invoked the 2nd time.
+// FIXME(primiano): remove once crbug.com/461788 gets fixed.
+TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) {
+  MockDumpProvider mdp1;
+  MockDumpProvider mdp2;
+
+  mdm_->RegisterDumpProvider(&mdp1);
+  mdm_->RegisterDumpProvider(&mdp2);
+  EnableTracing(kTraceCategory);
+
+  EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(false));
+  EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true));
+  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+  EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
+  EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(false));
+  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+  DisableTracing();
+}
+
 }  // namespace trace_Event
 }  // namespace base
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h
index 18363c5..1c5bbb1 100644
--- a/base/trace_event/memory_dump_provider.h
+++ b/base/trace_event/memory_dump_provider.h
@@ -17,7 +17,10 @@
 class BASE_EXPORT MemoryDumpProvider {
  public:
   // Called by the MemoryDumpManager when generating dump points.
-  virtual void DumpInto(ProcessMemoryDump* pmd) = 0;
+  // Returns: true if the |pmd| was successfully populated, false otherwise.
+  virtual bool DumpInto(ProcessMemoryDump* pmd) = 0;
+
+  virtual const char* GetFriendlyName() const = 0;
 
  protected:
   MemoryDumpProvider() {}
diff --git a/base/trace_event/process_memory_maps_dump_provider.cc b/base/trace_event/process_memory_maps_dump_provider.cc
index e1cefc3..93feded 100644
--- a/base/trace_event/process_memory_maps_dump_provider.cc
+++ b/base/trace_event/process_memory_maps_dump_provider.cc
@@ -15,6 +15,10 @@
 namespace base {
 namespace trace_event {
 
+namespace {
+const char kDumperFriendlyName[] = "ProcessMemoryMaps";
+}
+
 #if defined(OS_LINUX) || defined(OS_ANDROID)
 // static
 std::istream* ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = nullptr;
@@ -104,10 +108,9 @@
 }
 
 uint32 ReadLinuxProcSmapsFile(std::istream* smaps, ProcessMemoryMaps* pmm) {
-  if (!smaps->good()) {
-    LOG(ERROR) << "Could not read smaps file.";
+  if (!smaps->good())
     return 0;
-  }
+
   const uint32 kNumExpectedCountersPerRegion = 2;
   uint32 counters_parsed_for_current_region = 0;
   uint32 num_valid_regions = 0;
@@ -154,7 +157,7 @@
 
 // Called at trace dump point time. Creates a snapshot the memory maps for the
 // current process.
-void ProcessMemoryMapsDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+bool ProcessMemoryMapsDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
   uint32 res = 0;
 
 #if defined(OS_LINUX) || defined(OS_ANDROID)
@@ -168,8 +171,16 @@
   LOG(ERROR) << "ProcessMemoryMaps dump provider is supported only on Linux";
 #endif
 
-  if (res > 0)
+  if (res > 0) {
     pmd->set_has_process_mmaps();
+    return true;
+  }
+
+  return false;
+}
+
+const char* ProcessMemoryMapsDumpProvider::GetFriendlyName() const {
+  return kDumperFriendlyName;
 }
 
 }  // namespace trace_event
diff --git a/base/trace_event/process_memory_maps_dump_provider.h b/base/trace_event/process_memory_maps_dump_provider.h
index 543f7fd..0d30db2 100644
--- a/base/trace_event/process_memory_maps_dump_provider.h
+++ b/base/trace_event/process_memory_maps_dump_provider.h
@@ -20,7 +20,8 @@
   static ProcessMemoryMapsDumpProvider* GetInstance();
 
   // MemoryDumpProvider implementation.
-  void DumpInto(ProcessMemoryDump* pmd) override;
+  bool DumpInto(ProcessMemoryDump* pmd) override;
+  const char* GetFriendlyName() const override;
 
  private:
   friend struct DefaultSingletonTraits<ProcessMemoryMapsDumpProvider>;
diff --git a/base/trace_event/process_memory_totals_dump_provider.cc b/base/trace_event/process_memory_totals_dump_provider.cc
index cda0ff1..125be38 100644
--- a/base/trace_event/process_memory_totals_dump_provider.cc
+++ b/base/trace_event/process_memory_totals_dump_provider.cc
@@ -15,6 +15,9 @@
 uint64 ProcessMemoryTotalsDumpProvider::rss_bytes_for_testing = 0;
 
 namespace {
+
+const char kDumperFriendlyName[] = "ProcessMemoryTotals";
+
 ProcessMetrics* CreateProcessMetricsForCurrentProcess() {
 #if !defined(OS_MACOSX) || defined(OS_IOS)
   return ProcessMetrics::CreateProcessMetrics(GetCurrentProcessHandle());
@@ -41,12 +44,22 @@
 
 // Called at trace dump point time. Creates a snapshot the memory counters for
 // the current process.
-void ProcessMemoryTotalsDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
+bool ProcessMemoryTotalsDumpProvider::DumpInto(ProcessMemoryDump* pmd) {
   const uint64 rss_bytes = rss_bytes_for_testing
                                ? rss_bytes_for_testing
                                : process_metrics_->GetWorkingSetSize();
-  pmd->process_totals()->set_resident_set_bytes(rss_bytes);
-  pmd->set_has_process_totals();
+
+  if (rss_bytes > 0) {
+    pmd->process_totals()->set_resident_set_bytes(rss_bytes);
+    pmd->set_has_process_totals();
+    return true;
+  }
+
+  return false;
+}
+
+const char* ProcessMemoryTotalsDumpProvider::GetFriendlyName() const {
+  return kDumperFriendlyName;
 }
 
 }  // namespace trace_event
diff --git a/base/trace_event/process_memory_totals_dump_provider.h b/base/trace_event/process_memory_totals_dump_provider.h
index 45917a8..8dae966 100644
--- a/base/trace_event/process_memory_totals_dump_provider.h
+++ b/base/trace_event/process_memory_totals_dump_provider.h
@@ -22,7 +22,8 @@
   static ProcessMemoryTotalsDumpProvider* GetInstance();
 
   // MemoryDumpProvider implementation.
-  void DumpInto(ProcessMemoryDump* pmd) override;
+  bool DumpInto(ProcessMemoryDump* pmd) override;
+  const char* GetFriendlyName() const override;
 
  private:
   friend struct DefaultSingletonTraits<ProcessMemoryTotalsDumpProvider>;
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index e12d8f4..c30a84a 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -1039,6 +1039,7 @@
 #define TRACE_EVENT_PHASE_CREATE_OBJECT ('N')
 #define TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ('O')
 #define TRACE_EVENT_PHASE_DELETE_OBJECT ('D')
+#define TRACE_EVENT_PHASE_MEMORY_DUMP ('v')
 
 // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
 #define TRACE_EVENT_FLAG_NONE         (static_cast<unsigned char>(0))
diff --git a/base/values.cc b/base/values.cc
index 061b7a1..52876cf 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -1143,6 +1143,9 @@
 ValueSerializer::~ValueSerializer() {
 }
 
+ValueDeserializer::~ValueDeserializer() {
+}
+
 std::ostream& operator<<(std::ostream& out, const Value& value) {
   std::string json;
   JSONWriter::WriteWithOptions(&value,
diff --git a/base/values.h b/base/values.h
index 4648283..1e1cae3 100644
--- a/base/values.h
+++ b/base/values.h
@@ -492,13 +492,20 @@
   DISALLOW_COPY_AND_ASSIGN(ListValue);
 };
 
-// This interface is implemented by classes that know how to serialize and
-// deserialize Value objects.
+// This interface is implemented by classes that know how to serialize
+// Value objects.
 class BASE_EXPORT ValueSerializer {
  public:
   virtual ~ValueSerializer();
 
   virtual bool Serialize(const Value& root) = 0;
+};
+
+// This interface is implemented by classes that know how to deserialize Value
+// objects.
+class BASE_EXPORT ValueDeserializer {
+ public:
+  virtual ~ValueDeserializer();
 
   // This method deserializes the subclass-specific format into a Value object.
   // If the return value is non-NULL, the caller takes ownership of returned
diff --git a/base/win/pe_image_unittest.cc b/base/win/pe_image_unittest.cc
index 4134741..28b65a4 100644
--- a/base/win/pe_image_unittest.cc
+++ b/base/win/pe_image_unittest.cc
@@ -6,129 +6,10 @@
 #include <algorithm>
 #include <vector>
 
-#include "testing/gtest/include/gtest/gtest.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
 #include "base/win/pe_image.h"
-#include "base/win/windows_version.h"
-
-namespace {
-
-class Expectations {
- public:
-  enum Value {
-    SECTIONS = 0,
-    IMPORTS_DLLS,
-    DELAY_DLLS,
-    EXPORTS,
-    IMPORTS,
-    DELAY_IMPORTS,
-    RELOCS
-  };
-
-  enum Arch {
-    ARCH_X86 = 0,
-    ARCH_X64,
-    ARCH_ALL
-  };
-
-  Expectations();
-
-  void SetDefault(Value value, int count);
-  void SetOverride(Value value, base::win::Version version,
-                   Arch arch, int count);
-  void SetOverride(Value value, base::win::Version version, int count);
-  void SetOverride(Value value, Arch arch, int count);
-
-  // returns -1 on failure.
-  int GetExpectation(Value value);
-
- private:
-  class Override {
-   public:
-    enum MatchType { MATCH_VERSION, MATCH_ARCH, MATCH_BOTH, MATCH_NONE };
-
-    Override(Value value, base::win::Version version, Arch arch, int count)
-      : value_(value), version_(version), arch_(arch), count_(count) {
-    };
-
-    bool Matches(Value value, base::win::Version version,
-                 Arch arch, MatchType type) {
-      if (value_ != value)
-        return false;
-
-      switch (type) {
-        case MATCH_BOTH:
-          return (arch == arch_ && version == version_);
-        case MATCH_ARCH:
-          return (arch == arch_ && version_ == base::win::VERSION_WIN_LAST);
-        case MATCH_VERSION:
-          return (arch_ == ARCH_ALL && version == version_);
-        case MATCH_NONE:
-          return (arch_ == ARCH_ALL && version_ == base::win::VERSION_WIN_LAST);
-      }
-      return false;
-    }
-
-    int GetCount() { return count_; }
-
-   private:
-    Value value_;
-    base::win::Version version_;
-    Arch arch_;
-    int count_;
-  };
-
-  bool MatchesMyArch(Arch arch);
-
-  std::vector<Override> overrides_;
-  Arch my_arch_;
-  base::win::Version my_version_;
-};
-
-Expectations::Expectations() {
-  my_version_ = base::win::GetVersion();
-#if defined(ARCH_CPU_64_BITS)
-  my_arch_ = ARCH_X64;
-#else
-  my_arch_ = ARCH_X86;
-#endif
-}
-
-int Expectations::GetExpectation(Value value) {
-  // Prefer OS version specificity over Arch specificity.
-  for (auto type : { Override::MATCH_BOTH,
-                     Override::MATCH_VERSION,
-                     Override::MATCH_ARCH,
-                     Override::MATCH_NONE }) {
-    for (auto override : overrides_) {
-      if (override.Matches(value, my_version_, my_arch_, type))
-        return override.GetCount();
-    }
-  }
-  return -1;
-}
-
-void Expectations::SetDefault(Value value, int count) {
-  SetOverride(value, base::win::VERSION_WIN_LAST, ARCH_ALL, count);
-}
-
-void Expectations::SetOverride(Value value,
-                               base::win::Version version,
-                               Arch arch,
-                               int count) {
-  overrides_.push_back(Override(value, version, arch, count));
-}
-
-void Expectations::SetOverride(Value value,
-                               base::win::Version version,
-                               int count) {
-  SetOverride(value, version, ARCH_ALL, count);
-}
-
-void Expectations::SetOverride(Value value, Arch arch, int count) {
-  SetOverride(value, base::win::VERSION_WIN_LAST, arch, count);
-}
-
-}  // namespace
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
 namespace win {
@@ -210,41 +91,35 @@
 }  // namespace
 
 // Tests that we are able to enumerate stuff from a PE file, and that
-// the actual number of items found is within the expected range.
+// the actual number of items found matches an expected value.
 TEST(PEImageTest, EnumeratesPE) {
-  Expectations expectations;
+  base::FilePath pe_image_test_path;
+  ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &pe_image_test_path));
+  pe_image_test_path = pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image"));
 
-#ifndef NDEBUG
-  // Default Debug expectations.
-  expectations.SetDefault(Expectations::SECTIONS, 7);
-  expectations.SetDefault(Expectations::IMPORTS_DLLS, 3);
-  expectations.SetDefault(Expectations::DELAY_DLLS, 2);
-  expectations.SetDefault(Expectations::EXPORTS, 2);
-  expectations.SetDefault(Expectations::IMPORTS, 49);
-  expectations.SetDefault(Expectations::DELAY_IMPORTS, 2);
-  expectations.SetDefault(Expectations::RELOCS, 438);
-
-  // 64-bit Debug expectations.
-  expectations.SetOverride(Expectations::SECTIONS, Expectations::ARCH_X64, 8);
-  expectations.SetOverride(Expectations::IMPORTS, Expectations::ARCH_X64, 69);
-  expectations.SetOverride(Expectations::RELOCS, Expectations::ARCH_X64, 632);
+#if defined(ARCH_CPU_64_BITS)
+  pe_image_test_path =
+      pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_64.dll"));
+  const int sections = 6;
+  const int imports_dlls = 2;
+  const int delay_dlls = 2;
+  const int exports = 2;
+  const int imports = 69;
+  const int delay_imports = 2;
+  const int relocs = 632;
 #else
-  // Default Release expectations.
-  expectations.SetDefault(Expectations::SECTIONS, 5);
-  expectations.SetDefault(Expectations::IMPORTS_DLLS, 2);
-  expectations.SetDefault(Expectations::DELAY_DLLS, 2);
-  expectations.SetDefault(Expectations::EXPORTS, 2);
-  expectations.SetDefault(Expectations::IMPORTS, 66);
-  expectations.SetDefault(Expectations::DELAY_IMPORTS, 2);
-  expectations.SetDefault(Expectations::RELOCS, 1586);
-
-  // 64-bit Release expectations.
-  expectations.SetOverride(Expectations::SECTIONS, Expectations::ARCH_X64, 6);
-  expectations.SetOverride(Expectations::IMPORTS, Expectations::ARCH_X64, 69);
-  expectations.SetOverride(Expectations::RELOCS, Expectations::ARCH_X64, 632);
+  pe_image_test_path =
+      pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_32.dll"));
+  const int sections = 5;
+  const int imports_dlls = 2;
+  const int delay_dlls = 2;
+  const int exports = 2;
+  const int imports = 66;
+  const int delay_imports = 2;
+  const int relocs = 1586;
 #endif
 
-  HMODULE module = LoadLibrary(L"pe_image_test.dll");
+  HMODULE module = LoadLibrary(pe_image_test_path.value().c_str());
   ASSERT_TRUE(NULL != module);
 
   PEImage pe(module);
@@ -252,31 +127,31 @@
   EXPECT_TRUE(pe.VerifyMagic());
 
   pe.EnumSections(SectionsCallback, &count);
-  EXPECT_EQ(expectations.GetExpectation(Expectations::SECTIONS), count);
+  EXPECT_EQ(sections, count);
 
   count = 0;
   pe.EnumImportChunks(ImportChunksCallback, &count);
-  EXPECT_EQ(expectations.GetExpectation(Expectations::IMPORTS_DLLS), count);
+  EXPECT_EQ(imports_dlls, count);
 
   count = 0;
   pe.EnumDelayImportChunks(DelayImportChunksCallback, &count);
-  EXPECT_EQ(expectations.GetExpectation(Expectations::DELAY_DLLS), count);
+  EXPECT_EQ(delay_dlls, count);
 
   count = 0;
   pe.EnumExports(ExportsCallback, &count);
-  EXPECT_EQ(expectations.GetExpectation(Expectations::EXPORTS), count);
+  EXPECT_EQ(exports, count);
 
   count = 0;
   pe.EnumAllImports(ImportsCallback, &count);
-  EXPECT_EQ(expectations.GetExpectation(Expectations::IMPORTS), count);
+  EXPECT_EQ(imports, count);
 
   count = 0;
   pe.EnumAllDelayImports(ImportsCallback, &count);
-  EXPECT_EQ(expectations.GetExpectation(Expectations::DELAY_IMPORTS), count);
+  EXPECT_EQ(delay_imports, count);
 
   count = 0;
   pe.EnumRelocs(RelocsCallback, &count);
-  EXPECT_EQ(expectations.GetExpectation(Expectations::RELOCS), count);
+  EXPECT_EQ(relocs, count);
 
   FreeLibrary(module);
 }
diff --git a/base/win/scoped_process_information_unittest.cc b/base/win/scoped_process_information_unittest.cc
index ccfa729..614504d 100644
--- a/base/win/scoped_process_information_unittest.cc
+++ b/base/win/scoped_process_information_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/command_line.h"
 #include "base/process/kill.h"
+#include "base/process/process.h"
 #include "base/test/multiprocess_test.h"
 #include "base/win/scoped_process_information.h"
 #include "testing/multiprocess_func_list.h"
@@ -135,13 +136,13 @@
 
   // Validate that we have separate handles that are good.
   int exit_code = 0;
-  ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
-                                    &exit_code));
+  base::Process process(process_info.TakeProcessHandle());
+  ASSERT_TRUE(process.WaitForExit(&exit_code));
   ASSERT_EQ(7, exit_code);
 
   exit_code = 0;
-  ASSERT_TRUE(base::WaitForExitCode(duplicate.TakeProcessHandle(),
-                                    &exit_code));
+  base::Process dup_process(duplicate.TakeProcessHandle());
+  ASSERT_TRUE(dup_process.WaitForExit(&exit_code));
   ASSERT_EQ(7, exit_code);
 
   ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index a3c9ece..957f937 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -57,7 +57,7 @@
 
 // Returns true if a physical keyboard is detected on Windows 8 and up.
 // Uses the Setup APIs to enumerate the attached keyboards and returns true
-// if the keyboard count is more than 1. While this will work in most cases
+// if the keyboard count is 1 or more.. While this will work in most cases
 // it won't work if there are devices which expose keyboard interfaces which
 // are attached to the machine.
 bool IsKeyboardPresentOnSlate() {
@@ -89,6 +89,7 @@
     device_info_data.cbSize = sizeof(device_info_data);
     if (!SetupDiEnumDeviceInfo(device_info, i, &device_info_data))
       break;
+
     // Get the device ID.
     wchar_t device_id[MAX_DEVICE_ID_LEN];
     CONFIGRET status = CM_Get_Device_ID(device_info_data.DevInst,
@@ -96,20 +97,19 @@
                                         MAX_DEVICE_ID_LEN,
                                         0);
     if (status == CR_SUCCESS) {
-      // To reduce the scope of the hack we only look for PNP and HID
+      // To reduce the scope of the hack we only look for PNP, MSF and HID
       // keyboards.
-      if (StartsWith(L"ACPI\\PNP", device_id, false) ||
-          StartsWith(L"HID\\VID", device_id, false)) {
+      if (StartsWith(device_id, L"ACPI\\PNP", false) ||
+          StartsWith(device_id, L"ACPI\\MSF", false) ||
+          StartsWith(device_id, L"HID\\VID", false)) {
         keyboard_count++;
       }
     }
   }
-  // On a Windows machine, the API's always report 1 keyboard at least
-  // regardless of whether the machine has a keyboard attached or not.
-  // The heuristic we are using is to check the count and return true
-  // if the API's report more than one keyboard. Please note that this
+  // The heuristic we are using is to check the count of keyboards and return
+  // true if the API's report one or more keyboards. Please note that this
   // will break for non keyboard devices which expose a keyboard PDO.
-  return keyboard_count > 1;
+  return keyboard_count >= 1;
 }
 
 }  // namespace
diff --git a/build/all.gyp b/build/all.gyp
index 17958a0..499fc57 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -467,6 +467,12 @@
     }, # target_name: chromium_builder_tests
   ],
   'conditions': [
+    # TODO(GYP): make gn_migration.gypi work unconditionally.
+    ['OS=="linux" and target_arch=="x64" and chromeos==0 and chromecast==0 and disable_nacl==0', {
+      'includes': [
+        'gn_migration.gypi',
+      ],
+    }],
     ['OS!="ios"', {
       'targets': [
         {
@@ -516,156 +522,6 @@
     ['OS!="ios" and OS!="android"', {
       'targets': [
         {
-          # TODO(GYP) - make gyp_all and gn_all work on iOS and Android also.
-          'target_name': 'gyp_all',
-          'type': 'none',
-          'dependencies': [
-            ':gn_all',
-            '../chrome/chrome.gyp:chromedriver_unittests',
-            '../components/components_tests.gyp:components_browsertests',
-            # '../components/nacl.gyp:nacl_loader_unittests',  # TODO(GYP)
-            # '../remoting/remoting.gyp:remoting_unittests',  # TODO(GYP)
-            '../ui/compositor/compositor.gyp:compositor_unittests',
-          ],
-          'conditions': [
-            ['OS!="android"', {
-              'dependencies': [
-                # '../device/device_tests.gyp:device_unittests',  # TODO(GYP)
-                # '../google_apis/google_apis.gyp:google_apis_unittests',  # TODO(GYP)
-              ],
-            }],
-          ],
-        },
-        {
-          'target_name': 'gn_all',
-          'type': 'none',
-
-          'dependencies': [
-            '../base/base.gyp:base_unittests',
-            '../cc/cc_tests.gyp:cc_unittests',
-            '../chrome/chrome.gyp:chrome',
-            '../chrome/chrome.gyp:browser_tests',
-            '../chrome/chrome.gyp:interactive_ui_tests',
-            '../chrome/chrome.gyp:sync_integration_tests',
-            '../chrome/chrome.gyp:unit_tests',
-            '../components/components_tests.gyp:components_unittests',
-            '../content/content_shell_and_tests.gyp:content_shell',
-            '../content/content_shell_and_tests.gyp:content_browsertests',
-            '../content/content_shell_and_tests.gyp:content_perftests',
-            '../content/content_shell_and_tests.gyp:content_unittests',
-            '../crypto/crypto.gyp:crypto_unittests',
-            '../extensions/extensions_tests.gyp:extensions_browsertests',
-            '../extensions/extensions_tests.gyp:extensions_unittests',
-            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
-            '../gpu/gpu.gyp:gpu_unittests',
-            '../ipc/ipc.gyp:ipc_tests',
-            '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
-            '../jingle/jingle.gyp:jingle_unittests',
-            '../media/media.gyp:media_unittests',
-            '../media/cast/cast.gyp:cast_unittests',
-            '../mojo/mojo.gyp:mojo',
-            '../mojo/mojo_base.gyp:mojo_common_unittests',
-            '../net/net.gyp:net_unittests',
-            '../ppapi/ppapi_internal.gyp:ppapi_tests',
-            '../printing/printing.gyp:printing_unittests',
-            '../sql/sql.gyp:sql_unittests',
-            '../skia/skia_tests.gyp:skia_unittests',
-            '../sync/sync.gyp:sync_unit_tests',
-
-            # TODO(GYP): the Blink test targets should be public, but
-            # currently aren't. all_blink puls them in, though
-            # "//third_party/WebKit/Source/platform:heap_unittests",
-            # "//third_party/WebKit/Source/platform:platform_unittests",
-            # "//third_party/WebKit/Source/wtf:wtf_unittests",
-            '../third_party/WebKit/public/all.gyp:all_blink',
-
-            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
-
-            # TODO(GYP): Needed only w/ cld_version==1. What configs set that?
-            '../third_party/cld/cld.gyp:cld',
-
-            # TODO(GYP): This is needed only w/ use_system_fontconfig==0. What configs set that?
-            #'../third_party/fontconfig/fontconfig.gyp:fontconfig',
-
-            # TODO(GYP): This will be pulled in automatically when enable_webrtc==true.
-            # For now pull it in manually so that it doesn't regress.
-            '../third_party/libsrtp/libsrtp.gyp:libsrtp',
-
-            '../third_party/mojo/mojo_edk_tests.gyp:mojo_system_unittests',
-            '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests',
-            '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests',
-            '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
-            '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
-            '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
-            '../third_party/pdfium/samples/samples.gyp:pdfium_test',
-
-            # TODO(GYP): Verify that this is no longer needed.
-            '../third_party/smhasher/smhasher.gyp:pmurhash',
-
-            # TODO(GYP): This will be pulled in automatically when enable_webrtc==true.
-            # For now pull it in manually so that it doesn't regress.
-            '../third_party/usrsctp/usrsctp.gyp:usrsctplib',
-
-            '../tools/gn/gn.gyp:gn',
-            '../tools/gn/gn.gyp:gn_unittests',
-            '../ui/accessibility/accessibility.gyp:accessibility_unittests',
-            '../ui/app_list/app_list.gyp:app_list_unittests',
-            '../ui/base/ui_base_tests.gyp:ui_base_unittests',
-            '../ui/display/display.gyp:display_unittests',
-            '../ui/events/events.gyp:events_unittests',
-            '../ui/gfx/gfx_tests.gyp:gfx_unittests',
-            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
-            '../url/url.gyp:url_unittests',
-          ],
-          'conditions': [
-            ['OS!="win"', {
-              'dependencies': [
-                '../breakpad/breakpad.gyp:symupload',
-              ],
-            }],
-            ['use_x11==1', {
-              'dependencies': [
-                '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
-              ],
-            }],
-            ['toolkit_views==1', {
-              'dependencies': [
-                '../ui/views/views.gyp:views_unittests',
-              ],
-            }],
-            ['use_aura==1', {
-              'dependencies': [
-                '../ui/wm/wm.gyp:wm_unittests',
-              ],
-            }],
-            ['use_ozone==1', {
-              'dependencies': [
-                '../ui/ozone/ozone.gyp:ozone',
-              ],
-            }],
-            ['OS=="win" or OS=="mac" or OS=="android"', {
-              'dependencies': [
-                '../rlz/rlz.gyp:rlz_lib',
-              ],
-            }],
-            ['OS=="android"', {
-              'dependencies': [
-                '../chrome/chrome.gyp:chrome_shell_apk',
-                '../content/content_shell_and_tests.gyp:content_shell_apk',
-              ],
-              'dependencies!': [
-                '../url/url.gyp:url_unittests',
-              ],
-            }],
-            ['OS=="linux"', {
-              'dependencies': [
-                '../dbus/dbus.gyp:dbus_unittests',
-                '../sandbox/sandbox.gyp:sandbox_linux_unittests',
-              ],
-            }],
-          ],
-        },
-        {
           'target_name': 'chromium_builder_nacl_win_integration',
           'type': 'none',
           'dependencies': [
@@ -682,6 +538,7 @@
             '../chrome/chrome.gyp:performance_browser_tests',
             '../chrome/chrome.gyp:sync_performance_tests',
             '../content/content_shell_and_tests.gyp:content_shell',
+            '../gpu/gpu.gyp:gpu_perftests',
             '../media/media.gyp:media_perftests',
             '../tools/perf/clear_system_cache/clear_system_cache.gyp:*',
             '../tools/telemetry/telemetry.gyp:*',
diff --git a/build/android/OWNERS b/build/android/OWNERS
index bd675fb..9a5d270 100644
--- a/build/android/OWNERS
+++ b/build/android/OWNERS
@@ -1,2 +1,3 @@
 jbudorick@chromium.org
 klundberg@chromium.org
+pasko@chromium.org
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index 3bec158..8561c01 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -340,9 +340,12 @@
   if os.path.exists('/home/chrome-bot'):
     with open('/home/chrome-bot/.adb_device_info', 'w') as f:
       for device in json_data:
-        f.write('%s %s %s %.1fC %s%%\n' % (device['serial'], device['type'],
-            device['build'], float(device['battery']['temperature']) / 10,
-            device['battery']['level']))
+        try:
+          f.write('%s %s %s %.1fC %s%%\n' % (device['serial'], device['type'],
+              device['build'], float(device['battery']['temperature']) / 10,
+              device['battery']['level']))
+        except Exception:
+          pass
 
   err_msg = CheckForMissingDevices(options, devices) or []
 
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index a53bb56..c3c344b 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -218,7 +218,7 @@
   args = ['--browser', 'android-chrome-shell']
   devices = android_commands.GetAttachedDevices()
   if devices:
-    args = args + ['--device', devices[0]]
+    args = args + ['--device', 'android']
   bb_annotations.PrintNamedStep(step_name)
   RunCmd([run_tests_path] + args)
 
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py
index 38ff93a..29cce1b 100755
--- a/build/android/buildbot/bb_run_bot.py
+++ b/build/android/buildbot/bb_run_bot.py
@@ -160,7 +160,7 @@
       B('chromedriver-fyi-tests-dbg', H(std_test_steps),
         T(['chromedriver'],
           ['--install=ChromeShell', '--install=ChromeDriverWebViewShell',
-           '--skip-wipe', '--cleanup'])),
+           '--skip-wipe', '--disable-location', '--cleanup'])),
       B('fyi-x86-builder-dbg',
         H(compile_step + std_host_tests, experimental, target_arch='ia32')),
       B('fyi-builder-dbg',
diff --git a/build/android/findbugs_filter/findbugs_known_bugs.txt b/build/android/findbugs_filter/findbugs_known_bugs.txt
index 9afba51..01b546a 100644
--- a/build/android/findbugs_filter/findbugs_known_bugs.txt
+++ b/build/android/findbugs_filter/findbugs_known_bugs.txt
@@ -6,3 +6,5 @@
 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.requestId  In PendingDocumentData.java
+M D BC: Unchecked/unconfirmed cast from android.view.View to org.chromium.chrome.browser.firstrun.AccountFirstRunView in org.chromium.chrome.browser.firstrun.AccountFirstRunFragment.onViewCreated(View, Bundle)  At AccountFirstRunFragment.java
+M M LI: Incorrect lazy initialization and update of static field org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings.sSettings in org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings.initialize(Context)  At DataReductionProxySettings.java
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py
index ca58770..cb547fb 100755
--- a/build/android/gyp/proguard.py
+++ b/build/android/gyp/proguard.py
@@ -28,7 +28,31 @@
                   '-outjars', outjars,
                   '-libraryjars', libraryjars,
                   '@' + options.proguard_config]
-  build_utils.CheckOutput(proguard_cmd, print_stdout=True)
+  build_utils.CheckOutput(proguard_cmd, print_stdout=True,
+                          stdout_filter=FilterProguardOutput)
+
+
+def FilterProguardOutput(output):
+  '''ProGuard outputs boring stuff to stdout (proguard version, jar path, etc)
+  as well as interesting stuff (notes, warnings, etc). If stdout is entirely
+  boring, this method suppresses the output.
+  '''
+  ignore_patterns = [
+    'ProGuard, version ',
+    'Reading program jar [',
+    'Reading library jar [',
+    'Preparing output jar [',
+    '  Copying resources from program jar [',
+  ]
+  for line in output.splitlines():
+    for pattern in ignore_patterns:
+      if line.startswith(pattern):
+        break
+    else:
+      # line doesn't match any of the patterns; it's probably something worth
+      # printing out.
+      return output
+  return ''
 
 
 def main(args):
diff --git a/build/android/lint/OWNERS b/build/android/lint/OWNERS
new file mode 100644
index 0000000..cd396e7
--- /dev/null
+++ b/build/android/lint/OWNERS
@@ -0,0 +1,2 @@
+newt@chromium.org
+aurimas@chromium.org
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml
index 5a169c1..cfbf858 100644
--- a/build/android/lint/suppressions.xml
+++ b/build/android/lint/suppressions.xml
@@ -43,6 +43,8 @@
   </issue>
   <issue id="IconDensities">
     <!-- crbug.com/457918 is tracking missing assets -->
+    <ignore path="components/web_contents_delegate_android/android/java/res/drawable-xxhdpi"/>
+    <ignore path="components/web_contents_delegate_android/android/java/res/drawable-xxxhdpi"/>
     <ignore path="content/public/android/java/res/drawable-xxhdpi"/>
     <ignore path="content/public/android/java/res/drawable-xxxhdpi"/>
     <ignore path="chrome/android/java/res/drawable-xxhdpi"/>
@@ -62,9 +64,47 @@
   <issue id="MissingVersion">
     <ignore path="AndroidManifest.xml"/>
   </issue>
-  <!-- Disabling is InlinedApi and NewApi is bad but we have too many of these errors and nobody is fixing it. crbug.com/411461 -->
   <issue id="InlinedApi" severity="ignore"/>
-  <issue id="NewApi" severity="ignore"/>
+  <issue id="NewApi">
+    <ignore regexp="Attribute `paddingStart` referenced here can result in a crash on some specific devices older than API 17"/>
+    <ignore path="org/chromium/base/AnimationFrameTimeHistogram$Recorder.class"/>
+    <ignore path="org/chromium/base/JavaHandlerThread.class"/>
+    <ignore path="org/chromium/base/SysUtils.class"/>
+    <ignore path="org/chromium/chrome/browser/preferences/website/AddExceptionPreference.class"/>
+    <ignore path="org/chromium/chrome/browser/infobar/AnimationHelper$*.class"/>
+    <ignore path="org/chromium/chrome/browser/infobar/AppBannerInfoBar.class"/>
+    <ignore path="org/chromium/chrome/browser/BookmarkUtils.class"/>
+    <ignore path="org/chromium/chrome/browser/widget/ButtonCompat.class"/>
+    <ignore path="org/chromium/chrome/browser/autofill/CardUnmaskPrompt.class"/>
+    <ignore path="org/chromium/chrome/browser/LollipopTtsPlatformImpl.class"/>
+    <ignore path="org/chromium/chrome/browser/LollipopTtsPlatformImpl$*.class"/>
+    <ignore path="org/chromium/chrome/browser/TtsPlatformImpl.class"/>
+    <ignore path="org/chromium/chrome/browser/TtsPlatformImpl$*.class"/>
+    <ignore path="org/chromium/content/browser/accessibility/BrowserAccessibilityManager.class"/>
+    <ignore path="org/chromium/content/browser/ContentViewCore.class"/>
+    <ignore path="org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.class"/>
+    <ignore path="org/chromium/content/browser/accessibility/JellyBeanBrowserAccessibilityManager$*.class"/>
+    <ignore path="org/chromium/content/browser/accessibility/LollipopAccessibilityInjector.class"/>
+    <ignore path="org/chromium/content/browser/accessibility/LollipopAccessibilityInjector$*.class"/>
+    <ignore path="org/chromium/content/browser/accessibility/LollipopBrowserAccessibilityManager.class"/>
+    <ignore path="org/chromium/media/AudioManagerAndroid.class"/>
+    <ignore path="org/chromium/media/MediaCodecBridge.class"/>
+    <ignore path="org/chromium/media/MediaDrmBridge.class"/>
+    <ignore path="org/chromium/media/MediaDrmBridge$*.class"/>
+    <ignore path="org/chromium/media/VideoCaptureCamera.class"/>
+    <ignore path="org/chromium/media/VideoCaptureCamera2.class"/>
+    <ignore path="org/chromium/media/VideoCaptureCamera2$*.class"/>
+    <ignore path="org/chromium/media/WebAudioMediaCodecBridge.class"/>
+    <ignore path="org/chromium/printing/PrintDocumentAdapterWrapper.class"/>
+    <ignore path="org/chromium/printing/PrintManagerDelegateImpl.class"/>
+    <ignore path="org/chromium/printing/PrintingControllerImpl.class"/>
+    <ignore path="org/chromium/ui/base/Clipboard.class"/>
+    <ignore path="org/chromium/ui/ColorPickerAdvancedComponent.class"/>
+    <ignore path="org/chromium/ui/gfx/DeviceDisplayInfo.class"/>
+    <ignore path="org/chromium/ui/gl/SurfaceTexturePlatformWrapper.class"/>
+    <ignore path="org/chromium/ui/widget/TextViewWithClickableSpans.class"/>
+    <ignore path="org/chromium/ui/picker/TwoFieldDatePicker.class"/>
+  </issue>
   <issue id="OldTargetApi">
     <ignore path="AndroidManifest.xml"/>
   </issue>
@@ -79,9 +119,6 @@
   </issue>
   <issue id="SetJavaScriptEnabled" severity="ignore"/>
   <issue id="UnusedResources">
-    <!-- TODO(aurimas): remove suppression once crbug.com/458328 is fixed. -->
-    <ignore path="content/public/android/java/res/layout/validation_message_bubble.xml" />
-
     <!-- These files are used by chrome_shell_apk and chrome_apk targets. -->
     <ignore path="chrome/android/java/res/layout/accessibility_tab_switcher.xml" />
     <ignore path="chrome/android/java/res/drawable/btn_back.xml" />
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index 4835073..5f00b31 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -13,6 +13,7 @@
 import argparse
 import logging
 import os
+import posixpath
 import re
 import subprocess
 import sys
@@ -115,8 +116,16 @@
 
   # LOCAL_PROPERTIES_PATH = '/data/local.prop'
 
+def WriteAdbKeysFile(device, adb_keys_string):
+  dir_path = posixpath.dirname(constants.ADB_KEYS_FILE)
+  device.RunShellCommand('mkdir -p %s' % dir_path, as_root=True)
+  device.RunShellCommand('restorecon %s' % dir_path, as_root=True)
+  device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True)
+  device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE,
+                         as_root=True)
 
-def WipeDeviceData(device):
+
+def WipeDeviceData(device, options):
   """Wipes data from device, keeping only the adb_keys for authorization.
 
   After wiping data on a device that has been authorized, adb can still
@@ -130,22 +139,25 @@
   """
   device_authorized = device.FileExists(constants.ADB_KEYS_FILE)
   if device_authorized:
-    adb_keys = device.ReadFile(constants.ADB_KEYS_FILE, as_root=True)
+    adb_keys = device.ReadFile(constants.ADB_KEYS_FILE,
+                               as_root=True).splitlines()
   device.RunShellCommand('wipe data', as_root=True)
   if device_authorized:
-    path_list = constants.ADB_KEYS_FILE.split('/')
-    dir_path = '/'.join(path_list[:len(path_list)-1])
-    device.RunShellCommand('mkdir -p %s' % dir_path, as_root=True)
-    device.RunShellCommand('restorecon %s' % dir_path, as_root=True)
-    device.WriteFile(constants.ADB_KEYS_FILE, adb_keys, as_root=True)
-    device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE,
-                           as_root=True)
+    adb_keys_set = set(adb_keys)
+    for adb_key_file in options.adb_key_files or []:
+      try:
+        with open(adb_key_file, 'r') as f:
+          adb_public_keys = f.readlines()
+        adb_keys_set.update(adb_public_keys)
+      except IOError:
+        logging.warning('Unable to find adb keys file %s.' % adb_key_file)
+    WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
 
 
-def WipeDeviceIfPossible(device, timeout):
+def WipeDeviceIfPossible(device, timeout, options):
   try:
     device.EnableRoot()
-    WipeDeviceData(device)
+    WipeDeviceData(device, options)
     device.Reboot(True, timeout=timeout, retries=0)
   except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError):
     pass
@@ -176,7 +188,7 @@
 
   try:
     if not options.skip_wipe:
-      WipeDeviceIfPossible(device, reboot_timeout)
+      WipeDeviceIfPossible(device, reboot_timeout, options)
     try:
       device.EnableRoot()
     except device_errors.CommandFailedError as e:
@@ -196,7 +208,7 @@
           device, device_settings.NETWORK_DISABLED_SETTINGS)
     if options.min_battery_level is not None:
       try:
-        device.SetUsbCharging(True)
+        device.SetCharging(True)
         ChargeDeviceToLevel(device, options.min_battery_level)
       except device_errors.CommandFailedError as e:
         logging.exception('Unable to charge device to specified level.')
@@ -280,6 +292,8 @@
   parser.add_argument('-r', '--auto-reconnect', action='store_true',
                       help='push binary which will reboot the device on adb'
                       ' disconnections')
+  parser.add_argument('--adb-key-files', type=str, nargs='+',
+                      help='list of adb keys to push to device')
   args = parser.parse_args()
   constants.SetBuildType(args.target)
 
diff --git a/build/android/pylib/base/test_dispatcher.py b/build/android/pylib/base/test_dispatcher.py
index 929c408..1a8e0c1 100644
--- a/build/android/pylib/base/test_dispatcher.py
+++ b/build/android/pylib/base/test_dispatcher.py
@@ -116,7 +116,7 @@
         pass_results = base_test_result.TestRunResults()
         pass_results.AddResults(result.GetPass())
         out_results.append(pass_results)
-        logging.warning('Will retry test, try #%s.' % test.tries)
+        logging.warning('Will retry test %s, try #%s.', retry, test.tries)
         collection.add(_Test(test=retry, tries=test.tries))
       else:
         # All tests passed or retry limit reached. Either way, record results.
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py
index 8027012..b849a8d 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants.py
@@ -288,4 +288,5 @@
 
 # Exit codes
 ERROR_EXIT_CODE = 1
+INFRA_EXIT_CODE = 87
 WARNING_EXIT_CODE = 88
diff --git a/build/android/pylib/device/device_errors.py b/build/android/pylib/device/device_errors.py
index c47c966..26d9eaf 100644
--- a/build/android/pylib/device/device_errors.py
+++ b/build/android/pylib/device/device_errors.py
@@ -7,14 +7,10 @@
 """
 
 from pylib import cmd_helper
+from pylib.utils import base_error
 
 
-class BaseError(Exception):
-  """Base exception for all device and command errors."""
-  pass
-
-
-class CommandFailedError(BaseError):
+class CommandFailedError(base_error.BaseError):
   """Exception for command failures."""
 
   def __init__(self, message, device_serial=None):
@@ -64,19 +60,18 @@
       ['shell', command], output, status, device_serial, message)
 
 
-class CommandTimeoutError(BaseError):
+class CommandTimeoutError(base_error.BaseError):
   """Exception for command timeouts."""
   pass
 
 
-class DeviceUnreachableError(BaseError):
+class DeviceUnreachableError(base_error.BaseError):
   """Exception for device unreachable failures."""
   pass
 
 
-class NoDevicesError(BaseError):
+class NoDevicesError(base_error.BaseError):
   """Exception for having no devices attached."""
 
   def __init__(self):
     super(NoDevicesError, self).__init__('No devices attached.')
-
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 4d77fa8..b6fd732 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -29,6 +29,7 @@
 from pylib.device import logcat_monitor
 from pylib.device.commands import install_commands
 from pylib.utils import apk_helper
+from pylib.utils import base_error
 from pylib.utils import device_temp_file
 from pylib.utils import host_utils
 from pylib.utils import md5sum
@@ -44,7 +45,7 @@
 # the timeout_retry decorators.
 DEFAULT = object()
 
-_CONTROL_USB_CHARGING_COMMANDS = [
+_CONTROL_CHARGING_COMMANDS = [
   {
     # Nexus 4
     'witness_file': '/sys/module/pm8921_charger/parameters/disabled',
@@ -187,7 +188,7 @@
     """
     try:
       return self.adb.GetState() == 'device'
-    except device_errors.BaseError as exc:
+    except base_error.BaseError as exc:
       logging.info('Failed to get state: %s', exc)
       return False
 
@@ -1418,47 +1419,51 @@
     return result
 
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def GetUsbCharging(self, timeout=None, retries=None):
-    """Gets the USB charging state of the device.
+  def GetCharging(self, timeout=None, retries=None):
+    """Gets the charging state of the device.
 
     Args:
       timeout: timeout in seconds
       retries: number of retries
     Returns:
-      True if the device is charging via USB, false otherwise.
+      True if the device is charging, false otherwise.
     """
-    return (self.GetBatteryInfo().get('USB powered', '').lower()
-            in ('true', '1', 'yes'))
+    battery_info = self.GetBatteryInfo()
+    for k in ('AC powered', 'USB powered', 'Wireless powered'):
+      if (k in battery_info and
+          battery_info[k].lower() in ('true', '1', 'yes')):
+        return True
+    return False
 
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def SetUsbCharging(self, enabled, timeout=None, retries=None):
-    """Enables or disables USB charging on the device.
+  def SetCharging(self, enabled, timeout=None, retries=None):
+    """Enables or disables charging on the device.
 
     Args:
-      enabled: A boolean indicating whether USB charging should be enabled or
+      enabled: A boolean indicating whether charging should be enabled or
         disabled.
       timeout: timeout in seconds
       retries: number of retries
     """
-    if 'usb_charging_config' not in self._cache:
-      for c in _CONTROL_USB_CHARGING_COMMANDS:
+    if 'charging_config' not in self._cache:
+      for c in _CONTROL_CHARGING_COMMANDS:
         if self.FileExists(c['witness_file']):
-          self._cache['usb_charging_config'] = c
+          self._cache['charging_config'] = c
           break
       else:
         raise device_errors.CommandFailedError(
             'Unable to find charging commands.')
 
     if enabled:
-      command = self._cache['usb_charging_config']['enable_command']
+      command = self._cache['charging_config']['enable_command']
     else:
-      command = self._cache['usb_charging_config']['disable_command']
+      command = self._cache['charging_config']['disable_command']
 
-    def set_and_verify_usb_charging():
-      self.RunShellCommand(command)
-      return self.GetUsbCharging() == enabled
+    def set_and_verify_charging():
+      self.RunShellCommand(command, check_return=True)
+      return self.GetCharging() == enabled
 
-    timeout_retry.WaitFor(set_and_verify_usb_charging, wait_period=1)
+    timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def GetDevicePieWrapper(self, timeout=None, retries=None):
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 1b4d1cf..b7e807e 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -1411,51 +1411,61 @@
       self.assertEquals({}, self.device.GetBatteryInfo())
 
 
-class DeviceUtilsGetUsbChargingTest(DeviceUtilsTest):
-  def testGetUsbCharging_true(self):
+class DeviceUtilsGetChargingTest(DeviceUtilsTest):
+  def testGetCharging_usb(self):
     with self.assertCall(
         self.call.device.GetBatteryInfo(), {'USB powered': 'true'}):
-      self.assertTrue(self.device.GetUsbCharging())
+      self.assertTrue(self.device.GetCharging())
 
-  def testGetUsbCharging_false(self):
+  def testGetCharging_usbFalse(self):
     with self.assertCall(
         self.call.device.GetBatteryInfo(), {'USB powered': 'false'}):
-      self.assertFalse(self.device.GetUsbCharging())
+      self.assertFalse(self.device.GetCharging())
 
-  def testGetUsbCharging_unknown(self):
+  def testGetCharging_ac(self):
     with self.assertCall(
         self.call.device.GetBatteryInfo(), {'AC powered': 'true'}):
-      self.assertFalse(self.device.GetUsbCharging())
+      self.assertTrue(self.device.GetCharging())
+
+  def testGetCharging_wireless(self):
+    with self.assertCall(
+        self.call.device.GetBatteryInfo(), {'Wireless powered': 'true'}):
+      self.assertTrue(self.device.GetCharging())
+
+  def testGetCharging_unknown(self):
+    with self.assertCall(
+        self.call.device.GetBatteryInfo(), {'level': '42'}):
+      self.assertFalse(self.device.GetCharging())
 
 
-class DeviceUtilsSetUsbChargingTest(DeviceUtilsTest):
+class DeviceUtilsSetChargingTest(DeviceUtilsTest):
 
   @mock.patch('time.sleep', mock.Mock())
-  def testSetUsbCharging_enabled(self):
+  def testSetCharging_enabled(self):
     with self.assertCalls(
         (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY), []),
-        (self.call.device.GetUsbCharging(), False),
-        (self.call.device.RunShellCommand(mock.ANY), []),
-        (self.call.device.GetUsbCharging(), True)):
-      self.device.SetUsbCharging(True)
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.device.GetCharging(), False),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.device.GetCharging(), True)):
+      self.device.SetCharging(True)
 
-  def testSetUsbCharging_alreadyEnabled(self):
+  def testSetCharging_alreadyEnabled(self):
     with self.assertCalls(
         (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY), []),
-        (self.call.device.GetUsbCharging(), True)):
-      self.device.SetUsbCharging(True)
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.device.GetCharging(), True)):
+      self.device.SetCharging(True)
 
   @mock.patch('time.sleep', mock.Mock())
-  def testSetUsbCharging_disabled(self):
+  def testSetCharging_disabled(self):
     with self.assertCalls(
         (self.call.device.FileExists(mock.ANY), True),
-        (self.call.device.RunShellCommand(mock.ANY), []),
-        (self.call.device.GetUsbCharging(), True),
-        (self.call.device.RunShellCommand(mock.ANY), []),
-        (self.call.device.GetUsbCharging(), False)):
-      self.device.SetUsbCharging(False)
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.device.GetCharging(), True),
+        (self.call.device.RunShellCommand(mock.ANY, check_return=True), []),
+        (self.call.device.GetCharging(), False)):
+      self.device.SetCharging(False)
 
 
 
diff --git a/build/android/pylib/gtest/filter/content_browsertests_disabled b/build/android/pylib/gtest/filter/content_browsertests_disabled
index 1e3d523..613c833 100644
--- a/build/android/pylib/gtest/filter/content_browsertests_disabled
+++ b/build/android/pylib/gtest/filter/content_browsertests_disabled
@@ -2,40 +2,31 @@
 # Timeouts
 Http/MediaTest.*
 File/MediaTest.*
-WorkerTest.*
+WorkerTest.IncognitoSharedWorkers
+WorkerTest.MultipleSharedWorkers
+WorkerTest.PassMessagePortToSharedWorker
+WorkerTest.PassMessagePortToSharedWorkerDontWaitForConnect
+WorkerTest.SharedWorkerHttpAuth
+WorkerTest.SingleSharedWorker
+WorkerTest.WebSocketSharedWorker
 MediaTest.*
-MediaSourceTest.ConfigChangeVideo
-WebGLConformanceTest.*
-MessagePortTest.Tests
-CrossPlatformAccessibilityBrowserTest.*
 DatabaseTest.*
-ResourceDispatcherHostBrowserTest.SyncXMLHttpRequest_DuringUnload
 
 # Crashes
-ResourceDispatcherHostBrowserTest.CrossSiteAfterCrash
 RenderFrameHostManagerTest.IgnoreRendererDebugURLsWhenCrashed
-RenderFrameHostManagerTest.ProcessExitWithSwappedOutViews
 
 # Crashes due to using --disable-gpu.
 # Needs to investigate more in http://crbug.com/461624.
 ScreenOrientationBrowserTest.*
 
-# Failures
-RenderViewHostTest.BaseURLParam
-OffTheRecordClipboardTest.ClearContentData
-GpuPixelBrowserTest.*
-FileSystemBrowserTestWithLowQuota.QuotaTest
-ChildProcessSecurityPolicyInProcessBrowserTest.NoLeak
-
 # Plugins are not supported.
 BrowserPluginThreadedCompositorPixelTest.*
 BrowserPluginHostTest.*
 BrowserPluginTest.*
 PluginTest.*
 
-# These used to be test_shell_tests and were ported to content_browsertests in
-# https://codereview.chromium.org/14304004/. Investigate more.
-DomSerializerTests.*
+# http://crbug.com/463740
+CrossPlatformAccessibilityBrowserTest.SelectedEditableTextAccessibility
 
 # http://crbug.com/297230
 DumpAccessibilityTreeTest.AccessibilityAriaLevel
@@ -44,7 +35,6 @@
 DumpAccessibilityTreeTest.AccessibilityUl
 DumpAccessibilityTreeTest.AccessibilityCanvas
 RendererAccessibilityTest.DetachAccessibilityObject
-RendererAccessibilityTest.EditableTextModeFocusEvents
 DumpAccessibilityTreeTest.AccessibilityDialog
 DumpAccessibilityTreeTest.AccessibilityModalDialogClosed
 DumpAccessibilityTreeTest.AccessibilityModalDialogInIframeOpened
@@ -52,13 +42,9 @@
 
 # http://crbug.com/187500
 RenderViewImplTest.*
-RendererAccessibilityTest.EditableTextModeFocusNotifications
 RendererAccessibilityTest.SendFullAccessibilityTreeOnReload
 RendererAccessibilityTest.HideAccessibilityObject
 RendererAccessibilityTest.ShowAccessibilityObject
-RenderWidgetTest.OnMsgPaintAtSize
-PasswordFormConversionUtilsTest.ValidWebFormElementToPasswordForm
-PasswordFormConversionUtilsTest.InvalidWebFormElementToPasswordForm
 
 # http://crbug.com/215894
 DownloadContentTest.CancelInterruptedDownload
@@ -71,9 +57,6 @@
 DownloadContentTest.ResumeInterruptedDownloadBadPrecondition
 DownloadContentTest.ResumeWithDeletedFile
 
-# http://crbug.com/224134
-RenderWidgetHostBrowserTest.GetSnapshotFromRendererTest
-
 # http://crbug.com/386227
 IndexedDBBrowserTest.VersionChangeCrashResilience
 
@@ -86,28 +69,12 @@
 # http://crbug.com/342525
 IndexedDBBrowserTestSingleProcess.RenderThreadShutdownTest
 
-BookmarkletTest.NonEmptyResult
-
-# http://crbug.com/256238
-SignalTest.*
-
-# http://crbug.com/311344
-BrowserGpuChannelHostFactoryTest.AlreadyEstablished
-BrowserGpuChannelHostFactoryTest.Basic
-BrowserGpuChannelHostFactoryTest.CrashAndRecover
-BrowserGpuChannelHostFactoryTest.EstablishAndTerminate
-
-# http://crbug.com/338408
-TracingControllerTest.EnableCaptureAndDisableMonitoring
-
-# http://crbug.com/338411
-FrameTreeBrowserTest.NavigateWithLeftoverFrames
-
 # http://crbug.com/338421
 GinBrowserTest.GinAndGarbageCollection
 
-# http://crbug.com/341995
-TracingControllerTest.EnableCaptureAndDisableMonitoringWithFilePath
-
 # http://crbug.com/343604
 MSE_ClearKey/EncryptedMediaTest.ConfigChangeVideo/0
+
+# http://crbug.com/463041
+ScreenOrientationBrowserTest.ScreenOrientationChange
+ScreenOrientationBrowserTest.WindowOrientationCange
diff --git a/build/android/pylib/gtest/local_device_gtest_run.py b/build/android/pylib/gtest/local_device_gtest_run.py
index 3ca0374..c48c865 100644
--- a/build/android/pylib/gtest/local_device_gtest_run.py
+++ b/build/android/pylib/gtest/local_device_gtest_run.py
@@ -24,9 +24,6 @@
     'org.chromium.native_test.ChromeNativeTestActivity.CommandLineFile')
 _EXTRA_COMMAND_LINE_FLAGS = (
     'org.chromium.native_test.ChromeNativeTestActivity.CommandLineFlags')
-_EXTRA_ENABLE_TEST_SERVER_SPAWNER = (
-    'org.chromium.native_test.ChromeNativeTestInstrumentationTestRunner'
-        '.EnableTestServerSpawner')
 
 _MAX_SHARD_SIZE = 256
 
@@ -44,9 +41,6 @@
     self._component = '%s/%s' % (self._package, self._runner)
     self._enable_test_server_spawner = False
 
-  def EnableTestServerSpawner(self):
-    self._enable_test_server_spawner = True
-
   def Install(self, device):
     device.Install(self._apk)
 
@@ -57,8 +51,6 @@
       extras = {
         _EXTRA_COMMAND_LINE_FILE: command_line_file.name,
       }
-      if self._enable_test_server_spawner:
-        extras[_EXTRA_ENABLE_TEST_SERVER_SPAWNER] = '1'
 
       return device.StartInstrumentation(
           self._component, extras=extras, raw=False, **kwargs)
@@ -81,9 +73,6 @@
       self._deps_host_path = None
     self._test_run = tr
 
-  def EnableTestServerSpawner(self):
-    pass
-
   def Install(self, device):
     # TODO(jbudorick): Look into merging this with normal data deps pushing if
     # executables become supported on nonlocal environments.
@@ -143,6 +132,8 @@
     elif self._test_instance.exe:
       self._delegate = _ExeDelegate(self, self._test_instance.exe)
 
+    self._servers = {}
+
   #override
   def TestPackage(self):
     return self._test_instance._suite
@@ -161,8 +152,14 @@
           for h, d in host_device_tuples]
       dev.PushChangedFiles(host_device_tuples)
 
+      self._servers[str(dev)] = []
       if self.TestPackage() in _SUITE_REQUIRES_TEST_SERVER_SPAWNER:
-        self._delegate.EnableTestServerSpawner()
+        self._servers[str(dev)].append(
+            local_test_server_spawner.LocalTestServerSpawner(
+                ports.AllocateTestServerPort(), dev, self.GetTool(dev)))
+
+      for s in self._servers[str(dev)]:
+        s.SetUp()
 
     self._env.parallel_devices.pMap(individual_device_set_up,
                                     self._test_instance.GetDataDependencies())
@@ -194,6 +191,8 @@
     # Run the test.
     output = self._delegate.RunWithFlags(device, '--gtest_filter=%s' % test,
                                          timeout=900, retries=0)
+    for s in self._servers[str(device)]:
+      s.Reset()
     self._delegate.Clear(device)
 
     # Parse the output.
@@ -203,5 +202,9 @@
 
   #override
   def TearDown(self):
-    pass
+    def individual_device_tear_down(dev):
+      for s in self._servers[str(dev)]:
+        s.TearDown()
+
+    self._env.parallel_devices.pMap(individual_device_tear_down)
 
diff --git a/build/android/pylib/perf/test_runner.py b/build/android/pylib/perf/test_runner.py
index d9227a5..da66d07 100644
--- a/build/android/pylib/perf/test_runner.py
+++ b/build/android/pylib/perf/test_runner.py
@@ -250,9 +250,10 @@
     logging.info('%s : %s', test_name, cmd)
     start_time = datetime.datetime.now()
 
-    timeout = 5400
+    timeout = self._tests['steps'][test_name].get('timeout', 5400)
     if self._options.no_timeout:
       timeout = None
+    logging.info('Timeout for %s test: %s', test_name, timeout)
     full_cmd = cmd
     if self._options.dry_run:
       full_cmd = 'echo %s' % cmd
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index 2561180..3b0c029 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -183,6 +183,7 @@
     os.environ['APPURIFY_API_PROTO'] = self._api_protocol
     os.environ['APPURIFY_API_HOST'] = self._api_address
     os.environ['APPURIFY_API_PORT'] = self._api_port
+    os.environ['APPURIFY_STATUS_BASE_URL'] = 'none'
     self._GetAccessToken()
     if self._trigger:
       self._SelectDevice()
@@ -302,7 +303,8 @@
 
   def _NoDeviceFound(self):
     self._PrintAvailableDevices(self._GetDeviceList())
-    raise remote_device_helper.RemoteDeviceError('No device found.')
+    raise remote_device_helper.RemoteDeviceError(
+        'No device found.', is_infra_error=True)
 
   @property
   def collect(self):
diff --git a/build/android/pylib/remote/device/remote_device_helper.py b/build/android/pylib/remote/device/remote_device_helper.py
index 71603c3..5b1411e 100644
--- a/build/android/pylib/remote/device/remote_device_helper.py
+++ b/build/android/pylib/remote/device/remote_device_helper.py
@@ -4,7 +4,10 @@
 
 """Common functions and Exceptions for remote_device_*"""
 
-class RemoteDeviceError(Exception):
+from pylib.utils import base_error
+
+
+class RemoteDeviceError(base_error.BaseError):
   """Exception to throw when problems occur with remote device service."""
   pass
 
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 43a7399..a2d4a53 100644
--- a/build/android/pylib/remote/device/remote_device_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -93,7 +93,8 @@
         if timeout_counter > timeout:
           raise remote_device_helper.RemoteDeviceError(
               'Timeout while in %s state for %s seconds'
-              % (current_status, timeout))
+              % (current_status, timeout),
+              is_infra_error=True)
         time.sleep(self.WAIT_TIME)
         timeout_counter += self.WAIT_TIME
         heartbeat_counter += self.WAIT_TIME
diff --git a/build/android/pylib/remote/device/remote_device_uirobot_test_run.py b/build/android/pylib/remote/device/remote_device_uirobot_test_run.py
index 936db0a..f818c98 100644
--- a/build/android/pylib/remote/device/remote_device_uirobot_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_uirobot_test_run.py
@@ -43,7 +43,7 @@
       default_runner_type = 'ios_robot'
     else:
       raise remote_device_helper.RemoteDeviceError(
-          'Unkown device type: %s' % self._env.device_type)
+          'Unknown device type: %s' % self._env.device_type)
 
     self._app_id = self._UploadAppToDevice(self._test_instance.app_under_test)
     if not self._env.runner_type:
diff --git a/build/android/pylib/utils/base_error.py b/build/android/pylib/utils/base_error.py
new file mode 100644
index 0000000..31eaa54
--- /dev/null
+++ b/build/android/pylib/utils/base_error.py
@@ -0,0 +1,16 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class BaseError(Exception):
+  """Base error for all test runner errors."""
+
+  def __init__(self, message, is_infra_error=False):
+    super(BaseError, self).__init__(message)
+    self._is_infra_error = is_infra_error
+
+  @property
+  def is_infra_error(self):
+    """Property to indicate if error was caused by an infrastructure issue."""
+    return self._is_infra_error
\ No newline at end of file
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index f79e13e..368ac06 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -44,6 +44,7 @@
 from pylib.uiautomator import setup as uiautomator_setup
 from pylib.uiautomator import test_options as uiautomator_test_options
 from pylib.utils import apk_helper
+from pylib.utils import base_error
 from pylib.utils import reraiser_thread
 from pylib.utils import run_tests_helper
 
@@ -957,7 +958,7 @@
           json_results.GenerateJsonResultsFile(
               results, args.json_results_file)
 
-  return 0 if results.DidRunPass() else 1
+  return 0 if results.DidRunPass() else constants.ERROR_EXIT_CODE
 
 
 CommandConfigTuple = collections.namedtuple(
@@ -1013,7 +1014,18 @@
     config.add_options_func(subparser)
 
   args = parser.parse_args()
-  return RunTestsCommand(args, parser)
+
+  try:
+    return RunTestsCommand(args, parser)
+  except base_error.BaseError as e:
+    logging.exception('Error occurred.')
+    if e.is_infra_error:
+      return constants.INFRA_EXIT_CODE
+    else:
+      return constants.ERROR_EXIT_CODE
+  except: # pylint: disable=W0702
+    logging.exception('Unrecognized error occurred.')
+    return constants.ERROR_EXIT_CODE
 
 
 if __name__ == '__main__':
diff --git a/build/apk_test.gypi b/build/apk_test.gypi
index 5ee494c..05bafab 100644
--- a/build/apk_test.gypi
+++ b/build/apk_test.gypi
@@ -22,7 +22,6 @@
     '<(DEPTH)/base/base.gyp:base_java',
     '<(DEPTH)/build/android/pylib/device/commands/commands.gyp:chromium_commands',
     '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:remote_device_dummy_apk',
-    '<(DEPTH)/net/net.gyp:net_java_test_support',
     '<(DEPTH)/tools/android/android_tools.gyp:android_tools',
   ],
   'conditions': [
diff --git a/build/common.gypi b/build/common.gypi
index 4c2d696..d72c76f 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -184,6 +184,12 @@
         # below for MIPS targets.
         'mips_arch_variant%': '',
 
+        # MIPS DSP ASE revision. Possible values are:
+        #   0: unavailable
+        #   1: revision 1
+        #   2: revision 2
+        'mips_dsp_rev%': 0,
+
         'conditions': [
           # Ash needs Aura.
           ['use_aura==0', {
@@ -276,6 +282,7 @@
       'target_arch%': '<(target_arch)',
       'target_subarch%': '<(target_subarch)',
       'mips_arch_variant%': '<(mips_arch_variant)',
+      'mips_dsp_rev%': '<(mips_dsp_rev)',
       'toolkit_views%': '<(toolkit_views)',
       'desktop_linux%': '<(desktop_linux)',
       'use_aura%': '<(use_aura)',
@@ -1067,6 +1074,7 @@
     'target_arch%': '<(target_arch)',
     'target_subarch%': '<(target_subarch)',
     'mips_arch_variant%': '<(mips_arch_variant)',
+    'mips_dsp_rev%': '<(mips_dsp_rev)',
     'host_arch%': '<(host_arch)',
     'toolkit_views%': '<(toolkit_views)',
     'ui_compositor_image_transport%': '<(ui_compositor_image_transport)',
@@ -1663,11 +1671,16 @@
         # Location of Android NDK.
         'variables': {
           'variables': {
-            # Unfortunately we have to use absolute paths to the SDK/NDK because
-            # they're passed to ant which uses a different relative path from
-            # gyp.
-            'android_ndk_root%': '<!(cd <(DEPTH) && pwd -P)/third_party/android_tools/ndk/',
+            # Standard libraries can use the relative path to the NDK.
+            'android_ndk_root%': '../../third_party/android_tools/ndk/',
+            # Unfortunately, it is required to use the absolute path to the SDK
+            # because it us passed to ant which uses a different relative path
+            # from GYP.
             'android_sdk_root%': '<!(cd <(DEPTH) && pwd -P)/third_party/android_tools/sdk/',
+            # Similarly, gdbserver and the Android toolchain need to use the
+            # absolute path to the NDK because they are used at different levels
+            # in the GYP files.
+            'android_ndk_absolute_root%': '<!(cd <(DEPTH) && pwd -P)/third_party/android_tools/ndk/',
             'android_host_arch%': '<!(uname -m)',
             # Android API-level of the SDK used for compilation.
             'android_sdk_version%': '21',
@@ -1676,6 +1689,7 @@
           },
           # Copy conditionally-set variables out one scope.
           'android_ndk_root%': '<(android_ndk_root)',
+          'android_ndk_absolute_root%': '<(android_ndk_absolute_root)',
           'android_sdk_root%': '<(android_sdk_root)',
           'android_sdk_version%': '<(android_sdk_version)',
           'android_stlport_root': '<(android_ndk_root)/sources/cxx-stl/stlport',
@@ -1691,17 +1705,17 @@
           'conditions': [
             ['target_arch == "ia32"', {
               'android_app_abi%': 'x86',
-              'android_gdbserver%': '<(android_ndk_root)/prebuilt/android-x86/gdbserver/gdbserver',
+              'android_gdbserver%': '<(android_ndk_absolute_root)/prebuilt/android-x86/gdbserver/gdbserver',
               'android_ndk_sysroot%': '<(android_ndk_root)/platforms/android-14/arch-x86',
               'android_ndk_lib_dir%': 'usr/lib',
-              'android_toolchain%': '<(android_ndk_root)/toolchains/x86-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
+              'android_toolchain%': '<(android_ndk_absolute_root)/toolchains/x86-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
             }],
             ['target_arch == "x64"', {
               'android_app_abi%': 'x86_64',
-              'android_gdbserver%': '<(android_ndk_root)/prebuilt/android-x86_64/gdbserver/gdbserver',
+              'android_gdbserver%': '<(android_ndk_absolute_root)/prebuilt/android-x86_64/gdbserver/gdbserver',
               'android_ndk_sysroot%': '<(android_ndk_root)/platforms/android-21/arch-x86_64',
               'android_ndk_lib_dir%': 'usr/lib64',
-              'android_toolchain%': '<(android_ndk_root)/toolchains/x86_64-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
+              'android_toolchain%': '<(android_ndk_absolute_root)/toolchains/x86_64-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
             }],
             ['target_arch=="arm"', {
               'conditions': [
@@ -1711,32 +1725,31 @@
                   'android_app_abi%': 'armeabi-v7a',
                 }],
               ],
-              'android_gdbserver%': '<(android_ndk_root)/prebuilt/android-arm/gdbserver/gdbserver',
+              'android_gdbserver%': '<(android_ndk_absolute_root)/prebuilt/android-arm/gdbserver/gdbserver',
               'android_ndk_sysroot%': '<(android_ndk_root)/platforms/android-14/arch-arm',
               'android_ndk_lib_dir%': 'usr/lib',
-              'android_toolchain%': '<(android_ndk_root)/toolchains/arm-linux-androideabi-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
+              'android_toolchain%': '<(android_ndk_absolute_root)/toolchains/arm-linux-androideabi-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
             }],
             ['target_arch == "arm64"', {
               'android_app_abi%': 'arm64-v8a',
-              'android_gdbserver%': '<(android_ndk_root)/prebuilt/android-arm64/gdbserver/gdbserver',
+              'android_gdbserver%': '<(android_ndk_absolute_root)/prebuilt/android-arm64/gdbserver/gdbserver',
               'android_ndk_sysroot%': '<(android_ndk_root)/platforms/android-21/arch-arm64',
               'android_ndk_lib_dir%': 'usr/lib',
-              'android_toolchain%': '<(android_ndk_root)/toolchains/aarch64-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
+              'android_toolchain%': '<(android_ndk_absolute_root)/toolchains/aarch64-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
             }],
             ['target_arch == "mipsel"', {
               'android_app_abi%': 'mips',
-              'android_gdbserver%': '<(android_ndk_root)/prebuilt/android-mips/gdbserver/gdbserver',
+              'android_gdbserver%': '<(android_ndk_absolute_root)/prebuilt/android-mips/gdbserver/gdbserver',
               'android_ndk_sysroot%': '<(android_ndk_root)/platforms/android-14/arch-mips',
               'android_ndk_lib_dir%': 'usr/lib',
-              'android_toolchain%': '<(android_ndk_root)/toolchains/mipsel-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
+              'android_toolchain%': '<(android_ndk_absolute_root)/toolchains/mipsel-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
             }],
             ['target_arch == "mips64el"', {
               'android_app_abi%': 'mips64',
-              'android_gdbserver%': '<(android_ndk_root)/prebuilt/android-mips64/gdbserver/gdbserver',
+              'android_gdbserver%': '<(android_ndk_absolute_root)/prebuilt/android-mips64/gdbserver/gdbserver',
               'android_ndk_sysroot%': '<(android_ndk_root)/platforms/android-21/arch-mips64',
               'android_ndk_lib_dir%': 'usr/lib64',
-              'android_toolchain%': '<(android_ndk_root)/toolchains/mips64el-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
-              'gcc_version%': 49,
+              'android_toolchain%': '<(android_ndk_absolute_root)/toolchains/mips64el-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
             }],
           ],
         },
@@ -2149,9 +2162,8 @@
         'enable_service_discovery%': 1
       }],
       ['clang_use_chrome_plugins==1 and OS!="win"', {
-        'clang_chrome_plugins_flags': [
-          '<!@(<(DEPTH)/tools/clang/scripts/plugin_flags.sh)'
-        ],
+        'clang_chrome_plugins_flags%':
+          '<!(python <(DEPTH)/tools/clang/scripts/plugin_flags.py)',
       }],
       ['asan==1 or msan==1 or lsan==1 or tsan==1', {
         'clang%': 1,
@@ -2290,7 +2302,10 @@
         'arm_thumb%': 1,
       }],
 
-      # Set default compiler flags depending on MIPS architecture variant.
+      # Set default compiler flags for MIPS floating-point support.
+      ['target_arch=="mipsel" and android_webview_build==0', {
+        'mips_float_abi%': 'hard',
+      }],
       ['target_arch=="mipsel" and mips_arch_variant=="r2" and android_webview_build==0', {
         'mips_fpu_mode%': 'fp32',
       }],
@@ -2302,6 +2317,7 @@
         'arm_fpu%': '',
         'arm_float_abi%': '',
         'arm_thumb%': 0,
+        'mips_float_abi%': '',
         'mips_fpu_mode%': '',
       }],
 
@@ -2591,7 +2607,7 @@
           ],
         },
       }],
-      ['clang==1 and OS!="win"', {
+      ['(clang==1 or host_clang==1) and OS!="win"', {
         # This is here so that all files get recompiled after a clang roll and
         # when turning clang on or off.
         # (defines are passed via the command line, and build systems rebuild
@@ -4052,19 +4068,37 @@
             'target_conditions': [
               ['_toolset=="target"', {
                 'conditions': [
-                  ['android_webview_build==0 and mips_arch_variant=="r6"', {
-                    'cflags': ['-mips32r6', '-Wa,-mips32r6'],
+                  ['android_webview_build==0', {
                     'conditions': [
-                      ['OS=="android"', {
-                        'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
+                      ['mips_arch_variant=="r6"', {
+                        'cflags': ['-mips32r6', '-Wa,-mips32r6'],
+                        'conditions': [
+                          ['OS=="android"', {
+                            'ldflags': ['-mips32r6', '-Wl,-melf32ltsmip',],
+                          }],
+                        ],
+                      }],
+                      ['mips_arch_variant=="r2"', {
+                        'cflags': ['-mips32r2', '-Wa,-mips32r2'],
+                        'conditions': [
+                          ['mips_float_abi=="hard" and mips_fpu_mode!=""', {
+                            'cflags': ['-m<(mips_fpu_mode)'],
+                          }],
+                        ],
+                      }],
+                      ['mips_arch_variant=="r1"', {
+                        'cflags': ['-mips32', '-Wa,-mips32'],
+                      }],
+                      ['mips_dsp_rev==1', {
+                        'cflags': ['-mdsp'],
+                      }],
+                      ['mips_dsp_rev==2', {
+                        'cflags': ['-mdspr2'],
                       }],
                     ],
-                  }],
-                  ['android_webview_build==0 and mips_arch_variant=="r2"', {
-                    'cflags': ['-mips32r2', '-Wa,-mips32r2'],
-                  }],
-                  ['android_webview_build==0 and mips_arch_variant=="r1"', {
-                    'cflags': ['-mips32', '-Wa,-mips32'],
+                    'cflags': [
+                      '-m<(mips_float_abi)-float'
+                    ],
                   }],
                 ],
                 'ldflags': [
@@ -4080,13 +4114,17 @@
             'target_conditions': [
               ['_toolset=="target"', {
                 'conditions': [
-                  ['android_webview_build==0 and mips_arch_variant=="r6"', {
-                    'cflags': ['-mips64r6', '-Wa,-mips64r6'],
-                    'ldflags': [ '-mips64r6' ],
-                  }],
-                  ['android_webview_build==0 and mips_arch_variant=="r2"', {
-                    'cflags': ['-mips64r2', '-Wa,-mips64r2'],
-                    'ldflags': [ '-mips64r2' ],
+                  ['android_webview_build==0', {
+                    'conditions': [
+                      ['mips_arch_variant=="r6"', {
+                        'cflags': ['-mips64r6', '-Wa,-mips64r6'],
+                        'ldflags': ['-mips64r6'],
+                      }],
+                      ['mips_arch_variant=="r2"', {
+                        'cflags': ['-mips64r2', '-Wa,-mips64r2'],
+                        'ldflags': ['-mips64r2'],
+                      }],
+                    ],
                   }],
                 ],
                 'cflags_cc': [
@@ -5856,6 +5894,17 @@
         ],
       },
     }],
+    ['use_lto==1 and clang==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'arflags': [
+              '--plugin', '../../<(make_clang_dir)/lib/LLVMgold.so',
+            ],
+          }],
+        ],
+      },
+    }],
     ['(use_lto==1 or use_lto_o2==1) and clang==0', {
       'target_defaults': {
         'target_conditions': [
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index ea88ff5..3afba89 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -113,14 +113,10 @@
     # toolchains.
     cros_use_custom_toolchain = false
   }
-
-  # TODO(brettw) remove this flag (and therefore enable linking all targets) on
-  # Windows when we have sufficient bot capacity. In the meantime, you can
-  # enable linking for local compiles.
-  link_chrome_on_windows = true
 }
 
 # TODO(dpranke): Remove these asserts when os and cpu_arch are removed.
+assert(current_cpu == cpu_arch)
 assert(current_os == os)
 
 # =============================================================================
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index aa1fd2a..28608cb 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -160,11 +160,13 @@
     jni_target_name = "${target_name}__jni_${classname}"
     jni_actions += [ ":$jni_target_name" ]
     action(jni_target_name) {
+      # The sources aren't compiled so don't check their dependencies.
+      check_includes = false
       depfile = "$target_gen_dir/$target_name.d"
       script = "//base/android/jni_generator/jni_generator.py"
       sources = [
-        jni_generator_include,
         jar_file,
+        jni_generator_include,
       ]
       outputs = [
         depfile,
@@ -1499,7 +1501,6 @@
     deps = [
       "//base:base_java",
       "//build/android/pylib/remote/device/dummy:remote_device_dummy_apk",
-      "//net/android:net_java_test_support",
     ]
     if (defined(invoker.deps)) {
       deps += invoker.deps
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
index 39fe251..721e87c 100644
--- a/build/config/clang/BUILD.gn
+++ b/build/config/clang/BUILD.gn
@@ -21,13 +21,6 @@
               "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
               root_build_dir) ]
     }
-
-    cflags += [
-      "-Xclang",
-      "-add-plugin",
-      "-Xclang",
-      "find-bad-constructs",
-    ]
   }
 }
 
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 5cf0331..4397151 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -48,6 +48,13 @@
   # http://gcc.gnu.org/wiki/DebugFission
   use_debug_fission =
       !is_win && use_gold && linux_use_bundled_binutils && !use_ccache
+
+  if (is_win) {
+    # Whether the VS xtree header has been patched to disable warning 4702. If
+    # it has, then we don't need to disable 4702 (unreachable code warning).
+    # The patch is preapplied to the internal toolchain and hence all bots.
+    msvs_xtree_patched = false
+  }
 }
 
 # default_include_dirs ---------------------------------------------------------
@@ -295,12 +302,23 @@
             "-mips32r2",
             "-Wa,-mips32r2",
           ]
+          if (mips_float_abi == "hard" && mips_fpu_mode != "") {
+            cflags += [ "-m$mips_fpu_mode" ]
+          }
         } else if (mips_arch_variant == "r1") {
           cflags += [
             "-mips32",
             "-Wa,-mips32",
           ]
         }
+
+        if (mips_dsp_rev == 1) {
+          cflags += [ "-mdsp" ]
+        } else if (mips_dsp_rev == 2) {
+          cflags += [ "-mdspr2" ]
+        }
+
+        cflags += [ "-m${mips_float_abi}-float" ]
       }
     } else if (current_cpu == "mips64el") {
       # Don't set the compiler flags for the WebView build. These will come
@@ -709,6 +727,7 @@
   if (is_win) {
     cflags = [
       "/WX",  # Treat warnings as errors.
+
       # Warnings permanently disabled:
 
       # TODO(GYP) The GYP build doesn't have this globally enabled but disabled
@@ -763,6 +782,7 @@
       # have to turn off this warning (and be careful about how object
       # destruction happens in such cases).
       "/wd4611",
+
       # Warnings to evaluate and possibly fix/reenable later:
 
       "/wd4100",  # Unreferenced formal function parameter.
@@ -775,6 +795,14 @@
       "/wd4610",  # Class can never be instantiated, constructor required.
       "/wd4996",  # Deprecated function warning.
     ]
+
+    # VS xtree header file needs to be patched or 4702 (unreachable code
+    # warning) is reported if _HAS_EXCEPTIONS=0. Disable the warning if xtree is
+    # not patched.
+    if (!msvs_xtree_patched &&
+        exec_script("../../win_is_xtree_patched.py", [], "value") == 0) {
+      cflags += [ "/wd4702" ]  # Unreachable code.
+    }
   } else {
     # Common GCC warning setup.
     cflags = [
diff --git a/build/config/features.gni b/build/config/features.gni
index 5ee92f7..4d01a87 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -30,10 +30,10 @@
   # guarded by "is_nacl" directly rather than enable_nacl_untrusted, but
   # this will go away when Mac and Win are working and we can just use
   # the commented out logic.
-  # enable_nacl = !is_ios && !is_android
-  # Currently this *should* work:
-  # enable_nacl = (is_linux && build_cpu_arch == "x64") || is_nacl
-  enable_nacl = false
+  # Eventually we want this to be:
+  #   enable_nacl = !is_ios && !is_android
+  enable_nacl =
+      (is_linux && !is_chromeos && !is_debug && current_cpu == "x64") || is_nacl
   enable_nacl_untrusted = enable_nacl
   enable_pnacl = enable_nacl_untrusted
 
@@ -49,6 +49,29 @@
 
   # Enables proprietary codecs and demuxers; e.g. H264, MOV, AAC, and MP3.
   proprietary_codecs = false
+
+  enable_configuration_policy = true
+
+  # Enables support for background apps.
+  enable_background = !is_ios && !is_android
+
+  enable_captive_portal_detection = !is_android && !is_ios
+
+  # Enables use of the session service, which is enabled by default.
+  # Android stores them separately on the Java side.
+  enable_session_service = !is_android && !is_ios
+
+  enable_plugin_installation = is_win || is_mac
+
+  enable_app_list = !is_ios && !is_android
+
+  enable_supervised_users = !is_ios
+
+  enable_autofill_dialog = !is_ios && !(is_android && is_android_webview_build)
+
+  enable_google_now = !is_ios && !is_android
+
+  enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
 }
 
 # Additional dependent variables -----------------------------------------------
@@ -113,11 +136,6 @@
   safe_browsing_mode = 1
 }
 
-enable_configuration_policy = true
-
-# Enables support for background apps.
-enable_background = !is_ios && !is_android
-
 enable_task_manager = !is_ios && !is_android
 
 use_cups = is_desktop_linux || is_mac
@@ -127,27 +145,14 @@
 # TODO(scottmg) remove this when we've fixed printing.
 win_pdf_metafile_for_printing = true
 
-enable_captive_portal_detection = !is_android && !is_ios
-
-# Enables use of the session service, which is enabled by default.
-# Android stores them separately on the Java side.
-enable_session_service = !is_android && !is_ios
-
 # Whether we are using the rlz library or not.  Platforms like Android send
 # rlz codes for searches but do not use the library.
 enable_rlz = is_chrome_branded && (is_win || is_mac || is_ios || is_chromeos)
 
-enable_plugin_installation = is_win || is_mac
-
-enable_app_list = !is_ios && !is_android
 enable_settings_app = enable_app_list && !is_chromeos
 
-enable_supervised_users = !is_ios
-
 enable_service_discovery = enable_mdns || is_mac
 
-enable_autofill_dialog = !is_ios && !(is_android && is_android_webview_build)
-
 enable_wifi_bootstrapping = is_win || is_mac
 
 # Image loader extension is enabled on ChromeOS only.
@@ -155,10 +160,6 @@
 
 enable_remoting = !is_ios && !is_android
 
-enable_google_now = !is_ios && !is_android
-
-enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
-
 # Chrome OS: whether to also build the upcoming version of
 # ChromeVox, which can then be enabled via a command-line switch.
 enable_chromevox_next = false
diff --git a/build/config/linux/gtk/BUILD.gn b/build/config/linux/gtk/BUILD.gn
new file mode 100644
index 0000000..4968e2d
--- /dev/null
+++ b/build/config/linux/gtk/BUILD.gn
@@ -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.
+
+import("//build/config/linux/pkg_config.gni")
+
+assert(is_linux, "This file should only be referenced on Linux")
+
+# Depend on //build/config/linux/gtk to use GTK.
+#
+# GN doesn't check visibility for configs so we give this an obviously internal
+# name to discourage random targets from accidentally depending on this and
+# bypassing the GTK target's visibility.
+pkg_config("gtk_internal_config") {
+  # Gtk requires gmodule, but it does not list it as a dependency in some
+  # misconfigured systems.
+  packages = [
+    "gmodule-2.0",
+    "gtk+-2.0",
+    "gthread-2.0",
+  ]
+}
+
+# Basically no parts of Chrome should depend on GTK. To prevent accidents, the
+# parts that explicitly need GTK are whitelisted on this target.
+group("gtk") {
+  visibility = [
+    "//chrome/browser/ui/libgtk2ui",
+    "//remoting/host",
+  ]
+  direct_dependent_configs = [ ":gtk_internal_config" ]
+}
+
+# Depend on "gtkprint" to get this.
+pkg_config("gtkprint_internal_config") {
+  packages = [ "gtk+-unix-print-2.0" ]
+}
+
+group("gtkprint") {
+  visibility = [ "//chrome/browser/ui/libgtk2ui" ]
+  direct_dependent_configs = [ ":gtkprint_internal_config" ]
+}
diff --git a/build/config/mips.gni b/build/config/mips.gni
index 512552d..1b40657 100644
--- a/build/config/mips.gni
+++ b/build/config/mips.gni
@@ -2,12 +2,35 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# MIPS arch variant.
 if (current_cpu == "mipsel") {
   declare_args() {
+    # MIPS arch variant. Possible values are:
+    #   "r1"
+    #   "r2"
+    #   "r6"
     mips_arch_variant = "r1"
+
+    # MIPS DSP ASE revision. Possible values are:
+    #   0: unavailable
+    #   1: revision 1
+    #   2: revision 2
+    mips_dsp_rev = 0
+
+    # MIPS floating-point ABI. Possible values are:
+    #   "hard": sets the GCC -mhard-float option.
+    #   "soft": sets the GCC -msoft-float option.
+    mips_float_abi = "hard"
+
+    # MIPS32 floating-point register width. Possible values are:
+    #   "fp32": sets the GCC -mfp32 option.
+    #   "fp64": sets the GCC -mfp64 option.
+    #   "fpxx": sets the GCC -mfpxx option.
+    mips_fpu_mode = "fp32"
   }
 } else if (current_cpu == "mips64el") {
+  # MIPS arch variant. Possible values are:
+  #   "r2"
+  #   "r6"
   if (is_android) {
     declare_args() {
       mips_arch_variant = "r6"
diff --git a/build/download_gold_plugin.py b/build/download_gold_plugin.py
new file mode 100755
index 0000000..1d8be5a
--- /dev/null
+++ b/build/download_gold_plugin.py
@@ -0,0 +1,45 @@
+#!/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.
+
+"""Script to download LLVM gold plugin from google storage."""
+
+import json
+import os
+import shutil
+import subprocess
+import sys
+import zipfile
+
+SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
+CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
+sys.path.insert(0, os.path.join(CHROME_SRC, 'tools'))
+
+import find_depot_tools
+
+DEPOT_PATH = find_depot_tools.add_depot_tools_to_path()
+GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py')
+
+LLVM_BUILD_PATH = os.path.join(CHROME_SRC, 'third_party', 'llvm-build',
+                               'Release+Asserts')
+CLANG_UPDATE_SH = os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts',
+                               'update.sh')
+CLANG_REVISION = os.popen(CLANG_UPDATE_SH + ' --print-revision').read().rstrip()
+
+CLANG_BUCKET = 'gs://chromium-browser-clang/Linux_x64'
+
+def main():
+  targz_name = 'llvmgold-%s.tgz' % CLANG_REVISION
+  remote_path = '%s/%s' % (CLANG_BUCKET, targz_name)
+
+  os.chdir(LLVM_BUILD_PATH)
+
+  subprocess.check_call(['python', GSUTIL_PATH,
+                         'cp', remote_path, targz_name])
+  subprocess.check_call(['tar', 'xzf', targz_name])
+  os.remove(targz_name)
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
new file mode 100644
index 0000000..273c38e
--- /dev/null
+++ b/build/gn_migration.gypi
@@ -0,0 +1,502 @@
+# 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.
+
+# This file defines three targets that we are using to
+# track the progress of the GYP->GN migration:
+#
+# If you run 'ninja gn_build gyp_remaining gyp_groups', and then
+# run 'ninja', the second ninja invocation should do nothing. This
+# indicates that everything built by a ninja build is in fact
+# listed in one of these targets.
+#
+# 'gn_all' lists what GN is currently capable of building and should
+#          match the 'gn_all' target in //BUILD.gn.
+#
+# 'gyp_remaining' lists all of the targets that still need to be converted,
+#          i.e., all of the other (non-empty) targets that a GYP build
+#          will build.
+#
+# 'gyp_groups' lists any empty (group) targets in the GYP build that
+#          are not picked up by gn_all or gyp_remaining; this is a
+#          separate target to ensure that when we build it, only
+#          stamp targets file are we don't accidentally pick up something
+#          not listed in one of the other two targets.
+#
+# TODO(GYP), TODO(dpranke) Add a build step to the bot that enforces the
+#          above contracts.
+
+{
+  'targets': [
+    {
+      # This target should mirror the structure of //:gn_all
+      # as closely as possible, for ease of comparison.
+      'target_name': 'gn_all',
+      'type': 'none',
+      'dependencies': [
+        '../base/base.gyp:base_unittests',
+        '../cc/cc_tests.gyp:cc_unittests',
+        '../chrome/chrome.gyp:chrome',
+        '../chrome/chrome.gyp:browser_tests',
+        '../chrome/chrome.gyp:interactive_ui_tests',
+        '../chrome/chrome.gyp:sync_integration_tests',
+        '../chrome/chrome.gyp:unit_tests',
+        '../components/components_tests.gyp:components_unittests',
+        '../content/content_shell_and_tests.gyp:content_shell',
+        '../content/content_shell_and_tests.gyp:content_browsertests',
+        '../content/content_shell_and_tests.gyp:content_perftests',
+        '../content/content_shell_and_tests.gyp:content_unittests',
+        '../crypto/crypto.gyp:crypto_unittests',
+        '../extensions/extensions_tests.gyp:extensions_browsertests',
+        '../extensions/extensions_tests.gyp:extensions_unittests',
+        '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+        '../gpu/gpu.gyp:gpu_unittests',
+        '../ipc/ipc.gyp:ipc_tests',
+        '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
+        '../jingle/jingle.gyp:jingle_unittests',
+        '../media/media.gyp:media_unittests',
+        '../media/cast/cast.gyp:cast_unittests',
+        '../mojo/mojo.gyp:mojo',
+        '../mojo/mojo_base.gyp:mojo_common_unittests',
+        '../net/net.gyp:net_unittests',
+        '../printing/printing.gyp:printing_unittests',
+        '../skia/skia_tests.gyp:skia_unittests',
+        '../sql/sql.gyp:sql_unittests',
+        '../sync/sync.gyp:sync_unit_tests',
+        '../third_party/WebKit/public/all.gyp:all_blink',
+        '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+        '../third_party/codesighs/codesighs.gyp:codesighs',
+        '../third_party/mojo/mojo_edk_tests.gyp:mojo_system_unittests',
+        '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests',
+        '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests',
+        '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
+        '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
+        '../third_party/pdfium/samples/samples.gyp:pdfium_test',
+        '../third_party/smhasher/smhasher.gyp:pmurhash',
+        '../third_party/sqlite/sqlite.gyp:sqlite_shell',
+        '../tools/gn/gn.gyp:gn',
+        '../tools/gn/gn.gyp:gn_unittests',
+        '../ui/accessibility/accessibility.gyp:accessibility_unittests',
+        '../ui/app_list/app_list.gyp:app_list_unittests',
+        '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+        '../ui/display/display.gyp:display_unittests',
+        '../ui/events/events.gyp:events_unittests',
+        '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+        '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+        '../url/url.gyp:url_unittests',
+      ],
+      'conditions': [
+        ['enable_extensions==1 and OS!="mac"', {
+          'dependencies': [
+            '../extensions/shell/app_shell.gyp:app_shell_unittests',
+          ],
+        }],
+        ['OS!="win"', {
+          'dependencies': [
+            '../breakpad/breakpad.gyp:symupload',
+          ],
+        }],
+        ['use_x11==1', {
+          'dependencies': [
+            '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+          ],
+        }],
+        ['toolkit_views==1', {
+          'dependencies': [
+            '../ui/views/views.gyp:views_unittests',
+          ],
+        }],
+        ['use_aura==1', {
+          'dependencies': [
+            '../ui/wm/wm.gyp:wm_unittests',
+          ],
+        }],
+        ['use_ozone==1', {
+          'dependencies': [
+            '../ui/ozone/ozone.gyp:ozone',
+          ],
+        }],
+        ['OS=="win" or OS=="mac" or chromeos==1', {
+          'dependencies': [
+            '../rlz/rlz.gyp:rlz_lib',
+          ],
+        }],
+        ['OS=="android"', {
+          'dependencies': [
+            '../base/base.gyp:chromium_android_linker', 
+            '../build/android/rezip.gyp:rezip_apk_jar',
+            '../chrome/chrome.gyp:chrome_shell_apk',
+            '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
+            #"//clank" TODO(GYP) - conditional somehow?
+            '../tools/imagediff/imagediff.gyp:imagediff#host',
+            '../tools/telemetry/telemetry.gyp:bitmaptools#host',
+      
+            # TODO(GYP): Remove these when the components_unittests work.
+            #"//components/history/core/test:test",
+            #"//components/policy:policy_component_test_support",
+            #"//components/policy:test_support",
+            #"//components/rappor:test_support",
+            #"//components/signin/core/browser:test_support",
+            #"//components/sync_driver:test_support",
+            #"//components/user_manager",
+            #"//components/wallpaper",
+
+            '../content/content_shell_and_tests.gyp:content_shell_apk',
+      
+            # TODO(GYP): Are these needed, or will they be pulled in automatically?
+            #"//third_party/android_tools:android_gcm_java",
+            #"//third_party/android_tools:uiautomator_java",
+            #"//third_party/android_tools:android_support_v13_java",
+            #"//third_party/android_tools:android_support_v7_appcompat_java",
+            #"//third_party/android_tools:android_support_v7_mediarouter_java",
+            #"//third_party/mesa",
+            #"//third_party/mockito:mockito_java",
+            #"//third_party/openmax_dl/dl",
+            #"//third_party/speex",
+            #"//ui/android:ui_java",
+
+            # TODO(GYP): Are these needed?
+            #"//chrome/test:test_support_unit",
+            #"//third_party/smhasher:murmurhash3",
+            #"//ui/message_center:test_support",
+          ],
+          'dependencies!': [
+            '../breakpad/breakpad.gyp:symupload',
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:sync_integration_tests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../extensions/extensions_tests.gyp:extensions_browsertests',
+            '../extensions/extensions_tests.gyp:extensions_unittests',
+            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../net/net.gyp:net_unittests',
+            #"//ppapi/examples",
+            '../third_party/pdfium/samples/samples.gyp:pdfium_test',
+            '../tools/gn/gn.gyp:gn',
+            '../tools/gn/gn.gyp:gn_unittests',
+            '../ui/app_list/app_list.gyp:app_list_unittests',
+            '../url/url.gyp:url_unittests',
+          ],
+        }],
+        ['OS=="linux"', {
+          'dependencies': [
+            '../sandbox/sandbox.gyp:chrome_sandbox',
+            '../sandbox/sandbox.gyp:sandbox_linux_unittests',
+         ],
+        }],
+        ['OS=="mac"', {
+          'dependencies': [
+            '../third_party/apple_sample_code/apple_sample_code.gyp:apple_sample_code',
+            '../third_party/molokocacao/molokocacao.gyp:molokocacao',
+
+            # TODO(GYP): remove these when the corresponding root targets work.
+            "//cc/blink",
+            "//components/ui/zoom:ui_zoom",
+            "//content",
+            "//content/test:test_support",
+            "//device/battery",
+            "//device/bluetooth",
+            "//device/nfc",
+            "//device/usb",
+            "//device/vibration",
+            "//media/blink",
+            "//pdf",
+            "//storage/browser",
+            "//third_party/brotli",
+            "//third_party/flac",
+            "//third_party/hunspell",
+            "//third_party/iccjpeg",
+            "//third_party/libphonenumber",
+            "//third_party/ots",
+            "//third_party/qcms",
+            "//third_party/smhasher:murmurhash3",
+            "//third_party/speex",
+            "//third_party/webrtc/system_wrappers",
+            "//ui/native_theme",
+            "//ui/snapshot",
+            "//ui/surface",
+          ],
+          'dependencies!': [
+            "//chrome",  # TODO(GYP)
+            "//chrome/test:browser_tests",  # TODO(GYP)
+            "//chrome/test:interactive_ui_tests",  # TODO(GYP)
+            "//chrome/test:sync_integration_tests",  # TODO(GYP)
+            "//chrome/test:unit_tests",  # TODO(GYP)
+            "//components:components_unittests",  # TODO(GYP)
+            "//content/test:content_browsertests",  # TODO(GYP)
+            "//content/test:content_perftests",  # TODO(GYP)
+            "//content/test:content_unittests",  # TODO(GYP)
+            "//extensions:extensions_browsertests",  # TODO(GYP)
+            "//extensions:extensions_unittests",  # TODO(GYP)
+            "//net:net_unittests",  # TODO(GYP)
+            "//third_party/usrsctp",  # TODO(GYP)
+            "//ui/app_list:app_list_unittests",  # TODO(GYP)
+            "//ui/gfx:gfx_unittests",  # TODO(GYP)
+          ],
+        }],
+        ['OS=="win"', {
+          'dependencies': [
+            "//ui/metro_viewer",
+            '../third_party/codesighs/codesighs.gyp:msdump2symdb',
+          ],
+          'dependencies!': [
+            "//crypto:crypto_unittests",  # TODO(GYP)
+            "//net:net_unittests",  # TODO(GYP)
+          ],
+        }],
+      ],
+    },
+    {
+      # This target contains a list of things that actually currently
+      # build in GN, but aren't listed in //:gn_all
+      'target_name': 'add_to_gn_all',
+      'type': 'none',
+      'dependencies': [
+        '../breakpad/breakpad.gyp:microdump_stackwalk',
+        '../breakpad/breakpad.gyp:minidump_dump',
+        '../breakpad/breakpad.gyp:minidump_stackwalk',
+        '../cc/cc_tests.gyp:cc_perftests',
+        '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+        '../chrome/chrome.gyp:sync_performance_tests',
+        '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler',
+        '../courgette/courgette.gyp:courgette_minimal_tool',
+        '../courgette/courgette.gyp:courgette_unittests',
+        '../extensions/shell/app_shell.gyp:app_shell',
+        '../gin/gin.gyp:gin_unittests',
+        '../google_apis/google_apis.gyp:google_apis_unittests',
+        '../gpu/gpu.gyp:angle_unittests',
+        '../gpu/gpu.gyp:gpu_perftests',
+        '../ipc/ipc.gyp:ipc_perftests',
+        '../media/media.gyp:ffmpeg_regression_tests',  # TODO(GYP) this should be conditional on media_use_ffmpeg
+        '../media/media.gyp:media_perftests',
+        '../net/net.gyp:crash_cache',
+        '../net/net.gyp:crl_set_dump',
+        '../net/net.gyp:dns_fuzz_stub',
+        '../net/net.gyp:dump_cache',
+        '../net/net.gyp:gdig',
+        '../net/net.gyp:get_server_time',
+        '../net/net.gyp:net_watcher',  # TODO(GYP): This should be conditional on use_v8_in_net
+        '../net/net.gyp:run_testserver',
+        '../net/net.gyp:stress_cache',
+        '../net/net.gyp:tld_cleanup',
+        '../ppapi/ppapi_internal.gyp:ppapi_tests', # TODO(GYP): Split out the examples and tests
+        '../third_party/codesighs/codesighs.gyp:maptsvdifftool',
+        '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
+        '../ui/compositor/compositor.gyp:compositor_unittests',
+        '../ui/keyboard/keyboard.gyp:keyboard_unittests',
+        '../ui/snapshot/snapshot.gyp:snapshot_unittests',
+      ],
+      'conditions': [
+        ['use_aura==1', {
+          'dependencies': [
+            '../ui/aura/aura.gyp:aura_bench',
+          ],
+        }],
+        ['use_ash==1', {
+          'dependencies': [
+            '../ash/ash.gyp:ash_shell',
+            '../ash/ash.gyp:ash_shell_unittests',
+            '../ash/ash.gyp:ash_unittests',
+          ],
+        }],
+        ['OS=="android"', {
+          'dependencies': [
+            '../breakpad/breakpad.gyp:dump_syms',
+          ],
+        }],
+        ['OS=="linux"', {
+          'dependencies': [
+            '../breakpad/breakpad.gyp:breakpad_unittests',
+            '../breakpad/breakpad.gyp:dump_syms',
+            '../breakpad/breakpad.gyp:generate_test_dump',
+            '../breakpad/breakpad.gyp:minidump-2-core',
+            '../net/net.gyp:disk_cache_memory_test',
+            '../net/net.gyp:flip_in_mem_edsm_server',
+            '../net/net.gyp:flip_in_mem_edsm_server_unittests',
+            '../net/net.gyp:quic_client',
+            '../net/net.gyp:quic_server',
+            '../dbus/dbus.gyp:dbus_unittests',
+          ],
+        }],
+        ['OS!="win"', {
+          'dependencies': [
+            '../third_party/codesighs/codesighs.gyp:nm2tsv',
+          ],
+        }],
+        ['OS=="mac"', {
+          'dependencies': [
+            '../breakpad/breakpad.gyp:crash_inspector',
+            '../breakpad/breakpad.gyp:dump_syms',
+            '../breakpad/breakpad.gyp:symupload',
+          ],
+        }],
+        ['OS=="android" or OS=="linux"', {
+          'dependencies': [
+            '../net/net.gyp:disk_cache_memory_test',
+          ],
+        }],
+      ],
+    },
+    {
+      'target_name': 'gyp_remaining',
+      'type': 'none',
+      'dependencies': [
+        ':add_to_gn_all',
+      ],
+      'conditions': [
+        ['OS=="linux"', {
+          'dependencies': [
+            '../base/base.gyp:base_i18n_perftests',
+            '../base/base.gyp:base_perftests',
+            '../base/base.gyp:build_utf8_validator_tables#host',
+            '../base/base.gyp:check_example',
+            '../base/base.gyp:protect_file_posix',
+            '../breakpad/breakpad.gyp:core-2-minidump',
+            '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
+            '../chrome/chrome.gyp:chrome_app_unittests',
+            '../chrome/chrome.gyp:chromedriver',
+            '../chrome/chrome.gyp:chromedriver_tests',
+            '../chrome/chrome.gyp:chromedriver_unittests',
+            '../chrome/chrome.gyp:load_library_perf_tests',
+            '../chrome/chrome.gyp:performance_browser_tests',
+            '../chrome/chrome.gyp:service_discovery_sniffer',
+            '../cloud_print/cloud_print.gyp:cloud_print_unittests',
+            '../components/components.gyp:network_hints_browser',
+            '../components/components.gyp:policy_templates',
+            '../components/components.gyp:session_manager_component',
+            '../components/components_tests.gyp:components_browsertests',
+            '../components/components_tests.gyp:components_perftests',
+            '../content/content.gyp:content_app_browser',
+            '../content/content.gyp:content_app_child',
+            '../content/content_shell_and_tests.gyp:content_gl_benchmark',
+            '../content/content_shell_and_tests.gyp:content_gl_tests',
+            '../courgette/courgette.gyp:courgette',
+            '../courgette/courgette.gyp:courgette_fuzz',
+            '../dbus/dbus.gyp:dbus_test_server',
+            '../device/device_tests.gyp:device_unittests',
+            '../gin/gin.gyp:gin_v8_snapshot_fingerprint',
+            '../gin/gin.gyp:gin_shell',
+            '../google_apis/gcm/gcm.gyp:mcs_probe',
+            '../gpu/gpu.gyp:gl_tests',
+            '../gpu/tools/tools.gyp:compositor_model_bench',
+            '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
+            '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',
+            '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',
+            '../media/cast/cast.gyp:cast_benchmarks',
+            '../media/cast/cast.gyp:generate_barcode_video',
+            '../media/cast/cast.gyp:generate_timecode_audio',
+            '../media/cast/cast.gyp:tap_proxy',
+            '../media/media.gyp:player_x11',
+            '../mojo/mojo_base.gyp:mojo_application_chromium',
+            '../net/net.gyp:hpack_example_generator',
+            '../net/net.gyp:hpack_fuzz_mutator',
+            '../net/net.gyp:hpack_fuzz_wrapper',
+            '../net/net.gyp:net_perftests',
+            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+            '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
+            '../remoting/app_remoting_webapp.gyp:ar_sample_app',
+            '../remoting/remoting.gyp:remoting_host',
+            '../remoting/remoting.gyp:remoting_it2me_native_messaging_host',
+            '../remoting/remoting.gyp:remoting_me2me_host',
+            '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
+            '../remoting/remoting.gyp:remoting_native_messaging_manifests',
+            '../remoting/remoting.gyp:remoting_perftests',
+            '../remoting/remoting.gyp:remoting_start_host',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
+            '../skia/skia.gyp:filter_fuzz_stub',
+            '../skia/skia.gyp:image_operations_bench',
+            '../sync/sync.gyp:run_sync_testserver',
+            '../sync/sync.gyp:sync_endtoend_tests',
+            '../sync/tools/sync_tools.gyp:sync_client',
+            '../sync/tools/sync_tools.gyp:sync_listen_notifications',
+            '../testing/gmock.gyp:gmock_main',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/webrtc/tools/tools.gyp:frame_analyzer',
+            '../third_party/webrtc/tools/tools.gyp:rgba_to_i420_converter',
+            '../tools/gn/gn.gyp:generate_test_gn_data',
+            '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache',
+            #'../tools/telemetry/telemetry.gyp:bitmaptools', TODO(GYP) should this be #host ?
+            '../ui/app_list/app_list.gyp:app_list_demo',
+            '../ui/compositor/compositor.gyp:compositor_unittests',
+            '../ui/message_center/message_center.gyp:message_center_unittests',
+            '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
+            '../v8/tools/gyp/v8.gyp:v8_snapshot',
+            '../v8/tools/gyp/v8.gyp:postmortem-metadata',
+
+            # TODO(GYP) - list all of the examples explicitly.
+            '../ppapi/ppapi_internal.gyp:*',
+          ],
+          'conditions': [
+            ['disable_nacl==0 and disable_nacl_untrusted==0', {
+              'dependencies': [
+                '../components/nacl.gyp:nacl_loader_unittests',
+                '../mojo/mojo_nacl.gyp:monacl_shell',
+                '../remoting/remoting.gyp:remoting_key_tester',
+              ]
+            }],
+            ['test_isolation_mode!="noop"', {
+              'dependencies': [
+                '../ash/ash.gyp:ash_unittests_run',
+                '../base/base.gyp:base_unittests_run',
+                '../cc/cc_tests.gyp:cc_unittests_run',
+                '../chrome/chrome.gyp:browser_tests_run',
+                '../chrome/chrome.gyp:chrome_run',
+                '../chrome/chrome.gyp:interactive_ui_tests_run',
+                '../chrome/chrome.gyp:sync_integration_tests_run',
+                '../chrome/chrome.gyp:unit_tests_run',
+                '../components/components_tests.gyp:components_browsertests_run',
+                '../components/components_tests.gyp:components_unittests_run',
+                '../content/content_shell_and_tests.gyp:content_browsertests_run',
+                '../content/content_shell_and_tests.gyp:content_unittests_run',
+                '../crypto/crypto.gyp:crypto_unittests_run',
+                '../courgette/courgette.gyp:courgette_unittests_run',
+                '../gpu/gpu.gyp:gpu_unittests_run',
+                '../media/cast/cast.gyp:cast_unittests_run',
+                '../media/media.gyp:media_unittests_run',
+                '../net/net.gyp:net_unittests_run',
+                '../sandbox/sandbox.gyp:sandbox_linux_unittests_run',
+                '../sql/sql.gyp:sql_unittests_run',
+                '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run',
+                '../ui/accessibility/accessibility.gyp:accessibility_unittests_run',
+                '../ui/app_list/app_list.gyp:app_list_unittests_run',
+                '../ui/events/events.gyp:events_unittests_run',
+                '../ui/message_center/message_center.gyp:message_center_unittests_run',
+                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
+              ],
+            }],
+          ],
+        }],
+        ['use_aura==1', {
+          'dependencies': [
+            '../ui/aura/aura.gyp:aura_demo',
+            '../ui/aura/aura.gyp:aura_unittests',
+          ],
+        }],
+      ],
+    },
+    {
+      # This target, when built, should cause no actual work
+      # to be done, just update a bunch of stamp files.
+      'target_name': 'gyp_groups',
+      'type': 'none',
+      'dependencies': [
+        'All',
+        'aura_builder',
+        'blink_tests',
+        'chromium_builder_asan',
+        'chromium_builder_chromedriver',
+        'chromium_builder_perf',
+        'chromium_builder_tests',
+        'chromium_builder_webrtc',
+        'chromium_gpu_builder',
+        'chromium_gpu_debug_builder',
+      ],
+    },
+      ]
+}
+
diff --git a/build/gyp_helper.py b/build/gyp_helper.py
index 645943a..a2cc7e1 100644
--- a/build/gyp_helper.py
+++ b/build/gyp_helper.py
@@ -42,8 +42,12 @@
     file_val = file_data.get(var)
     if file_val:
       if var in os.environ:
-        print 'INFO: Environment value for "%s" overrides value in %s.' % (
-            var, os.path.abspath(file_path)
+        behavior = 'replaces'
+        if var == 'GYP_DEFINES':
+          os.environ[var] = file_val + ' ' + os.environ[var]
+          behavior = 'overrides'
+        print 'INFO: Environment value for "%s" %s value in %s' % (
+            var, behavior, os.path.abspath(file_path)
         )
       else:
         os.environ[var] = file_val
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 9079011..a71a5c5 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -63,6 +63,7 @@
       'udev_device_get_sysname',
       'udev_device_get_syspath',
       'udev_device_new_from_devnum',
+      'udev_device_new_from_subsystem_sysname',
       'udev_device_new_from_syspath',
       'udev_device_unref',
       'udev_enumerate_add_match_subsystem',
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 24c24d6..4659a3f 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -251,9 +251,6 @@
 // http://crbug.com/364006
 "race:gfx::ImageFamily::~ImageFamily\n"
 
-// http://crbug.com/364014
-"race:WTF::Latin1Encoding()::globalLatin1Encoding\n"
-
 // https://code.google.com/p/v8/issues/detail?id=3143
 "race:v8::internal::FLAG_track_double_fields\n"
 
@@ -328,9 +325,6 @@
 // https://crbug.com/459429
 "race:randomnessPid\n"
 
-// https://crbug.com/460243
-"race:IPC::ChannelMojoHost::OnClientLaunched\n"
-
 // https://crbug.com/454655
 "race:content::BrowserTestBase::PostTaskToInProcessRendererAndWait\n"
 
diff --git a/build/secondary/testing/gtest/BUILD.gn b/build/secondary/testing/gtest/BUILD.gn
index 96f4112..a20a09d 100644
--- a/build/secondary/testing/gtest/BUILD.gn
+++ b/build/secondary/testing/gtest/BUILD.gn
@@ -83,6 +83,9 @@
     "include/gtest/internal/gtest-type-util.h",
 
     #"gtest/src/gtest-all.cc",  # Not needed by our build.
+    "../multiprocess_func_list.cc",
+    "../multiprocess_func_list.h",
+    "../platform_test.h",
     "src/gtest-death-test.cc",
     "src/gtest-filepath.cc",
     "src/gtest-internal-inl.h",
@@ -91,9 +94,6 @@
     "src/gtest-test-part.cc",
     "src/gtest-typed-test.cc",
     "src/gtest.cc",
-    "../multiprocess_func_list.cc",
-    "../multiprocess_func_list.h",
-    "../platform_test.h",
   ]
 
   if (is_mac) {
diff --git a/build/secondary/third_party/cacheinvalidation/BUILD.gn b/build/secondary/third_party/cacheinvalidation/BUILD.gn
index feb93d7..2e02633 100644
--- a/build/secondary/third_party/cacheinvalidation/BUILD.gn
+++ b/build/secondary/third_party/cacheinvalidation/BUILD.gn
@@ -18,10 +18,10 @@
     "overrides/google/cacheinvalidation/deps/googletest.h",
     "overrides/google/cacheinvalidation/deps/logging.h",
     "overrides/google/cacheinvalidation/deps/mutex.h",
-    "overrides/google/cacheinvalidation/deps/random.h",
     "overrides/google/cacheinvalidation/deps/random.cc",
-    "overrides/google/cacheinvalidation/deps/sha1-digest-function.h",
+    "overrides/google/cacheinvalidation/deps/random.h",
     "overrides/google/cacheinvalidation/deps/scoped_ptr.h",
+    "overrides/google/cacheinvalidation/deps/sha1-digest-function.h",
     "overrides/google/cacheinvalidation/deps/stl-namespace.h",
     "overrides/google/cacheinvalidation/deps/string_util.h",
     "overrides/google/cacheinvalidation/deps/time.h",
@@ -49,8 +49,8 @@
     "src/google/cacheinvalidation/impl/persistence-utils.h",
     "src/google/cacheinvalidation/impl/proto-converter.cc",
     "src/google/cacheinvalidation/impl/proto-converter.h",
-    "src/google/cacheinvalidation/impl/proto-helpers.h",
     "src/google/cacheinvalidation/impl/proto-helpers.cc",
+    "src/google/cacheinvalidation/impl/proto-helpers.h",
     "src/google/cacheinvalidation/impl/protocol-handler.cc",
     "src/google/cacheinvalidation/impl/protocol-handler.h",
     "src/google/cacheinvalidation/impl/recurring-task.cc",
@@ -70,8 +70,8 @@
     "src/google/cacheinvalidation/impl/throttle.h",
     "src/google/cacheinvalidation/impl/ticl-message-validator.cc",
     "src/google/cacheinvalidation/impl/ticl-message-validator.h",
-    "src/google/cacheinvalidation/include/invalidation-client.h",
     "src/google/cacheinvalidation/include/invalidation-client-factory.h",
+    "src/google/cacheinvalidation/include/invalidation-client.h",
     "src/google/cacheinvalidation/include/invalidation-listener.h",
     "src/google/cacheinvalidation/include/system-resources.h",
     "src/google/cacheinvalidation/include/types.h",
@@ -89,16 +89,16 @@
 
 test("cacheinvalidation_unittests") {
   sources = [
+    "src/google/cacheinvalidation/impl/invalidation-client-impl_test.cc",
+    "src/google/cacheinvalidation/impl/protocol-handler_test.cc",
+    "src/google/cacheinvalidation/impl/recurring-task_test.cc",
+    "src/google/cacheinvalidation/impl/throttle_test.cc",
     "src/google/cacheinvalidation/test/deterministic-scheduler.cc",
     "src/google/cacheinvalidation/test/deterministic-scheduler.h",
     "src/google/cacheinvalidation/test/test-logger.cc",
     "src/google/cacheinvalidation/test/test-logger.h",
     "src/google/cacheinvalidation/test/test-utils.cc",
     "src/google/cacheinvalidation/test/test-utils.h",
-    "src/google/cacheinvalidation/impl/invalidation-client-impl_test.cc",
-    "src/google/cacheinvalidation/impl/protocol-handler_test.cc",
-    "src/google/cacheinvalidation/impl/recurring-task_test.cc",
-    "src/google/cacheinvalidation/impl/throttle_test.cc",
   ]
 
   deps = [
diff --git a/build/secondary/third_party/leveldatabase/BUILD.gn b/build/secondary/third_party/leveldatabase/BUILD.gn
index 19eef15..067af30 100644
--- a/build/secondary/third_party/leveldatabase/BUILD.gn
+++ b/build/secondary/third_party/leveldatabase/BUILD.gn
@@ -32,10 +32,10 @@
     "src/db/db_impl.h",
     "src/db/db_iter.cc",
     "src/db/db_iter.h",
-    "src/db/filename.cc",
-    "src/db/filename.h",
     "src/db/dbformat.cc",
     "src/db/dbformat.h",
+    "src/db/filename.cc",
+    "src/db/filename.h",
     "src/db/log_format.h",
     "src/db/log_reader.cc",
     "src/db/log_reader.h",
diff --git a/build/secondary/third_party/libsrtp/BUILD.gn b/build/secondary/third_party/libsrtp/BUILD.gn
index d9b658e..8b9647c 100644
--- a/build/secondary/third_party/libsrtp/BUILD.gn
+++ b/build/secondary/third_party/libsrtp/BUILD.gn
@@ -91,17 +91,17 @@
       "srtp/include/ut_sim.h",
 
       # headers
-      "srtp/crypto/include/aes_cbc.h",
       "srtp/crypto/include/aes.h",
+      "srtp/crypto/include/aes_cbc.h",
       "srtp/crypto/include/aes_icm.h",
       "srtp/crypto/include/alloc.h",
       "srtp/crypto/include/auth.h",
       "srtp/crypto/include/cipher.h",
-      "srtp/crypto/include/cryptoalg.h",
       "srtp/crypto/include/crypto.h",
       "srtp/crypto/include/crypto_kernel.h",
       "srtp/crypto/include/crypto_math.h",
       "srtp/crypto/include/crypto_types.h",
+      "srtp/crypto/include/cryptoalg.h",
       "srtp/crypto/include/datatypes.h",
       "srtp/crypto/include/err.h",
       "srtp/crypto/include/gf2_8.h",
@@ -120,8 +120,6 @@
       "srtp/crypto/include/xfm.h",
 
       # sources
-      "srtp/srtp/ekt.c",
-      "srtp/srtp/srtp.c",
       "srtp/crypto/cipher/aes.c",
       "srtp/crypto/cipher/aes_cbc.c",
       "srtp/crypto/cipher/aes_icm.c",
@@ -144,6 +142,8 @@
       "srtp/crypto/rng/ctr_prng.c",
       "srtp/crypto/rng/prng.c",
       "srtp/crypto/rng/rand_source.c",
+      "srtp/srtp/ekt.c",
+      "srtp/srtp/srtp.c",
     ]
 
     if (is_clang) {
@@ -214,10 +214,10 @@
         ":libsrtp",
       ]
       sources = [
+        "srtp/crypto/include/datatypes.h",
         "srtp/include/getopt_s.h",
         "srtp/include/rtp.h",
         "srtp/include/srtp.h",
-        "srtp/crypto/include/datatypes.h",
         "srtp/test/getopt_s.c",
         "srtp/test/rtp.c",
         "srtp/test/rtpw.c",
diff --git a/build/secondary/third_party/nss/BUILD.gn b/build/secondary/third_party/nss/BUILD.gn
index ee5f112..25d449e 100644
--- a/build/secondary/third_party/nss/BUILD.gn
+++ b/build/secondary/third_party/nss/BUILD.gn
@@ -61,16 +61,16 @@
       "nspr/lib/libc/src/strpbrk.c",
       "nspr/lib/libc/src/strstr.c",
       "nspr/lib/libc/src/strtok.c",
-      "nspr/pr/include/md/prosdep.h",
       "nspr/pr/include/md/_darwin.cfg",
       "nspr/pr/include/md/_darwin.h",
       "nspr/pr/include/md/_pcos.h",
       "nspr/pr/include/md/_pth.h",
-      "nspr/pr/include/md/_unixos.h",
       "nspr/pr/include/md/_unix_errors.h",
+      "nspr/pr/include/md/_unixos.h",
       "nspr/pr/include/md/_win32_errors.h",
       "nspr/pr/include/md/_win95.cfg",
       "nspr/pr/include/md/_win95.h",
+      "nspr/pr/include/md/prosdep.h",
       "nspr/pr/include/nspr.h",
       "nspr/pr/include/obsolete/pralarm.h",
       "nspr/pr/include/obsolete/probslet.h",
@@ -621,6 +621,7 @@
       "nss/lib/freebl/ec.h",
       "nss/lib/freebl/ecdecode.c",
       "nss/lib/freebl/ecl/ec2.h",
+      "nss/lib/freebl/ecl/ec_naf.c",
       "nss/lib/freebl/ecl/ecl-curve.h",
       "nss/lib/freebl/ecl/ecl-exp.h",
       "nss/lib/freebl/ecl/ecl-priv.h",
@@ -638,17 +639,19 @@
       "nss/lib/freebl/ecl/ecp_jac.c",
       "nss/lib/freebl/ecl/ecp_jm.c",
       "nss/lib/freebl/ecl/ecp_mont.c",
-      "nss/lib/freebl/ecl/ec_naf.c",
       "nss/lib/freebl/gcm.c",
       "nss/lib/freebl/gcm.h",
-      "nss/lib/freebl/intel-aes-x86-masm.asm",
-      "nss/lib/freebl/intel-aes.h",
       "nss/lib/freebl/hmacct.c",
       "nss/lib/freebl/hmacct.h",
+      "nss/lib/freebl/intel-aes-x86-masm.asm",
+      "nss/lib/freebl/intel-aes.h",
       "nss/lib/freebl/jpake.c",
       "nss/lib/freebl/md2.c",
       "nss/lib/freebl/md5.c",
       "nss/lib/freebl/mpi/logtab.h",
+      "nss/lib/freebl/mpi/mp_gf2m-priv.h",
+      "nss/lib/freebl/mpi/mp_gf2m.c",
+      "nss/lib/freebl/mpi/mp_gf2m.h",
       "nss/lib/freebl/mpi/mpcpucache.c",
       "nss/lib/freebl/mpi/mpi-config.h",
       "nss/lib/freebl/mpi/mpi-priv.h",
@@ -663,9 +666,6 @@
       "nss/lib/freebl/mpi/mpmontg.c",
       "nss/lib/freebl/mpi/mpprime.c",
       "nss/lib/freebl/mpi/mpprime.h",
-      "nss/lib/freebl/mpi/mp_gf2m-priv.h",
-      "nss/lib/freebl/mpi/mp_gf2m.c",
-      "nss/lib/freebl/mpi/mp_gf2m.h",
       "nss/lib/freebl/mpi/primes.c",
       "nss/lib/freebl/nss_build_config_mac.h",
       "nss/lib/freebl/poly1305/poly1305-donna-x64-sse2-incremental-source.c",
diff --git a/build/secondary/third_party/sfntly/BUILD.gn b/build/secondary/third_party/sfntly/BUILD.gn
index a4dbd23..111f1cd 100644
--- a/build/secondary/third_party/sfntly/BUILD.gn
+++ b/build/secondary/third_party/sfntly/BUILD.gn
@@ -4,6 +4,10 @@
 
 static_library("sfntly") {
   sources = [
+    "cpp/src/sample/chromium/font_subsetter.cc",
+    "cpp/src/sample/chromium/font_subsetter.h",
+    "cpp/src/sample/chromium/subsetter_impl.cc",
+    "cpp/src/sample/chromium/subsetter_impl.h",
     "cpp/src/sfntly/data/byte_array.cc",
     "cpp/src/sfntly/data/byte_array.h",
     "cpp/src/sfntly/data/font_data.cc",
@@ -113,10 +117,6 @@
     "cpp/src/sfntly/table/truetype/loca_table.h",
     "cpp/src/sfntly/tag.cc",
     "cpp/src/sfntly/tag.h",
-    "cpp/src/sample/chromium/font_subsetter.cc",
-    "cpp/src/sample/chromium/font_subsetter.h",
-    "cpp/src/sample/chromium/subsetter_impl.cc",
-    "cpp/src/sample/chromium/subsetter_impl.h",
   ]
 
   defines = [ "SFNTLY_NO_EXCEPTION" ]
diff --git a/build/toolchain/win/midl.gni b/build/toolchain/win/midl.gni
index 30bcbf7..748b0fc 100644
--- a/build/toolchain/win/midl.gni
+++ b/build/toolchain/win/midl.gni
@@ -16,6 +16,7 @@
 #   out_dir (optional)
 #       Directory to write the generated files to. Defaults to target_gen_dir.
 #
+#   deps (optional)
 #   visibility (optional)
 
 template("midl") {
@@ -82,6 +83,10 @@
       idl_target_platform,
       "/Oicf",
     ]
+
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    }
   }
 
   source_set(target_name) {
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index c29cda8..e217b12 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -718,158 +718,157 @@
   }
 }
 
-if (!is_win || link_chrome_on_windows) {
-  test("cc_unittests") {
-    sources = [
-      "animation/animation_unittest.cc",
-      "animation/keyframed_animation_curve_unittest.cc",
-      "animation/layer_animation_controller_unittest.cc",
-      "animation/scroll_offset_animation_curve_unittest.cc",
-      "animation/scrollbar_animation_controller_linear_fade_unittest.cc",
-      "animation/scrollbar_animation_controller_thinning_unittest.cc",
-      "animation/transform_operations_unittest.cc",
-      "base/float_quad_unittest.cc",
-      "base/math_util_unittest.cc",
-      "base/region_unittest.cc",
-      "base/rolling_time_delta_history_unittest.cc",
-      "base/scoped_ptr_vector_unittest.cc",
-      "base/simple_enclosed_region_unittest.cc",
-      "base/tiling_data_unittest.cc",
-      "base/util_unittest.cc",
-      "debug/frame_timing_tracker_unittest.cc",
-      "debug/micro_benchmark_controller_unittest.cc",
-      "input/top_controls_manager_unittest.cc",
-      "layers/contents_scaling_layer_unittest.cc",
-      "layers/delegated_frame_provider_unittest.cc",
-      "layers/delegated_frame_resource_collection_unittest.cc",
-      "layers/delegated_renderer_layer_impl_unittest.cc",
-      "layers/delegated_renderer_layer_unittest.cc",
-      "layers/heads_up_display_layer_impl_unittest.cc",
-      "layers/heads_up_display_unittest.cc",
-      "layers/io_surface_layer_impl_unittest.cc",
-      "layers/layer_impl_unittest.cc",
-      "layers/layer_iterator_unittest.cc",
-      "layers/layer_position_constraint_unittest.cc",
-      "layers/layer_unittest.cc",
-      "layers/layer_utils_unittest.cc",
-      "layers/nine_patch_layer_impl_unittest.cc",
-      "layers/nine_patch_layer_unittest.cc",
-      "layers/painted_scrollbar_layer_impl_unittest.cc",
-      "layers/picture_image_layer_impl_unittest.cc",
-      "layers/picture_image_layer_unittest.cc",
-      "layers/picture_layer_impl_unittest.cc",
-      "layers/picture_layer_unittest.cc",
-      "layers/render_surface_impl_unittest.cc",
-      "layers/render_surface_unittest.cc",
-      "layers/scrollbar_layer_unittest.cc",
-      "layers/solid_color_layer_impl_unittest.cc",
-      "layers/solid_color_scrollbar_layer_impl_unittest.cc",
-      "layers/surface_layer_impl_unittest.cc",
-      "layers/surface_layer_unittest.cc",
-      "layers/texture_layer_impl_unittest.cc",
-      "layers/texture_layer_unittest.cc",
-      "layers/tiled_layer_impl_unittest.cc",
-      "layers/tiled_layer_unittest.cc",
-      "layers/ui_resource_layer_impl_unittest.cc",
-      "layers/ui_resource_layer_unittest.cc",
-      "output/begin_frame_args_unittest.cc",
-      "output/delegating_renderer_unittest.cc",
-      "output/filter_operations_unittest.cc",
-      "output/gl_renderer_unittest.cc",
-      "output/output_surface_unittest.cc",
-      "output/overlay_unittest.cc",
-      "output/renderer_pixeltest.cc",
-      "output/renderer_unittest.cc",
-      "output/shader_unittest.cc",
-      "output/software_renderer_unittest.cc",
-      "quads/draw_quad_unittest.cc",
-      "quads/list_container_unittest.cc",
-      "quads/render_pass_unittest.cc",
-      "resources/display_item_list_unittest.cc",
-      "resources/layer_quad_unittest.cc",
-      "resources/picture_layer_tiling_set_unittest.cc",
-      "resources/picture_layer_tiling_unittest.cc",
-      "resources/picture_pile_impl_unittest.cc",
-      "resources/picture_pile_unittest.cc",
-      "resources/picture_unittest.cc",
-      "resources/platform_color_unittest.cc",
-      "resources/prioritized_resource_unittest.cc",
-      "resources/resource_provider_unittest.cc",
-      "resources/resource_update_controller_unittest.cc",
-      "resources/scoped_gpu_raster_unittest.cc",
-      "resources/scoped_resource_unittest.cc",
-      "resources/task_graph_runner_unittest.cc",
-      "resources/texture_mailbox_deleter_unittest.cc",
-      "resources/texture_uploader_unittest.cc",
-      "resources/tile_manager_unittest.cc",
-      "resources/tile_priority_unittest.cc",
-      "resources/tile_task_worker_pool_unittest.cc",
-      "scheduler/begin_frame_source_unittest.cc",
-      "scheduler/delay_based_time_source_unittest.cc",
-      "scheduler/scheduler_state_machine_unittest.cc",
-      "scheduler/scheduler_unittest.cc",
-      "test/layer_tree_json_parser_unittest.cc",
-      "test/test_web_graphics_context_3d_unittest.cc",
-      "trees/blocking_task_runner_unittest.cc",
-      "trees/damage_tracker_unittest.cc",
-      "trees/layer_sorter_unittest.cc",
-      "trees/layer_tree_host_common_unittest.cc",
-      "trees/layer_tree_host_impl_unittest.cc",
-      "trees/layer_tree_host_pixeltest_blending.cc",
-      "trees/layer_tree_host_pixeltest_filters.cc",
-      "trees/layer_tree_host_pixeltest_masks.cc",
-      "trees/layer_tree_host_pixeltest_readback.cc",
-      "trees/layer_tree_host_pixeltest_synchronous.cc",
-      "trees/layer_tree_host_unittest.cc",
-      "trees/layer_tree_host_unittest_animation.cc",
-      "trees/layer_tree_host_unittest_context.cc",
-      "trees/layer_tree_host_unittest_copyrequest.cc",
-      "trees/layer_tree_host_unittest_damage.cc",
-      "trees/layer_tree_host_unittest_delegated.cc",
-      "trees/layer_tree_host_unittest_no_message_loop.cc",
-      "trees/layer_tree_host_unittest_occlusion.cc",
-      "trees/layer_tree_host_unittest_picture.cc",
-      "trees/layer_tree_host_unittest_proxy.cc",
-      "trees/layer_tree_host_unittest_scroll.cc",
-      "trees/layer_tree_impl_unittest.cc",
-      "trees/occlusion_tracker_unittest.cc",
-      "trees/occlusion_unittest.cc",
-      "trees/property_tree_unittest.cc",
-      "trees/tree_synchronizer_unittest.cc",
+test("cc_unittests") {
+  sources = [
+    "animation/animation_unittest.cc",
+    "animation/keyframed_animation_curve_unittest.cc",
+    "animation/layer_animation_controller_unittest.cc",
+    "animation/scroll_offset_animation_curve_unittest.cc",
+    "animation/scrollbar_animation_controller_linear_fade_unittest.cc",
+    "animation/scrollbar_animation_controller_thinning_unittest.cc",
+    "animation/transform_operations_unittest.cc",
+    "base/float_quad_unittest.cc",
+    "base/math_util_unittest.cc",
+    "base/region_unittest.cc",
+    "base/rolling_time_delta_history_unittest.cc",
+    "base/scoped_ptr_vector_unittest.cc",
+    "base/simple_enclosed_region_unittest.cc",
+    "base/tiling_data_unittest.cc",
+    "base/util_unittest.cc",
+    "debug/frame_timing_tracker_unittest.cc",
+    "debug/micro_benchmark_controller_unittest.cc",
+    "input/top_controls_manager_unittest.cc",
+    "layers/contents_scaling_layer_unittest.cc",
+    "layers/delegated_frame_provider_unittest.cc",
+    "layers/delegated_frame_resource_collection_unittest.cc",
+    "layers/delegated_renderer_layer_impl_unittest.cc",
+    "layers/delegated_renderer_layer_unittest.cc",
+    "layers/heads_up_display_layer_impl_unittest.cc",
+    "layers/heads_up_display_unittest.cc",
+    "layers/io_surface_layer_impl_unittest.cc",
+    "layers/layer_impl_unittest.cc",
+    "layers/layer_iterator_unittest.cc",
+    "layers/layer_position_constraint_unittest.cc",
+    "layers/layer_unittest.cc",
+    "layers/layer_utils_unittest.cc",
+    "layers/nine_patch_layer_impl_unittest.cc",
+    "layers/nine_patch_layer_unittest.cc",
+    "layers/painted_scrollbar_layer_impl_unittest.cc",
+    "layers/picture_image_layer_impl_unittest.cc",
+    "layers/picture_image_layer_unittest.cc",
+    "layers/picture_layer_impl_unittest.cc",
+    "layers/picture_layer_unittest.cc",
+    "layers/render_surface_impl_unittest.cc",
+    "layers/render_surface_unittest.cc",
+    "layers/scrollbar_layer_unittest.cc",
+    "layers/solid_color_layer_impl_unittest.cc",
+    "layers/solid_color_scrollbar_layer_impl_unittest.cc",
+    "layers/surface_layer_impl_unittest.cc",
+    "layers/surface_layer_unittest.cc",
+    "layers/texture_layer_impl_unittest.cc",
+    "layers/texture_layer_unittest.cc",
+    "layers/tiled_layer_impl_unittest.cc",
+    "layers/tiled_layer_unittest.cc",
+    "layers/ui_resource_layer_impl_unittest.cc",
+    "layers/ui_resource_layer_unittest.cc",
+    "output/begin_frame_args_unittest.cc",
+    "output/delegating_renderer_unittest.cc",
+    "output/filter_operations_unittest.cc",
+    "output/gl_renderer_unittest.cc",
+    "output/output_surface_unittest.cc",
+    "output/overlay_unittest.cc",
+    "output/renderer_pixeltest.cc",
+    "output/renderer_unittest.cc",
+    "output/shader_unittest.cc",
+    "output/software_renderer_unittest.cc",
+    "quads/draw_quad_unittest.cc",
+    "quads/list_container_unittest.cc",
+    "quads/render_pass_unittest.cc",
+    "resources/display_item_list_unittest.cc",
+    "resources/layer_quad_unittest.cc",
+    "resources/picture_layer_tiling_set_unittest.cc",
+    "resources/picture_layer_tiling_unittest.cc",
+    "resources/picture_pile_impl_unittest.cc",
+    "resources/picture_pile_unittest.cc",
+    "resources/picture_unittest.cc",
+    "resources/platform_color_unittest.cc",
+    "resources/prioritized_resource_unittest.cc",
+    "resources/resource_provider_unittest.cc",
+    "resources/resource_update_controller_unittest.cc",
+    "resources/scoped_gpu_raster_unittest.cc",
+    "resources/scoped_resource_unittest.cc",
+    "resources/task_graph_runner_unittest.cc",
+    "resources/texture_mailbox_deleter_unittest.cc",
+    "resources/texture_uploader_unittest.cc",
+    "resources/tile_manager_unittest.cc",
+    "resources/tile_priority_unittest.cc",
+    "resources/tile_task_worker_pool_unittest.cc",
+    "resources/video_resource_updater_unittest.cc",
+    "scheduler/begin_frame_source_unittest.cc",
+    "scheduler/delay_based_time_source_unittest.cc",
+    "scheduler/scheduler_state_machine_unittest.cc",
+    "scheduler/scheduler_unittest.cc",
+    "test/layer_tree_json_parser_unittest.cc",
+    "test/test_web_graphics_context_3d_unittest.cc",
+    "trees/blocking_task_runner_unittest.cc",
+    "trees/damage_tracker_unittest.cc",
+    "trees/layer_sorter_unittest.cc",
+    "trees/layer_tree_host_common_unittest.cc",
+    "trees/layer_tree_host_impl_unittest.cc",
+    "trees/layer_tree_host_pixeltest_blending.cc",
+    "trees/layer_tree_host_pixeltest_filters.cc",
+    "trees/layer_tree_host_pixeltest_masks.cc",
+    "trees/layer_tree_host_pixeltest_readback.cc",
+    "trees/layer_tree_host_pixeltest_synchronous.cc",
+    "trees/layer_tree_host_unittest.cc",
+    "trees/layer_tree_host_unittest_animation.cc",
+    "trees/layer_tree_host_unittest_context.cc",
+    "trees/layer_tree_host_unittest_copyrequest.cc",
+    "trees/layer_tree_host_unittest_damage.cc",
+    "trees/layer_tree_host_unittest_delegated.cc",
+    "trees/layer_tree_host_unittest_no_message_loop.cc",
+    "trees/layer_tree_host_unittest_occlusion.cc",
+    "trees/layer_tree_host_unittest_picture.cc",
+    "trees/layer_tree_host_unittest_proxy.cc",
+    "trees/layer_tree_host_unittest_scroll.cc",
+    "trees/layer_tree_impl_unittest.cc",
+    "trees/occlusion_tracker_unittest.cc",
+    "trees/occlusion_unittest.cc",
+    "trees/property_tree_unittest.cc",
+    "trees/tree_synchronizer_unittest.cc",
 
-      # Surfaces test files.
-      "surfaces/surface_aggregator_test_helpers.cc",
-      "surfaces/surface_aggregator_test_helpers.h",
-      "surfaces/surface_aggregator_unittest.cc",
-      "surfaces/surface_unittest.cc",
-      "surfaces/surfaces_pixeltest.cc",
+    # Surfaces test files.
+    "surfaces/surface_aggregator_test_helpers.cc",
+    "surfaces/surface_aggregator_test_helpers.h",
+    "surfaces/surface_aggregator_unittest.cc",
+    "surfaces/surface_unittest.cc",
+    "surfaces/surfaces_pixeltest.cc",
 
-      # Setup.
-      "test/cc_test_suite.cc",
-      "test/run_all_unittests.cc",
-    ]
+    # Setup.
+    "test/cc_test_suite.cc",
+    "test/run_all_unittests.cc",
+  ]
 
-    configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 
-    deps = [
-      ":cc",
-      ":test_support",
-      "//base/test:test_support",
-      "//cc/surfaces",
-      "//cc/surfaces:surface_id",
-      "//gpu",
-      "//gpu:test_support",
-      "//gpu/command_buffer/client:gles2_interface",
-      "//gpu/command_buffer/common:gles2_utils",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//ui/events:events_base",
-      "//ui/gfx",
-      "//ui/gfx/geometry",
-      "//ui/gfx:test_support",
-      "//ui/gl",
-    ]
-  }
+  deps = [
+    ":cc",
+    ":test_support",
+    "//base/test:test_support",
+    "//cc/surfaces",
+    "//cc/surfaces:surface_id",
+    "//gpu",
+    "//gpu:test_support",
+    "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/common:gles2_utils",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//ui/events:events_base",
+    "//ui/gfx",
+    "//ui/gfx/geometry",
+    "//ui/gfx:test_support",
+    "//ui/gl",
+  ]
 }
 
 test("cc_perftests") {
diff --git a/cc/PRESUBMIT.py b/cc/PRESUBMIT.py
index dc826b1..fa15632 100644
--- a/cc/PRESUBMIT.py
+++ b/cc/PRESUBMIT.py
@@ -14,21 +14,11 @@
 CC_SOURCE_FILES=(r'^cc[\\/].*\.(cc|h)$',)
 
 def CheckChangeLintsClean(input_api, output_api):
-  input_api.cpplint._cpplint_state.ResetErrorCounts()  # reset global state
   source_filter = lambda x: input_api.FilterSourceFile(
     x, white_list=CC_SOURCE_FILES, black_list=None)
-  files = [f.AbsoluteLocalPath() for f in
-           input_api.AffectedSourceFiles(source_filter)]
-  level = 1  # strict, but just warn
 
-  for file_name in files:
-    input_api.cpplint.ProcessFile(file_name, level)
-
-  if not input_api.cpplint._cpplint_state.error_count:
-    return []
-
-  return [output_api.PresubmitPromptWarning(
-    'Changelist failed cpplint.py check.')]
+  return input_api.canned_checks.CheckChangeLintsClean(
+      input_api, output_api, source_filter, lint_filters=[], verbose_level=1)
 
 def CheckAsserts(input_api, output_api, white_list=CC_SOURCE_FILES, black_list=None):
   black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST)
diff --git a/cc/base/switches.cc b/cc/base/switches.cc
index 504e787..ae42482 100644
--- a/cc/base/switches.cc
+++ b/cc/base/switches.cc
@@ -24,9 +24,6 @@
 const char kEnableMainFrameBeforeActivation[] =
     "enable-main-frame-before-activation";
 
-const char kEnableTopControlsPositionCalculation[] =
-    "enable-top-controls-position-calculation";
-
 // Percentage of the top controls need to be hidden before they will auto hide.
 const char kTopControlsHideThreshold[] = "top-controls-hide-threshold";
 
diff --git a/cc/base/switches.h b/cc/base/switches.h
index 90caef8..46fe922 100644
--- a/cc/base/switches.h
+++ b/cc/base/switches.h
@@ -20,7 +20,6 @@
 CC_EXPORT extern const char kDisableCompositedAntialiasing[];
 CC_EXPORT extern const char kDisableMainFrameBeforeActivation[];
 CC_EXPORT extern const char kEnableMainFrameBeforeActivation[];
-CC_EXPORT extern const char kEnableTopControlsPositionCalculation[];
 CC_EXPORT extern const char kJankInsteadOfCheckerboard[];
 CC_EXPORT extern const char kTopControlsHideThreshold[];
 CC_EXPORT extern const char kTopControlsShowThreshold[];
diff --git a/cc/blink/BUILD.gn b/cc/blink/BUILD.gn
index 9d4007b..1769efb 100644
--- a/cc/blink/BUILD.gn
+++ b/cc/blink/BUILD.gn
@@ -9,8 +9,8 @@
   output_name = "cc_blink"
 
   sources = [
-    "context_provider_web_context.h",
     "cc_blink_export.h",
+    "context_provider_web_context.h",
     "scrollbar_impl.cc",
     "scrollbar_impl.h",
     "web_animation_curve_common.cc",
@@ -72,7 +72,7 @@
 
 # GYP version: //cc/blink/cc_blink_tests.gyp:cc_blink_unittests
 # TODO(GYP): make linking work on the mac.
-if (!is_mac && (!is_win || link_chrome_on_windows)) {
+if (!is_mac) {
   test("cc_blink_unittests") {
     sources = [
       "web_animation_unittest.cc",
diff --git a/cc/cc_unittests.isolate b/cc/cc_unittests.isolate
index db47aab..eab3396 100644
--- a/cc/cc_unittests.isolate
+++ b/cc/cc_unittests.isolate
@@ -21,7 +21,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
@@ -47,7 +46,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
@@ -65,7 +63,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
diff --git a/cc/debug/debug_rect_history.cc b/cc/debug/debug_rect_history.cc
index cde7765..c257c60 100644
--- a/cc/debug/debug_rect_history.cc
+++ b/cc/debug/debug_rect_history.cc
@@ -68,17 +68,21 @@
   // not. Therefore we traverse recursively over all layers, not just the render
   // surface list.
 
-  if (!layer->update_rect().IsEmpty() && layer->DrawsContent()) {
+  Region invalidation_region = layer->GetInvalidationRegion();
+  if (!invalidation_region.IsEmpty() && layer->DrawsContent()) {
     float width_scale = layer->content_bounds().width() /
                         static_cast<float>(layer->bounds().width());
     float height_scale = layer->content_bounds().height() /
                          static_cast<float>(layer->bounds().height());
-    gfx::Rect update_content_rect = gfx::ScaleToEnclosingRect(
-        layer->update_rect(), width_scale, height_scale);
-    debug_rects_.push_back(
-        DebugRect(PAINT_RECT_TYPE,
-                  MathUtil::MapEnclosingClippedRect(
-                      layer->screen_space_transform(), update_content_rect)));
+
+    for (Region::Iterator it(invalidation_region); it.has_rect(); it.next()) {
+      gfx::Rect update_content_rect =
+          gfx::ScaleToEnclosingRect(it.rect(), width_scale, height_scale);
+      debug_rects_.push_back(
+          DebugRect(PAINT_RECT_TYPE,
+                    MathUtil::MapEnclosingClippedRect(
+                        layer->screen_space_transform(), update_content_rect)));
+    }
   }
 
   for (unsigned i = 0; i < layer->children().size(); ++i)
@@ -163,10 +167,9 @@
 }
 
 void DebugRectHistory::SaveTouchEventHandlerRects(LayerImpl* layer) {
-  LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
-      layer,
-      base::Bind(&DebugRectHistory::SaveTouchEventHandlerRectsCallback,
-                 base::Unretained(this)));
+  LayerTreeHostCommon::CallFunctionForSubtree(layer, [this](LayerImpl* layer) {
+    SaveTouchEventHandlerRectsCallback(layer);
+  });
 }
 
 void DebugRectHistory::SaveTouchEventHandlerRectsCallback(LayerImpl* layer) {
@@ -183,10 +186,9 @@
 }
 
 void DebugRectHistory::SaveWheelEventHandlerRects(LayerImpl* layer) {
-  LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
-      layer,
-      base::Bind(&DebugRectHistory::SaveWheelEventHandlerRectsCallback,
-                 base::Unretained(this)));
+  LayerTreeHostCommon::CallFunctionForSubtree(layer, [this](LayerImpl* layer) {
+    SaveWheelEventHandlerRectsCallback(layer);
+  });
 }
 
 void DebugRectHistory::SaveWheelEventHandlerRectsCallback(LayerImpl* layer) {
@@ -204,10 +206,9 @@
 }
 
 void DebugRectHistory::SaveScrollEventHandlerRects(LayerImpl* layer) {
-  LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
-      layer,
-      base::Bind(&DebugRectHistory::SaveScrollEventHandlerRectsCallback,
-                 base::Unretained(this)));
+  LayerTreeHostCommon::CallFunctionForSubtree(layer, [this](LayerImpl* layer) {
+    SaveScrollEventHandlerRectsCallback(layer);
+  });
 }
 
 void DebugRectHistory::SaveScrollEventHandlerRectsCallback(LayerImpl* layer) {
@@ -225,10 +226,9 @@
 }
 
 void DebugRectHistory::SaveNonFastScrollableRects(LayerImpl* layer) {
-  LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
-      layer,
-      base::Bind(&DebugRectHistory::SaveNonFastScrollableRectsCallback,
-                 base::Unretained(this)));
+  LayerTreeHostCommon::CallFunctionForSubtree(layer, [this](LayerImpl* layer) {
+    SaveNonFastScrollableRectsCallback(layer);
+  });
 }
 
 void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) {
diff --git a/cc/debug/invalidation_benchmark.cc b/cc/debug/invalidation_benchmark.cc
index 1a6a2b8..bb98bcc 100644
--- a/cc/debug/invalidation_benchmark.cc
+++ b/cc/debug/invalidation_benchmark.cc
@@ -64,11 +64,7 @@
 void InvalidationBenchmark::DidUpdateLayers(LayerTreeHost* host) {
   LayerTreeHostCommon::CallFunctionForSubtree(
       host->root_layer(),
-      base::Bind(&InvalidationBenchmark::Run, base::Unretained(this)));
-}
-
-void InvalidationBenchmark::Run(Layer* layer) {
-  layer->RunMicroBenchmark(this);
+      [this](Layer* layer) { layer->RunMicroBenchmark(this); });
 }
 
 void InvalidationBenchmark::RunOnLayer(PictureLayer* layer) {
diff --git a/cc/debug/invalidation_benchmark.h b/cc/debug/invalidation_benchmark.h
index f17fdbd..9423d5d 100644
--- a/cc/debug/invalidation_benchmark.h
+++ b/cc/debug/invalidation_benchmark.h
@@ -31,7 +31,6 @@
  private:
   enum Mode { FIXED_SIZE, LAYER, VIEWPORT, RANDOM };
 
-  void Run(Layer* layer);
   float LCGRandom();
 
   Mode mode_;
diff --git a/cc/debug/picture_record_benchmark.cc b/cc/debug/picture_record_benchmark.cc
index b1b8188..3ef4708 100644
--- a/cc/debug/picture_record_benchmark.cc
+++ b/cc/debug/picture_record_benchmark.cc
@@ -57,7 +57,7 @@
 void PictureRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
   LayerTreeHostCommon::CallFunctionForSubtree(
       host->root_layer(),
-      base::Bind(&PictureRecordBenchmark::Run, base::Unretained(this)));
+      [this](Layer* layer) { layer->RunMicroBenchmark(this); });
 
   scoped_ptr<base::ListValue> results(new base::ListValue());
   for (std::map<std::pair<int, int>, TotalTime>::iterator it = times_.begin();
@@ -83,10 +83,6 @@
   NotifyDone(results.Pass());
 }
 
-void PictureRecordBenchmark::Run(Layer* layer) {
-  layer->RunMicroBenchmark(this);
-}
-
 void PictureRecordBenchmark::RunOnLayer(PictureLayer* layer) {
   ContentLayerClient* painter = layer->client();
   gfx::Size content_bounds = layer->content_bounds();
diff --git a/cc/debug/picture_record_benchmark.h b/cc/debug/picture_record_benchmark.h
index d6330fe..3710d83 100644
--- a/cc/debug/picture_record_benchmark.h
+++ b/cc/debug/picture_record_benchmark.h
@@ -27,8 +27,6 @@
   void RunOnLayer(PictureLayer* layer) override;
 
  private:
-  void Run(Layer* layer);
-
   typedef std::pair<base::TimeDelta, unsigned> TotalTime;
   std::map<std::pair<int, int>, TotalTime> times_;
   std::vector<std::pair<int, int>> dimensions_;
diff --git a/cc/debug/rasterize_and_record_benchmark.cc b/cc/debug/rasterize_and_record_benchmark.cc
index e56a1e1..e46dcfe 100644
--- a/cc/debug/rasterize_and_record_benchmark.cc
+++ b/cc/debug/rasterize_and_record_benchmark.cc
@@ -65,7 +65,7 @@
   host_ = host;
   LayerTreeHostCommon::CallFunctionForSubtree(
       host->root_layer(),
-      base::Bind(&RasterizeAndRecordBenchmark::Run, base::Unretained(this)));
+      [this](Layer* layer) { layer->RunMicroBenchmark(this); });
 
   DCHECK(!results_.get());
   results_ = make_scoped_ptr(new base::DictionaryValue);
@@ -102,10 +102,6 @@
                  weak_ptr_factory_.GetWeakPtr())));
 }
 
-void RasterizeAndRecordBenchmark::Run(Layer* layer) {
-  layer->RunMicroBenchmark(this);
-}
-
 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
   DCHECK(host_);
 
diff --git a/cc/debug/rasterize_and_record_benchmark.h b/cc/debug/rasterize_and_record_benchmark.h
index 30dcde0..bed446d 100644
--- a/cc/debug/rasterize_and_record_benchmark.h
+++ b/cc/debug/rasterize_and_record_benchmark.h
@@ -37,7 +37,6 @@
       scoped_refptr<base::MessageLoopProxy> origin_loop) override;
 
  private:
-  void Run(Layer* layer);
   void RunOnDisplayListLayer(PictureLayer* layer,
                              const gfx::Rect& visible_content_rect);
   void RunOnPictureLayer(PictureLayer* layer,
diff --git a/cc/debug/rasterize_and_record_benchmark_impl.cc b/cc/debug/rasterize_and_record_benchmark_impl.cc
index 5a9577b..443db8c 100644
--- a/cc/debug/rasterize_and_record_benchmark_impl.cc
+++ b/cc/debug/rasterize_and_record_benchmark_impl.cc
@@ -132,9 +132,10 @@
 void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
     LayerTreeHostImpl* host) {
   LayerTreeHostCommon::CallFunctionForSubtree(
-      host->RootLayer(),
-      base::Bind(&RasterizeAndRecordBenchmarkImpl::Run,
-                 base::Unretained(this)));
+      host->RootLayer(), [this](LayerImpl* layer) {
+        rasterize_results_.total_layers++;
+        layer->RunMicroBenchmark(this);
+      });
 
   scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
   result->SetDouble("rasterize_time_ms",
@@ -157,11 +158,6 @@
   NotifyDone(result.Pass());
 }
 
-void RasterizeAndRecordBenchmarkImpl::Run(LayerImpl* layer) {
-  rasterize_results_.total_layers++;
-  layer->RunMicroBenchmark(this);
-}
-
 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
   rasterize_results_.total_picture_layers++;
   if (!layer->CanHaveTilings()) {
diff --git a/cc/debug/rasterize_and_record_benchmark_impl.h b/cc/debug/rasterize_and_record_benchmark_impl.h
index e9ca27d..ae134ab 100644
--- a/cc/debug/rasterize_and_record_benchmark_impl.h
+++ b/cc/debug/rasterize_and_record_benchmark_impl.h
@@ -31,8 +31,6 @@
   void RunOnLayer(PictureLayerImpl* layer) override;
 
  private:
-  void Run(LayerImpl* layer);
-
   struct RasterizeResults {
     RasterizeResults();
     ~RasterizeResults();
diff --git a/cc/input/top_controls_manager.cc b/cc/input/top_controls_manager.cc
index 7362805..c8bd534 100644
--- a/cc/input/top_controls_manager.cc
+++ b/cc/input/top_controls_manager.cc
@@ -101,6 +101,9 @@
 
 gfx::Vector2dF TopControlsManager::ScrollBy(
     const gfx::Vector2dF& pending_delta) {
+  if (!TopControlsHeight())
+    return pending_delta;
+
   if (pinch_gesture_active_)
     return pending_delta;
 
@@ -180,6 +183,12 @@
   if (top_controls_animation_ && animation_direction_ == direction)
     return;
 
+  if (!TopControlsHeight()) {
+    client_->SetCurrentTopControlsShownRatio(
+        direction == HIDING_CONTROLS ? 0.f : 1.f);
+    return;
+  }
+
   top_controls_animation_ = KeyframedFloatAnimationCurve::Create();
   base::TimeDelta start_time = gfx::FrameTime::Now() - base::TimeTicks();
   top_controls_animation_->AddKeyframe(
diff --git a/cc/input/top_controls_manager_unittest.cc b/cc/input/top_controls_manager_unittest.cc
index 16d0e5d..4befa15 100644
--- a/cc/input/top_controls_manager_unittest.cc
+++ b/cc/input/top_controls_manager_unittest.cc
@@ -409,8 +409,9 @@
 TEST(TopControlsManagerTest, GrowingHeightKeepsTopControlsHidden) {
   MockTopControlsManagerClient client(0.f, 0.5f, 0.5f);
   TopControlsManager* manager = client.manager();
+  client.SetTopControlsHeight(1.f);
   manager->UpdateTopControlsState(HIDDEN, HIDDEN, false);
-  EXPECT_EQ(0.f, manager->ControlsTopOffset());
+  EXPECT_EQ(-1.f, manager->ControlsTopOffset());
   EXPECT_EQ(0.f, manager->ContentTopOffset());
 
   client.SetTopControlsHeight(50.f);
@@ -445,5 +446,50 @@
   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
 }
 
+TEST(TopControlsManagerTest, ZeroTopControlsHeightScrolling) {
+  MockTopControlsManagerClient client(0.f, 0.5f, 0.5f);
+  client.SetCurrentTopControlsShownRatio(0.f);
+  TopControlsManager* manager = client.manager();
+  manager->UpdateTopControlsState(BOTH, BOTH, false);
+
+  manager->ScrollBegin();
+  EXPECT_FLOAT_EQ(-10.f, manager->ScrollBy(gfx::Vector2dF(0.f, -10.f)).y());
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
+
+  client.SetTopControlsHeight(20.f);
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
+
+  EXPECT_FLOAT_EQ(0.f, manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)).y());
+  EXPECT_FLOAT_EQ(0.75f, manager->TopControlsShownRatio());
+  client.SetTopControlsHeight(0.f);
+  manager->ScrollEnd();
+
+  EXPECT_FALSE(manager->animation());
+  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
+}
+
+TEST(TopControlsManagerTest, ZeroTopControlsHeightAnimating) {
+  MockTopControlsManagerClient client(0.f, 0.5f, 0.5f);
+  client.SetCurrentTopControlsShownRatio(0.f);
+  TopControlsManager* manager = client.manager();
+
+  manager->UpdateTopControlsState(BOTH, HIDDEN, false);
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
+  manager->UpdateTopControlsState(BOTH, SHOWN, false);
+  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
+
+  manager->UpdateTopControlsState(BOTH, HIDDEN, true);
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
+  EXPECT_FALSE(manager->animation());
+  manager->UpdateTopControlsState(BOTH, SHOWN, true);
+  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
+  EXPECT_FALSE(manager->animation());
+
+  client.SetCurrentTopControlsShownRatio(0.3f);
+  manager->MainThreadHasStoppedFlinging();
+  EXPECT_FALSE(manager->animation());
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc
index e1056be..08f692f 100644
--- a/cc/layers/delegated_renderer_layer_impl.cc
+++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -172,6 +172,10 @@
 
   // Give back an empty array instead of nulls.
   render_passes_in_draw_order->clear();
+
+  // The render passes given here become part of the RenderSurfaceLayerList, so
+  // changing them requires recomputing the RenderSurfaceLayerList.
+  layer_tree_impl()->set_needs_update_draw_properties();
 }
 
 void DelegatedRendererLayerImpl::ClearRenderPasses() {
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc
index ce6ab56..04e1b85 100644
--- a/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -132,6 +132,169 @@
   DelegatedRendererLayerImpl* delegated_renderer_layer_;
 };
 
+TEST_F(DelegatedRendererLayerImplTest,
+       ChangeContributingRenderPassForNewFrame) {
+  FakeDelegatedRendererLayerImpl* fake_delegated_renderer_layer_impl;
+  {
+    scoped_ptr<LayerImpl> root_layer =
+        SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
+    scoped_ptr<FakeDelegatedRendererLayerImpl> delegated_renderer_layer =
+        FakeDelegatedRendererLayerImpl::Create(host_impl_->active_tree(), 2);
+
+    host_impl_->SetViewportSize(gfx::Size(100, 100));
+    root_layer->SetBounds(gfx::Size(100, 100));
+    root_layer->SetHasRenderSurface(true);
+
+    delegated_renderer_layer->SetPosition(gfx::Point(3, 3));
+    delegated_renderer_layer->SetBounds(gfx::Size(10, 10));
+    delegated_renderer_layer->SetContentBounds(gfx::Size(10, 10));
+    delegated_renderer_layer->SetDrawsContent(true);
+    delegated_renderer_layer->SetHasRenderSurface(true);
+    gfx::Transform transform;
+    transform.Translate(1.0, 1.0);
+    delegated_renderer_layer->SetTransform(transform);
+
+    RenderPassList delegated_render_passes;
+    TestRenderPass* pass1 =
+        AddRenderPass(&delegated_render_passes, RenderPassId(9, 6),
+                      gfx::Rect(6, 6, 6, 6), gfx::Transform(1, 0, 0, 1, 5, 6));
+    AddQuad(pass1, gfx::Rect(0, 0, 6, 6), 33u);
+    TestRenderPass* pass2 =
+        AddRenderPass(&delegated_render_passes, RenderPassId(9, 7),
+                      gfx::Rect(7, 7, 7, 7), gfx::Transform(1, 0, 0, 1, 7, 8));
+    AddQuad(pass2, gfx::Rect(0, 0, 7, 7), 22u);
+    AddRenderPassQuad(pass2, pass1);
+    TestRenderPass* pass3 =
+        AddRenderPass(&delegated_render_passes, RenderPassId(9, 8),
+                      gfx::Rect(0, 0, 8, 8), gfx::Transform(1, 0, 0, 1, 9, 10));
+    AddRenderPassQuad(pass3, pass2);
+    delegated_renderer_layer->SetFrameDataForRenderPasses(
+        1.f, delegated_render_passes);
+
+    fake_delegated_renderer_layer_impl = delegated_renderer_layer.get();
+
+    root_layer->AddChild(delegated_renderer_layer.Pass());
+
+    host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
+
+    LayerTreeHostImpl::FrameData frame;
+    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+
+    // Root layer has one render pass, and delegated renderer layer has two
+    // contributing render passes and its own render pass.
+    ASSERT_EQ(4u, frame.render_passes.size());
+
+    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+    host_impl_->DidDrawAllLayers(frame);
+  }
+  {
+    // New frame makes delegated renderer layer loses its contributing render
+    // passes.
+    RenderPassList delegated_render_passes;
+    AddRenderPass(&delegated_render_passes, RenderPassId(9, 8),
+                  gfx::Rect(0, 0, 8, 8), gfx::Transform(1, 0, 0, 1, 9, 10));
+    fake_delegated_renderer_layer_impl->SetFrameDataForRenderPasses(
+        1.f, delegated_render_passes);
+
+    // Force damage to redraw a new frame.
+    host_impl_->SetViewportDamage(gfx::Rect(10, 10));
+
+    LayerTreeHostImpl::FrameData frame;
+    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+
+    // Each non-DelegatedRendererLayer added one RenderPass. The
+    // DelegatedRendererLayer added two contributing passes.
+    ASSERT_EQ(1u, frame.render_passes.size());
+
+    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+    host_impl_->DidDrawAllLayers(frame);
+  }
+}
+
+TEST_F(DelegatedRendererLayerImplTest,
+       ChangeContributingRenderPassNonFullTreeSync) {
+  FakeDelegatedRendererLayerImpl* fake_delegated_renderer_layer_impl;
+  {
+    host_impl_->CreatePendingTree();
+    scoped_ptr<LayerImpl> root_layer =
+        SolidColorLayerImpl::Create(host_impl_->pending_tree(), 1);
+    scoped_ptr<FakeDelegatedRendererLayerImpl> delegated_renderer_layer =
+        FakeDelegatedRendererLayerImpl::Create(host_impl_->pending_tree(), 2);
+
+    host_impl_->SetViewportSize(gfx::Size(100, 100));
+    root_layer->SetBounds(gfx::Size(100, 100));
+    root_layer->SetHasRenderSurface(true);
+
+    delegated_renderer_layer->SetPosition(gfx::Point(3, 3));
+    delegated_renderer_layer->SetBounds(gfx::Size(10, 10));
+    delegated_renderer_layer->SetContentBounds(gfx::Size(10, 10));
+    delegated_renderer_layer->SetDrawsContent(true);
+    delegated_renderer_layer->SetHasRenderSurface(true);
+    gfx::Transform transform;
+    transform.Translate(1.0, 1.0);
+    delegated_renderer_layer->SetTransform(transform);
+
+    RenderPassList delegated_render_passes;
+    TestRenderPass* pass1 =
+        AddRenderPass(&delegated_render_passes, RenderPassId(9, 6),
+                      gfx::Rect(6, 6, 6, 6), gfx::Transform(1, 0, 0, 1, 5, 6));
+    AddQuad(pass1, gfx::Rect(0, 0, 6, 6), 33u);
+    TestRenderPass* pass2 =
+        AddRenderPass(&delegated_render_passes, RenderPassId(9, 7),
+                      gfx::Rect(7, 7, 7, 7), gfx::Transform(1, 0, 0, 1, 7, 8));
+    AddQuad(pass2, gfx::Rect(0, 0, 7, 7), 22u);
+    AddRenderPassQuad(pass2, pass1);
+    TestRenderPass* pass3 =
+        AddRenderPass(&delegated_render_passes, RenderPassId(9, 8),
+                      gfx::Rect(0, 0, 8, 8), gfx::Transform(1, 0, 0, 1, 9, 10));
+    AddRenderPassQuad(pass3, pass2);
+    delegated_renderer_layer->SetFrameDataForRenderPasses(
+        1.f, delegated_render_passes);
+
+    fake_delegated_renderer_layer_impl = delegated_renderer_layer.get();
+
+    root_layer->AddChild(delegated_renderer_layer.Pass());
+
+    host_impl_->pending_tree()->SetRootLayer(root_layer.Pass());
+    host_impl_->ActivateSyncTree();
+
+    LayerTreeHostImpl::FrameData frame;
+    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+
+    // Root layer has one render pass, and delegated renderer layer has two
+    // contributing render passes and its own render pass.
+    ASSERT_EQ(4u, frame.render_passes.size());
+
+    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+    host_impl_->DidDrawAllLayers(frame);
+  }
+  {
+    // Remove contributing render passes from the delegated renderer layer.
+    host_impl_->CreatePendingTree();
+    host_impl_->pending_tree()->set_needs_full_tree_sync(false);
+    RenderPassList delegated_render_passes;
+    AddRenderPass(&delegated_render_passes, RenderPassId(9, 8),
+                  gfx::Rect(0, 0, 8, 8), gfx::Transform(1, 0, 0, 1, 9, 10));
+
+    fake_delegated_renderer_layer_impl->SetFrameDataForRenderPasses(
+        1.f, delegated_render_passes);
+
+    // Force damage to redraw a new frame.
+
+    host_impl_->ActivateSyncTree();
+    host_impl_->SetViewportDamage(gfx::Rect(100, 100));
+    LayerTreeHostImpl::FrameData frame;
+    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+
+    // Root layer has one render pass, and delegated renderer layer no longer
+    // has contributing render passes.
+    ASSERT_EQ(1u, frame.render_passes.size());
+
+    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+    host_impl_->DidDrawAllLayers(frame);
+  }
+}
+
 TEST_F(DelegatedRendererLayerImplTestSimple, AddsContributingRenderPasses) {
   LayerTreeHostImpl::FrameData frame;
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 0c6ddf5..0353a78 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -1590,4 +1590,8 @@
   render_surface_.reset();
 }
 
+Region LayerImpl::GetInvalidationRegion() {
+  return Region(update_rect_);
+}
+
 }  // namespace cc
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 5de0d9a..0357252 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -596,6 +596,10 @@
 
   SyncedScrollOffset* synced_scroll_offset() { return scroll_offset_.get(); }
 
+  // Get the correct invalidation region instead of conservative Rect
+  // for layers that provide it.
+  virtual Region GetInvalidationRegion();
+
  protected:
   LayerImpl(LayerTreeImpl* layer_impl,
             int id,
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index e7918e2..1cfe1f1 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -89,6 +89,7 @@
                             host->settings().default_tile_grid_size));
       }
     }
+    recording_source_->DidMoveToNewCompositor();
     recording_source_->SetSlowdownRasterScaleFactor(
         host->debug_state().slow_down_raster_scale_factor);
   }
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index e819afd..93d6581 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -331,8 +331,8 @@
         CheckerboardDrawQuad* quad =
             render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
         SkColor color = DebugColors::DefaultCheckerboardColor();
-        quad->SetNew(
-            shared_quad_state, geometry_rect, visible_geometry_rect, color);
+        quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect,
+                     color, draw_properties().device_scale_factor);
       } else {
         SkColor color = SafeOpaqueBackgroundColor();
         SolidColorDrawQuad* quad =
@@ -605,6 +605,15 @@
   return raster_source_->GetFlattenedPicture();
 }
 
+Region PictureLayerImpl::GetInvalidationRegion() {
+  // |invalidation_| gives the invalidation contained in the source frame, but
+  // is not cleared after drawing from the layer. However, update_rect() is
+  // cleared once the invalidation is drawn, which is useful for debugging
+  // visualizations. This method intersects the two to give a more exact
+  // representation of what was invalidated that is cleared after drawing.
+  return IntersectRegions(invalidation_, update_rect());
+}
+
 scoped_refptr<Tile> PictureLayerImpl::CreateTile(
     float contents_scale,
     const gfx::Rect& content_rect) {
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 9500e22..397cb62 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -61,6 +61,7 @@
   void ReleaseResources() override;
   void RecreateResources() override;
   skia::RefPtr<SkPicture> GetPicture() override;
+  Region GetInvalidationRegion() override;
 
   // PictureLayerTilingClient overrides.
   scoped_refptr<Tile> CreateTile(float contents_scale,
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index afb6096..ab06bb0 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -8,6 +8,7 @@
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/resources/resource_update_queue.h"
 #include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_picture_layer.h"
 #include "cc/test/fake_picture_layer_impl.h"
 #include "cc/test/fake_proxy.h"
 #include "cc/test/impl_side_painting_settings.h"
@@ -111,5 +112,58 @@
   EXPECT_EQ(size.height(), 123);
 }
 
+// PicturePile uses the source frame number as a unit for measuring invalidation
+// frequency. When a pile moves between compositors, the frame number increases
+// non-monotonically. This executes that code path under this scenario allowing
+// for the code to verify correctness with DCHECKs.
+TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) {
+  LayerTreeSettings settings;
+  settings.single_thread_proxy_scheduler = false;
+
+  FakeLayerTreeHostClient host_client1(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client2(FakeLayerTreeHostClient::DIRECT_3D);
+  scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
+      new TestSharedBitmapManager());
+
+  MockContentLayerClient client;
+  scoped_refptr<FakePictureLayer> layer = FakePictureLayer::Create(&client);
+
+  scoped_ptr<LayerTreeHost> host1 = LayerTreeHost::CreateSingleThreaded(
+      &host_client1, &host_client1, shared_bitmap_manager.get(), nullptr,
+      settings, base::MessageLoopProxy::current(), nullptr);
+  host_client1.SetLayerTreeHost(host1.get());
+
+  scoped_ptr<LayerTreeHost> host2 = LayerTreeHost::CreateSingleThreaded(
+      &host_client2, &host_client2, shared_bitmap_manager.get(), nullptr,
+      settings, base::MessageLoopProxy::current(), nullptr);
+  host_client2.SetLayerTreeHost(host2.get());
+
+  // The PictureLayer is put in one LayerTreeHost.
+  host1->SetRootLayer(layer);
+  // Do a main frame, record the picture layers.
+  EXPECT_EQ(0u, layer->update_count());
+  layer->SetNeedsDisplay();
+  host1->Composite(base::TimeTicks::Now());
+  EXPECT_EQ(1u, layer->update_count());
+  EXPECT_EQ(1, host1->source_frame_number());
+
+  // The source frame number in |host1| is now higher than host2.
+  layer->SetNeedsDisplay();
+  host1->Composite(base::TimeTicks::Now());
+  EXPECT_EQ(2u, layer->update_count());
+  EXPECT_EQ(2, host1->source_frame_number());
+
+  // Then moved to another LayerTreeHost.
+  host1->SetRootLayer(nullptr);
+  host2->SetRootLayer(layer);
+
+  // Do a main frame, record the picture layers. The frame number has changed
+  // non-monotonically.
+  layer->SetNeedsDisplay();
+  host2->Composite(base::TimeTicks::Now());
+  EXPECT_EQ(3u, layer->update_count());
+  EXPECT_EQ(1, host2->source_frame_number());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc
index 234bd44..b78a1d8 100644
--- a/cc/layers/tiled_layer_impl.cc
+++ b/cc/layers/tiled_layer_impl.cc
@@ -241,8 +241,8 @@
 
         CheckerboardDrawQuad* checkerboard_quad =
             render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
-        checkerboard_quad->SetNew(
-            shared_quad_state, tile_rect, visible_tile_rect, checker_color);
+        checkerboard_quad->SetNew(shared_quad_state, tile_rect,
+                                  visible_tile_rect, checker_color, 1.f);
         append_quads_data->num_missing_tiles++;
         continue;
       }
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 5c560dc..578faa9 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -558,14 +558,16 @@
                      SkColorGetB(color) * (1.0f / 255.0f),
                      1));
 
-  const int checkerboard_width = 16;
-  float frequency = 1.0f / checkerboard_width;
+  const int kCheckerboardWidth = 16;
+  float frequency = 1.0f / kCheckerboardWidth;
 
   gfx::Rect tile_rect = quad->rect;
-  float tex_offset_x = tile_rect.x() % checkerboard_width;
-  float tex_offset_y = tile_rect.y() % checkerboard_width;
-  float tex_scale_x = tile_rect.width();
-  float tex_scale_y = tile_rect.height();
+  float tex_offset_x =
+      static_cast<int>(tile_rect.x() / quad->scale) % kCheckerboardWidth;
+  float tex_offset_y =
+      static_cast<int>(tile_rect.y() / quad->scale) % kCheckerboardWidth;
+  float tex_scale_x = tile_rect.width() / quad->scale;
+  float tex_scale_y = tile_rect.height() / quad->scale;
   GLC(gl_,
       gl_->Uniform4f(program->fragment_shader().tex_transform_location(),
                      tex_offset_x,
@@ -937,7 +939,9 @@
       DCHECK(!background_image);
       use_shaders_for_blending = false;
     } else if (background_image) {
-      background_texture.reset();
+      // Reset original background texture if there is not any mask
+      if (!quad->mask_resource_id)
+        background_texture.reset();
     } else if (CanApplyBlendModeUsingBlendFunc(blend_mode) &&
                ShouldApplyBackgroundFilters(frame, quad)) {
       // Something went wrong with applying background filters to the backdrop.
@@ -945,7 +949,11 @@
       background_texture.reset();
     }
   }
-
+  // Need original background texture for mask?
+  bool mask_for_background =
+      background_texture &&    // Have original background texture
+      background_image &&      // Have filtered background texture
+      quad->mask_resource_id;  // Have mask texture
   SetBlendEnabled(
       !use_shaders_for_blending &&
       (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode)));
@@ -1015,19 +1023,7 @@
       highp_threshold_min_,
       quad->shared_quad_state->visible_content_rect.bottom_right());
 
-  int shader_quad_location = -1;
-  int shader_edge_location = -1;
-  int shader_viewport_location = -1;
-  int shader_mask_sampler_location = -1;
-  int shader_mask_tex_coord_scale_location = -1;
-  int shader_mask_tex_coord_offset_location = -1;
-  int shader_matrix_location = -1;
-  int shader_alpha_location = -1;
-  int shader_color_matrix_location = -1;
-  int shader_color_offset_location = -1;
-  int shader_tex_transform_location = -1;
-  int shader_backdrop_location = -1;
-  int shader_backdrop_rect_location = -1;
+  ShaderLocations locations;
 
   DCHECK_EQ(background_texture || background_image, use_shaders_for_blending);
   BlendMode shader_blend_mode = use_shaders_for_blending
@@ -1036,163 +1032,67 @@
 
   if (use_aa && mask_texture_id && !use_color_matrix) {
     const RenderPassMaskProgramAA* program = GetRenderPassMaskProgramAA(
-        tex_coord_precision, mask_sampler, shader_blend_mode);
+        tex_coord_precision, mask_sampler,
+        shader_blend_mode, mask_for_background);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_quad_location = program->vertex_shader().quad_location();
-    shader_edge_location = program->vertex_shader().edge_location();
-    shader_viewport_location = program->vertex_shader().viewport_location();
-    shader_mask_sampler_location =
-        program->fragment_shader().mask_sampler_location();
-    shader_mask_tex_coord_scale_location =
-        program->fragment_shader().mask_tex_coord_scale_location();
-    shader_mask_tex_coord_offset_location =
-        program->fragment_shader().mask_tex_coord_offset_location();
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   } else if (!use_aa && mask_texture_id && !use_color_matrix) {
     const RenderPassMaskProgram* program = GetRenderPassMaskProgram(
-        tex_coord_precision, mask_sampler, shader_blend_mode);
+        tex_coord_precision, mask_sampler,
+        shader_blend_mode, mask_for_background);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_mask_sampler_location =
-        program->fragment_shader().mask_sampler_location();
-    shader_mask_tex_coord_scale_location =
-        program->fragment_shader().mask_tex_coord_scale_location();
-    shader_mask_tex_coord_offset_location =
-        program->fragment_shader().mask_tex_coord_offset_location();
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   } else if (use_aa && !mask_texture_id && !use_color_matrix) {
     const RenderPassProgramAA* program =
         GetRenderPassProgramAA(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_quad_location = program->vertex_shader().quad_location();
-    shader_edge_location = program->vertex_shader().edge_location();
-    shader_viewport_location = program->vertex_shader().viewport_location();
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   } else if (use_aa && mask_texture_id && use_color_matrix) {
     const RenderPassMaskColorMatrixProgramAA* program =
         GetRenderPassMaskColorMatrixProgramAA(
-            tex_coord_precision, mask_sampler, shader_blend_mode);
+            tex_coord_precision, mask_sampler,
+            shader_blend_mode, mask_for_background);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_quad_location = program->vertex_shader().quad_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_edge_location = program->vertex_shader().edge_location();
-    shader_viewport_location = program->vertex_shader().viewport_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_mask_sampler_location =
-        program->fragment_shader().mask_sampler_location();
-    shader_mask_tex_coord_scale_location =
-        program->fragment_shader().mask_tex_coord_scale_location();
-    shader_mask_tex_coord_offset_location =
-        program->fragment_shader().mask_tex_coord_offset_location();
-    shader_color_matrix_location =
-        program->fragment_shader().color_matrix_location();
-    shader_color_offset_location =
-        program->fragment_shader().color_offset_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   } else if (use_aa && !mask_texture_id && use_color_matrix) {
     const RenderPassColorMatrixProgramAA* program =
         GetRenderPassColorMatrixProgramAA(tex_coord_precision,
                                           shader_blend_mode);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_quad_location = program->vertex_shader().quad_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_edge_location = program->vertex_shader().edge_location();
-    shader_viewport_location = program->vertex_shader().viewport_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_color_matrix_location =
-        program->fragment_shader().color_matrix_location();
-    shader_color_offset_location =
-        program->fragment_shader().color_offset_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   } else if (!use_aa && mask_texture_id && use_color_matrix) {
     const RenderPassMaskColorMatrixProgram* program =
         GetRenderPassMaskColorMatrixProgram(
-            tex_coord_precision, mask_sampler, shader_blend_mode);
+            tex_coord_precision, mask_sampler,
+            shader_blend_mode, mask_for_background);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_mask_sampler_location =
-        program->fragment_shader().mask_sampler_location();
-    shader_mask_tex_coord_scale_location =
-        program->fragment_shader().mask_tex_coord_scale_location();
-    shader_mask_tex_coord_offset_location =
-        program->fragment_shader().mask_tex_coord_offset_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_color_matrix_location =
-        program->fragment_shader().color_matrix_location();
-    shader_color_offset_location =
-        program->fragment_shader().color_offset_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   } else if (!use_aa && !mask_texture_id && use_color_matrix) {
     const RenderPassColorMatrixProgram* program =
         GetRenderPassColorMatrixProgram(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_color_matrix_location =
-        program->fragment_shader().color_matrix_location();
-    shader_color_offset_location =
-        program->fragment_shader().color_offset_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   } else {
     const RenderPassProgram* program =
         GetRenderPassProgram(tex_coord_precision, shader_blend_mode);
     SetUseProgram(program->program());
-    GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-    shader_matrix_location = program->vertex_shader().matrix_location();
-    shader_alpha_location = program->fragment_shader().alpha_location();
-    shader_tex_transform_location =
-        program->vertex_shader().tex_transform_location();
-    shader_backdrop_location = program->fragment_shader().backdrop_location();
-    shader_backdrop_rect_location =
-        program->fragment_shader().backdrop_rect_location();
+    program->vertex_shader().FillLocations(&locations);
+    program->fragment_shader().FillLocations(&locations);
+    GLC(gl_, gl_->Uniform1i(locations.sampler, 0));
   }
   float tex_scale_x =
       quad->rect.width() / static_cast<float>(contents_texture->size().width());
@@ -1201,22 +1101,22 @@
   DCHECK_LE(tex_scale_x, 1.0f);
   DCHECK_LE(tex_scale_y, 1.0f);
 
-  DCHECK(shader_tex_transform_location != -1 || IsContextLost());
+  DCHECK(locations.tex_transform != -1 || IsContextLost());
   // Flip the content vertically in the shader, as the RenderPass input
   // texture is already oriented the same way as the framebuffer, but the
   // projection transform does a flip.
   GLC(gl_,
-      gl_->Uniform4f(shader_tex_transform_location,
+      gl_->Uniform4f(locations.tex_transform,
                      0.0f,
                      tex_scale_y,
                      tex_scale_x,
                      -tex_scale_y));
 
   GLint last_texture_unit = 0;
-  if (shader_mask_sampler_location != -1) {
-    DCHECK_NE(shader_mask_tex_coord_scale_location, 1);
-    DCHECK_NE(shader_mask_tex_coord_offset_location, 1);
-    GLC(gl_, gl_->Uniform1i(shader_mask_sampler_location, 1));
+  if (locations.mask_sampler != -1) {
+    DCHECK_NE(locations.mask_tex_coord_scale, 1);
+    DCHECK_NE(locations.mask_tex_coord_offset, 1);
+    GLC(gl_, gl_->Uniform1i(locations.mask_sampler, 1));
 
     gfx::RectF mask_uv_rect = quad->MaskUVRect();
     if (mask_sampler != SAMPLER_TYPE_2D) {
@@ -1228,56 +1128,56 @@
     // and the RenderPass contents texture, so we flip the tex coords from the
     // RenderPass texture to find the mask texture coords.
     GLC(gl_,
-        gl_->Uniform2f(shader_mask_tex_coord_offset_location,
+        gl_->Uniform2f(locations.mask_tex_coord_offset,
                        mask_uv_rect.x(),
                        mask_uv_rect.bottom()));
     GLC(gl_,
-        gl_->Uniform2f(shader_mask_tex_coord_scale_location,
+        gl_->Uniform2f(locations.mask_tex_coord_scale,
                        mask_uv_rect.width() / tex_scale_x,
                        -mask_uv_rect.height() / tex_scale_y));
 
     last_texture_unit = 1;
   }
 
-  if (shader_edge_location != -1)
-    GLC(gl_, gl_->Uniform3fv(shader_edge_location, 8, edge));
+  if (locations.edge != -1)
+    GLC(gl_, gl_->Uniform3fv(locations.edge, 8, edge));
 
-  if (shader_viewport_location != -1) {
+  if (locations.viewport != -1) {
     float viewport[4] = {static_cast<float>(viewport_.x()),
                          static_cast<float>(viewport_.y()),
                          static_cast<float>(viewport_.width()),
                          static_cast<float>(viewport_.height()), };
-    GLC(gl_, gl_->Uniform4fv(shader_viewport_location, 1, viewport));
+    GLC(gl_, gl_->Uniform4fv(locations.viewport, 1, viewport));
   }
 
-  if (shader_color_matrix_location != -1) {
+  if (locations.color_matrix != -1) {
     float matrix[16];
     for (int i = 0; i < 4; ++i) {
       for (int j = 0; j < 4; ++j)
         matrix[i * 4 + j] = SkScalarToFloat(color_matrix[j * 5 + i]);
     }
     GLC(gl_,
-        gl_->UniformMatrix4fv(shader_color_matrix_location, 1, false, matrix));
+        gl_->UniformMatrix4fv(locations.color_matrix, 1, false, matrix));
   }
   static const float kScale = 1.0f / 255.0f;
-  if (shader_color_offset_location != -1) {
+  if (locations.color_offset != -1) {
     float offset[4];
     for (int i = 0; i < 4; ++i)
       offset[i] = SkScalarToFloat(color_matrix[i * 5 + 4]) * kScale;
 
-    GLC(gl_, gl_->Uniform4fv(shader_color_offset_location, 1, offset));
+    GLC(gl_, gl_->Uniform4fv(locations.color_offset, 1, offset));
   }
 
   scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_background_sampler_lock;
-  if (shader_backdrop_location != -1) {
+  if (locations.backdrop != -1) {
     DCHECK(background_texture || background_image);
-    DCHECK_NE(shader_backdrop_location, 0);
-    DCHECK_NE(shader_backdrop_rect_location, 0);
+    DCHECK_NE(locations.backdrop, 0);
+    DCHECK_NE(locations.backdrop_rect, 0);
 
-    GLC(gl_, gl_->Uniform1i(shader_backdrop_location, ++last_texture_unit));
+    GLC(gl_, gl_->Uniform1i(locations.backdrop, ++last_texture_unit));
 
     GLC(gl_,
-        gl_->Uniform4f(shader_backdrop_rect_location,
+        gl_->Uniform4f(locations.backdrop_rect,
                        background_rect.x(),
                        background_rect.y(),
                        background_rect.width(),
@@ -1288,7 +1188,11 @@
       GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0 + last_texture_unit));
       gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle());
       GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
-    } else {
+      if (mask_for_background)
+        GLC(gl_, gl_->Uniform1i(locations.original_backdrop,
+                                ++last_texture_unit));
+    }
+    if (background_texture) {
       shader_background_sampler_lock = make_scoped_ptr(
           new ResourceProvider::ScopedSamplerGL(resource_provider_,
                                                 background_texture->id(),
@@ -1299,10 +1203,10 @@
     }
   }
 
-  SetShaderOpacity(quad->opacity(), shader_alpha_location);
-  SetShaderQuadF(surface_quad, shader_quad_location);
+  SetShaderOpacity(quad->opacity(), locations.alpha);
+  SetShaderQuadF(surface_quad, locations.quad);
   DrawQuadGeometry(
-      frame, quad->quadTransform(), quad->rect, shader_matrix_location);
+      frame, quad->quadTransform(), quad->rect, locations.matrix);
 
   // Flush the compositor context before the filter bitmap goes out of
   // scope, so the draw gets processed before the filter texture gets deleted.
@@ -2804,7 +2708,8 @@
 const GLRenderer::RenderPassMaskProgram* GLRenderer::GetRenderPassMaskProgram(
     TexCoordPrecision precision,
     SamplerType sampler,
-    BlendMode blend_mode) {
+    BlendMode blend_mode,
+    bool mask_for_background) {
   DCHECK_GE(precision, 0);
   DCHECK_LE(precision, LAST_TEX_COORD_PRECISION);
   DCHECK_GE(sampler, 0);
@@ -2812,11 +2717,13 @@
   DCHECK_GE(blend_mode, 0);
   DCHECK_LE(blend_mode, LAST_BLEND_MODE);
   RenderPassMaskProgram* program =
-      &render_pass_mask_program_[precision][sampler][blend_mode];
+      &render_pass_mask_program_[precision][sampler][blend_mode]
+                                [mask_for_background ? HAS_MASK : NO_MASK];
   if (!program->initialized()) {
     TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize");
     program->Initialize(
-        output_surface_->context_provider(), precision, sampler, blend_mode);
+        output_surface_->context_provider(), precision,
+        sampler, blend_mode, mask_for_background);
   }
   return program;
 }
@@ -2824,7 +2731,8 @@
 const GLRenderer::RenderPassMaskProgramAA*
 GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision,
                                        SamplerType sampler,
-                                       BlendMode blend_mode) {
+                                       BlendMode blend_mode,
+                                       bool mask_for_background) {
   DCHECK_GE(precision, 0);
   DCHECK_LE(precision, LAST_TEX_COORD_PRECISION);
   DCHECK_GE(sampler, 0);
@@ -2832,11 +2740,13 @@
   DCHECK_GE(blend_mode, 0);
   DCHECK_LE(blend_mode, LAST_BLEND_MODE);
   RenderPassMaskProgramAA* program =
-      &render_pass_mask_program_aa_[precision][sampler][blend_mode];
+      &render_pass_mask_program_aa_[precision][sampler][blend_mode]
+                                   [mask_for_background ? HAS_MASK : NO_MASK];
   if (!program->initialized()) {
     TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize");
     program->Initialize(
-        output_surface_->context_provider(), precision, sampler, blend_mode);
+        output_surface_->context_provider(), precision,
+        sampler, blend_mode, mask_for_background);
   }
   return program;
 }
@@ -2877,9 +2787,11 @@
 }
 
 const GLRenderer::RenderPassMaskColorMatrixProgram*
-GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision,
-                                                SamplerType sampler,
-                                                BlendMode blend_mode) {
+GLRenderer::GetRenderPassMaskColorMatrixProgram(
+    TexCoordPrecision precision,
+    SamplerType sampler,
+    BlendMode blend_mode,
+    bool mask_for_background) {
   DCHECK_GE(precision, 0);
   DCHECK_LE(precision, LAST_TEX_COORD_PRECISION);
   DCHECK_GE(sampler, 0);
@@ -2887,20 +2799,24 @@
   DCHECK_GE(blend_mode, 0);
   DCHECK_LE(blend_mode, LAST_BLEND_MODE);
   RenderPassMaskColorMatrixProgram* program =
-      &render_pass_mask_color_matrix_program_[precision][sampler][blend_mode];
+      &render_pass_mask_color_matrix_program_[precision][sampler][blend_mode]
+          [mask_for_background ? HAS_MASK : NO_MASK];
   if (!program->initialized()) {
     TRACE_EVENT0("cc",
                  "GLRenderer::renderPassMaskColorMatrixProgram::initialize");
     program->Initialize(
-        output_surface_->context_provider(), precision, sampler, blend_mode);
+        output_surface_->context_provider(), precision,
+        sampler, blend_mode, mask_for_background);
   }
   return program;
 }
 
 const GLRenderer::RenderPassMaskColorMatrixProgramAA*
-GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
-                                                  SamplerType sampler,
-                                                  BlendMode blend_mode) {
+GLRenderer::GetRenderPassMaskColorMatrixProgramAA(
+    TexCoordPrecision precision,
+    SamplerType sampler,
+    BlendMode blend_mode,
+    bool mask_for_background) {
   DCHECK_GE(precision, 0);
   DCHECK_LE(precision, LAST_TEX_COORD_PRECISION);
   DCHECK_GE(sampler, 0);
@@ -2908,13 +2824,14 @@
   DCHECK_GE(blend_mode, 0);
   DCHECK_LE(blend_mode, LAST_BLEND_MODE);
   RenderPassMaskColorMatrixProgramAA* program =
-      &render_pass_mask_color_matrix_program_aa_[precision][sampler]
-                                                [blend_mode];
+      &render_pass_mask_color_matrix_program_aa_[precision][sampler][blend_mode]
+          [mask_for_background ? HAS_MASK : NO_MASK];
   if (!program->initialized()) {
     TRACE_EVENT0("cc",
                  "GLRenderer::renderPassMaskColorMatrixProgramAA::initialize");
     program->Initialize(
-        output_surface_->context_provider(), precision, sampler, blend_mode);
+        output_surface_->context_provider(), precision,
+        sampler, blend_mode, mask_for_background);
   }
   return program;
 }
@@ -3141,10 +3058,12 @@
       tile_program_swizzle_aa_[i][j].Cleanup(gl_);
 
       for (int k = 0; k <= LAST_BLEND_MODE; k++) {
-        render_pass_mask_program_[i][j][k].Cleanup(gl_);
-        render_pass_mask_program_aa_[i][j][k].Cleanup(gl_);
-        render_pass_mask_color_matrix_program_aa_[i][j][k].Cleanup(gl_);
-        render_pass_mask_color_matrix_program_[i][j][k].Cleanup(gl_);
+        for (int l = 0; l <= LAST_MASK_VALUE; ++l) {
+          render_pass_mask_program_[i][j][k][l].Cleanup(gl_);
+          render_pass_mask_program_aa_[i][j][k][l].Cleanup(gl_);
+          render_pass_mask_color_matrix_program_aa_[i][j][k][l].Cleanup(gl_);
+          render_pass_mask_color_matrix_program_[i][j][k][l].Cleanup(gl_);
+        }
       }
     }
     for (int j = 0; j <= LAST_BLEND_MODE; j++) {
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 25c7096..01668ab 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -334,11 +334,13 @@
   const RenderPassMaskProgram* GetRenderPassMaskProgram(
       TexCoordPrecision precision,
       SamplerType sampler,
-      BlendMode blend_mode);
+      BlendMode blend_mode,
+      bool mask_for_background);
   const RenderPassMaskProgramAA* GetRenderPassMaskProgramAA(
       TexCoordPrecision precision,
       SamplerType sampler,
-      BlendMode blend_mode);
+      BlendMode blend_mode,
+      bool mask_for_background);
   const RenderPassColorMatrixProgram* GetRenderPassColorMatrixProgram(
       TexCoordPrecision precision,
       BlendMode blend_mode);
@@ -348,11 +350,13 @@
   const RenderPassMaskColorMatrixProgram* GetRenderPassMaskColorMatrixProgram(
       TexCoordPrecision precision,
       SamplerType sampler,
-      BlendMode blend_mode);
+      BlendMode blend_mode,
+      bool mask_for_background);
   const RenderPassMaskColorMatrixProgramAA*
   GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
                                         SamplerType sampler,
-                                        BlendMode blend_mode);
+                                        BlendMode blend_mode,
+                                        bool mask_for_background);
 
   const TextureProgram* GetTextureProgram(
       TexCoordPrecision precision);
@@ -407,12 +411,15 @@
   RenderPassProgramAA render_pass_program_aa_[LAST_TEX_COORD_PRECISION +
                                               1][LAST_BLEND_MODE + 1];
   RenderPassMaskProgram
-      render_pass_mask_program_[LAST_TEX_COORD_PRECISION +
-                                1][LAST_SAMPLER_TYPE + 1][LAST_BLEND_MODE + 1];
+      render_pass_mask_program_[LAST_TEX_COORD_PRECISION + 1]
+                               [LAST_SAMPLER_TYPE + 1]
+                               [LAST_BLEND_MODE + 1]
+                               [LAST_MASK_VALUE + 1];
   RenderPassMaskProgramAA
-      render_pass_mask_program_aa_[LAST_TEX_COORD_PRECISION +
-                                   1][LAST_SAMPLER_TYPE + 1][LAST_BLEND_MODE +
-                                                             1];
+      render_pass_mask_program_aa_[LAST_TEX_COORD_PRECISION + 1]
+                                  [LAST_SAMPLER_TYPE + 1]
+                                  [LAST_BLEND_MODE + 1]
+                                  [LAST_MASK_VALUE + 1];
   RenderPassColorMatrixProgram
       render_pass_color_matrix_program_[LAST_TEX_COORD_PRECISION +
                                         1][LAST_BLEND_MODE + 1];
@@ -420,13 +427,15 @@
       render_pass_color_matrix_program_aa_[LAST_TEX_COORD_PRECISION +
                                            1][LAST_BLEND_MODE + 1];
   RenderPassMaskColorMatrixProgram
-      render_pass_mask_color_matrix_program_[LAST_TEX_COORD_PRECISION +
-                                             1][LAST_SAMPLER_TYPE +
-                                                1][LAST_BLEND_MODE + 1];
+      render_pass_mask_color_matrix_program_[LAST_TEX_COORD_PRECISION + 1]
+                                            [LAST_SAMPLER_TYPE + 1]
+                                            [LAST_BLEND_MODE + 1]
+                                            [LAST_MASK_VALUE + 1];
   RenderPassMaskColorMatrixProgramAA
-      render_pass_mask_color_matrix_program_aa_[LAST_TEX_COORD_PRECISION +
-                                                1][LAST_SAMPLER_TYPE +
-                                                   1][LAST_BLEND_MODE + 1];
+      render_pass_mask_color_matrix_program_aa_[LAST_TEX_COORD_PRECISION + 1]
+                                               [LAST_SAMPLER_TYPE + 1]
+                                               [LAST_BLEND_MODE + 1]
+                                               [LAST_MASK_VALUE + 1];
 
   VideoYUVProgram video_yuv_program_[LAST_TEX_COORD_PRECISION + 1];
   VideoYUVAProgram video_yuva_program_[LAST_TEX_COORD_PRECISION + 1];
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index fc70900..cec0882 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -149,14 +149,20 @@
         renderer()->GetTileProgramSwizzleAA(precision, sampler));
     for (int i = 0; i <= LAST_BLEND_MODE; ++i) {
       BlendMode blend_mode = static_cast<BlendMode>(i);
-      EXPECT_PROGRAM_VALID(
-          renderer()->GetRenderPassMaskProgram(precision, sampler, blend_mode));
-      EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(
-          precision, sampler, blend_mode));
-      EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgramAA(
-          precision, sampler, blend_mode));
-      EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgram(
-          precision, sampler, blend_mode));
+      for (int l = 0; l <= 1; ++l) {
+        bool mask_for_background = (l == 1);
+        EXPECT_PROGRAM_VALID(
+            renderer()->GetRenderPassMaskProgram(precision,
+                                                 sampler,
+                                                 blend_mode,
+                                                 mask_for_background));
+        EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(
+            precision, sampler, blend_mode, mask_for_background));
+        EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgramAA(
+            precision, sampler, blend_mode, mask_for_background));
+        EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgram(
+            precision, sampler, blend_mode, mask_for_background));
+      }
     }
   }
 };
@@ -269,10 +275,15 @@
                                  SamplerType sampler,
                                  BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(
-        &renderer_->render_pass_mask_program_[precision][sampler][blend_mode]);
+        &renderer_->render_pass_mask_program_[precision]
+                                             [sampler]
+                                             [blend_mode]
+                                             [NO_MASK]);
     EXPECT_EQ(
-        renderer_->render_pass_mask_program_[precision][sampler][blend_mode]
-            .program(),
+        renderer_->render_pass_mask_program_[precision]
+                                            [sampler]
+                                            [blend_mode]
+                                            [NO_MASK].program(),
         renderer_->program_shadow_);
   }
 
@@ -280,9 +291,9 @@
                                             SamplerType sampler,
                                             BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_color_matrix_program_
-                              [precision][sampler][blend_mode]);
+                              [precision][sampler][blend_mode][NO_MASK]);
     EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_
-                  [precision][sampler][blend_mode].program(),
+                  [precision][sampler][blend_mode][NO_MASK].program(),
               renderer_->program_shadow_);
   }
 
@@ -311,10 +322,11 @@
                                    BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(
         &renderer_
-             ->render_pass_mask_program_aa_[precision][sampler][blend_mode]);
+             ->render_pass_mask_program_aa_
+                 [precision][sampler][blend_mode][NO_MASK]);
     EXPECT_EQ(
         renderer_->render_pass_mask_program_aa_[precision][sampler][blend_mode]
-            .program(),
+            [NO_MASK].program(),
         renderer_->program_shadow_);
   }
 
@@ -322,9 +334,9 @@
                                               SamplerType sampler,
                                               BlendMode blend_mode) {
     EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_color_matrix_program_aa_
-                              [precision][sampler][blend_mode]);
+                              [precision][sampler][blend_mode][NO_MASK]);
     EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_
-                  [precision][sampler][blend_mode].program(),
+                  [precision][sampler][blend_mode][NO_MASK].program(),
               renderer_->program_shadow_);
   }
 
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 6ee388a..5590ec3 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -234,7 +234,7 @@
                            const gfx::Rect& rect) {
   CheckerboardDrawQuad* checkerboard_quad =
       render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
-  checkerboard_quad->SetNew(shared_quad_state, rect, rect, SkColor());
+  checkerboard_quad->SetNew(shared_quad_state, rect, rect, SkColor(), 1.f);
 }
 
 void CreateFullscreenCheckeredQuad(ResourceProvider* resource_provider,
diff --git a/cc/output/program_binding.h b/cc/output/program_binding.h
index 9c3244c..1d5132b 100644
--- a/cc/output/program_binding.h
+++ b/cc/output/program_binding.h
@@ -58,8 +58,24 @@
 
   void Initialize(ContextProvider* context_provider,
                   TexCoordPrecision precision,
+                  SamplerType sampler) {
+    return Initialize(
+        context_provider, precision, sampler, BLEND_MODE_NONE, false);
+  }
+
+  void Initialize(ContextProvider* context_provider,
+                  TexCoordPrecision precision,
                   SamplerType sampler,
-                  BlendMode blend_mode = BLEND_MODE_NONE) {
+                  BlendMode blend_mode) {
+    return Initialize(
+        context_provider, precision, sampler, blend_mode, false);
+  }
+
+  void Initialize(ContextProvider* context_provider,
+                  TexCoordPrecision precision,
+                  SamplerType sampler,
+                  BlendMode blend_mode,
+                  bool mask_for_background) {
     DCHECK(context_provider);
     DCHECK(!initialized_);
 
@@ -67,6 +83,7 @@
       return;
 
     fragment_shader_.set_blend_mode(blend_mode);
+    fragment_shader_.set_mask_for_background(mask_for_background);
 
     if (!ProgramBindingBase::Init(
             context_provider->ContextGL(),
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index 9e9175e..81ad842 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -2045,6 +2045,109 @@
       FuzzyPixelOffByOneComparator(true)));
 }
 
+TYPED_TEST(RendererPixelTest, Checkerboards) {
+  gfx::Rect rect(this->device_viewport_size_);
+
+  RenderPassId id(1, 1);
+  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
+
+  SharedQuadState* shared_state =
+      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
+
+  // The color's alpha value is not used.
+  SkColor color1 = SK_ColorGREEN;
+  color1 = SkColorSetA(color1, 0);
+  SkColor color2 = SK_ColorBLUE;
+  color2 = SkColorSetA(color2, 0);
+
+  gfx::Rect content_rect(rect);
+
+  gfx::Rect top_left(content_rect);
+  gfx::Rect top_right(content_rect);
+  gfx::Rect bottom_left(content_rect);
+  gfx::Rect bottom_right(content_rect);
+  // The format is Inset(left, top, right, bottom).
+  top_left.Inset(0, 0, content_rect.width() / 2, content_rect.height() / 2);
+  top_right.Inset(content_rect.width() / 2, 0, 0, content_rect.height() / 2);
+  bottom_left.Inset(0, content_rect.height() / 2, content_rect.width() / 2, 0);
+  bottom_right.Inset(content_rect.width() / 2, content_rect.height() / 2, 0, 0);
+
+  // Appends checkerboard quads with a scale of 1.
+  CheckerboardDrawQuad* quad =
+      pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, top_left, top_left, color1, 1.f);
+  quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, top_right, top_right, color2, 1.f);
+  quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, bottom_left, bottom_left, color2, 1.f);
+  quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, bottom_right, bottom_right, color1, 1.f);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  base::FilePath::StringType path =
+      IsSoftwareRenderer<TypeParam>()
+          ? FILE_PATH_LITERAL("four_blue_green_checkers.png")
+          : FILE_PATH_LITERAL("checkers.png");
+  EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(path),
+                                 ExactPixelComparator(true)));
+}
+
+TYPED_TEST(RendererPixelTest, CheckerboardsScaled) {
+  gfx::Rect rect(this->device_viewport_size_);
+
+  RenderPassId id(1, 1);
+  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
+
+  gfx::Transform scale;
+  scale.Scale(2.f, 2.f);
+
+  SharedQuadState* shared_state =
+      CreateTestSharedQuadState(scale, rect, pass.get());
+
+  // The color's alpha value is not used.
+  SkColor color1 = SK_ColorGREEN;
+  color1 = SkColorSetA(color1, 0);
+  SkColor color2 = SK_ColorBLUE;
+  color2 = SkColorSetA(color2, 0);
+
+  gfx::Rect content_rect(rect);
+  content_rect.Inset(0, 0, rect.width() / 2, rect.height() / 2);
+
+  gfx::Rect top_left(content_rect);
+  gfx::Rect top_right(content_rect);
+  gfx::Rect bottom_left(content_rect);
+  gfx::Rect bottom_right(content_rect);
+  // The format is Inset(left, top, right, bottom).
+  top_left.Inset(0, 0, content_rect.width() / 2, content_rect.height() / 2);
+  top_right.Inset(content_rect.width() / 2, 0, 0, content_rect.height() / 2);
+  bottom_left.Inset(0, content_rect.height() / 2, content_rect.width() / 2, 0);
+  bottom_right.Inset(content_rect.width() / 2, content_rect.height() / 2, 0, 0);
+
+  // Appends checkerboard quads with a scale of 2, and a shared quad state
+  // with a scale of 2. The checkers should be scaled by 2 * 2 = 4.
+  CheckerboardDrawQuad* quad =
+      pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, top_left, top_left, color1, 2.f);
+  quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, top_right, top_right, color2, 2.f);
+  quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, bottom_left, bottom_left, color2, 2.f);
+  quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+  quad->SetNew(shared_state, bottom_right, bottom_right, color1, 2.f);
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  base::FilePath::StringType path =
+      IsSoftwareRenderer<TypeParam>()
+          ? FILE_PATH_LITERAL("four_blue_green_checkers.png")
+          : FILE_PATH_LITERAL("checkers_big.png");
+  EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(path),
+                                 ExactPixelComparator(true)));
+}
+
 #endif  // !defined(OS_ANDROID)
 
 }  // namespace
diff --git a/cc/output/shader.cc b/cc/output/shader.cc
index 1891546..883b683 100644
--- a/cc/output/shader.cc
+++ b/cc/output/shader.cc
@@ -144,6 +144,9 @@
 
 }  // namespace
 
+ShaderLocations::ShaderLocations() {
+}
+
 TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
                                             int* highp_threshold_cache,
                                             int highp_threshold_min,
@@ -347,6 +350,12 @@
   });
 }
 
+void VertexShaderPosTexTransform::FillLocations(
+    ShaderLocations* locations) const {
+  locations->matrix = matrix_location();
+  locations->tex_transform = tex_transform_location();
+}
+
 std::string VertexShaderPosTexIdentity::GetShaderString() const {
   return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 }
@@ -560,6 +569,16 @@
   });
 }
 
+void VertexShaderQuadTexTransformAA::FillLocations(
+    ShaderLocations* locations) const {
+  locations->quad = quad_location();
+  locations->edge = edge_location();
+  locations->viewport = viewport_location();
+  locations->matrix = matrix_location();
+  locations->tex_transform = tex_transform_location();
+}
+
+
 VertexShaderTile::VertexShaderTile()
     : matrix_location_(-1),
       quad_location_(-1),
@@ -722,19 +741,24 @@
   });
 }
 
-#define BLEND_MODE_UNIFORMS "s_backdropTexture", "backdropRect"
-#define UNUSED_BLEND_MODE_UNIFORMS (!has_blend_mode() ? 2 : 0)
+#define BLEND_MODE_UNIFORMS "s_backdropTexture", \
+                            "s_originalBackdropTexture", \
+                            "backdropRect"
+#define UNUSED_BLEND_MODE_UNIFORMS (!has_blend_mode() ? 3 : 0)
 #define BLEND_MODE_SET_LOCATIONS(X, POS)                   \
   if (has_blend_mode()) {                                  \
-    DCHECK_LT(static_cast<size_t>(POS) + 1, arraysize(X)); \
+    DCHECK_LT(static_cast<size_t>(POS) + 2, arraysize(X)); \
     backdrop_location_ = locations[POS];                   \
-    backdrop_rect_location_ = locations[POS + 1];          \
+    original_backdrop_location_ = locations[POS + 1];      \
+    backdrop_rect_location_ = locations[POS + 2];          \
   }
 
 FragmentTexBlendMode::FragmentTexBlendMode()
     : backdrop_location_(-1),
+      original_backdrop_location_(-1),
       backdrop_rect_location_(-1),
-      blend_mode_(BLEND_MODE_NONE) {
+      blend_mode_(BLEND_MODE_NONE),
+      mask_for_background_(false) {
 }
 
 std::string FragmentTexBlendMode::SetBlendModeFunctions(
@@ -743,28 +767,50 @@
     return shader_string;
 
   if (!has_blend_mode()) {
-    return "#define ApplyBlendMode(X) (X)\n" + shader_string;
+    return "#define ApplyBlendMode(X, Y) (X)\n" + shader_string;
+  }
+
+  static const std::string kUniforms = SHADER0([]() {
+    uniform sampler2D s_backdropTexture;
+    uniform sampler2D s_originalBackdropTexture;
+    uniform TexCoordPrecision vec4 backdropRect;
+  });
+
+  std::string mixFunction;
+  if (mask_for_background()) {
+    mixFunction = SHADER0([]() {
+      vec4 MixBackdrop(TexCoordPrecision vec2 bgTexCoord, float mask) {
+        vec4 backdrop = texture2D(s_backdropTexture, bgTexCoord);
+        vec4 original_backdrop =
+            texture2D(s_originalBackdropTexture, bgTexCoord);
+        return mix(original_backdrop, backdrop, mask);
+      }
+    });
+  } else {
+    mixFunction = SHADER0([]() {
+      vec4 MixBackdrop(TexCoordPrecision vec2 bgTexCoord, float mask) {
+        return texture2D(s_backdropTexture, bgTexCoord);
+      }
+    });
   }
 
   static const std::string kFunctionApplyBlendMode = SHADER0([]() {
-    uniform sampler2D s_backdropTexture;
-    uniform TexCoordPrecision vec4 backdropRect;
-
-    vec4 GetBackdropColor() {
+    vec4 GetBackdropColor(float mask) {
       TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
       bgTexCoord.x /= backdropRect.z;
       bgTexCoord.y /= backdropRect.w;
-      return texture2D(s_backdropTexture, bgTexCoord);
+      return MixBackdrop(bgTexCoord, mask);
     }
 
-    vec4 ApplyBlendMode(vec4 src) {
-      vec4 dst = GetBackdropColor();
+    vec4 ApplyBlendMode(vec4 src, float mask) {
+      vec4 dst = GetBackdropColor(mask);
       return Blend(src, dst);
     }
   });
 
   return "precision mediump float;" + GetHelperFunctions() +
-         GetBlendFunction() + kFunctionApplyBlendMode + shader_string;
+         GetBlendFunction() + kUniforms + mixFunction +
+         kFunctionApplyBlendMode + shader_string;
 }
 
 std::string FragmentTexBlendMode::GetHelperFunctions() const {
@@ -1100,11 +1146,19 @@
   return SHADER0([]() {
     void main() {
       vec4 texColor = TextureLookup(s_texture, v_texCoord);
-      gl_FragColor = ApplyBlendMode(texColor * alpha);
+      gl_FragColor = ApplyBlendMode(texColor * alpha, 0.0);
     }
   });
 }
 
+void FragmentShaderRGBATexAlpha::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->alpha = alpha_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+}
+
 std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString(
     TexCoordPrecision precision,
     SamplerType sampler) const {
@@ -1131,11 +1185,21 @@
       texColor = colorMatrix * texColor + colorOffset;
       texColor.rgb *= texColor.a;
       texColor = clamp(texColor, 0.0, 1.0);
-      gl_FragColor = ApplyBlendMode(texColor * alpha);
+      gl_FragColor = ApplyBlendMode(texColor * alpha, 0.0);
     }
   });
 }
 
+void FragmentShaderRGBATexColorMatrixAlpha::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->alpha = alpha_location();
+  locations->color_matrix = color_matrix_location();
+  locations->color_offset = color_offset_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+}
+
 std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
     TexCoordPrecision precision,
     SamplerType sampler) const {
@@ -1400,11 +1464,19 @@
       vec4 d4 = min(edge_dist[0], edge_dist[1]);
       vec2 d2 = min(d4.xz, d4.yw);
       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-      gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
+      gl_FragColor = ApplyBlendMode(texColor * alpha * aa, 0.0);
     }
   });
 }
 
+void FragmentShaderRGBATexAlphaAA::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->alpha = alpha_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+}
+
 FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding()
     : sampler_location_(-1),
       alpha_location_(-1),
@@ -1555,11 +1627,25 @@
           vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
       vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
-      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
+      gl_FragColor = ApplyBlendMode(
+          texColor * alpha * maskColor.w, maskColor.w);
     }
   });
 }
 
+void FragmentShaderRGBATexAlphaMask::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->mask_sampler = mask_sampler_location();
+  locations->mask_tex_coord_scale = mask_tex_coord_scale_location();
+  locations->mask_tex_coord_offset = mask_tex_coord_offset_location();
+  locations->alpha = alpha_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+  if (mask_for_background())
+    locations->original_backdrop = original_backdrop_location();
+}
+
 FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA()
     : sampler_location_(-1),
       mask_sampler_location_(-1),
@@ -1625,11 +1711,25 @@
       vec4 d4 = min(edge_dist[0], edge_dist[1]);
       vec2 d2 = min(d4.xz, d4.yw);
       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
+      gl_FragColor = ApplyBlendMode(
+          texColor * alpha * maskColor.w * aa, maskColor.w);
     }
   });
 }
 
+void FragmentShaderRGBATexAlphaMaskAA::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->mask_sampler = mask_sampler_location();
+  locations->mask_tex_coord_scale = mask_tex_coord_scale_location();
+  locations->mask_tex_coord_offset = mask_tex_coord_offset_location();
+  locations->alpha = alpha_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+  if (mask_for_background())
+    locations->original_backdrop = original_backdrop_location();
+}
+
 FragmentShaderRGBATexAlphaMaskColorMatrixAA::
     FragmentShaderRGBATexAlphaMaskColorMatrixAA()
     : sampler_location_(-1),
@@ -1709,11 +1809,27 @@
       vec4 d4 = min(edge_dist[0], edge_dist[1]);
       vec2 d2 = min(d4.xz, d4.yw);
       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
+      gl_FragColor = ApplyBlendMode(
+          texColor * alpha * maskColor.w * aa, maskColor.w);
     }
   });
 }
 
+void FragmentShaderRGBATexAlphaMaskColorMatrixAA::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->alpha = alpha_location();
+  locations->mask_sampler = mask_sampler_location();
+  locations->mask_tex_coord_scale = mask_tex_coord_scale_location();
+  locations->mask_tex_coord_offset = mask_tex_coord_offset_location();
+  locations->color_matrix = color_matrix_location();
+  locations->color_offset = color_offset_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+  if (mask_for_background())
+    locations->original_backdrop = original_backdrop_location();
+}
+
 FragmentShaderRGBATexAlphaColorMatrixAA::
     FragmentShaderRGBATexAlphaColorMatrixAA()
     : sampler_location_(-1),
@@ -1773,11 +1889,21 @@
       vec4 d4 = min(edge_dist[0], edge_dist[1]);
       vec2 d2 = min(d4.xz, d4.yw);
       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
-      gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
+      gl_FragColor = ApplyBlendMode(texColor * alpha * aa, 0.0);
     }
   });
 }
 
+void FragmentShaderRGBATexAlphaColorMatrixAA::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->alpha = alpha_location();
+  locations->color_matrix = color_matrix_location();
+  locations->color_offset = color_offset_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+}
+
 FragmentShaderRGBATexAlphaMaskColorMatrix::
     FragmentShaderRGBATexAlphaMaskColorMatrix()
     : sampler_location_(-1),
@@ -1850,11 +1976,27 @@
           vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
       vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
-      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
+      gl_FragColor = ApplyBlendMode(
+          texColor * alpha * maskColor.w, maskColor.w);
     }
   });
 }
 
+void FragmentShaderRGBATexAlphaMaskColorMatrix::FillLocations(
+    ShaderLocations* locations) const {
+  locations->sampler = sampler_location();
+  locations->mask_sampler = mask_sampler_location();
+  locations->mask_tex_coord_scale = mask_tex_coord_scale_location();
+  locations->mask_tex_coord_offset = mask_tex_coord_offset_location();
+  locations->alpha = alpha_location();
+  locations->color_matrix = color_matrix_location();
+  locations->color_offset = color_offset_location();
+  locations->backdrop = backdrop_location();
+  locations->backdrop_rect = backdrop_rect_location();
+  if (mask_for_background())
+    locations->original_backdrop = original_backdrop_location();
+}
+
 FragmentShaderYUVVideo::FragmentShaderYUVVideo()
     : y_texture_location_(-1),
       u_texture_location_(-1),
diff --git a/cc/output/shader.h b/cc/output/shader.h
index 93407d4..561fe28 100644
--- a/cc/output/shader.h
+++ b/cc/output/shader.h
@@ -59,6 +59,32 @@
   LAST_BLEND_MODE = BLEND_MODE_LUMINOSITY
 };
 
+enum MaskMode {
+  NO_MASK = 0,
+  HAS_MASK = 1,
+  LAST_MASK_VALUE = HAS_MASK
+};
+
+struct ShaderLocations {
+  ShaderLocations();
+
+  int sampler = -1;
+  int quad = -1;
+  int edge = -1;
+  int viewport = -1;
+  int mask_sampler = -1;
+  int mask_tex_coord_scale = -1;
+  int mask_tex_coord_offset = -1;
+  int matrix = -1;
+  int alpha = -1;
+  int color_matrix = -1;
+  int color_offset = -1;
+  int tex_transform = -1;
+  int backdrop = -1;
+  int backdrop_rect = -1;
+  int original_backdrop = -1;
+};
+
 // Note: The highp_threshold_cache must be provided by the caller to make
 // the caching multi-thread/context safe in an easy low-overhead manner.
 // The caller must make sure to clear highp_threshold_cache to 0, so it can be
@@ -156,6 +182,7 @@
   std::string GetShaderString() const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
+  void FillLocations(ShaderLocations* locations) const;
 
   int matrix_location() const { return matrix_location_; }
   int tex_transform_location() const { return tex_transform_location_; }
@@ -228,6 +255,7 @@
   std::string GetShaderString() const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
+  void FillLocations(ShaderLocations* locations) const;
 
   int matrix_location() const { return matrix_location_; }
   int viewport_location() const { return viewport_location_; }
@@ -325,11 +353,16 @@
 class FragmentTexBlendMode {
  public:
   int backdrop_location() const { return backdrop_location_; }
+  int original_backdrop_location() const { return original_backdrop_location_; }
   int backdrop_rect_location() const { return backdrop_rect_location_; }
 
   BlendMode blend_mode() const { return blend_mode_; }
   void set_blend_mode(BlendMode blend_mode) { blend_mode_ = blend_mode; }
   bool has_blend_mode() const { return blend_mode_ != BLEND_MODE_NONE; }
+  void set_mask_for_background(bool mask_for_background) {
+    mask_for_background_ = mask_for_background;
+  }
+  bool mask_for_background() const { return mask_for_background_; }
 
  protected:
   FragmentTexBlendMode();
@@ -337,10 +370,12 @@
   std::string SetBlendModeFunctions(std::string shader_string) const;
 
   int backdrop_location_;
+  int original_backdrop_location_;
   int backdrop_rect_location_;
 
  private:
   BlendMode blend_mode_;
+  bool mask_for_background_;
 
   std::string GetHelperFunctions() const;
   std::string GetBlendFunction() const;
@@ -460,6 +495,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
+  void FillLocations(ShaderLocations* locations) const;
 };
 
 class FragmentShaderRGBATexColorMatrixAlpha
@@ -469,6 +505,7 @@
                               SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
+  void FillLocations(ShaderLocations* locations) const;
 };
 
 class FragmentShaderRGBATexOpaque : public FragmentTexOpaqueBinding {
@@ -516,6 +553,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
+  void FillLocations(ShaderLocations* locations) const;
 
   int alpha_location() const { return alpha_location_; }
   int sampler_location() const { return sampler_location_; }
@@ -574,7 +612,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
-
+  void FillLocations(ShaderLocations* locations) const;
   void Init(gpu::gles2::GLES2Interface* context,
             unsigned program,
             int* base_uniform_index);
@@ -605,7 +643,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
-
+  void FillLocations(ShaderLocations* locations) const;
   void Init(gpu::gles2::GLES2Interface* context,
             unsigned program,
             int* base_uniform_index);
@@ -637,7 +675,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
-
+  void FillLocations(ShaderLocations* locations) const;
   void Init(gpu::gles2::GLES2Interface* context,
             unsigned program,
             int* base_uniform_index);
@@ -670,7 +708,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
-
+  void FillLocations(ShaderLocations* locations) const;
   void Init(gpu::gles2::GLES2Interface* context,
             unsigned program,
             int* base_uniform_index);
@@ -693,7 +731,7 @@
       TexCoordPrecision precision, SamplerType sampler) const;
   static std::string GetShaderHead();
   static std::string GetShaderBody();
-
+  void FillLocations(ShaderLocations* locations) const;
   void Init(gpu::gles2::GLES2Interface* context,
             unsigned program,
             int* base_uniform_index);
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index 5360d59..a4b5428 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -314,7 +314,7 @@
   gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
       QuadVertexRect(), quad->rect, quad->visible_rect);
   current_paint_.setColor(quad->color);
-  current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color));
+  current_paint_.setAlpha(quad->opacity());
   current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect),
                             current_paint_);
 }
diff --git a/cc/quads/checkerboard_draw_quad.cc b/cc/quads/checkerboard_draw_quad.cc
index 2d8957d..db6ad1e 100644
--- a/cc/quads/checkerboard_draw_quad.cc
+++ b/cc/quads/checkerboard_draw_quad.cc
@@ -10,17 +10,20 @@
 
 namespace cc {
 
-CheckerboardDrawQuad::CheckerboardDrawQuad() : color(0) {}
+CheckerboardDrawQuad::CheckerboardDrawQuad() : color(0), scale(0.f) {
+}
 
 void CheckerboardDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
                                   const gfx::Rect& rect,
                                   const gfx::Rect& visible_rect,
-                                  SkColor color) {
+                                  SkColor color,
+                                  float scale) {
   gfx::Rect opaque_rect = SkColorGetA(color) == 255 ? rect : gfx::Rect();
   bool needs_blending = false;
   DrawQuad::SetAll(shared_quad_state, DrawQuad::CHECKERBOARD, rect, opaque_rect,
                    visible_rect, needs_blending);
   this->color = color;
+  this->scale = scale;
 }
 
 void CheckerboardDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
@@ -28,10 +31,12 @@
                                   const gfx::Rect& opaque_rect,
                                   const gfx::Rect& visible_rect,
                                   bool needs_blending,
-                                  SkColor color) {
+                                  SkColor color,
+                                  float scale) {
   DrawQuad::SetAll(shared_quad_state, DrawQuad::CHECKERBOARD, rect, opaque_rect,
                    visible_rect, needs_blending);
   this->color = color;
+  this->scale = scale;
 }
 
 void CheckerboardDrawQuad::IterateResources(
@@ -46,6 +51,7 @@
 void CheckerboardDrawQuad::ExtendValue(
     base::trace_event::TracedValue* value) const {
   value->SetInteger("color", color);
+  value->SetDouble("scale", scale);
 }
 
 }  // namespace cc
diff --git a/cc/quads/checkerboard_draw_quad.h b/cc/quads/checkerboard_draw_quad.h
index 1ab6338..9ecf4f0 100644
--- a/cc/quads/checkerboard_draw_quad.h
+++ b/cc/quads/checkerboard_draw_quad.h
@@ -19,16 +19,19 @@
   void SetNew(const SharedQuadState* shared_quad_state,
               const gfx::Rect& rect,
               const gfx::Rect& visible_rect,
-              SkColor color);
+              SkColor color,
+              float scale);
 
   void SetAll(const SharedQuadState* shared_quad_state,
               const gfx::Rect& rect,
               const gfx::Rect& opaque_rect,
               const gfx::Rect& visible_rect,
               bool needs_blending,
-              SkColor color);
+              SkColor color,
+              float scale);
 
   SkColor color;
+  float scale;
 
   void IterateResources(const ResourceIteratorCallback& callback) override;
 
diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc
index b7c1bdf..5b5f0b9 100644
--- a/cc/quads/draw_quad_unittest.cc
+++ b/cc/quads/draw_quad_unittest.cc
@@ -369,16 +369,19 @@
 TEST(DrawQuadTest, CopyCheckerboardDrawQuad) {
   gfx::Rect visible_rect(40, 50, 30, 20);
   SkColor color = 0xfabb0011;
+  float scale = 2.3f;
   CREATE_SHARED_STATE();
 
-  CREATE_QUAD_2_NEW(CheckerboardDrawQuad, visible_rect, color);
+  CREATE_QUAD_3_NEW(CheckerboardDrawQuad, visible_rect, color, scale);
   EXPECT_EQ(DrawQuad::CHECKERBOARD, copy_quad->material);
   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
   EXPECT_EQ(color, copy_quad->color);
+  EXPECT_EQ(scale, copy_quad->scale);
 
-  CREATE_QUAD_1_ALL(CheckerboardDrawQuad, color);
+  CREATE_QUAD_2_ALL(CheckerboardDrawQuad, color, scale);
   EXPECT_EQ(DrawQuad::CHECKERBOARD, copy_quad->material);
   EXPECT_EQ(color, copy_quad->color);
+  EXPECT_EQ(scale, copy_quad->scale);
 }
 
 TEST(DrawQuadTest, CopyDebugBorderDrawQuad) {
@@ -736,9 +739,10 @@
 TEST_F(DrawQuadIteratorTest, CheckerboardDrawQuad) {
   gfx::Rect visible_rect(40, 50, 30, 20);
   SkColor color = 0xfabb0011;
+  float scale = 3.2f;
 
   CREATE_SHARED_STATE();
-  CREATE_QUAD_2_NEW(CheckerboardDrawQuad, visible_rect, color);
+  CREATE_QUAD_3_NEW(CheckerboardDrawQuad, visible_rect, color, scale);
   EXPECT_EQ(0, IterateAndCount(quad_new));
 }
 
diff --git a/cc/quads/render_pass_unittest.cc b/cc/quads/render_pass_unittest.cc
index 8775d81..e6f39bc 100644
--- a/cc/quads/render_pass_unittest.cc
+++ b/cc/quads/render_pass_unittest.cc
@@ -92,8 +92,8 @@
 
   CheckerboardDrawQuad* checkerboard_quad =
       pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
-  checkerboard_quad->SetNew(
-      pass->shared_quad_state_list.back(), gfx::Rect(), gfx::Rect(), SkColor());
+  checkerboard_quad->SetNew(pass->shared_quad_state_list.back(), gfx::Rect(),
+                            gfx::Rect(), SkColor(), 1.f);
 
   RenderPassId new_id(63, 4);
 
@@ -143,16 +143,14 @@
   CheckerboardDrawQuad* checkerboard_quad1 =
       pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
   checkerboard_quad1->SetNew(pass->shared_quad_state_list.back(),
-                             gfx::Rect(1, 1, 1, 1),
-                             gfx::Rect(1, 1, 1, 1),
-                             SkColor());
+                             gfx::Rect(1, 1, 1, 1), gfx::Rect(1, 1, 1, 1),
+                             SkColor(), 1.f);
 
   CheckerboardDrawQuad* checkerboard_quad2 =
       pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
   checkerboard_quad2->SetNew(pass->shared_quad_state_list.back(),
-                             gfx::Rect(2, 2, 2, 2),
-                             gfx::Rect(2, 2, 2, 2),
-                             SkColor());
+                             gfx::Rect(2, 2, 2, 2), gfx::Rect(2, 2, 2, 2),
+                             SkColor(), 1.f);
 
   // And two quads using another shared state.
   SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
@@ -168,16 +166,14 @@
   CheckerboardDrawQuad* checkerboard_quad3 =
       pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
   checkerboard_quad3->SetNew(pass->shared_quad_state_list.back(),
-                             gfx::Rect(3, 3, 3, 3),
-                             gfx::Rect(3, 3, 3, 3),
-                             SkColor());
+                             gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3),
+                             SkColor(), 1.f);
 
   CheckerboardDrawQuad* checkerboard_quad4 =
       pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
   checkerboard_quad4->SetNew(pass->shared_quad_state_list.back(),
-                             gfx::Rect(4, 4, 4, 4),
-                             gfx::Rect(4, 4, 4, 4),
-                             SkColor());
+                             gfx::Rect(4, 4, 4, 4), gfx::Rect(4, 4, 4, 4),
+                             SkColor(), 1.f);
 
   // A second render pass with a quad.
   RenderPassId contrib_id(4, 1);
@@ -208,9 +204,8 @@
   CheckerboardDrawQuad* contrib_quad =
       contrib->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
   contrib_quad->SetNew(contrib->shared_quad_state_list.back(),
-                       gfx::Rect(3, 3, 3, 3),
-                       gfx::Rect(3, 3, 3, 3),
-                       SkColor());
+                       gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3), SkColor(),
+                       1.f);
 
   // And a RenderPassDrawQuad for the contributing pass.
   scoped_ptr<RenderPassDrawQuad> pass_quad =
@@ -267,9 +262,8 @@
   CheckerboardDrawQuad* checkerboard_quad1 =
       pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
   checkerboard_quad1->SetNew(pass->shared_quad_state_list.back(),
-                             gfx::Rect(1, 1, 1, 1),
-                             gfx::Rect(1, 1, 1, 1),
-                             SkColor());
+                             gfx::Rect(1, 1, 1, 1), gfx::Rect(1, 1, 1, 1),
+                             SkColor(), 1.f);
 
   // A shared state with no quads, they were culled.
   SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
@@ -307,9 +301,8 @@
   CheckerboardDrawQuad* checkerboard_quad2 =
       pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
   checkerboard_quad2->SetNew(pass->shared_quad_state_list.back(),
-                             gfx::Rect(3, 3, 3, 3),
-                             gfx::Rect(3, 3, 3, 3),
-                             SkColor());
+                             gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3),
+                             SkColor(), 1.f);
 
   pass_list.push_back(pass.Pass());
 
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc
index 517f49f..8d2dc3e 100644
--- a/cc/resources/display_list_recording_source.cc
+++ b/cc/resources/display_list_recording_source.cc
@@ -115,6 +115,10 @@
   return true;
 }
 
+void DisplayListRecordingSource::DidMoveToNewCompositor() {
+  // No invalidation history to worry about here.
+}
+
 gfx::Size DisplayListRecordingSource::GetSize() const {
   return size_;
 }
diff --git a/cc/resources/display_list_recording_source.h b/cc/resources/display_list_recording_source.h
index 1e713e1..e827d29 100644
--- a/cc/resources/display_list_recording_source.h
+++ b/cc/resources/display_list_recording_source.h
@@ -24,6 +24,7 @@
                                    const gfx::Rect& visible_layer_rect,
                                    int frame_number,
                                    RecordingMode recording_mode) override;
+  void DidMoveToNewCompositor() override;
   scoped_refptr<RasterSource> CreateRasterSource(
       bool can_use_lcd_text) const override;
   gfx::Size GetSize() const final;
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index cf5e59b..30c5845 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -287,7 +287,7 @@
 }
 
 int Picture::Raster(SkCanvas* canvas,
-                    SkDrawPictureCallback* callback,
+                    SkPicture::AbortCallback* callback,
                     const Region& negated_content_region,
                     float contents_scale) const {
   TRACE_EVENT_BEGIN1(
@@ -323,10 +323,10 @@
   return bounds.width() * bounds.height();
 }
 
-void Picture::Replay(SkCanvas* canvas) {
+void Picture::Replay(SkCanvas* canvas, SkPicture::AbortCallback* callback) {
   TRACE_EVENT_BEGIN0("cc", "Picture::Replay");
   DCHECK(picture_);
-  picture_->playback(canvas);
+  picture_->playback(canvas, callback);
   SkIRect bounds;
   canvas->getClipDeviceBounds(&bounds);
   TRACE_EVENT_END1("cc", "Picture::Replay",
diff --git a/cc/resources/picture.h b/cc/resources/picture.h
index 81c9c53..089838c 100644
--- a/cc/resources/picture.h
+++ b/cc/resources/picture.h
@@ -23,7 +23,6 @@
 #include "third_party/skia/include/core/SkPicture.h"
 #include "ui/gfx/geometry/rect.h"
 
-class SkDrawPictureCallback;
 class SkPixelRef;
 
 namespace base {
@@ -70,13 +69,13 @@
   // raster operation, i.e., the parts of the canvas which will not get drawn
   // to.
   int Raster(SkCanvas* canvas,
-             SkDrawPictureCallback* callback,
+             SkPicture::AbortCallback* callback,
              const Region& negated_content_region,
              float contents_scale) const;
 
   // Draw the picture directly into the given canvas, without applying any
   // clip/scale/layer transformations.
-  void Replay(SkCanvas* canvas);
+  void Replay(SkCanvas* canvas, SkPicture::AbortCallback* callback = NULL);
 
   scoped_ptr<base::Value> AsValue() const;
 
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index d931543..bd150f4 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -53,48 +53,53 @@
 PictureLayerTilingSet::~PictureLayerTilingSet() {
 }
 
+void PictureLayerTilingSet::CopyTilingsFromPendingTwin(
+    const PictureLayerTilingSet* pending_twin_set,
+    const scoped_refptr<RasterSource>& raster_source) {
+  if (pending_twin_set->tilings_.empty()) {
+    // If the twin (pending) tiling set is empty, it was not updated for the
+    // current frame. So we drop tilings from our set as well, instead of
+    // leaving behind unshared tilings that are all non-ideal.
+    RemoveAllTilings();
+  }
+
+  for (PictureLayerTiling* pending_twin_tiling : pending_twin_set->tilings_) {
+    float contents_scale = pending_twin_tiling->contents_scale();
+    PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale);
+    if (!this_tiling) {
+      scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
+          contents_scale, raster_source, client_, max_tiles_for_interest_area_,
+          skewport_target_time_in_seconds_,
+          skewport_extrapolation_limit_in_content_pixels_);
+      tilings_.push_back(new_tiling.Pass());
+      this_tiling = tilings_.back();
+    }
+    this_tiling->CloneTilesAndPropertiesFrom(*pending_twin_tiling);
+  }
+}
+
 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSource(
     scoped_refptr<RasterSource> raster_source,
-    const PictureLayerTilingSet* twin_set,
+    const PictureLayerTilingSet* pending_twin_set,
     const Region& layer_invalidation,
     float minimum_contents_scale,
     float maximum_contents_scale) {
   RemoveTilingsBelowScale(minimum_contents_scale);
   RemoveTilingsAboveScale(maximum_contents_scale);
 
-  // Copy over tilings that are shared with the |twin_set| tiling set (if it
-  // exists).
-  if (twin_set) {
-    if (twin_set->tilings_.empty()) {
-      // If the twin (pending) tiling set is empty, it was not updated for the
-      // current frame. So we drop tilings from our set as well, instead of
-      // leaving behind unshared tilings that are all non-ideal.
-      RemoveAllTilings();
-    }
+  // Copy over tilings that are shared with the |pending_twin_set| tiling set
+  // (if it exists).
+  if (pending_twin_set)
+    CopyTilingsFromPendingTwin(pending_twin_set, raster_source);
 
-    for (PictureLayerTiling* twin_tiling : twin_set->tilings_) {
-      float contents_scale = twin_tiling->contents_scale();
-      DCHECK_GE(contents_scale, minimum_contents_scale);
-      DCHECK_LE(contents_scale, maximum_contents_scale);
-
-      PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale);
-      if (!this_tiling) {
-        scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
-            contents_scale, raster_source, client_,
-            max_tiles_for_interest_area_, skewport_target_time_in_seconds_,
-            skewport_extrapolation_limit_in_content_pixels_);
-        tilings_.push_back(new_tiling.Pass());
-        this_tiling = tilings_.back();
-      }
-      this_tiling->CloneTilesAndPropertiesFrom(*twin_tiling);
-    }
-  }
-
-  // For unshared tilings, invalidate tiles and update them to the new raster
-  // source.
+  // If the tiling is not shared (FindTilingWithScale returns nullptr) or if
+  // |this| is the sync set (pending_twin_set is nullptr), then invalidate
+  // tiles and update them to the new raster source.
   for (PictureLayerTiling* tiling : tilings_) {
-    if (twin_set && twin_set->FindTilingWithScale(tiling->contents_scale()))
+    if (pending_twin_set &&
+        pending_twin_set->FindTilingWithScale(tiling->contents_scale())) {
       continue;
+    }
 
     tiling->SetRasterSourceAndResize(raster_source);
     tiling->Invalidate(layer_invalidation);
@@ -104,9 +109,9 @@
     // raster source.
     tiling->CreateMissingTilesInLiveTilesRect();
 
-    // If |twin_set| is present, use the resolutions from there. Otherwise leave
-    // all resolutions as they are.
-    if (twin_set)
+    // If |pending_twin_set| is present, then |this| is active and |tiling| is
+    // not in the pending set, which means it is now NON_IDEAL_RESOLUTION.
+    if (pending_twin_set)
       tiling->set_resolution(NON_IDEAL_RESOLUTION);
   }
 
@@ -126,11 +131,12 @@
     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) {
+    if (pending_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()
+          << " num tilings on pending: " << pending_twin_set->tilings_.size()
+          << " num high res on pending: "
+          << pending_twin_set->NumHighResTilings()
           << " are on active tree: " << (client_->GetTree() == ACTIVE_TREE);
     }
   }
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index fc1e581..a4c2fd8 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -55,9 +55,15 @@
                       PictureLayerTilingSet* recycled_twin_set);
   void RemoveNonIdealTilings();
 
+  // This function can be called on both the active and pending tree.
+  // |pending_twin_set| represents the current pending twin. In situations where
+  // this is called on the active tree in two trees situations,
+  // |pending_twin_set| represents the tiling set from the pending twin layer.
+  // In situations where this is called on the sync tree (whether it's pending
+  // or active in cases of one tree), |pending_twin_set| should be nullptr.
   void UpdateTilingsToCurrentRasterSource(
       scoped_refptr<RasterSource> raster_source,
-      const PictureLayerTilingSet* twin_set,
+      const PictureLayerTilingSet* pending_twin_set,
       const Region& layer_invalidation,
       float minimum_contents_scale,
       float maximum_contents_scale);
@@ -163,6 +169,10 @@
       float skewport_target_time_in_seconds,
       int skewport_extrapolation_limit_in_content_pixels);
 
+  void CopyTilingsFromPendingTwin(
+      const PictureLayerTilingSet* pending_twin_set,
+      const scoped_refptr<RasterSource>& raster_source);
+
   // Remove one tiling.
   void Remove(PictureLayerTiling* tiling);
 
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index 2b15aea..04e0801 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -214,6 +214,11 @@
   return true;
 }
 
+void PicturePile::DidMoveToNewCompositor() {
+  for (auto& map_pair : picture_map_)
+    map_pair.second.ResetInvalidationHistory();
+}
+
 bool PicturePile::ApplyInvalidationAndResize(const gfx::Rect& interest_rect,
                                              Region* invalidation,
                                              const gfx::Size& layer_size,
@@ -747,6 +752,11 @@
           (GetInvalidationFrequency() < kInvalidationFrequencyThreshold));
 }
 
+void PicturePile::PictureInfo::ResetInvalidationHistory() {
+  invalidation_history_.reset();
+  last_frame_number_ = 0;
+}
+
 void PicturePile::SetBufferPixels(int new_buffer_pixels) {
   if (new_buffer_pixels == buffer_pixels())
     return;
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index bab06c8..bdba579 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -29,6 +29,7 @@
                                    const gfx::Rect& visible_layer_rect,
                                    int frame_number,
                                    RecordingMode recording_mode) override;
+  void DidMoveToNewCompositor() override;
   scoped_refptr<RasterSource> CreateRasterSource(
       bool can_use_lcd_text) const override;
   gfx::Size GetSize() const final;
@@ -57,6 +58,8 @@
       return GetInvalidationFrequency();
     }
 
+    void ResetInvalidationHistory();
+
    private:
     void AdvanceInvalidationHistory(int frame_number);
     float GetInvalidationFrequency() const;
diff --git a/cc/resources/recording_source.h b/cc/resources/recording_source.h
index fdd8eb4..a202e63 100644
--- a/cc/resources/recording_source.h
+++ b/cc/resources/recording_source.h
@@ -39,6 +39,8 @@
                                            int frame_number,
                                            RecordingMode recording_mode) = 0;
 
+  virtual void DidMoveToNewCompositor() = 0;
+
   virtual scoped_refptr<RasterSource> CreateRasterSource(
       bool can_use_lcd_text) const = 0;
 
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 115238f..25f6597 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -898,11 +898,9 @@
 
     GLES2Interface* gl = ContextGL();
     DCHECK(gl);
-    resource->gl_id = texture_id_allocator_->NextId();
-    GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
-    GLC(gl,
-        gl->ConsumeTextureCHROMIUM(resource->mailbox.target(),
-                                   resource->mailbox.name()));
+    resource->gl_id =
+        GLC(gl, gl->CreateAndConsumeTextureCHROMIUM(resource->mailbox.target(),
+                                                    resource->mailbox.name()));
   }
 
   if (!resource->pixels && resource->has_shared_bitmap_id &&
@@ -1595,9 +1593,6 @@
     LazyCreate(source);
     DCHECK(source->gl_id);
     DCHECK(source->origin == Resource::INTERNAL);
-    GLC(gl,
-        gl->BindTexture(resource->mailbox_holder.texture_target,
-                        source->gl_id));
     if (source->image_id) {
       DCHECK(source->dirty_image);
       BindImageForSampling(source);
@@ -1605,9 +1600,10 @@
     // This is a resource allocated by the compositor, we need to produce it.
     // Don't set a sync point, the caller will do it.
     GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name));
-    GLC(gl,
-        gl->ProduceTextureCHROMIUM(resource->mailbox_holder.texture_target,
-                                   resource->mailbox_holder.mailbox.name));
+    GLC(gl, gl->ProduceTextureDirectCHROMIUM(
+                source->gl_id, resource->mailbox_holder.texture_target,
+                resource->mailbox_holder.mailbox.name));
+
     source->mailbox = TextureMailbox(resource->mailbox_holder);
   } else {
     DCHECK(source->mailbox.IsTexture());
@@ -2107,15 +2103,11 @@
   }
   DCHECK(!dest_resource->image_id);
   dest_resource->allocated = true;
-  gl->CopyTextureCHROMIUM(dest_resource->target,
-                          source_resource->gl_id,
-                          dest_resource->gl_id,
-                          0,
-                          GLInternalFormat(dest_resource->format),
-                          GLDataType(dest_resource->format));
+  gl->CopySubTextureCHROMIUM(dest_resource->target, source_resource->gl_id,
+                             dest_resource->gl_id, 0, 0);
   if (source_resource->gl_read_lock_query_id) {
     // End query and create a read lock fence that will prevent access to
-    // source resource until CopyTextureCHROMIUM command has completed.
+// source resource until CopySubTextureCHROMIUM command has completed.
 #if defined(OS_CHROMEOS)
     gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
 #else
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index fdd7fc0..24b91bf 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -97,10 +97,10 @@
   MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
   MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
   MOCK_METHOD0(insertSyncPoint, GLuint(void));
-  MOCK_METHOD2(produceTextureCHROMIUM,
-               void(GLenum target, const GLbyte* mailbox));
-  MOCK_METHOD2(consumeTextureCHROMIUM,
-               void(GLenum target, const GLbyte* mailbox));
+  MOCK_METHOD3(produceTextureDirectCHROMIUM,
+               void(GLuint texture, GLenum target, const GLbyte* mailbox));
+  MOCK_METHOD2(createAndConsumeTextureCHROMIUM,
+               unsigned(GLenum target, const GLbyte* mailbox));
 
   // Force all textures to be consecutive numbers starting at "1",
   // so we easily can test for them.
@@ -258,25 +258,27 @@
     return shared_data_->GenMailbox(mailbox);
   }
 
-  void produceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
-    CheckTextureIsBound(target);
-
+  void produceTextureDirectCHROMIUM(GLuint texture,
+                                    GLenum target,
+                                    const GLbyte* mailbox) override {
     // Delay moving the texture into the mailbox until the next
     // InsertSyncPoint, so that it is not visible to other contexts that
     // haven't waited on that sync point.
     scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
     memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
     base::AutoLock lock_for_texture_access(namespace_->lock);
-    pending->texture = BoundTexture(target);
+    pending->texture = UnboundTexture(texture);
     pending_produce_textures_.push_back(pending.Pass());
   }
 
-  void consumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
-    CheckTextureIsBound(target);
+  GLuint createAndConsumeTextureCHROMIUM(GLenum target,
+                                         const GLbyte* mailbox) override {
+    GLuint texture_id = createTexture();
     base::AutoLock lock_for_texture_access(namespace_->lock);
     scoped_refptr<TestTexture> texture =
         shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
-    namespace_->textures.Replace(BoundTextureId(target), texture);
+    namespace_->textures.Replace(texture_id, texture);
+    return texture_id;
   }
 
   void GetPixels(const gfx::Size& size,
@@ -461,9 +463,9 @@
     if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
       unsigned texture = child_context_->createTexture();
       gpu::Mailbox gpu_mailbox;
-      child_context_->bindTexture(GL_TEXTURE_2D, texture);
       child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
-      child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
+      child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
+                                                   gpu_mailbox.name);
       *sync_point = child_context_->insertSyncPoint();
       EXPECT_LT(0u, *sync_point);
 
@@ -666,12 +668,11 @@
   }
 
   GLuint external_texture_id = child_context_->createExternalTexture();
-  child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
 
   gpu::Mailbox external_mailbox;
   child_context_->genMailboxCHROMIUM(external_mailbox.name);
-  child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
-                                         external_mailbox.name);
+  child_context_->produceTextureDirectCHROMIUM(
+      external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
   const GLuint external_sync_point = child_context_->insertSyncPoint();
   ResourceProvider::ResourceId id4 =
       child_resource_provider_->CreateResourceFromTextureMailbox(
@@ -1745,9 +1746,8 @@
       resource_ids_to_transfer.push_back(id);
       TransferableResourceArray list;
 
-      EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
       EXPECT_CALL(*child_context,
-                  produceTextureCHROMIUM(GL_TEXTURE_2D, _));
+                  produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
       EXPECT_CALL(*child_context, insertSyncPoint());
       child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
                                                    &list);
@@ -1757,8 +1757,9 @@
       EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
 
       EXPECT_CALL(*parent_context,
-                  bindTexture(GL_TEXTURE_2D, parent_texture_id));
-      EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
+                  createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
+          .WillOnce(Return(parent_texture_id));
+
       parent_resource_provider->ReceiveFromChild(child_id, list);
       {
         parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
@@ -1842,7 +1843,7 @@
       GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
   gpu::Mailbox mailbox;
   context()->genMailboxCHROMIUM(mailbox.name);
-  context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+  context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
   uint32 sync_point = context()->insertSyncPoint();
 
   // All the logic below assumes that the sync points are all positive.
@@ -1876,14 +1877,15 @@
     EXPECT_EQ(0u, release_sync_point);
 
     context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
-    unsigned other_texture = context()->createTexture();
-    context()->bindTexture(GL_TEXTURE_2D, other_texture);
-    context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+    unsigned other_texture =
+        context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
     uint8_t test_data[4] = { 0 };
     context()->GetPixels(
         gfx::Size(1, 1), RGBA_8888, test_data);
     EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
-    context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+
+    context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
+                                            mailbox.name);
     context()->deleteTexture(other_texture);
     list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
     EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
@@ -1927,14 +1929,15 @@
     EXPECT_EQ(0u, release_sync_point);
 
     context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
-    unsigned other_texture = context()->createTexture();
-    context()->bindTexture(GL_TEXTURE_2D, other_texture);
-    context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+    unsigned other_texture =
+        context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
     uint8_t test_data[4] = { 0 };
     context()->GetPixels(
         gfx::Size(1, 1), RGBA_8888, test_data);
     EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
-    context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+
+    context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
+                                            mailbox.name);
     context()->deleteTexture(other_texture);
     list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
     EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
@@ -1955,8 +1958,8 @@
   }
 
   context()->waitSyncPoint(release_sync_point);
-  context()->bindTexture(GL_TEXTURE_2D, texture);
-  context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+  texture =
+      context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
   context()->deleteTexture(texture);
 }
 
@@ -2264,7 +2267,7 @@
   context()->bindTexture(GL_TEXTURE_2D, texture);
   gpu::Mailbox mailbox;
   context()->genMailboxCHROMIUM(mailbox.name);
-  context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+  context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
   uint32 sync_point = context()->insertSyncPoint();
 
   EXPECT_LT(0u, sync_point);
@@ -2644,8 +2647,8 @@
     EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
     EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
     EXPECT_CALL(*context, insertSyncPoint()).Times(0);
-    EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
-    EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+    EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
+    EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
 
     gpu::Mailbox gpu_mailbox;
     memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
@@ -2674,12 +2677,12 @@
       resource_provider->WaitSyncPointIfNeeded(id);
       Mock::VerifyAndClearExpectations(context);
 
-      // Using the texture does a consume of the mailbox.
-      EXPECT_CALL(*context, bindTexture(target, texture_id)).Times(2);
-      EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
+      EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
+          .WillOnce(Return(texture_id));
+      EXPECT_CALL(*context, bindTexture(target, texture_id));
 
       EXPECT_CALL(*context, insertSyncPoint()).Times(0);
-      EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
+      EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
 
       // The sampler will reset these if |mailbox_nearest_neighbor| does not
       // match |sampler_filter|.
@@ -2698,10 +2701,10 @@
       // necessary.
       EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
       EXPECT_CALL(*context, insertSyncPoint());
-      EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
+      EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
 
       EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
-      EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+      EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
     }
 
     resource_provider->DeleteResource(id);
@@ -2786,15 +2789,14 @@
                                false,
                                1));
 
-  unsigned texture_id = 1;
   uint32 sync_point = 30;
   unsigned target = GL_TEXTURE_EXTERNAL_OES;
 
   EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
   EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
   EXPECT_CALL(*context, insertSyncPoint()).Times(0);
-  EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
-  EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+  EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
+  EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
 
   gpu::Mailbox gpu_mailbox;
   memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
@@ -2816,12 +2818,13 @@
     resource_provider->WaitSyncPointIfNeeded(id);
     Mock::VerifyAndClearExpectations(context);
 
-    // Using the texture does a consume of the mailbox.
-    EXPECT_CALL(*context, bindTexture(target, texture_id));
-    EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
+    unsigned texture_id = 1;
+
+    EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
+        .WillOnce(Return(texture_id));
 
     EXPECT_CALL(*context, insertSyncPoint()).Times(0);
-    EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
+    EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
 
     ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
     Mock::VerifyAndClearExpectations(context);
@@ -2830,10 +2833,10 @@
     // necessary.
     EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
     EXPECT_CALL(*context, insertSyncPoint());
-    EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
+    EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
 
     EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
-    EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+    EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
   }
 }
 
@@ -2867,8 +2870,8 @@
   EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
   EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
   EXPECT_CALL(*context, insertSyncPoint()).Times(0);
-  EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
-  EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+  EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
+  EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
 
   gpu::Mailbox gpu_mailbox;
   memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
@@ -2926,8 +2929,8 @@
   EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
   EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
   EXPECT_CALL(*context, insertSyncPoint()).Times(0);
-  EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
-  EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+  EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
+  EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
 
   gpu::Mailbox gpu_mailbox;
   memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
diff --git a/cc/resources/task_graph_runner.cc b/cc/resources/task_graph_runner.cc
index 1a67faa..e0b3f4c 100644
--- a/cc/resources/task_graph_runner.cc
+++ b/cc/resources/task_graph_runner.cc
@@ -290,6 +290,7 @@
 
   {
     base::AutoLock lock(lock_);
+    base::ThreadRestrictions::ScopedAllowWait allow_wait;
 
     TaskNamespaceMap::const_iterator it = namespaces_.find(token.id_);
     if (it == namespaces_.end())
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 904a057..70d726d 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -8,6 +8,7 @@
 
 #include "base/auto_reset.h"
 #include "base/logging.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
@@ -78,7 +79,6 @@
     const SchedulerSettings& scheduler_settings,
     int layer_tree_host_id,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-    base::PowerMonitor* power_monitor,
     scoped_ptr<BeginFrameSource> external_begin_frame_source,
     SchedulerFrameSourcesConstructor* frame_sources_constructor)
     : frame_source_(),
@@ -92,7 +92,6 @@
       client_(client),
       layer_tree_host_id_(layer_tree_host_id),
       task_runner_(task_runner),
-      power_monitor_(power_monitor),
       state_machine_(scheduler_settings),
       inside_process_scheduled_actions_(false),
       inside_action_(SchedulerStateMachine::ACTION_NONE),
@@ -131,12 +130,9 @@
   unthrottled_frame_source_ =
       frame_sources_constructor->ConstructUnthrottledFrameSource(this);
   frame_source_->AddSource(unthrottled_frame_source_);
-
-  SetupPowerMonitoring();
 }
 
 Scheduler::~Scheduler() {
-  TeardownPowerMonitoring();
   if (frame_source_->NeedsBeginFrames())
     frame_source_->SetNeedsBeginFrames(false);
 }
@@ -150,27 +146,6 @@
   return now;
 }
 
-void Scheduler::SetupPowerMonitoring() {
-  if (settings_.disable_hi_res_timer_tasks_on_battery) {
-    DCHECK(power_monitor_);
-    power_monitor_->AddObserver(this);
-    state_machine_.SetImplLatencyTakesPriorityOnBattery(
-        power_monitor_->IsOnBatteryPower());
-  }
-}
-
-void Scheduler::TeardownPowerMonitoring() {
-  if (settings_.disable_hi_res_timer_tasks_on_battery) {
-    DCHECK(power_monitor_);
-    power_monitor_->RemoveObserver(this);
-  }
-}
-
-void Scheduler::OnPowerStateChange(bool on_battery_power) {
-  DCHECK(settings_.disable_hi_res_timer_tasks_on_battery);
-  state_machine_.SetImplLatencyTakesPriorityOnBattery(on_battery_power);
-}
-
 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
                                       base::TimeDelta interval) {
   // TODO(brianderson): We should not be receiving 0 intervals.
@@ -647,11 +622,25 @@
   //     order to wait for more user-input before starting the next commit.
   // * Creating a new OuputSurface will not occur during the deadline in
   //     order to allow the state machine to "settle" first.
+
+  // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "461509 Scheduler::OnBeginImplFrameDeadline1"));
   state_machine_.OnBeginImplFrameDeadline();
   ProcessScheduledActions();
+
+  // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is fixed.
+  tracked_objects::ScopedTracker tracking_profile2(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "461509 Scheduler::OnBeginImplFrameDeadline2"));
   state_machine_.OnBeginImplFrameIdle();
   ProcessScheduledActions();
 
+  // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is fixed.
+  tracked_objects::ScopedTracker tracking_profile3(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "461509 Scheduler::OnBeginImplFrameDeadline3"));
   client_->DidBeginImplFrameDeadline();
 }
 
@@ -692,6 +681,10 @@
 
   SchedulerStateMachine::Action action;
   do {
+    // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is fixed.
+    tracked_objects::ScopedTracker tracking_profile1(
+        FROM_HERE_WITH_EXPLICIT_FUNCTION(
+            "461509 Scheduler::ProcessScheduledActions1"));
     action = state_machine_.NextAction();
     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
                  "SchedulerStateMachine",
@@ -706,40 +699,96 @@
     switch (action) {
       case SchedulerStateMachine::ACTION_NONE:
         break;
-      case SchedulerStateMachine::ACTION_ANIMATE:
+      case SchedulerStateMachine::ACTION_ANIMATE: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile2(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions2"));
         client_->ScheduledActionAnimate();
         break;
-      case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME:
+      }
+      case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile3(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions3"));
         client_->ScheduledActionSendBeginMainFrame();
         break;
-      case SchedulerStateMachine::ACTION_COMMIT:
+      }
+      case SchedulerStateMachine::ACTION_COMMIT: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile4(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions4"));
         client_->ScheduledActionCommit();
         break;
-      case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE:
+      }
+      case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile5(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions5"));
         client_->ScheduledActionActivateSyncTree();
         break;
-      case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
+      }
+      case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile6(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions6"));
         DrawAndSwapIfPossible();
         break;
-      case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
+      }
+      case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile7(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions7"));
         client_->ScheduledActionDrawAndSwapForced();
         break;
+      }
       case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT:
         // No action is actually performed, but this allows the state machine to
         // advance out of its waiting to draw state without actually drawing.
         break;
-      case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
+      case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile8(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions8"));
         client_->ScheduledActionBeginOutputSurfaceCreation();
         break;
-      case SchedulerStateMachine::ACTION_PREPARE_TILES:
+      }
+      case SchedulerStateMachine::ACTION_PREPARE_TILES: {
+        // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
+        // fixed.
+        tracked_objects::ScopedTracker tracking_profile9(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "461509 Scheduler::ProcessScheduledActions9"));
         client_->ScheduledActionPrepareTiles();
         break;
+      }
     }
   } while (action != SchedulerStateMachine::ACTION_NONE);
 
+  // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is fixed.
+  tracked_objects::ScopedTracker tracking_profile10(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "461509 Scheduler::ProcessScheduledActions10"));
   SetupNextBeginFrameIfNeeded();
   client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
 
+  // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is fixed.
+  tracked_objects::ScopedTracker tracking_profile11(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "461509 Scheduler::ProcessScheduledActions11"));
   RescheduleBeginImplFrameDeadlineIfNeeded();
 }
 
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 370ac25..8ed584a 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -11,8 +11,6 @@
 #include "base/basictypes.h"
 #include "base/cancelable_callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_observer.h"
 #include "base/time/time.h"
 #include "cc/base/cc_export.h"
 #include "cc/output/begin_frame_args.h"
@@ -75,22 +73,19 @@
   friend class Scheduler;
 };
 
-class CC_EXPORT Scheduler : public BeginFrameObserverMixIn,
-                            public base::PowerObserver {
+class CC_EXPORT Scheduler : public BeginFrameObserverMixIn {
  public:
   static scoped_ptr<Scheduler> Create(
       SchedulerClient* client,
       const SchedulerSettings& scheduler_settings,
       int layer_tree_host_id,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-      base::PowerMonitor* power_monitor,
       scoped_ptr<BeginFrameSource> external_begin_frame_source) {
     SchedulerFrameSourcesConstructor frame_sources_constructor;
     return make_scoped_ptr(new Scheduler(client,
                                          scheduler_settings,
                                          layer_tree_host_id,
                                          task_runner,
-                                         power_monitor,
                                          external_begin_frame_source.Pass(),
                                          &frame_sources_constructor));
   }
@@ -100,9 +95,6 @@
   // BeginFrameObserverMixin
   bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) override;
 
-  // base::PowerObserver method.
-  void OnPowerStateChange(bool on_battery_power) override;
-
   const SchedulerSettings& settings() const { return settings_; }
 
   void CommitVSyncParameters(base::TimeTicks timebase,
@@ -179,7 +171,6 @@
             const SchedulerSettings& scheduler_settings,
             int layer_tree_host_id,
             const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-            base::PowerMonitor* power_monitor,
             scoped_ptr<BeginFrameSource> external_begin_frame_source,
             SchedulerFrameSourcesConstructor* frame_sources_constructor);
 
@@ -205,8 +196,6 @@
   int layer_tree_host_id_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
-  base::PowerMonitor* power_monitor_;
-
   base::TimeDelta estimated_parent_draw_time_;
 
   std::deque<BeginFrameArgs> begin_retro_frame_args_;
@@ -243,8 +232,6 @@
   void OnBeginImplFrameDeadline();
   void PollForAnticipatedDrawTriggers();
   void PollToAdvanceCommitState();
-  void SetupPowerMonitoring();
-  void TeardownPowerMonitoring();
   void UpdateActiveFrameSource();
 
   base::TimeDelta EstimatedParentDrawTime() {
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 4e6509f..f2f6636 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -47,7 +47,6 @@
       skip_next_begin_main_frame_to_reduce_latency_(false),
       skip_begin_main_frame_to_reduce_latency_(false),
       continuous_painting_(false),
-      impl_latency_takes_priority_on_battery_(false),
       children_need_begin_frames_(false),
       defer_commits_(false) {
 }
@@ -236,8 +235,6 @@
   state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
                     skip_next_begin_main_frame_to_reduce_latency_);
   state->SetBoolean("continuous_painting", continuous_painting_);
-  state->SetBoolean("impl_latency_takes_priority_on_battery",
-                    impl_latency_takes_priority_on_battery_);
   state->SetBoolean("children_need_begin_frames", children_need_begin_frames_);
   state->SetBoolean("defer_commits", defer_commits_);
   state->EndDictionary();
@@ -903,11 +900,6 @@
   if (impl_latency_takes_priority_)
     return true;
 
-  // If we are on battery power and want to prioritize impl latency because
-  // we don't trust deadline tasks to execute at the right time.
-  if (impl_latency_takes_priority_on_battery_)
-    return true;
-
   return false;
 }
 
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index f77df28..a411022 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -254,12 +254,6 @@
 
   bool CouldSendBeginMainFrame() const;
 
-  void SetImplLatencyTakesPriorityOnBattery(
-      bool impl_latency_takes_priority_on_battery) {
-    impl_latency_takes_priority_on_battery_ =
-        impl_latency_takes_priority_on_battery;
-  }
-
   void SetDeferCommits(bool defer_commits);
 
   // TODO(zmo): This is temporary for debugging crbug.com/393331.
@@ -341,7 +335,6 @@
   bool skip_next_begin_main_frame_to_reduce_latency_;
   bool skip_begin_main_frame_to_reduce_latency_;
   bool continuous_painting_;
-  bool impl_latency_takes_priority_on_battery_;
   bool children_need_begin_frames_;
   bool defer_commits_;
 
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index 50cc846..9346536 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -10,8 +10,6 @@
 #include "base/logging.h"
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
-#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_source.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
@@ -198,21 +196,6 @@
   TestScheduler* scheduler_;
 };
 
-class FakePowerMonitorSource : public base::PowerMonitorSource {
- public:
-  FakePowerMonitorSource() {}
-  ~FakePowerMonitorSource() override {}
-  void GeneratePowerStateEvent(bool on_battery_power) {
-    on_battery_power_impl_ = on_battery_power;
-    ProcessPowerEvent(POWER_STATE_EVENT);
-    base::MessageLoop::current()->RunUntilIdle();
-  }
-  bool IsOnBatteryPowerImpl() override { return on_battery_power_impl_; }
-
- private:
-  bool on_battery_power_impl_;
-};
-
 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn {
  public:
   explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
@@ -240,10 +223,7 @@
   SchedulerTest()
       : now_src_(TestNowSource::Create()),
         task_runner_(new OrderedSimpleTaskRunner(now_src_, true)),
-        fake_external_begin_frame_source_(nullptr),
-        fake_power_monitor_source_(new FakePowerMonitorSource),
-        power_monitor_(make_scoped_ptr<base::PowerMonitorSource>(
-            fake_power_monitor_source_)) {
+        fake_external_begin_frame_source_(nullptr) {
     // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
     now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
     // Fail if we need to run 100 tasks in a row.
@@ -261,9 +241,9 @@
       fake_external_begin_frame_source_ =
           fake_external_begin_frame_source.get();
     }
-    scheduler_ = TestScheduler::Create(
-        now_src_, client_.get(), scheduler_settings_, 0, task_runner_,
-        &power_monitor_, fake_external_begin_frame_source.Pass());
+    scheduler_ = TestScheduler::Create(now_src_, client_.get(),
+                                       scheduler_settings_, 0, task_runner_,
+                                       fake_external_begin_frame_source.Pass());
     DCHECK(scheduler_);
     client_->set_scheduler(scheduler_.get());
     return scheduler_.get();
@@ -386,11 +366,6 @@
         CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()));
   }
 
-  base::PowerMonitor* PowerMonitor() { return &power_monitor_; }
-  FakePowerMonitorSource* PowerMonitorSource() {
-    return fake_power_monitor_source_;
-  }
-
   FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
     return fake_external_begin_frame_source_;
   }
@@ -412,8 +387,6 @@
   scoped_refptr<TestNowSource> now_src_;
   scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
   FakeExternalBeginFrameSource* fake_external_begin_frame_source_;
-  FakePowerMonitorSource* fake_power_monitor_source_;
-  base::PowerMonitor power_monitor_;
   SchedulerSettings scheduler_settings_;
   scoped_ptr<FakeSchedulerClient> client_;
   scoped_ptr<TestScheduler> scheduler_;
@@ -2119,131 +2092,6 @@
   EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
 }
 
-TEST_F(SchedulerTest, SchedulerPowerMonitoring) {
-  scheduler_settings_.disable_hi_res_timer_tasks_on_battery = true;
-  SetUpScheduler(true);
-
-  base::TimeTicks before_deadline, after_deadline;
-
-  scheduler_->SetNeedsCommit();
-  scheduler_->SetNeedsRedraw();
-  client_->Reset();
-
-  // On non-battery power
-  EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower());
-
-  EXPECT_SCOPED(AdvanceFrame());
-  client_->Reset();
-
-  before_deadline = now_src()->Now();
-  EXPECT_TRUE(
-      task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)));
-  after_deadline = now_src()->Now();
-
-  // We post a non-zero deadline task when not on battery
-  EXPECT_LT(before_deadline, after_deadline);
-
-  // Switch to battery power
-  PowerMonitorSource()->GeneratePowerStateEvent(true);
-  EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
-
-  EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->SetNeedsCommit();
-  scheduler_->SetNeedsRedraw();
-  client_->Reset();
-
-  before_deadline = now_src()->Now();
-  EXPECT_TRUE(
-      task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)));
-  after_deadline = now_src()->Now();
-
-  // We post a zero deadline task when on battery
-  EXPECT_EQ(before_deadline, after_deadline);
-
-  // Switch to non-battery power
-  PowerMonitorSource()->GeneratePowerStateEvent(false);
-  EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower());
-
-  EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->SetNeedsCommit();
-  scheduler_->SetNeedsRedraw();
-  client_->Reset();
-
-  // Same as before
-  before_deadline = now_src()->Now();
-  EXPECT_TRUE(
-      task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)));
-  after_deadline = now_src()->Now();
-}
-
-TEST_F(SchedulerTest,
-       SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOff) {
-  scheduler_settings_.use_external_begin_frame_source = true;
-  SetUpScheduler(true);
-
-  // Set needs commit so that the scheduler tries to wait for the main thread
-  scheduler_->SetNeedsCommit();
-  // Set needs redraw so that the scheduler doesn't wait too long
-  scheduler_->SetNeedsRedraw();
-  client_->Reset();
-
-  // Switch to battery power
-  PowerMonitorSource()->GeneratePowerStateEvent(true);
-  EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
-
-  EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->SetNeedsCommit();
-  scheduler_->SetNeedsRedraw();
-  client_->Reset();
-
-  // Disable auto-advancing of now_src
-  task_runner().SetAutoAdvanceNowToPendingTasks(false);
-
-  // Deadline task is pending
-  EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
-  task_runner().RunPendingTasks();
-  // Deadline task is still pending
-  EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
-
-  // Advance now by 15 ms - same as windows low res timer
-  now_src()->AdvanceNowMicroseconds(15000);
-  EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
-  task_runner().RunPendingTasks();
-  // Deadline task finally completes
-  EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
-}
-
-TEST_F(SchedulerTest,
-       SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOn) {
-  scheduler_settings_.disable_hi_res_timer_tasks_on_battery = true;
-  scheduler_settings_.use_external_begin_frame_source = true;
-  SetUpScheduler(true);
-
-  // Set needs commit so that the scheduler tries to wait for the main thread
-  scheduler_->SetNeedsCommit();
-  // Set needs redraw so that the scheduler doesn't wait too long
-  scheduler_->SetNeedsRedraw();
-  client_->Reset();
-
-  // Switch to battery power
-  PowerMonitorSource()->GeneratePowerStateEvent(true);
-  EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
-
-  EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->SetNeedsCommit();
-  scheduler_->SetNeedsRedraw();
-  client_->Reset();
-
-  // Disable auto-advancing of now_src
-  task_runner().SetAutoAdvanceNowToPendingTasks(false);
-
-  // Deadline task is pending
-  EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
-  task_runner().RunPendingTasks();
-  // Deadline task runs immediately
-  EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
-}
-
 // Tests to ensure frame sources can be successfully changed while drawing.
 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
   scheduler_settings_.use_external_begin_frame_source = true;
diff --git a/cc/test/data/checkers.png b/cc/test/data/checkers.png
new file mode 100644
index 0000000..fdd2ee3
--- /dev/null
+++ b/cc/test/data/checkers.png
Binary files differ
diff --git a/cc/test/data/checkers_big.png b/cc/test/data/checkers_big.png
new file mode 100644
index 0000000..48edf60
--- /dev/null
+++ b/cc/test/data/checkers_big.png
Binary files differ
diff --git a/cc/test/data/mask_of_background_filter.png b/cc/test/data/mask_of_background_filter.png
new file mode 100644
index 0000000..2a96d49
--- /dev/null
+++ b/cc/test/data/mask_of_background_filter.png
Binary files differ
diff --git a/cc/test/data/mask_of_layer_with_blend.png b/cc/test/data/mask_of_layer_with_blend.png
new file mode 100644
index 0000000..35faaba
--- /dev/null
+++ b/cc/test/data/mask_of_layer_with_blend.png
Binary files differ
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc
index ab958e9..ffef555 100644
--- a/cc/test/fake_content_layer_client.cc
+++ b/cc/test/fake_content_layer_client.cc
@@ -71,8 +71,8 @@
     const SkPaint& paint = it->second;
     canvas =
         skia::SharePtr(recorder.beginRecording(gfx::RectFToSkRect(draw_rect)));
-    canvas->drawRectCoords(0.f, 0.f, draw_rect.width(), draw_rect.height(),
-                           paint);
+    canvas->drawRectCoords(draw_rect.x(), draw_rect.y(), draw_rect.width(),
+                           draw_rect.height(), paint);
     picture = skia::AdoptRef(recorder.endRecording());
     list->AppendItem(DrawingDisplayItem::Create(picture));
   }
@@ -81,7 +81,7 @@
        it != draw_bitmaps_.end(); ++it) {
     canvas = skia::SharePtr(
         recorder.beginRecording(it->bitmap.width(), it->bitmap.height()));
-    canvas->drawBitmap(it->bitmap, 0.f, 0.f, &it->paint);
+    canvas->drawBitmap(it->bitmap, it->point.x(), it->point.y(), &it->paint);
     picture = skia::AdoptRef(recorder.endRecording());
     list->AppendItem(DrawingDisplayItem::Create(picture));
   }
diff --git a/cc/test/ordered_texture_map.cc b/cc/test/ordered_texture_map.cc
index ee3e2f3..649700c 100644
--- a/cc/test/ordered_texture_map.cc
+++ b/cc/test/ordered_texture_map.cc
@@ -32,7 +32,10 @@
 
 void OrderedTextureMap::Remove(GLuint id) {
   TextureMap::iterator map_it = textures_.find(id);
-  DCHECK(map_it != textures_.end());
+  // for some test we generate dummy tex id, which are not registered,
+  // nothing to remove in that case.
+  if (map_it == textures_.end())
+    return;
   textures_.erase(map_it);
 
   TextureList::iterator list_it =
diff --git a/cc/test/render_pass_test_common.cc b/cc/test/render_pass_test_common.cc
index 0e3fe22..3f7f7c0 100644
--- a/cc/test/render_pass_test_common.cc
+++ b/cc/test/render_pass_test_common.cc
@@ -94,7 +94,7 @@
 
   CheckerboardDrawQuad* checkerboard_quad =
       this->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
-  checkerboard_quad->SetNew(shared_state, rect, visible_rect, SK_ColorRED);
+  checkerboard_quad->SetNew(shared_state, rect, visible_rect, SK_ColorRED, 1.f);
 
   DebugBorderDrawQuad* debug_border_quad =
       this->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
diff --git a/cc/test/scheduler_test_common.cc b/cc/test/scheduler_test_common.cc
index 94bcf5f..f25d6eb 100644
--- a/cc/test/scheduler_test_common.cc
+++ b/cc/test/scheduler_test_common.cc
@@ -131,14 +131,12 @@
     const SchedulerSettings& scheduler_settings,
     int layer_tree_host_id,
     const scoped_refptr<OrderedSimpleTaskRunner>& test_task_runner,
-    base::PowerMonitor* power_monitor,
     TestSchedulerFrameSourcesConstructor* frame_sources_constructor,
     scoped_ptr<BeginFrameSource> external_begin_frame_source)
     : Scheduler(client,
                 scheduler_settings,
                 layer_tree_host_id,
                 test_task_runner,
-                power_monitor,
                 external_begin_frame_source.Pass(),
                 frame_sources_constructor),
       now_src_(now_src) {
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 00cdd75..763ccc8 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -164,7 +164,6 @@
       const SchedulerSettings& scheduler_settings,
       int layer_tree_host_id,
       const scoped_refptr<OrderedSimpleTaskRunner>& task_runner,
-      base::PowerMonitor* power_monitor,
       scoped_ptr<BeginFrameSource> external_begin_frame_source) {
     TestSchedulerFrameSourcesConstructor frame_sources_constructor(
         task_runner.get(), now_src.get());
@@ -174,7 +173,6 @@
                                    scheduler_settings,
                                    layer_tree_host_id,
                                    task_runner,
-                                   power_monitor,
                                    &frame_sources_constructor,
                                    external_begin_frame_source.Pass()));
   }
@@ -209,7 +207,6 @@
       const SchedulerSettings& scheduler_settings,
       int layer_tree_host_id,
       const scoped_refptr<OrderedSimpleTaskRunner>& test_task_runner,
-      base::PowerMonitor* power_monitor,
       TestSchedulerFrameSourcesConstructor* frame_sources_constructor,
       scoped_ptr<BeginFrameSource> external_begin_frame_source);
 
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc
index 28b16c8..9f20bb8 100644
--- a/cc/test/test_web_graphics_context_3d.cc
+++ b/cc/test/test_web_graphics_context_3d.cc
@@ -356,6 +356,13 @@
   return namespace_->textures.TextureForId(BoundTextureId(target));
 }
 
+scoped_refptr<TestTexture> TestWebGraphicsContext3D::UnboundTexture(
+    GLuint texture) {
+  // The caller is expected to lock the namespace for texture access.
+  namespace_->lock.AssertAcquired();
+  return namespace_->textures.TextureForId(texture);
+}
+
 void TestWebGraphicsContext3D::CheckTextureIsBound(GLenum target) {
   DCHECK(BoundTextureId(target));
 }
@@ -466,7 +473,9 @@
 GLuint TestWebGraphicsContext3D::createAndConsumeTextureCHROMIUM(
     GLenum target,
     const GLbyte* mailbox) {
-  return createTexture();
+  GLuint texture_id = createTexture();
+  consumeTextureCHROMIUM(target, mailbox);
+  return texture_id;
 }
 
 void TestWebGraphicsContext3D::loseContextCHROMIUM(GLenum current,
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h
index c2dee45..d8219f5 100644
--- a/cc/test/test_web_graphics_context_3d.h
+++ b/cc/test/test_web_graphics_context_3d.h
@@ -441,6 +441,7 @@
   void CreateNamespace();
   GLuint BoundTextureId(GLenum target);
   scoped_refptr<TestTexture> BoundTexture(GLenum target);
+  scoped_refptr<TestTexture> UnboundTexture(GLuint texture);
   void CheckTextureIsBound(GLenum target);
 
   unsigned context_id_;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index abc63fc..d893b33 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -211,10 +211,6 @@
   proxy_->SetLayerTreeHostClientReady();
 }
 
-static void LayerTreeHostOnOutputSurfaceCreatedCallback(Layer* layer) {
-  layer->OnOutputSurfaceCreated();
-}
-
 void LayerTreeHost::DeleteContentsTexturesOnImplThread(
     ResourceProvider* resource_provider) {
   DCHECK(proxy_->IsImplThread());
@@ -427,7 +423,7 @@
 
   if (root_layer()) {
     LayerTreeHostCommon::CallFunctionForSubtree(
-        root_layer(), base::Bind(&LayerTreeHostOnOutputSurfaceCreatedCallback));
+        root_layer(), [](Layer* layer) { layer->OnOutputSurfaceCreated(); });
   }
 
   client_->DidInitializeOutputSurface();
@@ -452,11 +448,8 @@
   host_impl->SetUseGpuRasterization(UseGpuRasterization());
   shared_bitmap_manager_ = NULL;
   gpu_memory_buffer_manager_ = NULL;
-  if (settings_.calculate_top_controls_position &&
-      host_impl->top_controls_manager()) {
-    top_controls_manager_weak_ptr_ =
-        host_impl->top_controls_manager()->AsWeakPtr();
-  }
+  top_controls_manager_weak_ptr_ =
+      host_impl->top_controls_manager()->AsWeakPtr();
   input_handler_weak_ptr_ = host_impl->AsWeakPtr();
   return host_impl.Pass();
 }
@@ -873,17 +866,12 @@
   SetNeedsCommit();
 }
 
-static void LayerTreeHostReduceMemoryCallback(Layer* layer) {
-  layer->ReduceMemoryUsage();
-}
-
 void LayerTreeHost::ReduceMemoryUsage() {
   if (!root_layer())
     return;
 
   LayerTreeHostCommon::CallFunctionForSubtree(
-      root_layer(),
-      base::Bind(&LayerTreeHostReduceMemoryCallback));
+      root_layer(), [](Layer* layer) { layer->ReduceMemoryUsage(); });
 }
 
 void LayerTreeHost::SetPrioritiesForSurfaces(size_t surface_memory_bytes) {
@@ -1167,9 +1155,6 @@
 void LayerTreeHost::UpdateTopControlsState(TopControlsState constraints,
                                            TopControlsState current,
                                            bool animate) {
-  if (!settings_.calculate_top_controls_position)
-    return;
-
   // Top controls are only used in threaded mode.
   proxy_->ImplThreadTaskRunner()->PostTask(
       FROM_HERE,
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index a84cae6..e468c07 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -2495,12 +2495,6 @@
          std::abs(r1.height() - r2.height()) <= tolerance;
 }
 
-static bool ApproximatelyEqual(const gfx::Transform& a,
-                               const gfx::Transform& b) {
-  static const float tolerance = 0.01f;
-  return gfx::MatrixDistance(a, b) < tolerance;
-}
-
 void LayerTreeHostCommon::CalculateDrawProperties(
     CalcDrawPropsMainInputs* inputs) {
   UpdateRenderSurfaces(inputs->root_layer,
@@ -2512,30 +2506,42 @@
   ProcessCalcDrawPropsInputs(*inputs, &globals, &data_for_recursion);
 
   PreCalculateMetaInformationRecursiveData recursive_data;
-  PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
-  std::vector<AccumulatedSurfaceState<Layer>> accumulated_surface_state;
-  CalculateDrawPropertiesInternal<Layer>(
-      inputs->root_layer, globals, data_for_recursion,
-      inputs->render_surface_layer_list, &dummy_layer_list,
-      &accumulated_surface_state, inputs->current_render_surface_layer_list_id);
 
-  // The dummy layer list should not have been used.
-  DCHECK_EQ(0u, dummy_layer_list.size());
-  // A root layer render_surface should always exist after
-  // CalculateDrawProperties.
-  DCHECK(inputs->root_layer->render_surface());
+  if (!inputs->verify_property_trees) {
+    PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
+    std::vector<AccumulatedSurfaceState<Layer>> accumulated_surface_state;
+    CalculateDrawPropertiesInternal<Layer>(
+        inputs->root_layer, globals, data_for_recursion,
+        inputs->render_surface_layer_list, &dummy_layer_list,
+        &accumulated_surface_state,
+        inputs->current_render_surface_layer_list_id);
+  } else {
+    {
+      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
+                   "LayerTreeHostCommon::CalculateDrawProperties");
+      PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
+      std::vector<AccumulatedSurfaceState<Layer>> accumulated_surface_state;
+      CalculateDrawPropertiesInternal<Layer>(
+          inputs->root_layer, globals, data_for_recursion,
+          inputs->render_surface_layer_list, &dummy_layer_list,
+          &accumulated_surface_state,
+          inputs->current_render_surface_layer_list_id);
+    }
 
-  if (inputs->verify_property_trees) {
     // The translation from layer to property trees is an intermediate state. We
     // will eventually get these data passed directly to the compositor.
     TransformTree transform_tree;
     ClipTree clip_tree;
     OpacityTree opacity_tree;
-    ComputeVisibleRectsUsingPropertyTrees(
-        inputs->root_layer, inputs->page_scale_application_layer,
-        inputs->page_scale_factor, inputs->device_scale_factor,
-        gfx::Rect(inputs->device_viewport_size), inputs->device_transform,
-        &transform_tree, &clip_tree, &opacity_tree);
+    {
+      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
+                   "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees");
+      ComputeVisibleRectsUsingPropertyTrees(
+          inputs->root_layer, inputs->page_scale_application_layer,
+          inputs->page_scale_factor, inputs->device_scale_factor,
+          gfx::Rect(inputs->device_viewport_size), inputs->device_transform,
+          &transform_tree, &clip_tree, &opacity_tree);
+    }
 
     LayerIterator<Layer> it, end;
     for (it = LayerIterator<Layer>::Begin(inputs->render_surface_layer_list),
@@ -2550,17 +2556,18 @@
                              current_layer->visible_rect_from_property_trees());
       CHECK(visible_rects_match);
 
-      const bool draw_transforms_match = ApproximatelyEqual(
-          current_layer->draw_transform(),
-          current_layer->draw_transform_from_property_trees(transform_tree));
-      CHECK(draw_transforms_match);
-
       const bool draw_opacities_match =
           current_layer->draw_opacity() ==
           current_layer->DrawOpacityFromPropertyTrees(opacity_tree);
       CHECK(draw_opacities_match);
     }
   }
+
+  // The dummy layer list should not have been used.
+  DCHECK_EQ(0u, dummy_layer_list.size());
+  // A root layer render_surface should always exist after
+  // CalculateDrawProperties.
+  DCHECK(inputs->root_layer->render_surface());
 }
 
 void LayerTreeHostCommon::CalculateDrawProperties(
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h
index 8666617..6c03511 100644
--- a/cc/trees/layer_tree_host_common.h
+++ b/cc/trees/layer_tree_host_common.h
@@ -125,10 +125,9 @@
   static bool RenderSurfaceContributesToTarget(LayerType*,
                                                int target_surface_layer_id);
 
-  template <typename LayerType>
-  static void CallFunctionForSubtree(
-      LayerType* root_layer,
-      const base::Callback<void(LayerType* layer)>& function);
+  template <typename LayerType, typename Function>
+  static void CallFunctionForSubtree(LayerType* layer,
+                                     const Function& function);
 
   // Returns a layer with the given id if one exists in the subtree starting
   // from the given root layer (including mask and replica layers).
@@ -205,22 +204,21 @@
   return NULL;
 }
 
-template <typename LayerType>
-void LayerTreeHostCommon::CallFunctionForSubtree(
-    LayerType* root_layer,
-    const base::Callback<void(LayerType* layer)>& function) {
-  function.Run(root_layer);
+template <typename LayerType, typename Function>
+void LayerTreeHostCommon::CallFunctionForSubtree(LayerType* layer,
+                                                 const Function& function) {
+  function(layer);
 
-  if (LayerType* mask_layer = root_layer->mask_layer())
-    function.Run(mask_layer);
-  if (LayerType* replica_layer = root_layer->replica_layer()) {
-    function.Run(replica_layer);
+  if (LayerType* mask_layer = layer->mask_layer())
+    function(mask_layer);
+  if (LayerType* replica_layer = layer->replica_layer()) {
+    function(replica_layer);
     if (LayerType* mask_layer = replica_layer->mask_layer())
-      function.Run(mask_layer);
+      function(mask_layer);
   }
 
-  for (size_t i = 0; i < root_layer->children().size(); ++i) {
-    CallFunctionForSubtree(get_layer_as_raw_ptr(root_layer->children(), i),
+  for (size_t i = 0; i < layer->children().size(); ++i) {
+    CallFunctionForSubtree(get_layer_as_raw_ptr(layer->children(), i),
                            function);
   }
 }
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 6f05035..6234d87 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -8812,5 +8812,43 @@
   EXPECT_FALSE(grandchild->FilterIsAnimating());
 }
 
+// Ensures that the property tree code accounts for offsets between fixed
+// position layers and their respective containers.
+TEST_F(LayerTreeHostCommonTest, PropertyTreesAccountForFixedParentOffset) {
+  scoped_refptr<Layer> root = Layer::Create();
+  scoped_refptr<Layer> child = Layer::Create();
+  scoped_refptr<LayerWithForcedDrawsContent> grandchild =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+
+  root->AddChild(child);
+  child->AddChild(grandchild);
+
+  gfx::Transform identity_transform;
+  SetLayerPropertiesForTesting(root.get(), identity_transform, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), true, false);
+  SetLayerPropertiesForTesting(child.get(), identity_transform, gfx::Point3F(),
+                               gfx::PointF(1000, 1000), gfx::Size(50, 50), true,
+                               false);
+  SetLayerPropertiesForTesting(grandchild.get(), identity_transform,
+                               gfx::Point3F(), gfx::PointF(-1000, -1000),
+                               gfx::Size(50, 50), true, false);
+
+  root->SetMasksToBounds(true);
+  root->SetIsContainerForFixedPositionLayers(true);
+  LayerPositionConstraint constraint;
+  constraint.set_is_fixed_position(true);
+  grandchild->SetPositionConstraint(constraint);
+
+  root->SetIsContainerForFixedPositionLayers(true);
+
+  scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost());
+  host->SetRootLayer(root);
+
+  ExecuteCalculateDrawProperties(root.get());
+
+  EXPECT_EQ(gfx::Rect(0, 0, 50, 50),
+            grandchild->visible_rect_from_property_trees());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index eddbc60..2f4d9a9 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -241,12 +241,10 @@
   TRACE_EVENT_OBJECT_CREATED_WITH_ID(
       TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", id_);
 
-  if (settings.calculate_top_controls_position) {
-    top_controls_manager_ =
-        TopControlsManager::Create(this,
-                                   settings.top_controls_show_threshold,
-                                   settings.top_controls_hide_threshold);
-  }
+  top_controls_manager_ =
+      TopControlsManager::Create(this,
+                                 settings.top_controls_show_threshold,
+                                 settings.top_controls_hide_threshold);
 }
 
 LayerTreeHostImpl::~LayerTreeHostImpl() {
@@ -916,8 +914,7 @@
 }
 
 void LayerTreeHostImpl::MainThreadHasStoppedFlinging() {
-  if (top_controls_manager_)
-    top_controls_manager_->MainThreadHasStoppedFlinging();
+  top_controls_manager_->MainThreadHasStoppedFlinging();
   if (input_handler_client_)
     input_handler_client_->MainThreadHasStoppedFlinging();
 }
@@ -1423,12 +1420,10 @@
   metadata.root_layer_size = active_tree_->ScrollableSize();
   metadata.min_page_scale_factor = active_tree_->min_page_scale_factor();
   metadata.max_page_scale_factor = active_tree_->max_page_scale_factor();
-  if (top_controls_manager_) {
-    metadata.location_bar_offset =
-        gfx::Vector2dF(0.f, top_controls_manager_->ControlsTopOffset());
-    metadata.location_bar_content_translation =
-        gfx::Vector2dF(0.f, top_controls_manager_->ContentTopOffset());
-  }
+  metadata.location_bar_offset =
+      gfx::Vector2dF(0.f, top_controls_manager_->ControlsTopOffset());
+  metadata.location_bar_content_translation =
+      gfx::Vector2dF(0.f, top_controls_manager_->ContentTopOffset());
 
   active_tree_->GetViewportSelection(&metadata.selection_start,
                                      &metadata.selection_end);
@@ -1453,10 +1448,6 @@
   return metadata;
 }
 
-static void LayerTreeHostImplDidBeginTracingCallback(LayerImpl* layer) {
-  layer->DidBeginTracing();
-}
-
 void LayerTreeHostImpl::DrawLayers(FrameData* frame,
                                    base::TimeTicks frame_begin_time) {
   TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers");
@@ -1506,11 +1497,11 @@
     if (pending_tree_) {
       LayerTreeHostCommon::CallFunctionForSubtree(
           pending_tree_->root_layer(),
-          base::Bind(&LayerTreeHostImplDidBeginTracingCallback));
+          [](LayerImpl* layer) { layer->DidBeginTracing(); });
     }
     LayerTreeHostCommon::CallFunctionForSubtree(
         active_tree_->root_layer(),
-        base::Bind(&LayerTreeHostImplDidBeginTracingCallback));
+        [](LayerImpl* layer) { layer->DidBeginTracing(); });
   }
 
   {
@@ -1662,7 +1653,7 @@
   LayerImpl* inner_container = active_tree_->InnerViewportContainerLayer();
   LayerImpl* outer_container = active_tree_->OuterViewportContainerLayer();
 
-  if (!inner_container || !top_controls_manager_)
+  if (!inner_container)
     return;
 
   ViewportAnchor anchor(InnerViewportScrollLayer(),
@@ -2360,8 +2351,7 @@
     InputHandler::ScrollInputType type) {
   TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBegin");
 
-  if (top_controls_manager_)
-    top_controls_manager_->ScrollBegin();
+  top_controls_manager_->ScrollBegin();
 
   DCHECK(!CurrentlyScrollingLayer());
   ClearCurrentlyScrollingLayer();
@@ -2572,9 +2562,6 @@
     const gfx::Vector2dF& scroll_delta) const {
   DCHECK(CurrentlyScrollingLayer());
 
-  if (!top_controls_manager_)
-    return false;
-
   // Always consume if it's in the direction to show the top controls.
   if (scroll_delta.y() < 0)
     return true;
@@ -2815,8 +2802,7 @@
 }
 
 void LayerTreeHostImpl::ScrollEnd() {
-  if (top_controls_manager_)
-    top_controls_manager_->ScrollEnd();
+  top_controls_manager_->ScrollEnd();
   ClearCurrentlyScrollingLayer();
 }
 
@@ -2937,8 +2923,7 @@
     active_tree_->SetCurrentlyScrollingLayer(
         active_tree_->InnerViewportScrollLayer());
   }
-  if (top_controls_manager_)
-    top_controls_manager_->PinchBegin();
+  top_controls_manager_->PinchBegin();
 }
 
 void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
@@ -2997,8 +2982,7 @@
     pinch_gesture_end_should_clear_scrolling_layer_ = false;
     ClearCurrentlyScrollingLayer();
   }
-  if (top_controls_manager_)
-    top_controls_manager_->PinchEnd();
+  top_controls_manager_->PinchEnd();
   client_->SetNeedsCommitOnImplThread();
   // When a pinch ends, we may be displaying content cached at incorrect scales,
   // so updating draw properties and drawing will ensure we are using the right
@@ -3093,7 +3077,7 @@
 }
 
 void LayerTreeHostImpl::AnimateTopControls(base::TimeTicks time) {
-  if (!top_controls_manager_ || !top_controls_manager_->animation())
+  if (!top_controls_manager_->animation())
     return;
 
   gfx::Vector2dF scroll = top_controls_manager_->Animate(time);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index b5e3a81..7ffa683 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -2473,7 +2473,6 @@
       : layer_size_(10, 10),
         clip_size_(layer_size_),
         top_controls_height_(50) {
-    settings_.calculate_top_controls_position = true;
     settings_.use_pinch_virtual_viewport = true;
 
     viewport_size_ = gfx::Size(clip_size_.width(),
@@ -2484,7 +2483,7 @@
                       scoped_ptr<OutputSurface> output_surface) override {
     bool init =
         LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
-    if (init && settings.calculate_top_controls_position) {
+    if (init) {
       host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
       host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
     }
@@ -7426,7 +7425,6 @@
  public:
   void SetUp() override {
     LayerTreeSettings settings = DefaultSettings();
-    settings.calculate_top_controls_position = true;
     CreateHostImpl(settings, CreateOutputSurface());
     host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
     host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index eecc5a0..7b0e53b 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -282,6 +282,188 @@
 
 #endif  // !defined(OS_WIN)
 
+class CheckerContentLayerClient : public ContentLayerClient {
+ public:
+  CheckerContentLayerClient(const gfx::Size& bounds,
+                           SkColor color,
+                           bool vertical)
+      : bounds_(bounds), color_(color), vertical_(vertical) {}
+  ~CheckerContentLayerClient() override {}
+  bool FillsBoundsCompletely() const override { return false; }
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& rect,
+                     PaintingControlSetting picture_control) override {
+    SkPaint paint;
+    paint.setStyle(SkPaint::kStroke_Style);
+    paint.setStrokeWidth(SkIntToScalar(4));
+    paint.setColor(color_);
+    canvas->clear(SK_ColorTRANSPARENT);
+    if (vertical_) {
+      for (int i = 4; i < bounds_.width(); i += 16) {
+        canvas->drawLine(i, 0, i, bounds_.height(), paint);
+      }
+    } else {
+      for (int i = 4; i < bounds_.height(); i += 16) {
+        canvas->drawLine(0, i, bounds_.width(), i, paint);
+      }
+    }
+  }
+  scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
+      const gfx::Rect& clip,
+      PaintingControlSetting picture_control) override {
+    NOTIMPLEMENTED();
+    return DisplayItemList::Create();
+  }
+
+ private:
+  gfx::Size bounds_;
+  SkColor color_;
+  bool vertical_;
+};
+
+class CircleContentLayerClient : public ContentLayerClient {
+ public:
+  explicit CircleContentLayerClient(const gfx::Size& bounds)
+      : bounds_(bounds) {}
+  ~CircleContentLayerClient() override {}
+  bool FillsBoundsCompletely() const override { return false; }
+  void PaintContents(SkCanvas* canvas,
+                     const gfx::Rect& rect,
+                     PaintingControlSetting picture_control) override {
+    SkPaint paint;
+    paint.setStyle(SkPaint::kFill_Style);
+    paint.setColor(SK_ColorWHITE);
+    canvas->clear(SK_ColorTRANSPARENT);
+    canvas->drawCircle(bounds_.width() / 2,
+                       bounds_.height() / 2,
+                       bounds_.width() / 4,
+                       paint);
+  }
+  scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
+      const gfx::Rect& clip,
+      PaintingControlSetting picture_control) override {
+    NOTIMPLEMENTED();
+    return DisplayItemList::Create();
+  }
+
+ private:
+  gfx::Size bounds_;
+};
+
+using LayerTreeHostMasksForBackgroundFiltersPixelTest =
+    ParameterizedPixelResourceTest;
+
+INSTANTIATE_TEST_CASE_P(
+    PixelResourceTest,
+    LayerTreeHostMasksForBackgroundFiltersPixelTest,
+    ::testing::Values(
+        // SOFTWARE, Background filters aren't implemented in software
+        GL_GPU_RASTER_2D_DRAW,
+        GL_ONE_COPY_2D_STAGING_2D_DRAW,
+        GL_ONE_COPY_RECT_STAGING_2D_DRAW,
+        GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW,
+        GL_ZERO_COPY_2D_DRAW,
+        GL_ZERO_COPY_RECT_DRAW,
+        GL_ZERO_COPY_EXTERNAL_DRAW,
+        GL_ASYNC_UPLOAD_2D_DRAW));
+
+TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
+       MaskOfLayerWithBackgroundFilter) {
+  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
+      gfx::Rect(256, 256), SK_ColorWHITE);
+
+  gfx::Size picture_bounds(256, 256);
+  CheckerContentLayerClient picture_client(picture_bounds, SK_ColorGREEN, true);
+  scoped_refptr<PictureLayer> picture = PictureLayer::Create(&picture_client);
+  picture->SetBounds(picture_bounds);
+  picture->SetIsDrawable(true);
+
+  scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayer(
+      gfx::Rect(256, 256), SK_ColorTRANSPARENT);
+  background->AddChild(picture);
+  background->AddChild(blur);
+
+  FilterOperations filters;
+  filters.Append(FilterOperation::CreateBlurFilter(2.f));
+  blur->SetBackgroundFilters(filters);
+
+  gfx::Size mask_bounds(256, 256);
+  CircleContentLayerClient mask_client(mask_bounds);
+  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client);
+  mask->SetBounds(mask_bounds);
+  mask->SetIsDrawable(true);
+  mask->SetIsMask(true);
+  blur->SetMaskLayer(mask.get());
+
+  float percentage_pixels_large_error = 2.5f;  // 2.5%, ~1600px / (256*256)
+  float percentage_pixels_small_error = 0.0f;
+  float average_error_allowed_in_bad_pixels = 60.0f;
+  int large_error_allowed = 100;
+  int small_error_allowed = 0;
+  pixel_comparator_.reset(new FuzzyPixelComparator(
+      true,  // discard_alpha
+      percentage_pixels_large_error,
+      percentage_pixels_small_error,
+      average_error_allowed_in_bad_pixels,
+      large_error_allowed,
+      small_error_allowed));
+
+  RunPixelResourceTest(background,
+                       base::FilePath(
+                           FILE_PATH_LITERAL("mask_of_background_filter.png")));
+}
+
+TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
+       MaskOfLayerWithBlend) {
+  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
+      gfx::Rect(256, 256), SK_ColorWHITE);
+
+  gfx::Size picture_bounds(256, 256);
+  CheckerContentLayerClient picture_client_vertical(
+      picture_bounds, SK_ColorGREEN, true);
+  scoped_refptr<PictureLayer> picture_vertical =
+      PictureLayer::Create(&picture_client_vertical);
+  picture_vertical->SetBounds(picture_bounds);
+  picture_vertical->SetIsDrawable(true);
+
+  CheckerContentLayerClient picture_client_horizontal(
+      picture_bounds, SK_ColorMAGENTA, false);
+  scoped_refptr<PictureLayer> picture_horizontal =
+      PictureLayer::Create(&picture_client_horizontal);
+  picture_horizontal->SetBounds(picture_bounds);
+  picture_horizontal->SetIsDrawable(true);
+  picture_horizontal->SetContentsOpaque(false);
+  picture_horizontal->SetBlendMode(SkXfermode::kMultiply_Mode);
+
+  background->AddChild(picture_vertical);
+  background->AddChild(picture_horizontal);
+
+  gfx::Size mask_bounds(256, 256);
+  CircleContentLayerClient mask_client(mask_bounds);
+  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client);
+  mask->SetBounds(mask_bounds);
+  mask->SetIsDrawable(true);
+  mask->SetIsMask(true);
+  picture_horizontal->SetMaskLayer(mask.get());
+
+  float percentage_pixels_large_error = 0.01f;  // 0.01%, ~6px / (256*256)
+  float percentage_pixels_small_error = 0.0f;
+  float average_error_allowed_in_bad_pixels = 256.0f;
+  int large_error_allowed = 256;
+  int small_error_allowed = 0;
+  pixel_comparator_.reset(new FuzzyPixelComparator(
+      true,  // discard_alpha
+      percentage_pixels_large_error,
+      percentage_pixels_small_error,
+      average_error_allowed_in_bad_pixels,
+      large_error_allowed,
+      small_error_allowed));
+
+  RunPixelResourceTest(background,
+                       base::FilePath(
+                           FILE_PATH_LITERAL("mask_of_layer_with_blend.png")));
+}
+
 }  // namespace
 }  // namespace cc
 
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index f9b690d..1be61a5 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1438,7 +1438,6 @@
         // Verify that used texture is correct.
         EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
         EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
-        context->ResetUsedTextures();
         break;
       case 1:
         // Number of textures should be doubled as the first context layer
@@ -1456,7 +1455,6 @@
         // New textures should have been used.
         EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
         EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
-        context->ResetUsedTextures();
         break;
       case 2:
         EndTest();
@@ -2656,8 +2654,8 @@
                                   GLenum type,
                                   GLintptr offset));
   MOCK_METHOD1(deleteTexture, void(GLenum texture));
-  MOCK_METHOD2(produceTextureCHROMIUM,
-               void(GLenum target, const GLbyte* mailbox));
+  MOCK_METHOD3(produceTextureDirectCHROMIUM,
+               void(GLuint texture, GLenum target, const GLbyte* mailbox));
 };
 
 class LayerTreeHostTestIOSurfaceDrawing : public LayerTreeHostTest {
@@ -2747,12 +2745,10 @@
               resource_provider->TargetForTesting(
                   io_surface_draw_quad->io_surface_resource_id));
 
-    EXPECT_CALL(*mock_context_, bindTexture(GL_TEXTURE_RECTANGLE_ARB, 1))
-        .Times(1);
     if (delegating_renderer()) {
       // The io surface layer's resource should be sent to the parent.
-      EXPECT_CALL(*mock_context_,
-                  produceTextureCHROMIUM(GL_TEXTURE_RECTANGLE_ARB, _)).Times(1);
+      EXPECT_CALL(*mock_context_, produceTextureDirectCHROMIUM(
+                                      _, GL_TEXTURE_RECTANGLE_ARB, _)).Times(1);
     } else {
       // The io surface layer's texture is drawn.
       EXPECT_CALL(*mock_context_, activeTexture(GL_TEXTURE0)).Times(AtLeast(1));
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 62e4cd3..5114fdc 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -121,13 +121,18 @@
 }
 
 void LayerTreeImpl::ReleaseResources() {
-  if (root_layer_)
-    ProcessLayersRecursive(root_layer_.get(), &LayerImpl::ReleaseResources);
+  if (root_layer_) {
+    LayerTreeHostCommon::CallFunctionForSubtree(
+        root_layer_.get(), [](LayerImpl* layer) { layer->ReleaseResources(); });
+  }
 }
 
 void LayerTreeImpl::RecreateResources() {
-  if (root_layer_)
-    ProcessLayersRecursive(root_layer_.get(), &LayerImpl::RecreateResources);
+  if (root_layer_) {
+    LayerTreeHostCommon::CallFunctionForSubtree(
+        root_layer_.get(),
+        [](LayerImpl* layer) { layer->RecreateResources(); });
+  }
 }
 
 void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
@@ -475,10 +480,6 @@
                                            gfx::Rect(layer->content_bounds()));
 }
 
-static void ApplySentScrollDeltasFromAbortedCommitTo(LayerImpl* layer) {
-  layer->ApplySentScrollDeltasFromAbortedCommit();
-}
-
 void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() {
   DCHECK(IsActiveTree());
 
@@ -490,7 +491,9 @@
     return;
 
   LayerTreeHostCommon::CallFunctionForSubtree(
-      root_layer(), base::Bind(&ApplySentScrollDeltasFromAbortedCommitTo));
+      root_layer(), [](LayerImpl* layer) {
+        layer->ApplySentScrollDeltasFromAbortedCommit();
+      });
 }
 
 void LayerTreeImpl::SetViewportLayersFromIds(
@@ -748,17 +751,6 @@
           currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0));
 }
 
-static void DidBecomeActiveRecursive(LayerImpl* layer) {
-  layer->DidBecomeActive();
-  if (layer->mask_layer())
-    layer->mask_layer()->DidBecomeActive();
-  if (layer->replica_layer() && layer->replica_layer()->mask_layer())
-    layer->replica_layer()->mask_layer()->DidBecomeActive();
-
-  for (size_t i = 0; i < layer->children().size(); ++i)
-    DidBecomeActiveRecursive(layer->children()[i]);
-}
-
 void LayerTreeImpl::DidBecomeActive() {
   if (next_activation_forces_redraw_) {
     layer_tree_host_impl_->SetFullRootLayerDamage();
@@ -774,8 +766,10 @@
   // if we were in a good state.
   layer_tree_host_impl_->ResetRequiresHighResToDraw();
 
-  if (root_layer())
-    DidBecomeActiveRecursive(root_layer());
+  if (root_layer()) {
+    LayerTreeHostCommon::CallFunctionForSubtree(
+        root_layer(), [](LayerImpl* layer) { layer->DidBecomeActive(); });
+  }
 
   devtools_instrumentation::DidActivateLayerTree(layer_tree_host_impl_->id(),
                                                  source_frame_number_);
@@ -1267,18 +1261,6 @@
   return layers_with_copy_output_request_;
 }
 
-void LayerTreeImpl::ProcessLayersRecursive(LayerImpl* current,
-                                           void (LayerImpl::*function)()) {
-  DCHECK(current);
-  (current->*function)();
-  if (current->mask_layer())
-    ProcessLayersRecursive(current->mask_layer(), function);
-  if (current->replica_layer())
-    ProcessLayersRecursive(current->replica_layer(), function);
-  for (size_t i = 0; i < current->children().size(); ++i)
-    ProcessLayersRecursive(current->children()[i], function);
-}
-
 template <typename LayerType>
 static inline bool LayerClipsSubtree(LayerType* layer) {
   return layer->masks_to_bounds() || layer->mask_layer();
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index f7b6ee4..3105e6f 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -335,8 +335,6 @@
       scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
       scoped_refptr<SyncedTopControls> top_controls_shown_ratio,
       scoped_refptr<SyncedElasticOverscroll> elastic_overscroll);
-  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 9d605ae..0088e91 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -39,7 +39,6 @@
       scrollbar_fade_duration_ms(0),
       scrollbar_show_scale_threshold(1.0f),
       solid_color_scrollbar_color(SK_ColorWHITE),
-      calculate_top_controls_position(false),
       timeout_and_draw_when_animation_checkerboards(true),
       maximum_number_of_failed_draws_before_draw_is_forced_(3),
       layer_transforms_should_scale_layer_contents(false),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 06c319a..ce8d856 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -51,7 +51,6 @@
   int scrollbar_fade_duration_ms;
   float scrollbar_show_scale_threshold;
   SkColor solid_color_scrollbar_color;
-  bool calculate_top_controls_position;
   bool timeout_and_draw_when_animation_checkerboards;
   int maximum_number_of_failed_draws_before_draw_is_forced_;
   bool layer_transforms_should_scale_layer_contents;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 0c080dd..6f3f792 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -128,10 +128,9 @@
                                  layer->should_flatten_transform() &&
                                  !layer->parent()->should_flatten_transform();
 
-  bool requires_node = is_root || is_scrollable || is_fixed ||
-                       has_significant_transform || has_animated_transform ||
-                       is_page_scale_application_layer || flattening_change ||
-                       has_surface;
+  bool requires_node = is_root || is_scrollable || has_significant_transform ||
+                       has_animated_transform || has_surface ||
+                       is_page_scale_application_layer || flattening_change;
 
   Layer* transform_parent = GetTransformParent(data_from_ancestor, layer);
 
@@ -139,8 +138,21 @@
   gfx::Vector2dF parent_offset;
   if (transform_parent) {
     // TODO(vollick): This is to mimic existing bugs (crbug.com/441447).
-    if (!is_fixed)
+    if (!is_fixed) {
       parent_offset = transform_parent->offset_to_transform_parent();
+    } else if (data_from_ancestor.transform_tree_parent !=
+               data_from_ancestor.transform_fixed_parent) {
+      gfx::Vector2dF fixed_offset = data_from_ancestor.transform_tree_parent
+                                        ->offset_to_transform_parent();
+      gfx::Transform parent_to_parent;
+      data_from_ancestor.transform_tree->ComputeTransform(
+          data_from_ancestor.transform_tree_parent->transform_tree_index(),
+          data_from_ancestor.transform_fixed_parent->transform_tree_index(),
+          &parent_to_parent);
+
+      fixed_offset += parent_to_parent.To2dTranslation();
+      parent_offset += fixed_offset;
+    }
 
     gfx::Transform to_parent;
     Layer* source = data_from_ancestor.transform_tree_parent;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index e45b182..401a4b8 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -104,7 +104,6 @@
                           scheduler_settings,
                           layer_tree_host_->id(),
                           MainThreadTaskRunner(),
-                          base::PowerMonitor::Get(),
                           external_begin_frame_source_.Pass());
     scheduler_on_impl_thread_->SetCanStart();
     scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 4efb401..8c766f2 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -1171,7 +1171,6 @@
                          scheduler_settings,
                          impl().layer_tree_host_id,
                          ImplThreadTaskRunner(),
-                         base::PowerMonitor::Get(),
                          impl().external_begin_frame_source.Pass());
   impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible());
   impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
diff --git a/examples/bitmap_uploader/bitmap_uploader.h b/examples/bitmap_uploader/bitmap_uploader.h
index d7c84c2..56d06dd 100644
--- a/examples/bitmap_uploader/bitmap_uploader.h
+++ b/examples/bitmap_uploader/bitmap_uploader.h
@@ -22,7 +22,7 @@
 class BitmapUploader : public ResourceReturner {
  public:
   explicit BitmapUploader(View* view);
-  virtual ~BitmapUploader();
+  ~BitmapUploader() override;
 
   void Init(Shell* shell);
 
diff --git a/examples/browser/browser.cc b/examples/browser/browser.cc
index 527cbb9..22c6f1e 100644
--- a/examples/browser/browser.cc
+++ b/examples/browser/browser.cc
@@ -39,7 +39,7 @@
     browser_host_services_impl_.AddService(this);
   }
 
-  virtual ~Browser() {
+  ~Browser() override {
     if (root_)
       root_->RemoveObserver(this);
   }
diff --git a/examples/content_handler_demo/content_handler_demo.cc b/examples/content_handler_demo/content_handler_demo.cc
index 29166f8..e0081ee 100644
--- a/examples/content_handler_demo/content_handler_demo.cc
+++ b/examples/content_handler_demo/content_handler_demo.cc
@@ -21,17 +21,17 @@
                        ScopedDataPipeConsumerHandle body)
       : binding_(this, request.Pass()), body_(body.Pass()) {}
 
-  virtual void Initialize(ShellPtr shell,
-                          Array<String> args,
-                          const mojo::String& url) override {
+  void Initialize(ShellPtr shell,
+                  Array<String> args,
+                  const mojo::String& url) override {
     shell_ = shell.Pass();
   }
-  virtual void RequestQuit() override {}
+  void RequestQuit() override {}
 
-  virtual void AcceptConnection(const String& requestor_url,
-                                InterfaceRequest<ServiceProvider> services,
-                                ServiceProviderPtr exported_services,
-                                const String& url) override {
+  void AcceptConnection(const String& requestor_url,
+                        InterfaceRequest<ServiceProvider> services,
+                        ServiceProviderPtr exported_services,
+                        const String& url) override {
     printf(
         "ContentHandler::OnConnect - url:%s - requestor_url:%s - body "
         "follows\n\n",
diff --git a/examples/echo/echo_client.cc b/examples/echo/echo_client.cc
index 5e18a07..36b0fd3 100644
--- a/examples/echo/echo_client.cc
+++ b/examples/echo/echo_client.cc
@@ -25,7 +25,7 @@
 
 class EchoClientDelegate : public ApplicationDelegate {
  public:
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     app->ConnectToService("mojo:echo_server", &echo_);
 
     echo_->EchoString("hello world", ResponsePrinter());
diff --git a/examples/embedded_app/embedded_app.cc b/examples/embedded_app/embedded_app.cc
index cc3d6b0..e1ddcd0 100644
--- a/examples/embedded_app/embedded_app.cc
+++ b/examples/embedded_app/embedded_app.cc
@@ -50,43 +50,42 @@
       public ViewObserver {
  public:
   EmbeddedApp() : shell_(nullptr) { url::AddStandardScheme("mojo"); }
-  virtual ~EmbeddedApp() {}
+  ~EmbeddedApp() override {}
 
  private:
 
   // Overridden from ApplicationDelegate:
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     shell_ = app->shell();
     view_manager_client_factory_.reset(
         new ViewManagerClientFactory(app->shell(), this));
   }
 
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->AddService(view_manager_client_factory_.get());
     return true;
   }
 
   // Overridden from ViewManagerDelegate:
-  virtual void OnEmbed(View* root,
-                       InterfaceRequest<ServiceProvider> services,
-                       ServiceProviderPtr exposed_services) override {
+  void OnEmbed(View* root,
+               InterfaceRequest<ServiceProvider> services,
+               ServiceProviderPtr exposed_services) override {
     root->AddObserver(this);
     Window* window = new Window(root, exposed_services.Pass(), shell_);
     windows_[root->id()] = window;
     window->bitmap_uploader.SetColor(
         kColors[next_color_++ % arraysize(kColors)]);
   }
-  virtual void OnViewManagerDisconnected(ViewManager* view_manager) override {
+  void OnViewManagerDisconnected(ViewManager* view_manager) override {
     base::MessageLoop::current()->Quit();
   }
 
   // Overridden from ViewObserver:
-  virtual void OnViewDestroyed(View* view) override {
+  void OnViewDestroyed(View* view) override {
     DCHECK(windows_.find(view->id()) != windows_.end());
     windows_.erase(view->id());
   }
-  virtual void OnViewInputEvent(View* view, const EventPtr& event) override {
+  void OnViewInputEvent(View* view, const EventPtr& event) override {
     if (event->action == EVENT_TYPE_MOUSE_RELEASED) {
       if (event->flags & EVENT_FLAGS_LEFT_MOUSE_BUTTON) {
         URLRequestPtr request(URLRequest::New());
diff --git a/examples/forwarding_content_handler/forwarding_content_handler.cc b/examples/forwarding_content_handler/forwarding_content_handler.cc
index fbee750..b394f99 100644
--- a/examples/forwarding_content_handler/forwarding_content_handler.cc
+++ b/examples/forwarding_content_handler/forwarding_content_handler.cc
@@ -57,14 +57,13 @@
 
  private:
   // Overridden from ApplicationDelegate:
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->AddService(&content_handler_factory_);
     return true;
   }
 
   // Overridden from ContentHandlerFactory::ManagedDelegate:
-  virtual scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
+  scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
   CreateApplication(InterfaceRequest<Application> application_request,
                     URLResponsePtr response) override {
     CHECK(!response.is_null());
diff --git a/examples/ganesh_app/ganesh_app.cc b/examples/ganesh_app/ganesh_app.cc
index 0896fb4..9c860cc 100644
--- a/examples/ganesh_app/ganesh_app.cc
+++ b/examples/ganesh_app/ganesh_app.cc
@@ -19,7 +19,7 @@
                   public mojo::ViewManagerDelegate {
  public:
   GaneshApp() {}
-  virtual ~GaneshApp() {}
+  ~GaneshApp() override {}
 
   void Initialize(mojo::ApplicationImpl* app) override {
     shell_ = app->shell();
diff --git a/examples/ganesh_app/ganesh_view.h b/examples/ganesh_app/ganesh_view.h
index a066bcd..d072893 100644
--- a/examples/ganesh_app/ganesh_view.h
+++ b/examples/ganesh_app/ganesh_view.h
@@ -20,7 +20,7 @@
 class GaneshView : public TextureUploader::Client, public mojo::ViewObserver {
  public:
   GaneshView(mojo::Shell* shell, mojo::View* view);
-  ~GaneshView();
+  ~GaneshView() override;
 
  private:
   void OnViewDestroyed(mojo::View* view) override;
diff --git a/examples/ganesh_app/texture_uploader.h b/examples/ganesh_app/texture_uploader.h
index 01374c5..20fc6da 100644
--- a/examples/ganesh_app/texture_uploader.h
+++ b/examples/ganesh_app/texture_uploader.h
@@ -34,7 +34,7 @@
   TextureUploader(Client* client,
                   mojo::Shell* shell,
                   base::WeakPtr<mojo::GLContext> context);
-  ~TextureUploader();
+  ~TextureUploader() override;
 
   void Upload(scoped_ptr<mojo::GLTexture> texture);
 
diff --git a/examples/nesting_app/nesting_app.cc b/examples/nesting_app/nesting_app.cc
index 7d45df2..5b00f6d 100644
--- a/examples/nesting_app/nesting_app.cc
+++ b/examples/nesting_app/nesting_app.cc
@@ -39,28 +39,27 @@
       public ViewObserver {
  public:
   NestingApp() : nested_(nullptr), shell_(nullptr) {}
-  virtual ~NestingApp() {}
+  ~NestingApp() override {}
 
  private:
   // Overridden from ApplicationDelegate:
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     shell_ = app->shell();
     view_manager_client_factory_.reset(
         new ViewManagerClientFactory(app->shell(), this));
   }
 
   // Overridden from ApplicationImpl:
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->ConnectToService(&window_manager_);
     connection->AddService(view_manager_client_factory_.get());
     return true;
   }
 
   // Overridden from ViewManagerDelegate:
-  virtual void OnEmbed(View* root,
-                       InterfaceRequest<ServiceProvider> services,
-                       ServiceProviderPtr exposed_services) override {
+  void OnEmbed(View* root,
+               InterfaceRequest<ServiceProvider> services,
+               ServiceProviderPtr exposed_services) override {
     root->AddObserver(this);
     bitmap_uploader_.reset(new BitmapUploader(root));
     bitmap_uploader_->Init(shell_);
@@ -75,16 +74,16 @@
     nested_->SetVisible(true);
     nested_->Embed(kEmbeddedAppURL);
   }
-  virtual void OnViewManagerDisconnected(ViewManager* view_manager) override {
-    base::MessageLoop::current()->Quit();
+  void OnViewManagerDisconnected(ViewManager* view_manager) override {
+   base::MessageLoop::current()->Quit();
   }
 
   // Overridden from ViewObserver:
-  virtual void OnViewDestroyed(View* view) override {
+  void OnViewDestroyed(View* view) override {
     // TODO(beng): reap views & child Views.
     nested_ = NULL;
   }
-  virtual void OnViewInputEvent(View* view, const EventPtr& event) override {
+  void OnViewInputEvent(View* view, const EventPtr& event) override {
     if (event->action == EVENT_TYPE_MOUSE_RELEASED)
       window_manager_->CloseWindow(view->id());
   }
diff --git a/examples/pdf_viewer/pdf_viewer.cc b/examples/pdf_viewer/pdf_viewer.cc
index 8fb502d..bd9ff04 100644
--- a/examples/pdf_viewer/pdf_viewer.cc
+++ b/examples/pdf_viewer/pdf_viewer.cc
@@ -58,7 +58,7 @@
     FetchPDF(response.Pass());
   }
 
-  virtual ~PDFView() {
+  ~PDFView() override {
     if (doc_)
       FPDF_CloseDocument(doc_);
     for (auto& roots : embedder_for_roots_) {
@@ -69,22 +69,21 @@
 
  private:
   // Overridden from ApplicationDelegate:
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     app_ = app;
     view_manager_client_factory_.reset(
         new ViewManagerClientFactory(app->shell(), this));
   }
 
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->AddService(view_manager_client_factory_.get());
     return true;
   }
 
   // Overridden from ViewManagerDelegate:
-  virtual void OnEmbed(View* root,
-                       InterfaceRequest<ServiceProvider> services,
-                       ServiceProviderPtr exposed_services) override {
+  void OnEmbed(View* root,
+               InterfaceRequest<ServiceProvider> services,
+               ServiceProviderPtr exposed_services) override {
     DCHECK(embedder_for_roots_.find(root) == embedder_for_roots_.end());
     root->AddObserver(this);
     EmbedderData* embedder_data = new EmbedderData(app_->shell(), root);
@@ -92,17 +91,17 @@
     DrawBitmap(embedder_data);
   }
 
-  virtual void OnViewManagerDisconnected(ViewManager* view_manager) override {}
+  void OnViewManagerDisconnected(ViewManager* view_manager) override {}
 
   // Overridden from ViewObserver:
-  virtual void OnViewBoundsChanged(View* view,
-                                   const Rect& old_bounds,
-                                   const Rect& new_bounds) override {
+  void OnViewBoundsChanged(View* view,
+                           const Rect& old_bounds,
+                           const Rect& new_bounds) override {
     DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end());
     DrawBitmap(embedder_for_roots_[view]);
   }
 
-  virtual void OnViewInputEvent(View* view, const EventPtr& event) override {
+  void OnViewInputEvent(View* view, const EventPtr& event) override {
     DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end());
     if (event->key_data &&
         (event->action != EVENT_TYPE_KEY_PRESSED || event->key_data->is_char)) {
@@ -125,7 +124,7 @@
     }
   }
 
-  virtual void OnViewDestroyed(View* view) override {
+  void OnViewDestroyed(View* view) override {
     DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end());
     const auto& it = embedder_for_roots_.find(view);
     DCHECK(it != embedder_for_roots_.end());
@@ -218,18 +217,17 @@
     FPDF_InitLibrary();
   }
 
-  virtual ~PDFViewer() { FPDF_DestroyLibrary(); }
+  ~PDFViewer() override { FPDF_DestroyLibrary(); }
 
  private:
   // Overridden from ApplicationDelegate:
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->AddService(&content_handler_factory_);
     return true;
   }
 
   // Overridden from ContentHandlerFactory::ManagedDelegate:
-  virtual scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
+  scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
   CreateApplication(InterfaceRequest<Application> application_request,
                     URLResponsePtr response) override {
     return make_handled_factory_holder(new mojo::ApplicationImpl(
diff --git a/examples/png_viewer/png_viewer.cc b/examples/png_viewer/png_viewer.cc
index e929cdb..8e0be4d 100644
--- a/examples/png_viewer/png_viewer.cc
+++ b/examples/png_viewer/png_viewer.cc
@@ -62,7 +62,7 @@
     DecodePNG(response.Pass());
   }
 
-  virtual ~PNGView() {
+  ~PNGView() override {
     for (auto& roots : embedder_for_roots_) {
       roots.first->RemoveObserver(this);
       delete roots.second;
@@ -76,23 +76,23 @@
   static const uint16_t kZoomStep = 20;
 
   // Overridden from ApplicationDelegate:
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     app_ = app;
     view_manager_client_factory_.reset(
         new ViewManagerClientFactory(app->shell(), this));
   }
 
   // Overridden from ApplicationDelegate:
-  virtual bool ConfigureIncomingConnection(
+  bool ConfigureIncomingConnection(
       ApplicationConnection* connection) override {
     connection->AddService(view_manager_client_factory_.get());
     return true;
   }
 
   // Overridden from ViewManagerDelegate:
-  virtual void OnEmbed(View* root,
-                       InterfaceRequest<ServiceProvider> services,
-                       ServiceProviderPtr exposed_services) override {
+  void OnEmbed(View* root,
+               InterfaceRequest<ServiceProvider> services,
+               ServiceProviderPtr exposed_services) override {
     // TODO(qsr): The same view should be embeddable on multiple views.
     DCHECK(embedder_for_roots_.find(root) == embedder_for_roots_.end());
     root->AddObserver(this);
@@ -104,17 +104,17 @@
         BitmapUploader::BGRA);
   }
 
-  virtual void OnViewManagerDisconnected(ViewManager* view_manager) override {
+  void OnViewManagerDisconnected(ViewManager* view_manager) override {
   }
 
   // Overridden from ViewObserver:
-  virtual void OnViewBoundsChanged(View* view,
-                                   const Rect& old_bounds,
-                                   const Rect& new_bounds) override {
+  void OnViewBoundsChanged(View* view,
+                           const Rect& old_bounds,
+                           const Rect& new_bounds) override {
     DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end());
   }
 
-  virtual void OnViewDestroyed(View* view) override {
+  void OnViewDestroyed(View* view) override {
     // TODO(aa): Need to figure out how shutdown works.
     const auto& it = embedder_for_roots_.find(view);
     DCHECK(it != embedder_for_roots_.end());
@@ -202,14 +202,13 @@
 
  private:
   // Overridden from ApplicationDelegate:
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->AddService(&content_handler_factory_);
     return true;
   }
 
   // Overridden from ContentHandlerFactory::ManagedDelegate:
-  virtual scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
+  scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
   CreateApplication(InterfaceRequest<Application> application_request,
                     URLResponsePtr response) override {
     return make_handled_factory_holder(new mojo::ApplicationImpl(
diff --git a/examples/recursive_content_handler/recursive_content_handler.cc b/examples/recursive_content_handler/recursive_content_handler.cc
index 42a73f8..f93c427 100644
--- a/examples/recursive_content_handler/recursive_content_handler.cc
+++ b/examples/recursive_content_handler/recursive_content_handler.cc
@@ -23,14 +23,14 @@
 
  private:
   // Overridden from ApplicationDelegate:
-  virtual bool ConfigureIncomingConnection(
+  bool ConfigureIncomingConnection(
       ApplicationConnection* connection) override {
     connection->AddService(&content_handler_factory_);
     return true;
   }
 
   // Overridden from ContentHandlerFactory::ManagedDelegate:
-  virtual scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
+  scoped_ptr<ContentHandlerFactory::HandledApplicationHolder>
   CreateApplication(InterfaceRequest<Application> application_request,
                     URLResponsePtr response) override {
     LOG(INFO) << "RecursiveContentHandler called with url: " << response->url;
diff --git a/examples/sky_compositor_app/sky_compositor_app.cc b/examples/sky_compositor_app/sky_compositor_app.cc
index 1a72095..dd4589d 100644
--- a/examples/sky_compositor_app/sky_compositor_app.cc
+++ b/examples/sky_compositor_app/sky_compositor_app.cc
@@ -35,7 +35,7 @@
                          public sky::LayerHostClient {
  public:
   SkyCompositorApp() : shell_(nullptr), view_(nullptr) {}
-  virtual ~SkyCompositorApp() {}
+  ~SkyCompositorApp() override {}
 
   void Initialize(mojo::ApplicationImpl* app) override {
     shell_ = app->shell();
diff --git a/examples/surfaces_app/child_app.cc b/examples/surfaces_app/child_app.cc
index f154536..0344610 100644
--- a/examples/surfaces_app/child_app.cc
+++ b/examples/surfaces_app/child_app.cc
@@ -17,23 +17,22 @@
 class ChildApp : public ApplicationDelegate, public InterfaceFactory<Child> {
  public:
   ChildApp() {}
-  virtual ~ChildApp() {}
+  ~ChildApp() override {}
 
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     surfaces_service_connection_ =
         app->ConnectToApplication("mojo:surfaces_service");
   }
 
   // ApplicationDelegate implementation.
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->AddService(this);
     return true;
   }
 
   // InterfaceFactory<Child> implementation.
-  virtual void Create(ApplicationConnection* connection,
-                      InterfaceRequest<Child> request) override {
+  void Create(ApplicationConnection* connection,
+              InterfaceRequest<Child> request) override {
     new ChildImpl(surfaces_service_connection_, request.Pass());
   }
 
diff --git a/examples/surfaces_app/child_gl_app.cc b/examples/surfaces_app/child_gl_app.cc
index 5630b24..77c8561 100644
--- a/examples/surfaces_app/child_gl_app.cc
+++ b/examples/surfaces_app/child_gl_app.cc
@@ -19,9 +19,9 @@
 class ChildGLApp : public ApplicationDelegate, public InterfaceFactory<Child> {
  public:
   ChildGLApp() {}
-  virtual ~ChildGLApp() {}
+  ~ChildGLApp() override {}
 
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     surfaces_service_connection_ =
         app->ConnectToApplication("mojo:surfaces_service");
     // TODO(jamesr): Should be mojo:gpu_service
@@ -29,15 +29,15 @@
   }
 
   // ApplicationDelegate implementation.
-  virtual bool ConfigureIncomingConnection(
+  bool ConfigureIncomingConnection(
       ApplicationConnection* connection) override {
     connection->AddService(this);
     return true;
   }
 
   // InterfaceFactory<Child> implementation.
-  virtual void Create(ApplicationConnection* connection,
-                      InterfaceRequest<Child> request) override {
+  void Create(ApplicationConnection* connection,
+              InterfaceRequest<Child> request) override {
     CommandBufferPtr command_buffer;
     gpu_service_->CreateOffscreenGLES2Context(GetProxy(&command_buffer));
     new ChildGLImpl(surfaces_service_connection_, command_buffer.Pass(),
diff --git a/examples/wget/wget.cc b/examples/wget/wget.cc
index 3db71f4..455bf77 100644
--- a/examples/wget/wget.cc
+++ b/examples/wget/wget.cc
@@ -71,7 +71,7 @@
 
 class WGetApp : public ApplicationDelegate {
  public:
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     app->ConnectToService("mojo:network_service", &network_service_);
     Start(app->args());
   }
diff --git a/examples/window_manager/window_manager.cc b/examples/window_manager/window_manager.cc
index fe57255..d363ab9 100644
--- a/examples/window_manager/window_manager.cc
+++ b/examples/window_manager/window_manager.cc
@@ -287,8 +287,7 @@
     window_manager_app_->Initialize(app);
   }
 
-  virtual bool ConfigureIncomingConnection(
-      ApplicationConnection* connection) override {
+  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
     connection->AddService<IWindowManager>(this);
     window_manager_app_->ConfigureIncomingConnection(connection);
     return true;
diff --git a/examples/wm_flow/app/app.cc b/examples/wm_flow/app/app.cc
index 8827191..dcb7ee2 100644
--- a/examples/wm_flow/app/app.cc
+++ b/examples/wm_flow/app/app.cc
@@ -85,13 +85,13 @@
                   public mojo::ViewObserver {
  public:
   WMFlowApp() : shell_(nullptr), embed_count_(0) {}
-  virtual ~WMFlowApp() { STLDeleteValues(&uploaders_); }
+  ~WMFlowApp() override { STLDeleteValues(&uploaders_); }
 
  private:
   typedef std::map<mojo::View*, mojo::BitmapUploader*> ViewToUploader;
 
   // Overridden from ApplicationDelegate:
-  virtual void Initialize(mojo::ApplicationImpl* app) override {
+  void Initialize(mojo::ApplicationImpl* app) override {
     shell_ = app->shell();
     view_manager_client_factory_.reset(
         new mojo::ViewManagerClientFactory(app->shell(), this));
@@ -103,16 +103,16 @@
     OpenNewWindow();
     OpenNewWindow();
   }
-  virtual bool ConfigureIncomingConnection(
+  bool ConfigureIncomingConnection(
       mojo::ApplicationConnection* connection) override {
     connection->AddService(view_manager_client_factory_.get());
     return true;
   }
 
   // Overridden from mojo::ViewManagerDelegate:
-  virtual void OnEmbed(mojo::View* root,
-                       mojo::InterfaceRequest<mojo::ServiceProvider> services,
-                       mojo::ServiceProviderPtr exposed_services) override {
+  void OnEmbed(mojo::View* root,
+               mojo::InterfaceRequest<mojo::ServiceProvider> services,
+               mojo::ServiceProviderPtr exposed_services) override {
     root->AddObserver(this);
     mojo::BitmapUploader* uploader = new mojo::BitmapUploader(root);
     uploaders_[root] = uploader;
@@ -148,20 +148,19 @@
     embeddee_->HelloBack(base::Bind(&WMFlowApp::HelloBackAck,
                                     base::Unretained(this)));
   }
-  virtual void OnViewManagerDisconnected(
-      mojo::ViewManager* view_manager) override {
+  void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override {
     STLDeleteValues(&uploaders_);
   }
 
   // Overridden from mojo::ViewObserver:
-  virtual void OnViewInputEvent(mojo::View* view,
-                                const mojo::EventPtr& event) override {
+  void OnViewInputEvent(mojo::View* view,
+                        const mojo::EventPtr& event) override {
     if (event->action == mojo::EVENT_TYPE_MOUSE_RELEASED &&
         event->flags & mojo::EVENT_FLAGS_LEFT_MOUSE_BUTTON) {
       OpenNewWindow();
     }
   }
-  virtual void OnViewDestroyed(mojo::View* view) override {
+  void OnViewDestroyed(mojo::View* view) override {
     if (uploaders_.find(view) != uploaders_.end()) {
       delete uploaders_[view];
       uploaders_.erase(view);
diff --git a/examples/wm_flow/embedded/embedded.cc b/examples/wm_flow/embedded/embedded.cc
index fe79eee..6c7ac0f 100644
--- a/examples/wm_flow/embedded/embedded.cc
+++ b/examples/wm_flow/embedded/embedded.cc
@@ -50,7 +50,7 @@
   WMFlowEmbedded() : shell_(nullptr) {
     embeddee_provider_impl_.AddService(this);
   }
-  virtual ~WMFlowEmbedded() {}
+  ~WMFlowEmbedded() override {}
 
  private:
   // Overridden from Application:
diff --git a/examples/wm_flow/wm/frame_controller.h b/examples/wm_flow/wm/frame_controller.h
index e251c76..025b1c0 100644
--- a/examples/wm_flow/wm/frame_controller.h
+++ b/examples/wm_flow/wm/frame_controller.h
@@ -36,7 +36,7 @@
                   mojo::View* view,
                   mojo::View** app_view,
                   window_manager::WindowManagerApp* window_manager_app);
-  virtual ~FrameController();
+  ~FrameController() override;
 
   // mojo::InterfaceFactory<examples::WindowFrameHost> implementation.
   void Create(
diff --git a/examples/wm_flow/wm/wm.cc b/examples/wm_flow/wm/wm.cc
index c7dfc52..492f9bb 100644
--- a/examples/wm_flow/wm/wm.cc
+++ b/examples/wm_flow/wm/wm.cc
@@ -29,26 +29,26 @@
         root_(NULL),
         window_container_(NULL),
         next_window_origin_(10, 10) {}
-  virtual ~SimpleWM() {}
+  ~SimpleWM() override {}
 
  private:
   // Overridden from mojo::ApplicationDelegate:
-  virtual void Initialize(mojo::ApplicationImpl* impl) override {
+  void Initialize(mojo::ApplicationImpl* impl) override {
     // FIXME: Mojo applications don't know their URLs yet:
     // https://docs.google.com/a/chromium.org/document/d/1AQ2y6ekzvbdaMF5WrUQmneyXJnke-MnYYL4Gz1AKDos
     url_ = GURL(impl->args()[1]);
     window_manager_app_->Initialize(impl);
   }
-  virtual bool ConfigureIncomingConnection(
+  bool ConfigureIncomingConnection(
       mojo::ApplicationConnection* connection) override {
     window_manager_app_->ConfigureIncomingConnection(connection);
     return true;
   }
 
   // Overridden from mojo::ViewManagerDelegate:
-  virtual void OnEmbed(mojo::View* root,
-                       mojo::InterfaceRequest<mojo::ServiceProvider> services,
-                       mojo::ServiceProviderPtr exposed_services) override {
+  void OnEmbed(mojo::View* root,
+               mojo::InterfaceRequest<mojo::ServiceProvider> services,
+               mojo::ServiceProviderPtr exposed_services) override {
     root_ = root;
 
     window_container_ = root->view_manager()->CreateView();
@@ -59,15 +59,14 @@
     window_manager_app_->InitFocus(make_scoped_ptr(
         new window_manager::BasicFocusRules(window_container_)));
   }
-  virtual void OnViewManagerDisconnected(
-      mojo::ViewManager* view_manager) override {
+  void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override {
     root_ = NULL;
   }
 
   // Overridden from mojo::WindowManagerDelegate:
-  virtual void Embed(const mojo::String& url,
-                     mojo::InterfaceRequest<mojo::ServiceProvider> services,
-                     mojo::ServiceProviderPtr exposed_services) override {
+  void Embed(const mojo::String& url,
+             mojo::InterfaceRequest<mojo::ServiceProvider> services,
+             mojo::ServiceProviderPtr exposed_services) override {
     DCHECK(root_);
     mojo::View* app_view = NULL;
     CreateTopLevelWindow(&app_view);
@@ -75,15 +74,15 @@
   }
 
   // Overridden from mojo::ViewObserver:
-  virtual void OnViewInputEvent(mojo::View* view,
-                                const mojo::EventPtr& event) override {
+  void OnViewInputEvent(mojo::View* view,
+                        const mojo::EventPtr& event) override {
     if (event->action == mojo::EVENT_TYPE_MOUSE_RELEASED &&
         event->flags & mojo::EVENT_FLAGS_RIGHT_MOUSE_BUTTON &&
         view->parent() == window_container_) {
       CloseWindow(view);
     }
   }
-  virtual void OnViewDestroyed(mojo::View* view) override {
+  void OnViewDestroyed(mojo::View* view) override {
     view->RemoveObserver(this);
   }
 
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 5b39586..6f011f7 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -64,221 +64,219 @@
   ]
 }
 
-if (!is_win || link_chrome_on_windows) {
-  test("gl_tests") {
-    sources = [
-      "command_buffer/tests/compressed_texture_test.cc",
-      "command_buffer/tests/gl_bind_uniform_location_unittest.cc",
-      "command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc",
-      "command_buffer/tests/gl_chromium_path_rendering_unittest.cc",
-      "command_buffer/tests/gl_clear_framebuffer_unittest.cc",
-      "command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc",
-      "command_buffer/tests/gl_depth_texture_unittest.cc",
-      "command_buffer/tests/gl_gpu_memory_buffer_unittest.cc",
-      "command_buffer/tests/gl_lose_context_chromium_unittest.cc",
-      "command_buffer/tests/gl_manager.cc",
-      "command_buffer/tests/gl_manager.h",
-      "command_buffer/tests/gl_pointcoord_unittest.cc",
-      "command_buffer/tests/gl_program_unittest.cc",
-      "command_buffer/tests/gl_query_unittest.cc",
-      "command_buffer/tests/gl_readback_unittest.cc",
-      "command_buffer/tests/gl_shared_resources_unittest.cc",
-      "command_buffer/tests/gl_stream_draw_unittest.cc",
-      "command_buffer/tests/gl_test_utils.cc",
-      "command_buffer/tests/gl_test_utils.h",
-      "command_buffer/tests/gl_tests_main.cc",
-      "command_buffer/tests/gl_texture_mailbox_unittest.cc",
-      "command_buffer/tests/gl_texture_storage_unittest.cc",
-      "command_buffer/tests/gl_unittest.cc",
-      "command_buffer/tests/gl_unittests_android.cc",
-      "command_buffer/tests/gl_virtual_contexts_unittest.cc",
-      "command_buffer/tests/occlusion_query_unittest.cc",
-    ]
+test("gl_tests") {
+  sources = [
+    "command_buffer/tests/compressed_texture_test.cc",
+    "command_buffer/tests/gl_bind_uniform_location_unittest.cc",
+    "command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc",
+    "command_buffer/tests/gl_chromium_path_rendering_unittest.cc",
+    "command_buffer/tests/gl_clear_framebuffer_unittest.cc",
+    "command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc",
+    "command_buffer/tests/gl_depth_texture_unittest.cc",
+    "command_buffer/tests/gl_gpu_memory_buffer_unittest.cc",
+    "command_buffer/tests/gl_lose_context_chromium_unittest.cc",
+    "command_buffer/tests/gl_manager.cc",
+    "command_buffer/tests/gl_manager.h",
+    "command_buffer/tests/gl_pointcoord_unittest.cc",
+    "command_buffer/tests/gl_program_unittest.cc",
+    "command_buffer/tests/gl_query_unittest.cc",
+    "command_buffer/tests/gl_readback_unittest.cc",
+    "command_buffer/tests/gl_shared_resources_unittest.cc",
+    "command_buffer/tests/gl_stream_draw_unittest.cc",
+    "command_buffer/tests/gl_test_utils.cc",
+    "command_buffer/tests/gl_test_utils.h",
+    "command_buffer/tests/gl_tests_main.cc",
+    "command_buffer/tests/gl_texture_mailbox_unittest.cc",
+    "command_buffer/tests/gl_texture_storage_unittest.cc",
+    "command_buffer/tests/gl_unittest.cc",
+    "command_buffer/tests/gl_unittests_android.cc",
+    "command_buffer/tests/gl_virtual_contexts_unittest.cc",
+    "command_buffer/tests/occlusion_query_unittest.cc",
+  ]
 
-    defines = [ "GL_GLEXT_PROTOTYPES" ]
+  defines = [ "GL_GLEXT_PROTOTYPES" ]
 
-    configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 
-    deps = [
-      ":gpu",
-      ":test_support",
-      "//base",
-      "//base/test:test_support",
-      "//base/third_party/dynamic_annotations",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//third_party/angle:translator",
-      "//ui/gfx",
-      "//ui/gfx:test_support",
-      "//ui/gfx/geometry",
-      "//ui/gl",
-      "//gpu/command_buffer/common:gles2_utils",
-      "//gpu/command_buffer/client:gles2_c_lib",
-      "//gpu/command_buffer/client:gles2_implementation",
-    ]
+  deps = [
+    ":gpu",
+    ":test_support",
+    "//base",
+    "//base/test:test_support",
+    "//base/third_party/dynamic_annotations",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/angle:translator",
+    "//ui/gfx",
+    "//ui/gfx:test_support",
+    "//ui/gfx/geometry",
+    "//ui/gl",
+    "//gpu/command_buffer/common:gles2_utils",
+    "//gpu/command_buffer/client:gles2_c_lib",
+    "//gpu/command_buffer/client:gles2_implementation",
+  ]
 
-    libs = []
+  libs = []
 
-    if (is_android) {
-      deps += [ "//testing/android:native_test_native_code" ]
-      libs += [ "android" ]
-    }
-
-    # TODO(GYP)
-    #     ['OS == "win"', {
-    #       'dependencies': [
-    #         '../third_party/angle/src/build_angle.gyp:libEGL',
-    #         '../third_party/angle/src/build_angle.gyp:libGLESv2',
-    #       ],
-    #     }],
+  if (is_android) {
+    deps += [ "//testing/android:native_test_native_code" ]
+    libs += [ "android" ]
   }
 
-  test("gpu_unittests") {
-    sources = [
-      "command_buffer/client/buffer_tracker_unittest.cc",
-      "command_buffer/client/client_test_helper.cc",
-      "command_buffer/client/client_test_helper.h",
-      "command_buffer/client/cmd_buffer_helper_test.cc",
-      "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",
-      "command_buffer/client/vertex_array_object_manager_unittest.cc",
-      "command_buffer/common/bitfield_helpers_test.cc",
-      "command_buffer/common/command_buffer_mock.cc",
-      "command_buffer/common/command_buffer_mock.h",
-      "command_buffer/common/command_buffer_shared_test.cc",
-      "command_buffer/common/debug_marker_manager_unittest.cc",
-      "command_buffer/common/gles2_cmd_format_test.cc",
-      "command_buffer/common/gles2_cmd_format_test_autogen.h",
-      "command_buffer/common/gles2_cmd_utils_unittest.cc",
-      "command_buffer/common/id_allocator_test.cc",
-      "command_buffer/common/trace_event.h",
-      "command_buffer/common/unittest_main.cc",
-      "command_buffer/service/async_pixel_transfer_delegate_mock.cc",
-      "command_buffer/service/async_pixel_transfer_delegate_mock.h",
-      "command_buffer/service/async_pixel_transfer_manager_mock.cc",
-      "command_buffer/service/async_pixel_transfer_manager_mock.h",
-      "command_buffer/service/buffer_manager_unittest.cc",
-      "command_buffer/service/cmd_parser_test.cc",
-      "command_buffer/service/command_buffer_service_unittest.cc",
-      "command_buffer/service/common_decoder_unittest.cc",
-      "command_buffer/service/context_group_unittest.cc",
-      "command_buffer/service/feature_info_unittest.cc",
-      "command_buffer/service/framebuffer_manager_unittest.cc",
-      "command_buffer/service/gl_surface_mock.cc",
-      "command_buffer/service/gl_surface_mock.h",
-      "command_buffer/service/gles2_cmd_decoder_unittest.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest.h",
-      "command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h",
-      "command_buffer/service/gles2_cmd_decoder_unittest_1.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h",
-      "command_buffer/service/gles2_cmd_decoder_unittest_2.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h",
-      "command_buffer/service/gles2_cmd_decoder_unittest_3.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h",
-      "command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_base.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_base.h",
-      "command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_programs.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_textures.cc",
-      "command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc",
-      "command_buffer/service/gpu_scheduler_unittest.cc",
-      "command_buffer/service/gpu_service_test.cc",
-      "command_buffer/service/gpu_service_test.h",
-      "command_buffer/service/gpu_tracer_unittest.cc",
-      "command_buffer/service/id_manager_unittest.cc",
-      "command_buffer/service/mailbox_manager_unittest.cc",
-      "command_buffer/service/memory_program_cache_unittest.cc",
-      "command_buffer/service/mocks.cc",
-      "command_buffer/service/mocks.h",
-      "command_buffer/service/program_cache_unittest.cc",
-      "command_buffer/service/program_manager_unittest.cc",
-      "command_buffer/service/query_manager_unittest.cc",
-      "command_buffer/service/renderbuffer_manager_unittest.cc",
-      "command_buffer/service/shader_manager_unittest.cc",
-      "command_buffer/service/shader_translator_cache_unittest.cc",
-      "command_buffer/service/shader_translator_unittest.cc",
-      "command_buffer/service/test_helper.cc",
-      "command_buffer/service/test_helper.h",
-      "command_buffer/service/texture_manager_unittest.cc",
-      "command_buffer/service/transfer_buffer_manager_unittest.cc",
-      "command_buffer/service/valuebuffer_manager_unittest.cc",
-      "command_buffer/service/vertex_array_manager_unittest.cc",
-      "command_buffer/service/vertex_attrib_manager_unittest.cc",
-      "config/gpu_blacklist_unittest.cc",
-      "config/gpu_control_list_entry_unittest.cc",
-      "config/gpu_control_list_number_info_unittest.cc",
-      "config/gpu_control_list_os_info_unittest.cc",
-      "config/gpu_control_list_unittest.cc",
-      "config/gpu_control_list_version_info_unittest.cc",
-      "config/gpu_driver_bug_list_unittest.cc",
-      "config/gpu_info_collector_unittest.cc",
-      "config/gpu_info_unittest.cc",
-      "config/gpu_test_config_unittest.cc",
-      "config/gpu_test_expectations_parser_unittest.cc",
-      "config/gpu_util_unittest.cc",
-    ]
+  # TODO(GYP)
+  #     ['OS == "win"', {
+  #       'dependencies': [
+  #         '../third_party/angle/src/build_angle.gyp:libEGL',
+  #         '../third_party/angle/src/build_angle.gyp:libGLESv2',
+  #       ],
+  #     }],
+}
 
-    configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+test("gpu_unittests") {
+  sources = [
+    "command_buffer/client/buffer_tracker_unittest.cc",
+    "command_buffer/client/client_test_helper.cc",
+    "command_buffer/client/client_test_helper.h",
+    "command_buffer/client/cmd_buffer_helper_test.cc",
+    "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",
+    "command_buffer/client/vertex_array_object_manager_unittest.cc",
+    "command_buffer/common/bitfield_helpers_test.cc",
+    "command_buffer/common/command_buffer_mock.cc",
+    "command_buffer/common/command_buffer_mock.h",
+    "command_buffer/common/command_buffer_shared_test.cc",
+    "command_buffer/common/debug_marker_manager_unittest.cc",
+    "command_buffer/common/gles2_cmd_format_test.cc",
+    "command_buffer/common/gles2_cmd_format_test_autogen.h",
+    "command_buffer/common/gles2_cmd_utils_unittest.cc",
+    "command_buffer/common/id_allocator_test.cc",
+    "command_buffer/common/trace_event.h",
+    "command_buffer/common/unittest_main.cc",
+    "command_buffer/service/async_pixel_transfer_delegate_mock.cc",
+    "command_buffer/service/async_pixel_transfer_delegate_mock.h",
+    "command_buffer/service/async_pixel_transfer_manager_mock.cc",
+    "command_buffer/service/async_pixel_transfer_manager_mock.h",
+    "command_buffer/service/buffer_manager_unittest.cc",
+    "command_buffer/service/cmd_parser_test.cc",
+    "command_buffer/service/command_buffer_service_unittest.cc",
+    "command_buffer/service/common_decoder_unittest.cc",
+    "command_buffer/service/context_group_unittest.cc",
+    "command_buffer/service/feature_info_unittest.cc",
+    "command_buffer/service/framebuffer_manager_unittest.cc",
+    "command_buffer/service/gl_surface_mock.cc",
+    "command_buffer/service/gl_surface_mock.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest_1.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest_2.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest_3.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_base.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_base.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_programs.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_textures.cc",
+    "command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc",
+    "command_buffer/service/gpu_scheduler_unittest.cc",
+    "command_buffer/service/gpu_service_test.cc",
+    "command_buffer/service/gpu_service_test.h",
+    "command_buffer/service/gpu_tracer_unittest.cc",
+    "command_buffer/service/id_manager_unittest.cc",
+    "command_buffer/service/mailbox_manager_unittest.cc",
+    "command_buffer/service/memory_program_cache_unittest.cc",
+    "command_buffer/service/mocks.cc",
+    "command_buffer/service/mocks.h",
+    "command_buffer/service/program_cache_unittest.cc",
+    "command_buffer/service/program_manager_unittest.cc",
+    "command_buffer/service/query_manager_unittest.cc",
+    "command_buffer/service/renderbuffer_manager_unittest.cc",
+    "command_buffer/service/shader_manager_unittest.cc",
+    "command_buffer/service/shader_translator_cache_unittest.cc",
+    "command_buffer/service/shader_translator_unittest.cc",
+    "command_buffer/service/test_helper.cc",
+    "command_buffer/service/test_helper.h",
+    "command_buffer/service/texture_manager_unittest.cc",
+    "command_buffer/service/transfer_buffer_manager_unittest.cc",
+    "command_buffer/service/valuebuffer_manager_unittest.cc",
+    "command_buffer/service/vertex_array_manager_unittest.cc",
+    "command_buffer/service/vertex_attrib_manager_unittest.cc",
+    "config/gpu_blacklist_unittest.cc",
+    "config/gpu_control_list_entry_unittest.cc",
+    "config/gpu_control_list_number_info_unittest.cc",
+    "config/gpu_control_list_os_info_unittest.cc",
+    "config/gpu_control_list_unittest.cc",
+    "config/gpu_control_list_version_info_unittest.cc",
+    "config/gpu_driver_bug_list_unittest.cc",
+    "config/gpu_info_collector_unittest.cc",
+    "config/gpu_info_unittest.cc",
+    "config/gpu_test_config_unittest.cc",
+    "config/gpu_test_expectations_parser_unittest.cc",
+    "config/gpu_util_unittest.cc",
+  ]
 
-    deps = [
-      ":gpu",
-      ":test_support",
-      "//base",
-      "//base/test:test_support",
-      "//base/third_party/dynamic_annotations",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//third_party/angle:translator",
-      "//ui/gfx",
-      "//ui/gfx:test_support",
-      "//ui/gfx/geometry",
-      "//ui/gl",
-      "//gpu/command_buffer/common:gles2_utils",
-      "//gpu/command_buffer/client:gles2_c_lib",
-      "//gpu/command_buffer/client:gles2_implementation",
-    ]
-  }
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 
-  test("gpu_perftests") {
-    sources = [
-      "perftests/measurements.cc",
-      "perftests/run_all_tests.cc",
-      "perftests/texture_upload_perftest.cc",
-    ]
+  deps = [
+    ":gpu",
+    ":test_support",
+    "//base",
+    "//base/test:test_support",
+    "//base/third_party/dynamic_annotations",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/angle:translator",
+    "//ui/gfx",
+    "//ui/gfx:test_support",
+    "//ui/gfx/geometry",
+    "//ui/gl",
+    "//gpu/command_buffer/common:gles2_utils",
+    "//gpu/command_buffer/client:gles2_c_lib",
+    "//gpu/command_buffer/client:gles2_implementation",
+  ]
+}
 
-    deps = [
-      "//base",
-      "//base/test:test_support",
-      "//gpu/command_buffer/service",
-      "//testing/gtest",
-      "//testing/perf",
-      "//ui/gfx/geometry",
-      "//ui/gl",
-    ]
-  }
+test("gpu_perftests") {
+  sources = [
+    "perftests/measurements.cc",
+    "perftests/run_all_tests.cc",
+    "perftests/texture_upload_perftest.cc",
+  ]
 
-  test("angle_unittests") {
-    sources = [
-      "angle_unittest_main.cc",
-    ]
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//gpu/command_buffer/service",
+    "//testing/gtest",
+    "//testing/perf",
+    "//ui/gfx/geometry",
+    "//ui/gl",
+  ]
+}
 
-    deps = [
-      "//base",
-      "//base/test:test_support",
-      "//base/third_party/dynamic_annotations",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//third_party/angle:translator_static",
-    ]
-  }
+test("angle_unittests") {
+  sources = [
+    "angle_unittest_main.cc",
+  ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//base/third_party/dynamic_annotations",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/angle:translator_static",
+  ]
 }
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt
index ad9ca68..6845991 100644
--- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt
+++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt
@@ -36,15 +36,18 @@
 
 New Procedures and Functions
 
-    void glCopyTextureCHROMIUM (GLenum target, GLenum source_id,
-                                GLenum dest_id, GLint level,
-                                GLint internal_format, GLenum dest_type)
+    The command
 
-    Copies the contents of texture referred to by <source_id> to texture
-    <dest_id>.
+        void glCopyTextureCHROMIUM (GLenum target, GLenum source_id,
+                                    GLenum dest_id,
+                                    GLint internal_format, GLenum dest_type)
 
-    Texture level 0 is copied from the source image to level <level> of the
-    destination texture. The level parameter must be 0 at present.
+    Copies the contents of texture referred to by <source_id> to <dest_id>
+    texture. If <source_id> texture is not defined or has different dimension
+    to <dest_id> texture, define <source_id> texture same to <dest_id> texture.
+
+    Texture level 0 is copied from the source image to level 0 of the
+    destination texture.
 
     The internal format of the destination texture is converted to that
     specified by <internal_format>. Must be one of the following symbolic
@@ -87,8 +90,37 @@
     been bound as GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB or
     GL_TEXTURE_EXTERNAL_OES objects.
 
-    INVALID_VALUE is generated if <level> is not a valid level of the
-    destination texture, or if level 0 of the source texture is not defined.
+    INVALID_VALUE is generated if level 0 of the source texture is not defined.
+
+    The command
+
+        void glCopySubTextureCHROMIUM (GLenum target, GLenum source_id,
+                                       GLenum dest_id,
+                                       GLint xoffset, GLint yoffset)
+
+    Copies the sub contents of texture referred to by <source_id> to <dest_id>
+    texture without redefining <dest_id> texture.
+
+    See CopyTextureCHROMIUM for the interpretation of the <target> arguments.
+
+    <xoffset> and <yoffset> specify a texel offset in the x and y direction
+    respectively within the destination texture.
+
+    INVALID_OPERATION is generated if source internal_format and destination
+    internal_format are not one of the valid formats described above.
+
+    INVALID_VALUE is generated if <target> is not GL_TEXTURE_2D.
+
+    INVALID_OPERATION is generated if the destination texture has not been
+    defined.
+
+    INVALID_VALUE is generated if level 0 of the source texture or
+    the destination texture is not defined.
+
+    INVALID_VALUE is generated if <xoffset> < 0 , or <yoffset> < 0.
+
+    INVALID_VALUE is generated if (<xoffset> + source_width) > dest_width,
+    or (<yoffset> + source_height) > dest_height.
 
 Errors
 
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index af745c1..60404dc 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -279,6 +279,7 @@
 #define glPostSubBufferCHROMIUM GLES2_GET_FUN(PostSubBufferCHROMIUM)
 #define glTexImageIOSurface2DCHROMIUM GLES2_GET_FUN(TexImageIOSurface2DCHROMIUM)
 #define glCopyTextureCHROMIUM GLES2_GET_FUN(CopyTextureCHROMIUM)
+#define glCopySubTextureCHROMIUM GLES2_GET_FUN(CopySubTextureCHROMIUM)
 #define glDrawArraysInstancedANGLE GLES2_GET_FUN(DrawArraysInstancedANGLE)
 #define glDrawElementsInstancedANGLE GLES2_GET_FUN(DrawElementsInstancedANGLE)
 #define glVertexAttribDivisorANGLE GLES2_GET_FUN(VertexAttribDivisorANGLE)
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index 6a31b8f..ec85bf2 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -394,13 +394,29 @@
 #define GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM 0x9241
 #endif
 #ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM(
-    GLenum target, GLenum source_id, GLenum dest_id, GLint level,
-    GLint internalformat, GLenum dest_type);
+GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM(GLenum target,
+                                                  GLenum source_id,
+                                                  GLenum dest_id,
+                                                  GLint internalformat,
+                                                  GLenum dest_type);
+
+GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM(GLenum target,
+                                                     GLenum source_id,
+                                                     GLenum dest_id,
+                                                     GLint xoffset,
+                                                     GLint yoffset);
 #endif
-typedef void (GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMPROC) (
-    GLenum target, GLenum source_id, GLenum dest_id, GLint level,
-    GLint internalformat, GLenum dest_type);
+typedef void(GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMPROC)(GLenum target,
+                                                        GLenum source_id,
+                                                        GLenum dest_id,
+                                                        GLint internalformat,
+                                                        GLenum dest_type);
+
+typedef void(GL_APIENTRYP PFNGLCOPYSUBTEXTURECHROMIUMPROC)(GLenum target,
+                                                           GLenum source_id,
+                                                           GLenum dest_id,
+                                                           GLint xoffset,
+                                                           GLint yoffset);
 #endif  /* GL_CHROMIUM_copy_texture */
 
 /* GL_CHROMIUM_lose_context */
diff --git a/gpu/blink/webgraphicscontext3d_impl.cc b/gpu/blink/webgraphicscontext3d_impl.cc
index 4f728cf..581e102 100644
--- a/gpu/blink/webgraphicscontext3d_impl.cc
+++ b/gpu/blink/webgraphicscontext3d_impl.cc
@@ -809,8 +809,39 @@
 DELEGATE_TO_GL_3(getQueryObjectuivEXT, GetQueryObjectuivEXT,
                  WebGLId, WGC3Denum, WGC3Duint*)
 
-DELEGATE_TO_GL_6(copyTextureCHROMIUM, CopyTextureCHROMIUM,  WGC3Denum,
-                 WebGLId, WebGLId, WGC3Dint, WGC3Denum, WGC3Denum);
+void WebGraphicsContext3DImpl::copyTextureCHROMIUM(WGC3Denum target,
+                                                   WebGLId source_id,
+                                                   WebGLId dest_id,
+                                                   WGC3Dint level,
+                                                   WGC3Denum internal_format,
+                                                   WGC3Denum dest_type) {
+  copyTextureCHROMIUM(target, source_id, dest_id, internal_format, dest_type);
+}
+
+void WebGraphicsContext3DImpl::copySubTextureCHROMIUM(WGC3Denum target,
+                                                      WebGLId source_id,
+                                                      WebGLId dest_id,
+                                                      WGC3Dint level,
+                                                      WGC3Dint xoffset,
+                                                      WGC3Dint yoffset) {
+  copySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset);
+}
+
+DELEGATE_TO_GL_5(copyTextureCHROMIUM,
+                 CopyTextureCHROMIUM,
+                 WGC3Denum,
+                 WebGLId,
+                 WebGLId,
+                 WGC3Denum,
+                 WGC3Denum);
+
+DELEGATE_TO_GL_5(copySubTextureCHROMIUM,
+                 CopySubTextureCHROMIUM,
+                 WGC3Denum,
+                 WebGLId,
+                 WebGLId,
+                 WGC3Dint,
+                 WGC3Dint);
 
 DELEGATE_TO_GL_3(bindUniformLocationCHROMIUM, BindUniformLocationCHROMIUM,
                  WebGLId, WGC3Dint, const WGC3Dchar*)
@@ -1183,6 +1214,8 @@
   output_attribs->fail_if_major_perf_caveat =
       attributes.failIfMajorPerformanceCaveat;
   output_attribs->bind_generates_resource = false;
+  output_attribs->es3_context_required =
+      (attributes.webGL && attributes.webGLVersion == 2);
 }
 
 }  // namespace gpu_blink
diff --git a/gpu/blink/webgraphicscontext3d_impl.h b/gpu/blink/webgraphicscontext3d_impl.h
index ff2ca97..a0d1461 100644
--- a/gpu/blink/webgraphicscontext3d_impl.h
+++ b/gpu/blink/webgraphicscontext3d_impl.h
@@ -451,11 +451,33 @@
   virtual void getQueryObjectuivEXT(
       WebGLId query, WGC3Denum pname, WGC3Duint* params);
 
-  virtual void copyTextureCHROMIUM(WGC3Denum target, WebGLId source_id,
-                                   WebGLId dest_id, WGC3Dint level,
+  // TODO(dshwang): Remove |level| in Blink and then remove it.
+  void copyTextureCHROMIUM(WGC3Denum target,
+                           WebGLId source_id,
+                           WebGLId dest_id,
+                           WGC3Dint level,
+                           WGC3Denum internal_format,
+                           WGC3Denum dest_type) override;
+
+  void copySubTextureCHROMIUM(WGC3Denum target,
+                              WebGLId source_id,
+                              WebGLId dest_id,
+                              WGC3Dint level,
+                              WGC3Dint xoffset,
+                              WGC3Dint yoffset) override;
+
+  virtual void copyTextureCHROMIUM(WGC3Denum target,
+                                   WebGLId source_id,
+                                   WebGLId dest_id,
                                    WGC3Denum internal_format,
                                    WGC3Denum dest_type);
 
+  virtual void copySubTextureCHROMIUM(WGC3Denum target,
+                                      WebGLId sourceId,
+                                      WebGLId destId,
+                                      WGC3Dint xoffset,
+                                      WGC3Dint yoffset);
+
   virtual void bindUniformLocationCHROMIUM(WebGLId program, WGC3Dint location,
                                            const WGC3Dchar* uniform);
 
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 8dba53b..5e6d9d9 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -3008,6 +3008,12 @@
     'extension': True,
     'chromium': True,
   },
+  'CopySubTextureCHROMIUM': {
+    'decoder_func': 'DoCopySubTextureCHROMIUM',
+    'unit_test': False,
+    'extension': True,
+    'chromium': True,
+  },
   'TexStorage2DEXT': {
     'unit_test': False,
     'extension': True,
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn
index a5532cb..7e47f24 100644
--- a/gpu/command_buffer/client/BUILD.gn
+++ b/gpu/command_buffer/client/BUILD.gn
@@ -140,6 +140,27 @@
   ]
 }
 
+# Library emulates GLES2 using command_buffers.
+component("gles2_implementation_no_check") {
+  sources = gles2_implementation_source_files
+
+  # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+  defines = [
+    "GLES2_IMPL_IMPLEMENTATION",
+    "GLES2_CONFORMANCE_TESTS=1",
+  ]
+
+  deps = [
+    ":gles2_cmd_helper",
+    "//base",
+    "//gpu/command_buffer/common:gles2_utils",
+    "//ui/gfx",
+    "//ui/gfx/geometry",
+  ]
+}
+
 component("gl_in_process_context") {
   sources = [
     "gl_in_process_context.cc",
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 87616e7..7e0da4b 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1158,12 +1158,19 @@
 void GLES2CopyTextureCHROMIUM(GLenum target,
                               GLenum source_id,
                               GLenum dest_id,
-                              GLint level,
                               GLint internalformat,
                               GLenum dest_type) {
-  gles2::GetGLContext()->CopyTextureCHROMIUM(target, source_id, dest_id, level,
+  gles2::GetGLContext()->CopyTextureCHROMIUM(target, source_id, dest_id,
                                              internalformat, dest_type);
 }
+void GLES2CopySubTextureCHROMIUM(GLenum target,
+                                 GLenum source_id,
+                                 GLenum dest_id,
+                                 GLint xoffset,
+                                 GLint yoffset) {
+  gles2::GetGLContext()->CopySubTextureCHROMIUM(target, source_id, dest_id,
+                                                xoffset, yoffset);
+}
 void GLES2DrawArraysInstancedANGLE(GLenum mode,
                                    GLint first,
                                    GLsizei count,
@@ -2361,6 +2368,10 @@
      reinterpret_cast<GLES2FunctionPointer>(glCopyTextureCHROMIUM),
     },
     {
+     "glCopySubTextureCHROMIUM",
+     reinterpret_cast<GLES2FunctionPointer>(glCopySubTextureCHROMIUM),
+    },
+    {
      "glDrawArraysInstancedANGLE",
      reinterpret_cast<GLES2FunctionPointer>(glDrawArraysInstancedANGLE),
     },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 4c1ad05..ad3eb58 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2312,13 +2312,24 @@
 void CopyTextureCHROMIUM(GLenum target,
                          GLenum source_id,
                          GLenum dest_id,
-                         GLint level,
                          GLint internalformat,
                          GLenum dest_type) {
   gles2::cmds::CopyTextureCHROMIUM* c =
       GetCmdSpace<gles2::cmds::CopyTextureCHROMIUM>();
   if (c) {
-    c->Init(target, source_id, dest_id, level, internalformat, dest_type);
+    c->Init(target, source_id, dest_id, internalformat, dest_type);
+  }
+}
+
+void CopySubTextureCHROMIUM(GLenum target,
+                            GLenum source_id,
+                            GLenum dest_id,
+                            GLint xoffset,
+                            GLint yoffset) {
+  gles2::cmds::CopySubTextureCHROMIUM* c =
+      GetCmdSpace<gles2::cmds::CopySubTextureCHROMIUM>();
+  if (c) {
+    c->Init(target, source_id, dest_id, xoffset, yoffset);
   }
 }
 
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index c570c45..8e032e4 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -873,10 +873,15 @@
 void CopyTextureCHROMIUM(GLenum target,
                          GLenum source_id,
                          GLenum dest_id,
-                         GLint level,
                          GLint internalformat,
                          GLenum dest_type) override;
 
+void CopySubTextureCHROMIUM(GLenum target,
+                            GLenum source_id,
+                            GLenum dest_id,
+                            GLint xoffset,
+                            GLint yoffset) override;
+
 void DrawArraysInstancedANGLE(GLenum mode,
                               GLint first,
                               GLsizei count,
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index 641efde..98447bf 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -3108,18 +3108,32 @@
 void GLES2Implementation::CopyTextureCHROMIUM(GLenum target,
                                               GLenum source_id,
                                               GLenum dest_id,
-                                              GLint level,
                                               GLint internalformat,
                                               GLenum dest_type) {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCopyTextureCHROMIUM("
                      << GLES2Util::GetStringEnum(target) << ", "
                      << GLES2Util::GetStringEnum(source_id) << ", "
-                     << GLES2Util::GetStringEnum(dest_id) << ", " << level
-                     << ", " << internalformat << ", "
+                     << GLES2Util::GetStringEnum(dest_id) << ", "
+                     << internalformat << ", "
                      << GLES2Util::GetStringPixelType(dest_type) << ")");
-  helper_->CopyTextureCHROMIUM(target, source_id, dest_id, level,
-                               internalformat, dest_type);
+  helper_->CopyTextureCHROMIUM(target, source_id, dest_id, internalformat,
+                               dest_type);
+  CheckGLError();
+}
+
+void GLES2Implementation::CopySubTextureCHROMIUM(GLenum target,
+                                                 GLenum source_id,
+                                                 GLenum dest_id,
+                                                 GLint xoffset,
+                                                 GLint yoffset) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCopySubTextureCHROMIUM("
+                     << GLES2Util::GetStringEnum(target) << ", "
+                     << GLES2Util::GetStringEnum(source_id) << ", "
+                     << GLES2Util::GetStringEnum(dest_id) << ", " << xoffset
+                     << ", " << yoffset << ")");
+  helper_->CopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset);
   CheckGLError();
 }
 
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 2acbc63..3af9413 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -381,8 +381,7 @@
   static const GLuint kMaxTransformFeedbackSeparateAttribs = 4;
   static const GLuint kMaxUniformBufferBindings = 36;
   static const GLuint kStartId = 1024;
-  static const GLuint kBuffersStartId =
-      GLES2Implementation::kClientSideArrayId + 2 * kNumTestContexts;
+  static const GLuint kBuffersStartId = 1;
   static const GLuint kFramebuffersStartId = 1;
   static const GLuint kProgramsAndShadersStartId = 1;
   static const GLuint kRenderbuffersStartId = 1;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 9b43afe..2d8480a 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -2749,9 +2749,20 @@
     cmds::CopyTextureCHROMIUM cmd;
   };
   Cmds expected;
-  expected.cmd.Init(1, 2, 3, 4, GL_ALPHA, GL_UNSIGNED_BYTE);
+  expected.cmd.Init(1, 2, 3, GL_ALPHA, GL_UNSIGNED_BYTE);
 
-  gl_->CopyTextureCHROMIUM(1, 2, 3, 4, GL_ALPHA, GL_UNSIGNED_BYTE);
+  gl_->CopyTextureCHROMIUM(1, 2, 3, GL_ALPHA, GL_UNSIGNED_BYTE);
+  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
+TEST_F(GLES2ImplementationTest, CopySubTextureCHROMIUM) {
+  struct Cmds {
+    cmds::CopySubTextureCHROMIUM cmd;
+  };
+  Cmds expected;
+  expected.cmd.Init(1, 2, 3, 4, 5);
+
+  gl_->CopySubTextureCHROMIUM(1, 2, 3, 4, 5);
   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
 }
 
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index d5b4f93..f93ec07 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -641,9 +641,13 @@
 virtual void CopyTextureCHROMIUM(GLenum target,
                                  GLenum source_id,
                                  GLenum dest_id,
-                                 GLint level,
                                  GLint internalformat,
                                  GLenum dest_type) = 0;
+virtual void CopySubTextureCHROMIUM(GLenum target,
+                                    GLenum source_id,
+                                    GLenum dest_id,
+                                    GLint xoffset,
+                                    GLint yoffset) = 0;
 virtual void DrawArraysInstancedANGLE(GLenum mode,
                                       GLint first,
                                       GLsizei count,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 5ad9385..0381b32 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -624,9 +624,13 @@
 void CopyTextureCHROMIUM(GLenum target,
                          GLenum source_id,
                          GLenum dest_id,
-                         GLint level,
                          GLint internalformat,
                          GLenum dest_type) override;
+void CopySubTextureCHROMIUM(GLenum target,
+                            GLenum source_id,
+                            GLenum dest_id,
+                            GLint xoffset,
+                            GLint yoffset) override;
 void DrawArraysInstancedANGLE(GLenum mode,
                               GLint first,
                               GLsizei count,
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 b3f40ac..0f2e5fd 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -1069,10 +1069,15 @@
 void GLES2InterfaceStub::CopyTextureCHROMIUM(GLenum /* target */,
                                              GLenum /* source_id */,
                                              GLenum /* dest_id */,
-                                             GLint /* level */,
                                              GLint /* internalformat */,
                                              GLenum /* dest_type */) {
 }
+void GLES2InterfaceStub::CopySubTextureCHROMIUM(GLenum /* target */,
+                                                GLenum /* source_id */,
+                                                GLenum /* dest_id */,
+                                                GLint /* xoffset */,
+                                                GLint /* yoffset */) {
+}
 void GLES2InterfaceStub::DrawArraysInstancedANGLE(GLenum /* mode */,
                                                   GLint /* first */,
                                                   GLsizei /* count */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index e5a69a4..8a9be79 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -624,9 +624,13 @@
 void CopyTextureCHROMIUM(GLenum target,
                          GLenum source_id,
                          GLenum dest_id,
-                         GLint level,
                          GLint internalformat,
                          GLenum dest_type) override;
+void CopySubTextureCHROMIUM(GLenum target,
+                            GLenum source_id,
+                            GLenum dest_id,
+                            GLint xoffset,
+                            GLint yoffset) override;
 void DrawArraysInstancedANGLE(GLenum mode,
                               GLint first,
                               GLsizei count,
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 6dbbc93..d1479b1 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -1821,14 +1821,22 @@
 void GLES2TraceImplementation::CopyTextureCHROMIUM(GLenum target,
                                                    GLenum source_id,
                                                    GLenum dest_id,
-                                                   GLint level,
                                                    GLint internalformat,
                                                    GLenum dest_type) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CopyTextureCHROMIUM");
-  gl_->CopyTextureCHROMIUM(target, source_id, dest_id, level, internalformat,
+  gl_->CopyTextureCHROMIUM(target, source_id, dest_id, internalformat,
                            dest_type);
 }
 
+void GLES2TraceImplementation::CopySubTextureCHROMIUM(GLenum target,
+                                                      GLenum source_id,
+                                                      GLenum dest_id,
+                                                      GLint xoffset,
+                                                      GLint yoffset) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CopySubTextureCHROMIUM");
+  gl_->CopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset);
+}
+
 void GLES2TraceImplementation::DrawArraysInstancedANGLE(GLenum mode,
                                                         GLint first,
                                                         GLsizei count,
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index a03af9e..140db2c 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -263,7 +263,8 @@
 GL_APICALL void         GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLidShader shader, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* source);
 GL_APICALL void         GL_APIENTRY glPostSubBufferCHROMIUM (GLint x, GLint y, GLint width, GLint height);
 GL_APICALL void         GL_APIENTRY glTexImageIOSurface2DCHROMIUM (GLenumTextureBindTarget target, GLsizei width, GLsizei height, GLuint ioSurfaceId, GLuint plane);
-GL_APICALL void         GL_APIENTRY glCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLint level, GLintTextureInternalFormat internalformat, GLenumPixelType dest_type);
+GL_APICALL void         GL_APIENTRY glCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLintTextureInternalFormat internalformat, GLenumPixelType dest_type);
+GL_APICALL void         GL_APIENTRY glCopySubTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, GLint yoffset);
 GL_APICALL void         GL_APIENTRY glDrawArraysInstancedANGLE (GLenumDrawMode mode, GLint first, GLsizei count, GLsizei primcount);
 GL_APICALL void         GL_APIENTRY glDrawElementsInstancedANGLE (GLenumDrawMode mode, GLsizei count, GLenumIndexType type, const void* indices, GLsizei primcount);
 GL_APICALL void         GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 71b1f3f..d3cb00a 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -11375,14 +11375,12 @@
   void Init(GLenum _target,
             GLenum _source_id,
             GLenum _dest_id,
-            GLint _level,
             GLint _internalformat,
             GLenum _dest_type) {
     SetHeader();
     target = _target;
     source_id = _source_id;
     dest_id = _dest_id;
-    level = _level;
     internalformat = _internalformat;
     dest_type = _dest_type;
   }
@@ -11391,11 +11389,10 @@
             GLenum _target,
             GLenum _source_id,
             GLenum _dest_id,
-            GLint _level,
             GLint _internalformat,
             GLenum _dest_type) {
-    static_cast<ValueType*>(cmd)->Init(_target, _source_id, _dest_id, _level,
-                                       _internalformat, _dest_type);
+    static_cast<ValueType*>(cmd)
+        ->Init(_target, _source_id, _dest_id, _internalformat, _dest_type);
     return NextCmdAddress<ValueType>(cmd);
   }
 
@@ -11403,13 +11400,12 @@
   uint32_t target;
   uint32_t source_id;
   uint32_t dest_id;
-  int32_t level;
   int32_t internalformat;
   uint32_t dest_type;
 };
 
-static_assert(sizeof(CopyTextureCHROMIUM) == 28,
-              "size of CopyTextureCHROMIUM should be 28");
+static_assert(sizeof(CopyTextureCHROMIUM) == 24,
+              "size of CopyTextureCHROMIUM should be 24");
 static_assert(offsetof(CopyTextureCHROMIUM, header) == 0,
               "offset of CopyTextureCHROMIUM header should be 0");
 static_assert(offsetof(CopyTextureCHROMIUM, target) == 4,
@@ -11418,12 +11414,69 @@
               "offset of CopyTextureCHROMIUM source_id should be 8");
 static_assert(offsetof(CopyTextureCHROMIUM, dest_id) == 12,
               "offset of CopyTextureCHROMIUM dest_id should be 12");
-static_assert(offsetof(CopyTextureCHROMIUM, level) == 16,
-              "offset of CopyTextureCHROMIUM level should be 16");
-static_assert(offsetof(CopyTextureCHROMIUM, internalformat) == 20,
-              "offset of CopyTextureCHROMIUM internalformat should be 20");
-static_assert(offsetof(CopyTextureCHROMIUM, dest_type) == 24,
-              "offset of CopyTextureCHROMIUM dest_type should be 24");
+static_assert(offsetof(CopyTextureCHROMIUM, internalformat) == 16,
+              "offset of CopyTextureCHROMIUM internalformat should be 16");
+static_assert(offsetof(CopyTextureCHROMIUM, dest_type) == 20,
+              "offset of CopyTextureCHROMIUM dest_type should be 20");
+
+struct CopySubTextureCHROMIUM {
+  typedef CopySubTextureCHROMIUM ValueType;
+  static const CommandId kCmdId = kCopySubTextureCHROMIUM;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+  static uint32_t ComputeSize() {
+    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(GLenum _target,
+            GLenum _source_id,
+            GLenum _dest_id,
+            GLint _xoffset,
+            GLint _yoffset) {
+    SetHeader();
+    target = _target;
+    source_id = _source_id;
+    dest_id = _dest_id;
+    xoffset = _xoffset;
+    yoffset = _yoffset;
+  }
+
+  void* Set(void* cmd,
+            GLenum _target,
+            GLenum _source_id,
+            GLenum _dest_id,
+            GLint _xoffset,
+            GLint _yoffset) {
+    static_cast<ValueType*>(cmd)
+        ->Init(_target, _source_id, _dest_id, _xoffset, _yoffset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t target;
+  uint32_t source_id;
+  uint32_t dest_id;
+  int32_t xoffset;
+  int32_t yoffset;
+};
+
+static_assert(sizeof(CopySubTextureCHROMIUM) == 24,
+              "size of CopySubTextureCHROMIUM should be 24");
+static_assert(offsetof(CopySubTextureCHROMIUM, header) == 0,
+              "offset of CopySubTextureCHROMIUM header should be 0");
+static_assert(offsetof(CopySubTextureCHROMIUM, target) == 4,
+              "offset of CopySubTextureCHROMIUM target should be 4");
+static_assert(offsetof(CopySubTextureCHROMIUM, source_id) == 8,
+              "offset of CopySubTextureCHROMIUM source_id should be 8");
+static_assert(offsetof(CopySubTextureCHROMIUM, dest_id) == 12,
+              "offset of CopySubTextureCHROMIUM dest_id should be 12");
+static_assert(offsetof(CopySubTextureCHROMIUM, xoffset) == 16,
+              "offset of CopySubTextureCHROMIUM xoffset should be 16");
+static_assert(offsetof(CopySubTextureCHROMIUM, yoffset) == 20,
+              "offset of CopySubTextureCHROMIUM yoffset should be 20");
 
 struct DrawArraysInstancedANGLE {
   typedef DrawArraysInstancedANGLE ValueType;
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 1d18fa8..3162276 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3914,19 +3914,34 @@
 
 TEST_F(GLES2FormatTest, CopyTextureCHROMIUM) {
   cmds::CopyTextureCHROMIUM& cmd = *GetBufferAs<cmds::CopyTextureCHROMIUM>();
-  void* next_cmd =
-      cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLenum>(12),
-              static_cast<GLenum>(13), static_cast<GLint>(14),
-              static_cast<GLint>(15), static_cast<GLenum>(16));
+  void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11),
+                           static_cast<GLenum>(12), static_cast<GLenum>(13),
+                           static_cast<GLint>(14), static_cast<GLenum>(15));
   EXPECT_EQ(static_cast<uint32_t>(cmds::CopyTextureCHROMIUM::kCmdId),
             cmd.header.command);
   EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
   EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
   EXPECT_EQ(static_cast<GLenum>(12), cmd.source_id);
   EXPECT_EQ(static_cast<GLenum>(13), cmd.dest_id);
-  EXPECT_EQ(static_cast<GLint>(14), cmd.level);
-  EXPECT_EQ(static_cast<GLint>(15), cmd.internalformat);
-  EXPECT_EQ(static_cast<GLenum>(16), cmd.dest_type);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.internalformat);
+  EXPECT_EQ(static_cast<GLenum>(15), cmd.dest_type);
+  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, CopySubTextureCHROMIUM) {
+  cmds::CopySubTextureCHROMIUM& cmd =
+      *GetBufferAs<cmds::CopySubTextureCHROMIUM>();
+  void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11),
+                           static_cast<GLenum>(12), static_cast<GLenum>(13),
+                           static_cast<GLint>(14), static_cast<GLint>(15));
+  EXPECT_EQ(static_cast<uint32_t>(cmds::CopySubTextureCHROMIUM::kCmdId),
+            cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLenum>(12), cmd.source_id);
+  EXPECT_EQ(static_cast<GLenum>(13), cmd.dest_id);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.xoffset);
+  EXPECT_EQ(static_cast<GLint>(15), cmd.yoffset);
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index eec1c04..1c739e8 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -254,41 +254,42 @@
   OP(PostSubBufferCHROMIUM)                    /* 495 */ \
   OP(TexImageIOSurface2DCHROMIUM)              /* 496 */ \
   OP(CopyTextureCHROMIUM)                      /* 497 */ \
-  OP(DrawArraysInstancedANGLE)                 /* 498 */ \
-  OP(DrawElementsInstancedANGLE)               /* 499 */ \
-  OP(VertexAttribDivisorANGLE)                 /* 500 */ \
-  OP(GenMailboxCHROMIUM)                       /* 501 */ \
-  OP(ProduceTextureCHROMIUMImmediate)          /* 502 */ \
-  OP(ProduceTextureDirectCHROMIUMImmediate)    /* 503 */ \
-  OP(ConsumeTextureCHROMIUMImmediate)          /* 504 */ \
-  OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 505 */ \
-  OP(BindUniformLocationCHROMIUMBucket)        /* 506 */ \
-  OP(GenValuebuffersCHROMIUMImmediate)         /* 507 */ \
-  OP(DeleteValuebuffersCHROMIUMImmediate)      /* 508 */ \
-  OP(IsValuebufferCHROMIUM)                    /* 509 */ \
-  OP(BindValuebufferCHROMIUM)                  /* 510 */ \
-  OP(SubscribeValueCHROMIUM)                   /* 511 */ \
-  OP(PopulateSubscribedValuesCHROMIUM)         /* 512 */ \
-  OP(UniformValuebufferCHROMIUM)               /* 513 */ \
-  OP(BindTexImage2DCHROMIUM)                   /* 514 */ \
-  OP(ReleaseTexImage2DCHROMIUM)                /* 515 */ \
-  OP(TraceBeginCHROMIUM)                       /* 516 */ \
-  OP(TraceEndCHROMIUM)                         /* 517 */ \
-  OP(AsyncTexSubImage2DCHROMIUM)               /* 518 */ \
-  OP(AsyncTexImage2DCHROMIUM)                  /* 519 */ \
-  OP(WaitAsyncTexImage2DCHROMIUM)              /* 520 */ \
-  OP(WaitAllAsyncTexImage2DCHROMIUM)           /* 521 */ \
-  OP(DiscardFramebufferEXTImmediate)           /* 522 */ \
-  OP(LoseContextCHROMIUM)                      /* 523 */ \
-  OP(InsertSyncPointCHROMIUM)                  /* 524 */ \
-  OP(WaitSyncPointCHROMIUM)                    /* 525 */ \
-  OP(DrawBuffersEXTImmediate)                  /* 526 */ \
-  OP(DiscardBackbufferCHROMIUM)                /* 527 */ \
-  OP(ScheduleOverlayPlaneCHROMIUM)             /* 528 */ \
-  OP(SwapInterval)                             /* 529 */ \
-  OP(MatrixLoadfCHROMIUMImmediate)             /* 530 */ \
-  OP(MatrixLoadIdentityCHROMIUM)               /* 531 */ \
-  OP(BlendBarrierKHR)                          /* 532 */
+  OP(CopySubTextureCHROMIUM)                   /* 498 */ \
+  OP(DrawArraysInstancedANGLE)                 /* 499 */ \
+  OP(DrawElementsInstancedANGLE)               /* 500 */ \
+  OP(VertexAttribDivisorANGLE)                 /* 501 */ \
+  OP(GenMailboxCHROMIUM)                       /* 502 */ \
+  OP(ProduceTextureCHROMIUMImmediate)          /* 503 */ \
+  OP(ProduceTextureDirectCHROMIUMImmediate)    /* 504 */ \
+  OP(ConsumeTextureCHROMIUMImmediate)          /* 505 */ \
+  OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 506 */ \
+  OP(BindUniformLocationCHROMIUMBucket)        /* 507 */ \
+  OP(GenValuebuffersCHROMIUMImmediate)         /* 508 */ \
+  OP(DeleteValuebuffersCHROMIUMImmediate)      /* 509 */ \
+  OP(IsValuebufferCHROMIUM)                    /* 510 */ \
+  OP(BindValuebufferCHROMIUM)                  /* 511 */ \
+  OP(SubscribeValueCHROMIUM)                   /* 512 */ \
+  OP(PopulateSubscribedValuesCHROMIUM)         /* 513 */ \
+  OP(UniformValuebufferCHROMIUM)               /* 514 */ \
+  OP(BindTexImage2DCHROMIUM)                   /* 515 */ \
+  OP(ReleaseTexImage2DCHROMIUM)                /* 516 */ \
+  OP(TraceBeginCHROMIUM)                       /* 517 */ \
+  OP(TraceEndCHROMIUM)                         /* 518 */ \
+  OP(AsyncTexSubImage2DCHROMIUM)               /* 519 */ \
+  OP(AsyncTexImage2DCHROMIUM)                  /* 520 */ \
+  OP(WaitAsyncTexImage2DCHROMIUM)              /* 521 */ \
+  OP(WaitAllAsyncTexImage2DCHROMIUM)           /* 522 */ \
+  OP(DiscardFramebufferEXTImmediate)           /* 523 */ \
+  OP(LoseContextCHROMIUM)                      /* 524 */ \
+  OP(InsertSyncPointCHROMIUM)                  /* 525 */ \
+  OP(WaitSyncPointCHROMIUM)                    /* 526 */ \
+  OP(DrawBuffersEXTImmediate)                  /* 527 */ \
+  OP(DiscardBackbufferCHROMIUM)                /* 528 */ \
+  OP(ScheduleOverlayPlaneCHROMIUM)             /* 529 */ \
+  OP(SwapInterval)                             /* 530 */ \
+  OP(MatrixLoadfCHROMIUMImmediate)             /* 531 */ \
+  OP(MatrixLoadIdentityCHROMIUM)               /* 532 */ \
+  OP(BlendBarrierKHR)                          /* 533 */
 
 enum CommandId {
   kStartPoint = cmd::kLastCommonId,  // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 3985193..0950b41 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -894,6 +894,7 @@
 const int32 kBindGeneratesResource = 0x10000;
 const int32 kFailIfMajorPerfCaveat = 0x10001;
 const int32 kLoseContextWhenOutOfMemory = 0x10002;
+const int32 kES3ContextRequired = 0x10003;
 
 }  // namespace
 
@@ -909,7 +910,8 @@
       buffer_preserved(true),
       bind_generates_resource(true),
       fail_if_major_perf_caveat(false),
-      lose_context_when_out_of_memory(false) {}
+      lose_context_when_out_of_memory(false),
+      es3_context_required(false) {}
 
 void ContextCreationAttribHelper::Serialize(std::vector<int32>* attribs) const {
   if (alpha_size != -1) {
@@ -952,6 +954,8 @@
   attribs->push_back(fail_if_major_perf_caveat ? 1 : 0);
   attribs->push_back(kLoseContextWhenOutOfMemory);
   attribs->push_back(lose_context_when_out_of_memory ? 1 : 0);
+  attribs->push_back(kES3ContextRequired);
+  attribs->push_back(es3_context_required ? 1 : 0);
   attribs->push_back(kNone);
 }
 
@@ -1006,6 +1010,9 @@
       case kLoseContextWhenOutOfMemory:
         lose_context_when_out_of_memory = value != 0;
         break;
+      case kES3ContextRequired:
+        es3_context_required = value != 0;
+        break;
       case kNone:
         // Terminate list, even if more attributes.
         return true;
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 3528cfd..9dd8f28 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -223,6 +223,7 @@
   bool bind_generates_resource;
   bool fail_if_major_perf_caveat;
   bool lose_context_when_out_of_memory;
+  bool es3_context_required;
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/common/id_allocator.cc b/gpu/command_buffer/common/id_allocator.cc
index 507b14e..eccb468 100644
--- a/gpu/command_buffer/common/id_allocator.cc
+++ b/gpu/command_buffer/common/id_allocator.cc
@@ -6,84 +6,200 @@
 
 #include "gpu/command_buffer/common/id_allocator.h"
 
+#include <limits>
 #include "base/logging.h"
 
 namespace gpu {
 
-IdAllocator::IdAllocator() {}
+IdAllocator::IdAllocator() {
+  COMPILE_ASSERT(kInvalidResource == 0u, invalid_resource_is_not_zero);
+  // Simplify the code by making sure that lower_bound(id) never
+  // returns the beginning of the map, if id is valid (eg !=
+  // kInvalidResource).
+  used_ids_.insert(std::make_pair(0u, 0u));
+}
 
 IdAllocator::~IdAllocator() {}
 
 ResourceId IdAllocator::AllocateID() {
-  ResourceId id;
-  ResourceIdSet::iterator iter = free_ids_.begin();
-  if (iter != free_ids_.end()) {
-    id = *iter;
-  } else {
-    id = LastUsedId() + 1;
-    if (!id) {
-      // We wrapped around to 0.
-      id = FindFirstUnusedId();
-    }
-  }
-  MarkAsUsed(id);
-  return id;
+  return AllocateIDRange(1u);
 }
 
 ResourceId IdAllocator::AllocateIDAtOrAbove(ResourceId desired_id) {
-  ResourceId id;
-  ResourceIdSet::iterator iter = free_ids_.lower_bound(desired_id);
-  if (iter != free_ids_.end()) {
-    id = *iter;
-  } else if (LastUsedId() < desired_id) {
-    id = desired_id;
-  } else {
-    id = LastUsedId() + 1;
-    if (!id) {
-      // We wrapped around to 0.
-      id = FindFirstUnusedId();
-    }
+  if (desired_id == 0u || desired_id == 1u) {
+    return AllocateIDRange(1u);
   }
-  MarkAsUsed(id);
-  return id;
+
+  ResourceIdRangeMap::iterator current = used_ids_.lower_bound(desired_id);
+  ResourceIdRangeMap::iterator next = current;
+  if (current == used_ids_.end() || current->first > desired_id) {
+    current--;
+  } else {
+    next++;
+  }
+
+  ResourceId first_id = current->first;
+  ResourceId last_id = current->second;
+
+  DCHECK(desired_id >= first_id);
+
+  if (desired_id - 1u <= last_id) {
+    // Append to current range.
+    last_id++;
+    if (last_id == 0) {
+      // The increment overflowed.
+      return AllocateIDRange(1u);
+    }
+
+    current->second = last_id;
+
+    if (next != used_ids_.end() && next->first - 1u == last_id) {
+      // Merge with next range.
+      current->second = next->second;
+      used_ids_.erase(next);
+    }
+    return last_id;
+  } else if (next != used_ids_.end() && next->first - 1u == desired_id) {
+    // Prepend to next range.
+    ResourceId last_existing_id = next->second;
+    used_ids_.erase(next);
+    used_ids_.insert(std::make_pair(desired_id, last_existing_id));
+    return desired_id;
+  }
+  used_ids_.insert(std::make_pair(desired_id, desired_id));
+  return desired_id;
+}
+
+ResourceId IdAllocator::AllocateIDRange(uint32_t range) {
+  DCHECK(range > 0u);
+
+  ResourceIdRangeMap::iterator current = used_ids_.begin();
+  ResourceIdRangeMap::iterator next = current;
+
+  while (++next != used_ids_.end()) {
+    if (next->first - current->second > range) {
+      break;
+    }
+    current = next;
+  }
+
+  ResourceId first_id = current->second + 1u;
+  ResourceId last_id = first_id + range - 1u;
+
+  if (first_id == 0u || last_id < first_id) {
+    return kInvalidResource;
+  }
+
+  current->second = last_id;
+
+  if (next != used_ids_.end() && next->first - 1u == last_id) {
+    // Merge with next range.
+    current->second = next->second;
+    used_ids_.erase(next);
+  }
+
+  return first_id;
 }
 
 bool IdAllocator::MarkAsUsed(ResourceId id) {
   DCHECK(id);
-  free_ids_.erase(id);
-  std::pair<ResourceIdSet::iterator, bool> result = used_ids_.insert(id);
-  return result.second;
+  ResourceIdRangeMap::iterator current = used_ids_.lower_bound(id);
+  if (current != used_ids_.end() && current->first == id) {
+    return false;
+  }
+
+  ResourceIdRangeMap::iterator next = current;
+  --current;
+
+  if (current->second >= id) {
+    return false;
+  }
+
+  DCHECK(current->first < id && current->second < id);
+
+  if (current->second + 1u == id) {
+    // Append to current range.
+    current->second = id;
+    if (next != used_ids_.end() && next->first - 1u == id) {
+      // Merge with next range.
+      current->second = next->second;
+      used_ids_.erase(next);
+    }
+    return true;
+  } else if (next != used_ids_.end() && next->first - 1u == id) {
+    // Prepend to next range.
+    ResourceId last_existing_id = next->second;
+    used_ids_.erase(next);
+    used_ids_.insert(std::make_pair(id, last_existing_id));
+    return true;
+  }
+
+  used_ids_.insert(std::make_pair(id, id));
+  return true;
 }
 
 void IdAllocator::FreeID(ResourceId id) {
-  if (id) {
-    used_ids_.erase(id);
-    free_ids_.insert(id);
+  FreeIDRange(id, 1u);
+}
+
+void IdAllocator::FreeIDRange(ResourceId first_id, uint32 range) {
+  COMPILE_ASSERT(kInvalidResource == 0u, invalid_resource_is_not_zero);
+
+  if (range == 0u || (first_id == 0u && range == 1u)) {
+    return;
+  }
+
+  if (first_id == 0u) {
+    first_id++;
+    range--;
+  }
+
+  ResourceId last_id = first_id + range - 1u;
+  if (last_id < first_id) {
+    last_id = std::numeric_limits<ResourceId>::max();
+  }
+
+  while (true) {
+    ResourceIdRangeMap::iterator current = used_ids_.lower_bound(last_id);
+    if (current == used_ids_.end() || current->first > last_id) {
+      --current;
+    }
+
+    if (current->second < first_id) {
+      return;
+    }
+
+    if (current->first >= first_id) {
+      ResourceId last_existing_id = current->second;
+      used_ids_.erase(current);
+      if (last_id < last_existing_id) {
+        used_ids_.insert(std::make_pair(last_id + 1u, last_existing_id));
+      }
+    } else if (current->second <= last_id) {
+      current->second = first_id - 1u;
+    } else {
+      DCHECK(current->first < first_id && current->second > last_id);
+      ResourceId last_existing_id = current->second;
+      current->second = first_id - 1u;
+      used_ids_.insert(std::make_pair(last_id + 1u, last_existing_id));
+    }
   }
 }
 
 bool IdAllocator::InUse(ResourceId id) const {
-  return id == kInvalidResource || used_ids_.find(id) != used_ids_.end();
-}
-
-ResourceId IdAllocator::LastUsedId() const {
-  if (used_ids_.empty()) {
-    return 0u;
-  } else {
-    return *used_ids_.rbegin();
+  if (id == kInvalidResource) {
+    return false;
   }
-}
 
-ResourceId IdAllocator::FindFirstUnusedId() const {
-  ResourceId id = 1;
-  for (ResourceIdSet::const_iterator it = used_ids_.begin();
-       it != used_ids_.end(); ++it) {
-    if ((*it) != id) {
-      return id;
+  ResourceIdRangeMap::const_iterator current = used_ids_.lower_bound(id);
+  if (current != used_ids_.end()) {
+    if (current->first == id) {
+      return true;
     }
-    ++id;
   }
-  return id;
+
+  --current;
+  return current->second >= id;
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/common/id_allocator.h b/gpu/command_buffer/common/id_allocator.h
index b877083..118424f 100644
--- a/gpu/command_buffer/common/id_allocator.h
+++ b/gpu/command_buffer/common/id_allocator.h
@@ -9,7 +9,7 @@
 
 #include <stdint.h>
 
-#include <set>
+#include <map>
 #include <utility>
 
 #include "base/compiler_specific.h"
@@ -36,27 +36,28 @@
   // Note: may wrap if it starts near limit.
   ResourceId AllocateIDAtOrAbove(ResourceId desired_id);
 
+  // Allocates |range| amount of contiguous ids.
+  // Returns the first id to |first_id| or |kInvalidResource| if
+  // allocation failed.
+  ResourceId AllocateIDRange(uint32_t range);
+
   // Marks an id as used. Returns false if id was already used.
   bool MarkAsUsed(ResourceId id);
 
   // Frees a resource ID.
   void FreeID(ResourceId id);
 
+  // Frees a |range| amount of contiguous ids, starting from |first_id|.
+  void FreeIDRange(ResourceId first_id, uint32_t range);
+
   // Checks whether or not a resource ID is in use.
   bool InUse(ResourceId id) const;
 
  private:
-  // TODO(gman): This would work much better with ranges or a hash table.
-  typedef std::set<ResourceId> ResourceIdSet;
+  // first_id -> last_id mapping.
+  typedef std::map<ResourceId, ResourceId> ResourceIdRangeMap;
 
-  // The highest ID on the used list.
-  ResourceId LastUsedId() const;
-
-  // Lowest ID that isn't on the used list. This is slow, use as a last resort.
-  ResourceId FindFirstUnusedId() const;
-
-  ResourceIdSet used_ids_;
-  ResourceIdSet free_ids_;
+  ResourceIdRangeMap used_ids_;
 
   DISALLOW_COPY_AND_ASSIGN(IdAllocator);
 };
diff --git a/gpu/command_buffer/common/id_allocator_test.cc b/gpu/command_buffer/common/id_allocator_test.cc
index adeed5b..7d93906 100644
--- a/gpu/command_buffer/common/id_allocator_test.cc
+++ b/gpu/command_buffer/common/id_allocator_test.cc
@@ -125,4 +125,123 @@
   EXPECT_NE(kInvalidResource, id3);
 }
 
+TEST_F(IdAllocatorTest, AllocateIDRange) {
+  const ResourceId kMaxPossibleOffset = std::numeric_limits<ResourceId>::max();
+
+  IdAllocator* allocator = id_allocator();
+
+  ResourceId id1 = allocator->AllocateIDRange(1);
+  EXPECT_EQ(1u, id1);
+  ResourceId id2 = allocator->AllocateIDRange(2);
+  EXPECT_EQ(2u, id2);
+  ResourceId id3 = allocator->AllocateIDRange(3);
+  EXPECT_EQ(4u, id3);
+  ResourceId id4 = allocator->AllocateID();
+  EXPECT_EQ(7u, id4);
+  allocator->FreeID(3);
+  ResourceId id5 = allocator->AllocateIDRange(1);
+  EXPECT_EQ(3u, id5);
+  allocator->FreeID(5);
+  allocator->FreeID(2);
+  allocator->FreeID(4);
+  ResourceId id6 = allocator->AllocateIDRange(2);
+  EXPECT_EQ(4u, id6);
+  ResourceId id7 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset);
+  EXPECT_EQ(kMaxPossibleOffset, id7);
+  ResourceId id8 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset);
+  EXPECT_EQ(2u, id8);
+  ResourceId id9 = allocator->AllocateIDRange(50);
+  EXPECT_EQ(8u, id9);
+  ResourceId id10 = allocator->AllocateIDRange(50);
+  EXPECT_EQ(58u, id10);
+  // Remove all the low-numbered ids.
+  allocator->FreeID(1);
+  allocator->FreeID(15);
+  allocator->FreeIDRange(2, 107);
+  ResourceId id11 = allocator->AllocateIDRange(100);
+  EXPECT_EQ(1u, id11);
+  allocator->FreeID(kMaxPossibleOffset);
+  ResourceId id12 = allocator->AllocateIDRange(100);
+  EXPECT_EQ(101u, id12);
+
+  ResourceId id13 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset - 2u);
+  EXPECT_EQ(kMaxPossibleOffset - 2u, id13);
+  ResourceId id14 = allocator->AllocateIDRange(3);
+  EXPECT_EQ(201u, id14);
+}
+
+TEST_F(IdAllocatorTest, AllocateIDRangeEndNoEffect) {
+  const ResourceId kMaxPossibleOffset = std::numeric_limits<ResourceId>::max();
+
+  IdAllocator* allocator = id_allocator();
+  ResourceId id1 = allocator->AllocateIDAtOrAbove(kMaxPossibleOffset - 2u);
+  EXPECT_EQ(kMaxPossibleOffset - 2u, id1);
+  ResourceId id3 = allocator->AllocateIDRange(3);
+  EXPECT_EQ(1u, id3);
+  ResourceId id2 = allocator->AllocateIDRange(2);
+  EXPECT_EQ(4u, id2);
+}
+
+TEST_F(IdAllocatorTest, AllocateFullIDRange) {
+  const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+  const ResourceId kFreedId = 555u;
+  IdAllocator* allocator = id_allocator();
+
+  ResourceId id1 = allocator->AllocateIDRange(kMaxPossibleRange);
+  EXPECT_EQ(1u, id1);
+  ResourceId id2 = allocator->AllocateID();
+  EXPECT_EQ(0u, id2);
+  allocator->FreeID(kFreedId);
+  ResourceId id3 = allocator->AllocateID();
+  EXPECT_EQ(kFreedId, id3);
+  ResourceId id4 = allocator->AllocateID();
+  EXPECT_EQ(0u, id4);
+  allocator->FreeID(kFreedId + 1u);
+  allocator->FreeID(kFreedId + 4u);
+  allocator->FreeID(kFreedId + 3u);
+  allocator->FreeID(kFreedId + 5u);
+  allocator->FreeID(kFreedId + 2u);
+  ResourceId id5 = allocator->AllocateIDRange(5);
+  EXPECT_EQ(kFreedId + 1u, id5);
+}
+
+TEST_F(IdAllocatorTest, AllocateIDRangeNoWrapInRange) {
+  const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+  const ResourceId kAllocId = 10u;
+  IdAllocator* allocator = id_allocator();
+
+  ResourceId id1 = allocator->AllocateIDAtOrAbove(kAllocId);
+  EXPECT_EQ(kAllocId, id1);
+  ResourceId id2 = allocator->AllocateIDRange(kMaxPossibleRange - 5u);
+  EXPECT_EQ(0u, id2);
+  ResourceId id3 = allocator->AllocateIDRange(kMaxPossibleRange - kAllocId);
+  EXPECT_EQ(kAllocId + 1u, id3);
+}
+
+TEST_F(IdAllocatorTest, AllocateIdMax) {
+  const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+
+  IdAllocator* allocator = id_allocator();
+  ResourceId id = allocator->AllocateIDRange(kMaxPossibleRange);
+  EXPECT_EQ(1u, id);
+  allocator->FreeIDRange(id, kMaxPossibleRange - 1u);
+  ResourceId id2 = allocator->AllocateIDRange(kMaxPossibleRange);
+  EXPECT_EQ(0u, id2);
+  allocator->FreeIDRange(id, kMaxPossibleRange);
+  ResourceId id3 = allocator->AllocateIDRange(kMaxPossibleRange);
+  EXPECT_EQ(1u, id3);
+}
+
+TEST_F(IdAllocatorTest, ZeroIdCases) {
+  IdAllocator* allocator = id_allocator();
+  EXPECT_FALSE(allocator->InUse(0));
+  ResourceId id1 = allocator->AllocateIDAtOrAbove(0);
+  EXPECT_NE(0u, id1);
+  EXPECT_FALSE(allocator->InUse(0));
+  allocator->FreeID(0);
+  EXPECT_FALSE(allocator->InUse(0));
+  EXPECT_TRUE(allocator->InUse(id1));
+  allocator->FreeID(id1);
+  EXPECT_FALSE(allocator->InUse(id1));
+}
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
index 9098aba..d41ee9d 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -32,6 +32,11 @@
 
 namespace {
 
+const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
+                                     0.0f, 1.0f, 0.0f, 0.0f,
+                                     0.0f, 0.0f, 1.0f, 0.0f,
+                                     0.0f, 0.0f, 0.0f, 1.0f};
+
 enum VertexShaderId {
   VERTEX_SHADER_COPY_TEXTURE,
   VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
@@ -188,7 +193,6 @@
 
 bool BindFramebufferTexture2D(GLenum target,
                               GLuint texture_id,
-                              GLint level,
                               GLuint framebuffer) {
   DCHECK(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB);
   glActiveTexture(GL_TEXTURE0);
@@ -200,8 +204,8 @@
   glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
-  glFramebufferTexture2DEXT(
-      GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture_id, level);
+  glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
+                            texture_id, 0);
 
 #ifndef NDEBUG
   GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
@@ -217,28 +221,20 @@
                       GLenum source_target,
                       GLuint source_id,
                       GLuint dest_id,
-                      GLint dest_level,
                       GLenum dest_internal_format,
                       GLsizei width,
                       GLsizei height,
                       GLuint framebuffer) {
   DCHECK(source_target == GL_TEXTURE_2D ||
          source_target == GL_TEXTURE_RECTANGLE_ARB);
-  if (BindFramebufferTexture2D(
-          source_target, source_id, 0 /* level */, framebuffer)) {
+  if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
     glBindTexture(GL_TEXTURE_2D, dest_id);
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glCopyTexImage2D(GL_TEXTURE_2D,
-                     dest_level,
-                     dest_internal_format,
-                     0 /* x */,
-                     0 /* y */,
-                     width,
-                     height,
-                     0 /* border */);
+    glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format,
+                     0 /* x */, 0 /* y */, width, height, 0 /* border */);
   }
 
   decoder->RestoreTextureState(source_id);
@@ -248,6 +244,45 @@
   decoder->RestoreFramebufferBindings();
 }
 
+void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
+                         GLenum source_target,
+                         GLuint source_id,
+                         GLuint dest_id,
+                         GLint xoffset,
+                         GLint yoffset,
+                         GLsizei source_width,
+                         GLsizei source_height,
+                         GLuint framebuffer) {
+  DCHECK(source_target == GL_TEXTURE_2D ||
+         source_target == GL_TEXTURE_RECTANGLE_ARB);
+  if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
+    glBindTexture(GL_TEXTURE_2D, dest_id);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset,
+                        0 /* x */, 0 /* y */, source_width, source_height);
+  }
+
+  decoder->RestoreTextureState(source_id);
+  decoder->RestoreTextureState(dest_id);
+  decoder->RestoreTextureUnitBindings(0);
+  decoder->RestoreActiveTexture();
+  decoder->RestoreFramebufferBindings();
+}
+
+// Copy from SkMatrix44::preTranslate
+void PreTranslate(GLfloat* matrix, GLfloat dx, GLfloat dy, GLfloat dz) {
+  if (!dx && !dy && !dz)
+    return;
+
+  for (int i = 0; i < 4; ++i) {
+    matrix[(3 * 4) + i] = matrix[(0 * 4) + i] * dx + matrix[(1 * 4) + i] * dy +
+                          matrix[(2 * 4) + i] * dz + matrix[(3 * 4) + i];
+  }
+}
+
 }  // namespace
 
 namespace gpu {
@@ -318,7 +353,6 @@
     GLuint source_id,
     GLenum source_internal_format,
     GLuint dest_id,
-    GLint dest_level,
     GLenum dest_internal_format,
     GLsizei width,
     GLsizei height,
@@ -342,7 +376,6 @@
                      source_target,
                      source_id,
                      dest_id,
-                     dest_level,
                      dest_internal_format,
                      width,
                      height,
@@ -350,22 +383,51 @@
     return;
   }
 
-  // Use default transform matrix if no transform passed in.
-  const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
-                                             0.0f, 1.0f, 0.0f, 0.0f,
-                                             0.0f, 0.0f, 1.0f, 0.0f,
-                                             0.0f, 0.0f, 0.0f, 1.0f};
-  DoCopyTextureWithTransform(decoder,
-                             source_target,
-                             source_id,
-                             dest_id,
-                             dest_level,
-                             width,
-                             height,
-                             flip_y,
-                             premultiply_alpha,
-                             unpremultiply_alpha,
-                             default_matrix);
+  // Use kIdentityMatrix if no transform passed in.
+  DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width,
+                             height, flip_y, premultiply_alpha,
+                             unpremultiply_alpha, kIdentityMatrix);
+}
+
+void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
+    const gles2::GLES2Decoder* decoder,
+    GLenum source_target,
+    GLuint source_id,
+    GLenum source_internal_format,
+    GLuint dest_id,
+    GLenum dest_internal_format,
+    GLint xoffset,
+    GLint yoffset,
+    GLsizei dest_width,
+    GLsizei dest_height,
+    GLsizei source_width,
+    GLsizei source_height,
+    bool flip_y,
+    bool premultiply_alpha,
+    bool unpremultiply_alpha) {
+  bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
+  // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
+  // format does not contain a superset of the components required by the base
+  // format of internalformat.
+  // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
+  bool source_format_contain_superset_of_dest_format =
+      (source_internal_format == dest_internal_format &&
+       source_internal_format != GL_BGRA_EXT) ||
+      (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
+  // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
+  // so restrict this to GL_TEXTURE_2D.
+  if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
+      source_format_contain_superset_of_dest_format) {
+    DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset,
+                        yoffset, source_width, source_height, framebuffer_);
+    return;
+  }
+
+  // Use kIdentityMatrix if no transform passed in.
+  DoCopySubTextureWithTransform(
+      decoder, source_target, source_id, dest_id, xoffset, yoffset, dest_width,
+      dest_height, source_width, source_height, flip_y, premultiply_alpha,
+      unpremultiply_alpha, kIdentityMatrix);
 }
 
 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
@@ -373,16 +435,61 @@
     GLenum source_target,
     GLuint source_id,
     GLuint dest_id,
-    GLint dest_level,
     GLsizei width,
     GLsizei height,
     bool flip_y,
     bool premultiply_alpha,
     bool unpremultiply_alpha,
     const GLfloat transform_matrix[16]) {
+  GLsizei dest_width = width;
+  GLsizei dest_height = height;
+  DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0,
+                        dest_width, dest_height, width, height, flip_y,
+                        premultiply_alpha, unpremultiply_alpha,
+                        transform_matrix);
+}
+
+void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform(
+    const gles2::GLES2Decoder* decoder,
+    GLenum source_target,
+    GLuint source_id,
+    GLuint dest_id,
+    GLint xoffset,
+    GLint yoffset,
+    GLsizei dest_width,
+    GLsizei dest_height,
+    GLsizei source_width,
+    GLsizei source_height,
+    bool flip_y,
+    bool premultiply_alpha,
+    bool unpremultiply_alpha,
+    const GLfloat transform_matrix[16]) {
+  DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset,
+                        yoffset, dest_width, dest_height, source_width,
+                        source_height, flip_y, premultiply_alpha,
+                        unpremultiply_alpha, transform_matrix);
+}
+
+void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
+    const gles2::GLES2Decoder* decoder,
+    GLenum source_target,
+    GLuint source_id,
+    GLuint dest_id,
+    GLint xoffset,
+    GLint yoffset,
+    GLsizei dest_width,
+    GLsizei dest_height,
+    GLsizei source_width,
+    GLsizei source_height,
+    bool flip_y,
+    bool premultiply_alpha,
+    bool unpremultiply_alpha,
+    const GLfloat transform_matrix[16]) {
   DCHECK(source_target == GL_TEXTURE_2D ||
          source_target == GL_TEXTURE_RECTANGLE_ARB ||
          source_target == GL_TEXTURE_EXTERNAL_OES);
+  DCHECK(xoffset >= 0 && xoffset + source_width <= dest_width);
+  DCHECK(yoffset >= 0 && yoffset + source_height <= dest_height);
   if (!initialized_) {
     DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager.";
     return;
@@ -426,24 +533,38 @@
   }
   glUseProgram(info->program);
 
-#ifndef NDEBUG
-  glValidateProgram(info->program);
-  GLint validation_status;
-  glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status);
-  if (GL_TRUE != validation_status) {
-    DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader.";
-    return;
-  }
-#endif
+  if (!xoffset && !yoffset) {
+    glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix);
+  } else {
+    // transform offsets from ([0, dest_width], [0, dest_height]) coord.
+    // to ([-1, 1], [-1, 1]) coord.
+    GLfloat xoffset_on_vertex = ((2.f * xoffset) / dest_width);
+    GLfloat yoffset_on_vertex = ((2.f * yoffset) / dest_height);
 
-  glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix);
+    // Pass view_matrix * offset_matrix to the program.
+    GLfloat view_transform[16];
+    memcpy(view_transform, transform_matrix, 16 * sizeof(GLfloat));
+    PreTranslate(view_transform, xoffset_on_vertex, yoffset_on_vertex, 0);
+    glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, view_transform);
+  }
   if (source_target == GL_TEXTURE_RECTANGLE_ARB)
-    glUniform2f(info->half_size_handle, width / 2.0f, height / 2.0f);
+    glUniform2f(info->half_size_handle, source_width / 2.0f,
+                source_height / 2.0f);
   else
     glUniform2f(info->half_size_handle, 0.5f, 0.5f);
 
-  if (BindFramebufferTexture2D(
-          GL_TEXTURE_2D, dest_id, dest_level, framebuffer_)) {
+  if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) {
+#ifndef NDEBUG
+    // glValidateProgram of MACOSX validates FBO unlike other platforms, so
+    // glValidateProgram must be called after FBO binding. crbug.com/463439
+    glValidateProgram(info->program);
+    GLint validation_status;
+    glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status);
+    if (GL_TRUE != validation_status) {
+      DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader.";
+      return;
+    }
+#endif
     decoder->ClearAllAttributes();
     glEnableVertexAttribArray(kVertexPositionAttrib);
 
@@ -466,7 +587,7 @@
     glDepthMask(GL_FALSE);
     glDisable(GL_BLEND);
 
-    glViewport(0, 0, width, height);
+    glViewport(0, 0, dest_width, dest_height);
     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
   }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h
index 083fc4c..5c62141 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h
@@ -35,7 +35,6 @@
                      GLuint source_id,
                      GLenum source_internal_format,
                      GLuint dest_id,
-                     GLint dest_level,
                      GLenum dest_internal_format,
                      GLsizei width,
                      GLsizei height,
@@ -43,13 +42,28 @@
                      bool premultiply_alpha,
                      bool unpremultiply_alpha);
 
+  void DoCopySubTexture(const gles2::GLES2Decoder* decoder,
+                        GLenum source_target,
+                        GLuint source_id,
+                        GLenum source_internal_format,
+                        GLuint dest_id,
+                        GLenum dest_internal_format,
+                        GLint xoffset,
+                        GLint yoffset,
+                        GLsizei dest_width,
+                        GLsizei dest_height,
+                        GLsizei source_width,
+                        GLsizei source_height,
+                        bool flip_y,
+                        bool premultiply_alpha,
+                        bool unpremultiply_alpha);
+
   // This will apply a transform on the source texture before copying to
   // destination texture.
   void DoCopyTextureWithTransform(const gles2::GLES2Decoder* decoder,
                                   GLenum source_target,
                                   GLuint source_id,
                                   GLuint dest_id,
-                                  GLint dest_level,
                                   GLsizei width,
                                   GLsizei height,
                                   bool flip_y,
@@ -57,6 +71,21 @@
                                   bool unpremultiply_alpha,
                                   const GLfloat transform_matrix[16]);
 
+  void DoCopySubTextureWithTransform(const gles2::GLES2Decoder* decoder,
+                                     GLenum source_target,
+                                     GLuint source_id,
+                                     GLuint dest_id,
+                                     GLint xoffset,
+                                     GLint yoffset,
+                                     GLsizei dest_width,
+                                     GLsizei dest_height,
+                                     GLsizei source_width,
+                                     GLsizei source_height,
+                                     bool flip_y,
+                                     bool premultiply_alpha,
+                                     bool unpremultiply_alpha,
+                                     const GLfloat transform_matrix[16]);
+
   // The attributes used during invocation of the extension.
   static const GLuint kVertexPositionAttrib = 0;
 
@@ -74,6 +103,21 @@
     GLuint sampler_handle;
   };
 
+  void DoCopyTextureInternal(const gles2::GLES2Decoder* decoder,
+                             GLenum source_target,
+                             GLuint source_id,
+                             GLuint dest_id,
+                             GLint xoffset,
+                             GLint yoffset,
+                             GLsizei dest_width,
+                             GLsizei dest_height,
+                             GLsizei source_width,
+                             GLsizei source_height,
+                             bool flip_y,
+                             bool premultiply_alpha,
+                             bool unpremultiply_alpha,
+                             const GLfloat transform_matrix[16]);
+
   bool initialized_;
   typedef std::vector<GLuint> ShaderVector;
   ShaderVector vertex_shaders_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 8c24d3c..f76c085 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -81,10 +81,15 @@
 
 namespace {
 
-static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
-static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
-static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
-static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
+const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
+const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
+const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
+const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
+
+const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
+                                     0.0f, 1.0f, 0.0f, 0.0f,
+                                     0.0f, 0.0f, 1.0f, 0.0f,
+                                     0.0f, 0.0f, 0.0f, 1.0f};
 
 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
                                             GLint rangeMax,
@@ -585,7 +590,7 @@
   bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
                   const scoped_refptr<gfx::GLContext>& context,
                   bool offscreen,
-                  const gfx::Size& size,
+                  const gfx::Size& offscreen_size,
                   const DisallowedFeatures& disallowed_features,
                   const std::vector<int32>& attribs) override;
   void Destroy(bool have_context) override;
@@ -936,13 +941,17 @@
       GLuint io_surface_id,
       GLuint plane);
 
-  void DoCopyTextureCHROMIUM(
-      GLenum target,
-      GLuint source_id,
-      GLuint target_id,
-      GLint level,
-      GLenum internal_format,
-      GLenum dest_type);
+  void DoCopyTextureCHROMIUM(GLenum target,
+                             GLuint source_id,
+                             GLuint dest_id,
+                             GLenum internal_format,
+                             GLenum dest_type);
+
+  void DoCopySubTextureCHROMIUM(GLenum target,
+                                GLuint source_id,
+                                GLuint dest_id,
+                                GLint xoffset,
+                                GLint yoffset);
 
   // Wrapper for TexStorage2DEXT.
   void DoTexStorage2DEXT(
@@ -1658,6 +1667,11 @@
     GLenum target, GLint level, GLint xoffset, GLint yoffset,
     GLsizei width, GLsizei height, GLenum format,
     Texture* texture);
+  bool ValidateCopyTextureCHROMIUM(const char* function_name,
+                                   GLenum target,
+                                   TextureRef* source_texture_ref,
+                                   TextureRef* dest_texture_ref,
+                                   GLenum dest_internal_format);
 
   void RenderWarning(const char* filename, int line, const std::string& msg);
   void PerformanceWarning(
@@ -2434,13 +2448,17 @@
     const scoped_refptr<gfx::GLSurface>& surface,
     const scoped_refptr<gfx::GLContext>& context,
     bool offscreen,
-    const gfx::Size& size,
+    const gfx::Size& offscreen_size,
     const DisallowedFeatures& disallowed_features,
     const std::vector<int32>& attribs) {
   TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
   DCHECK(context->IsCurrent(surface.get()));
   DCHECK(!context_.get());
 
+  ContextCreationAttribHelper attrib_parser;
+  if (!attrib_parser.Parse(attribs))
+    return false;
+
   surfaceless_ = surface->IsSurfaceless() && !offscreen;
 
   set_initialized();
@@ -2457,7 +2475,10 @@
   }
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableUnsafeES3APIs)) {
+          switches::kEnableUnsafeES3APIs) &&
+      attrib_parser.es3_context_required) {
+    // TODO(zmo): We need to implement capabilities check to ensure we can
+    // actually create ES3 contexts.
     set_unsafe_es3_apis_enabled(true);
   }
 
@@ -2470,10 +2491,6 @@
   context_ = context;
   surface_ = surface;
 
-  ContextCreationAttribHelper attrib_parser;
-  if (!attrib_parser.Parse(attribs))
-    return false;
-
   // Create GPU Tracer for timing values.
   gpu_tracer_.reset(new GPUTracer(this));
 
@@ -2675,12 +2692,15 @@
 
     // Allocate the render buffers at their initial size and check the status
     // of the frame buffers is okay.
-    if (!ResizeOffscreenFrameBuffer(size)) {
+    if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
       LOG(ERROR) << "Could not allocate offscreen buffer storage.";
       Destroy(true);
       return false;
     }
 
+    state_.viewport_width = offscreen_size.width();
+    state_.viewport_height = offscreen_size.height();
+
     // Allocate the offscreen saved color texture.
     DCHECK(offscreen_saved_color_format_);
     offscreen_saved_color_texture_->AllocateStorage(
@@ -2720,6 +2740,9 @@
       glGetIntegerv(GL_STENCIL_BITS, &v);
       back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0;
     }
+
+    state_.viewport_width = surface->GetSize().width();
+    state_.viewport_height = surface->GetSize().height();
   }
 
   // OpenGL ES 2.0 implicitly enables the desktop GL capability
@@ -2742,9 +2765,6 @@
     return false;
   }
 
-  state_.viewport_width = size.width();
-  state_.viewport_height = size.height();
-
   GLint viewport_params[4] = { 0 };
   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
   viewport_max_width_ = viewport_params[0];
@@ -2956,9 +2976,15 @@
         features().nv_draw_buffers ? 1 : 0;
   }
 
-  ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
-                                                          : SH_GLES2_SPEC;
-  if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
+  ShShaderSpec shader_spec;
+  if (force_webgl_glsl_validation_) {
+    shader_spec = unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
+  } else {
+    shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
+  }
+
+  if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
+      features().enable_shader_name_hashing)
     resources.HashFunction = &CityHash64;
   else
     resources.HashFunction = NULL;
@@ -10935,40 +10961,78 @@
   }
 }
 
-void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
-    GLenum target, GLuint source_id, GLuint dest_id, GLint level,
-    GLenum internal_format, GLenum dest_type) {
-  TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
-
-  TextureRef* dest_texture_ref = GetTexture(dest_id);
-  TextureRef* source_texture_ref = GetTexture(source_id);
-
+bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
+    const char* function_name,
+    GLenum target,
+    TextureRef* source_texture_ref,
+    TextureRef* dest_texture_ref,
+    GLenum dest_internal_format) {
   if (!source_texture_ref || !dest_texture_ref) {
-    LOCAL_SET_GL_ERROR(
-        GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
-    return;
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
+    return false;
   }
 
   if (GL_TEXTURE_2D != target) {
-    LOCAL_SET_GL_ERROR(
-        GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
-    return;
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
+                       "invalid texture target");
+    return false;
   }
 
   Texture* source_texture = source_texture_ref->texture();
   Texture* dest_texture = dest_texture_ref->texture();
+  if (source_texture == dest_texture) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+                       "source and destination textures are the same");
+    return false;
+  }
+
   if (dest_texture->target() != GL_TEXTURE_2D ||
       (source_texture->target() != GL_TEXTURE_2D &&
        source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
        source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
-                       "glCopyTextureCHROMIUM",
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
                        "invalid texture target binding");
-    return;
+    return false;
   }
 
-  int source_width, source_height, dest_width, dest_height;
+  GLenum source_type = 0;
+  GLenum source_internal_format = 0;
+  source_texture->GetLevelType(source_texture->target(), 0, &source_type,
+                               &source_internal_format);
 
+  // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
+  // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
+  // renderable on some platforms.
+  bool valid_dest_format = dest_internal_format == GL_RGB ||
+                           dest_internal_format == GL_RGBA ||
+                           dest_internal_format == GL_BGRA_EXT;
+  bool valid_source_format = source_internal_format == GL_ALPHA ||
+                             source_internal_format == GL_RGB ||
+                             source_internal_format == GL_RGBA ||
+                             source_internal_format == GL_LUMINANCE ||
+                             source_internal_format == GL_LUMINANCE_ALPHA ||
+                             source_internal_format == GL_BGRA_EXT;
+  if (!valid_source_format || !valid_dest_format) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+                       "invalid internal format");
+    return false;
+  }
+  return true;
+}
+
+void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target,
+                                             GLuint source_id,
+                                             GLuint dest_id,
+                                             GLenum internal_format,
+                                             GLenum dest_type) {
+  TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
+
+  TextureRef* source_texture_ref = GetTexture(source_id);
+  TextureRef* dest_texture_ref = GetTexture(dest_id);
+  Texture* source_texture = source_texture_ref->texture();
+  Texture* dest_texture = dest_texture_ref->texture();
+  int source_width = 0;
+  int source_height = 0;
   gfx::GLImage* image =
       source_texture->GetLevelImage(source_texture->target(), 0);
   if (image) {
@@ -10991,43 +11055,36 @@
     }
 
     // Check that this type of texture is allowed.
-    if (!texture_manager()->ValidForTarget(
-             source_texture->target(), level, source_width, source_height, 1)) {
+    if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
+                                           source_width, source_height, 1)) {
       LOCAL_SET_GL_ERROR(
           GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
       return;
     }
   }
 
-  // Clear the source texture if necessary.
-  if (!texture_manager()->ClearTextureLevel(
-          this, source_texture_ref, source_texture->target(), 0)) {
-    LOCAL_SET_GL_ERROR(
-        GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
-    return;
-  }
-
   GLenum source_type = 0;
   GLenum source_internal_format = 0;
   source_texture->GetLevelType(
       source_texture->target(), 0, &source_type, &source_internal_format);
 
-  // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
-  // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
-  // renderable on some platforms.
-  bool valid_dest_format = internal_format == GL_RGB ||
-                           internal_format == GL_RGBA ||
-                           internal_format == GL_BGRA_EXT;
-  bool valid_source_format = source_internal_format == GL_ALPHA ||
-                             source_internal_format == GL_RGB ||
-                             source_internal_format == GL_RGBA ||
-                             source_internal_format == GL_LUMINANCE ||
-                             source_internal_format == GL_LUMINANCE_ALPHA ||
-                             source_internal_format == GL_BGRA_EXT;
-  if (!valid_source_format || !valid_dest_format) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
-                       "glCopyTextureCHROMIUM",
-                       "invalid internal format");
+  if (dest_texture->IsImmutable()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
+                       "texture is immutable");
+    return;
+  }
+
+  if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
+                                   source_texture_ref, dest_texture_ref,
+                                   internal_format)) {
+    return;
+  }
+
+  // Clear the source texture if necessary.
+  if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
+                                            source_texture->target(), 0)) {
+    LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
+                       "dimensions too big");
     return;
   }
 
@@ -11044,11 +11101,13 @@
 
   GLenum dest_type_previous = dest_type;
   GLenum dest_internal_format = internal_format;
-  bool dest_level_defined = dest_texture->GetLevelSize(
-      GL_TEXTURE_2D, level, &dest_width, &dest_height);
+  int dest_width = 0;
+  int dest_height = 0;
+  bool dest_level_defined =
+      dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
 
   if (dest_level_defined) {
-    dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
+    dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
                                &dest_internal_format);
   }
 
@@ -11060,9 +11119,8 @@
     // Ensure that the glTexImage2D succeeds.
     LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
     glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
-    glTexImage2D(
-        GL_TEXTURE_2D, level, internal_format, source_width, source_height,
-        0, internal_format, dest_type, NULL);
+    glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
+                 0, internal_format, dest_type, NULL);
     GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
     if (error != GL_NO_ERROR) {
       RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
@@ -11070,11 +11128,11 @@
     }
 
     texture_manager()->SetLevelInfo(
-        dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
+        dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
         source_height, 1, 0, internal_format, dest_type, true);
   } else {
-    texture_manager()->SetLevelCleared(
-        dest_texture_ref, GL_TEXTURE_2D, level, true);
+    texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
+                                       true);
   }
 
   ScopedModifyPixels modify(dest_texture_ref);
@@ -11082,7 +11140,7 @@
   // Try using GLImage::CopyTexImage when possible.
   bool unpack_premultiply_alpha_change =
       unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
-  if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change && !level) {
+  if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
     glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
     if (image->CopyTexImage(GL_TEXTURE_2D))
       return;
@@ -11094,36 +11152,159 @@
   // before presenting.
   if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
     // TODO(hkuang): get the StreamTexture transform matrix in GPU process
-    // instead of using default matrix crbug.com/226218.
-    const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
-                                               0.0f, 1.0f, 0.0f, 0.0f,
-                                               0.0f, 0.0f, 1.0f, 0.0f,
-                                               0.0f, 0.0f, 0.0f, 1.0f};
+    // instead of using kIdentityMatrix crbug.com/226218.
     copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
-        this,
-        source_texture->target(),
-        source_texture->service_id(),
-        dest_texture->service_id(),
-        level,
-        source_width,
-        source_height,
-        unpack_flip_y_,
-        unpack_premultiply_alpha_,
-        unpack_unpremultiply_alpha_,
-        default_matrix);
+        this, source_texture->target(), source_texture->service_id(),
+        dest_texture->service_id(), source_width, source_height, unpack_flip_y_,
+        unpack_premultiply_alpha_, unpack_unpremultiply_alpha_,
+        kIdentityMatrix);
   } else {
-    copy_texture_CHROMIUM_->DoCopyTexture(this,
-                                          source_texture->target(),
-                                          source_texture->service_id(),
-                                          source_internal_format,
-                                          dest_texture->service_id(),
-                                          level,
-                                          internal_format,
-                                          source_width,
-                                          source_height,
-                                          unpack_flip_y_,
-                                          unpack_premultiply_alpha_,
-                                          unpack_unpremultiply_alpha_);
+    copy_texture_CHROMIUM_->DoCopyTexture(
+        this, source_texture->target(), source_texture->service_id(),
+        source_internal_format, dest_texture->service_id(), internal_format,
+        source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
+        unpack_unpremultiply_alpha_);
+  }
+
+  DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
+}
+
+void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target,
+                                                GLuint source_id,
+                                                GLuint dest_id,
+                                                GLint xoffset,
+                                                GLint yoffset) {
+  TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
+
+  TextureRef* source_texture_ref = GetTexture(source_id);
+  TextureRef* dest_texture_ref = GetTexture(dest_id);
+  Texture* source_texture = source_texture_ref->texture();
+  Texture* dest_texture = dest_texture_ref->texture();
+  int source_width = 0;
+  int source_height = 0;
+  gfx::GLImage* image =
+      source_texture->GetLevelImage(source_texture->target(), 0);
+  if (image) {
+    gfx::Size size = image->GetSize();
+    source_width = size.width();
+    source_height = size.height();
+    if (source_width <= 0 || source_height <= 0) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
+                         "invalid image size");
+      return;
+    }
+  } else {
+    if (!source_texture->GetLevelSize(source_texture->target(), 0,
+                                      &source_width, &source_height)) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
+                         "source texture has no level 0");
+      return;
+    }
+
+    // Check that this type of texture is allowed.
+    if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
+                                           source_width, source_height, 1)) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
+                         "source texture bad dimensions");
+      return;
+    }
+  }
+
+  GLenum source_type = 0;
+  GLenum source_internal_format = 0;
+  source_texture->GetLevelType(source_texture->target(), 0, &source_type,
+                               &source_internal_format);
+  GLenum dest_type = 0;
+  GLenum dest_internal_format = 0;
+  bool dest_level_defined = dest_texture->GetLevelType(
+      dest_texture->target(), 0, &dest_type, &dest_internal_format);
+  if (!dest_level_defined) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
+                       "destination texture is not defined");
+    return;
+  }
+  if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
+                                     yoffset, source_width, source_height,
+                                     dest_type)) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
+                       "destination texture bad dimensions.");
+    return;
+  }
+
+  if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
+                                   source_texture_ref, dest_texture_ref,
+                                   dest_internal_format)) {
+    return;
+  }
+
+  // Clear the source texture if necessary.
+  if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
+                                            source_texture->target(), 0)) {
+    LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
+                       "source texture dimensions too big");
+    return;
+  }
+
+  // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
+  // needed because it takes 10s of milliseconds to initialize.
+  if (!copy_texture_CHROMIUM_.get()) {
+    LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
+    copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
+    copy_texture_CHROMIUM_->Initialize(this);
+    RestoreCurrentFramebufferBindings();
+    if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
+      return;
+  }
+
+  int dest_width = 0;
+  int dest_height = 0;
+  bool ok =
+      dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
+  DCHECK(ok);
+  if (xoffset != 0 || yoffset != 0 || source_width != dest_width ||
+      source_height != dest_height) {
+    if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
+                                              0)) {
+      LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
+                         "destination texture dimensions too big");
+      return;
+    }
+  } else {
+    texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
+                                       true);
+  }
+
+  ScopedModifyPixels modify(dest_texture_ref);
+
+  // Try using GLImage::CopyTexSubImage when possible.
+  bool unpack_premultiply_alpha_change =
+      unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
+  if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change &&
+      !xoffset && !yoffset) {
+    glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
+    if (image->CopyTexImage(GL_TEXTURE_2D))
+      return;
+  }
+
+  DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
+
+  // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
+  // before presenting.
+  if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
+    // TODO(hkuang): get the StreamTexture transform matrix in GPU process
+    // instead of using kIdentityMatrix crbug.com/226218.
+    copy_texture_CHROMIUM_->DoCopySubTextureWithTransform(
+        this, source_texture->target(), source_texture->service_id(),
+        dest_texture->service_id(), xoffset, yoffset, dest_width, dest_height,
+        source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
+        unpack_unpremultiply_alpha_, kIdentityMatrix);
+  } else {
+    copy_texture_CHROMIUM_->DoCopySubTexture(
+        this, source_texture->target(), source_texture->service_id(),
+        source_internal_format, dest_texture->service_id(),
+        dest_internal_format, xoffset, yoffset, dest_width, dest_height,
+        source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
+        unpack_unpremultiply_alpha_);
   }
 
   DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
@@ -11728,10 +11909,6 @@
     return;
   }
 
-  static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-                                        0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-                                        0.0f, 0.0f, 0.0f, 1.0f};
-
   GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
                                ? state_.projection_matrix
                                : state_.modelview_matrix;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 5ccdf7b..0cbe0fe 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -115,13 +115,13 @@
   //  offscreen: whether to make the context offscreen or not. When FBO 0 is
   //      bound, offscreen contexts render to an internal buffer, onscreen ones
   //      to the surface.
-  //  size: the size if the GL context is offscreen.
+  //  offscreen_size: the size if the GL context is offscreen.
   // Returns:
   //   true if successful.
   virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
                           const scoped_refptr<gfx::GLContext>& context,
                           bool offscreen,
-                          const gfx::Size& size,
+                          const gfx::Size& offscreen_size,
                           const DisallowedFeatures& disallowed_features,
                           const std::vector<int32>& attribs) = 0;
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index c3dfb5d..3c353c4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -4330,7 +4330,6 @@
   GLenum target = static_cast<GLenum>(c.target);
   GLenum source_id = static_cast<GLenum>(c.source_id);
   GLenum dest_id = static_cast<GLenum>(c.dest_id);
-  GLint level = static_cast<GLint>(c.level);
   GLint internalformat = static_cast<GLint>(c.internalformat);
   GLenum dest_type = static_cast<GLenum>(c.dest_type);
   if (!validators_->texture_internal_format.IsValid(internalformat)) {
@@ -4343,8 +4342,22 @@
                                     "dest_type");
     return error::kNoError;
   }
-  DoCopyTextureCHROMIUM(target, source_id, dest_id, level, internalformat,
-                        dest_type);
+  DoCopyTextureCHROMIUM(target, source_id, dest_id, internalformat, dest_type);
+  return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleCopySubTextureCHROMIUM(
+    uint32_t immediate_data_size,
+    const void* cmd_data) {
+  const gles2::cmds::CopySubTextureCHROMIUM& c =
+      *static_cast<const gles2::cmds::CopySubTextureCHROMIUM*>(cmd_data);
+  (void)c;
+  GLenum target = static_cast<GLenum>(c.target);
+  GLenum source_id = static_cast<GLenum>(c.source_id);
+  GLenum dest_id = static_cast<GLenum>(c.dest_id);
+  GLint xoffset = static_cast<GLint>(c.xoffset);
+  GLint yoffset = static_cast<GLint>(c.yoffset);
+  DoCopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, yoffset);
   return error::kNoError;
 }
 
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 f8f4984..29a55ba 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
@@ -235,6 +235,7 @@
 // TODO(gman): PostSubBufferCHROMIUM
 // TODO(gman): TexImageIOSurface2DCHROMIUM
 // TODO(gman): CopyTextureCHROMIUM
+// TODO(gman): CopySubTextureCHROMIUM
 // TODO(gman): DrawArraysInstancedANGLE
 // TODO(gman): DrawElementsInstancedANGLE
 // TODO(gman): VertexAttribDivisorANGLE
diff --git a/gpu/command_buffer/service/gpu_switches.cc b/gpu/command_buffer/service/gpu_switches.cc
index a2d43e9..2e4e083 100644
--- a/gpu/command_buffer/service/gpu_switches.cc
+++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -65,9 +65,6 @@
 const char kEnableThreadedTextureMailboxes[] =
     "enable-threaded-texture-mailboxes";
 
-// Enable OpenGL ES 3 APIs without proper service side validation.
-const char kEnableUnsafeES3APIs[] = "enable-unsafe-es3-apis";
-
 // Include ANGLE's intermediate representation (AST) output in shader
 // compilation info logs.
 const char kGLShaderIntermOutput[] = "gl-shader-interm-output";
@@ -92,7 +89,6 @@
   kGpuProgramCacheSizeKb,
   kDisableGpuShaderDiskCache,
   kEnableShareGroupAsyncTextureUpload,
-  kEnableUnsafeES3APIs,
   kEnableSubscribeUniformExtension,
   kGLShaderIntermOutput,
   kEmulateShaderPrecision,
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h
index 5ed2861..47364a1 100644
--- a/gpu/command_buffer/service/gpu_switches.h
+++ b/gpu/command_buffer/service/gpu_switches.h
@@ -28,7 +28,6 @@
 GPU_EXPORT extern const char kEnableShareGroupAsyncTextureUpload[];
 GPU_EXPORT extern const char kEnableSubscribeUniformExtension[];
 GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[];
-GPU_EXPORT extern const char kEnableUnsafeES3APIs[];
 GPU_EXPORT extern const char kGLShaderIntermOutput[];
 GPU_EXPORT extern const char kEmulateShaderPrecision[];
 
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc
index 6566f6a..946d8ae 100644
--- a/gpu/command_buffer/service/gpu_tracer_unittest.cc
+++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -207,6 +207,15 @@
       extensions = "GL_ARB_timer_query GL_ARB_occlusion_query";
     }
     GpuServiceTest::SetUpWithGLVersion(gl_version, extensions);
+
+    // Disjoint check should only be called by kTracerTypeDisjointTimer type.
+    if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) {
+      EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(AtLeast(1))
+          .WillRepeatedly(
+              Invoke(&gl_fake_queries_, &GlFakeQueries::GetIntegerv));
+    } else {
+      EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(Exactly(0));
+    }
     gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient();
     gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime));
     gl_fake_queries_.Reset();
@@ -290,15 +299,6 @@
   }
 
   void ExpectTracerOffsetQueryMocks() {
-    // Disjoint check should only be called by kTracerTypeDisjointTimer type.
-    if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) {
-      EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(AtLeast(1))
-          .WillRepeatedly(
-              Invoke(&gl_fake_queries_, &GlFakeQueries::GetIntegerv));
-    } else {
-      EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(Exactly(0));
-    }
-
     if (GetTimerType() != gfx::GPUTiming::kTimerTypeARB) {
       EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull()))
           .Times(Exactly(0));
@@ -537,7 +537,17 @@
 
     gl_fake_queries_.SetCurrentGLTime(end_timestamp);
     g_fakeCPUTime = expect_end_time;
+
+    // Create GPUTimingClient to make sure disjoint value is correct. This
+    // should not interfere with the tracer's disjoint value.
+    scoped_refptr<gfx::GPUTimingClient>  disjoint_client =
+        GetGLContext()->CreateGPUTimingClient();
+
+    // We assert here based on the disjoint_client because if disjoints are not
+    // working properly there is no point testing the tracer output.
+    ASSERT_FALSE(disjoint_client->CheckAndResetTimerErrors());
     gl_fake_queries_.SetDisjoint();
+    ASSERT_TRUE(disjoint_client->CheckAndResetTimerErrors());
 
     ExpectOutputterEndMocks(outputter_ref_.get(), category_name, trace_name,
                             expect_start_time, expect_end_time, false);
@@ -642,6 +652,37 @@
   ASSERT_TRUE(tracer_tester_->EndDecoding());
 }
 
+TEST_F(GpuDisjointTimerTracerTest, MultipleClientsDisjointTest) {
+  scoped_refptr<gfx::GPUTimingClient> client1 =
+      GetGLContext()->CreateGPUTimingClient();
+  scoped_refptr<gfx::GPUTimingClient>  client2 =
+      GetGLContext()->CreateGPUTimingClient();
+
+  // Test both clients are initialized as no errors.
+  ASSERT_FALSE(client1->CheckAndResetTimerErrors());
+  ASSERT_FALSE(client2->CheckAndResetTimerErrors());
+
+  // Issue a disjoint.
+  gl_fake_queries_.SetDisjoint();
+
+  ASSERT_TRUE(client1->CheckAndResetTimerErrors());
+  ASSERT_TRUE(client2->CheckAndResetTimerErrors());
+
+  // Test both are now reset.
+  ASSERT_FALSE(client1->CheckAndResetTimerErrors());
+  ASSERT_FALSE(client2->CheckAndResetTimerErrors());
+
+  // Issue a disjoint.
+  gl_fake_queries_.SetDisjoint();
+
+  // Test new client disjoint value is cleared.
+  scoped_refptr<gfx::GPUTimingClient>  client3 =
+      GetGLContext()->CreateGPUTimingClient();
+  ASSERT_TRUE(client1->CheckAndResetTimerErrors());
+  ASSERT_TRUE(client2->CheckAndResetTimerErrors());
+  ASSERT_FALSE(client3->CheckAndResetTimerErrors());
+}
+
 }  // namespace
 }  // namespace gles2
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/image_factory.cc b/gpu/command_buffer/service/image_factory.cc
index 1665c1e..9a2d458 100644
--- a/gpu/command_buffer/service/image_factory.cc
+++ b/gpu/command_buffer/service/image_factory.cc
@@ -4,6 +4,7 @@
 
 #include "gpu/command_buffer/service/image_factory.h"
 
+#include "gpu/command_buffer/common/capabilities.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace gpu {
@@ -93,4 +94,52 @@
   }
 }
 
+// static
+bool ImageFactory::IsGpuMemoryBufferFormatSupported(
+    gfx::GpuMemoryBuffer::Format format,
+    const gpu::Capabilities& capabilities) {
+  switch (format) {
+    case gfx::GpuMemoryBuffer::ATC:
+    case gfx::GpuMemoryBuffer::ATCIA:
+      return capabilities.texture_format_atc;
+    case gfx::GpuMemoryBuffer::BGRA_8888:
+      return capabilities.texture_format_bgra8888;
+    case gfx::GpuMemoryBuffer::DXT1:
+      return capabilities.texture_format_dxt1;
+    case gfx::GpuMemoryBuffer::DXT5:
+      return capabilities.texture_format_dxt5;
+    case gfx::GpuMemoryBuffer::ETC1:
+      return capabilities.texture_format_etc1;
+    case gfx::GpuMemoryBuffer::RGBA_8888:
+    case gfx::GpuMemoryBuffer::RGBX_8888:
+      return true;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+// static
+bool ImageFactory::IsImageSizeValidForGpuMemoryBufferFormat(
+    const gfx::Size& size,
+    gfx::GpuMemoryBuffer::Format format) {
+  switch (format) {
+    case gfx::GpuMemoryBuffer::ATC:
+    case gfx::GpuMemoryBuffer::ATCIA:
+    case gfx::GpuMemoryBuffer::DXT1:
+    case gfx::GpuMemoryBuffer::DXT5:
+    case gfx::GpuMemoryBuffer::ETC1:
+      // Compressed images must have a width and height that's evenly divisible
+      // by the block size.
+      return size.width() % 4 == 0 && size.height() % 4 == 0;
+    case gfx::GpuMemoryBuffer::RGBA_8888:
+    case gfx::GpuMemoryBuffer::BGRA_8888:
+    case gfx::GpuMemoryBuffer::RGBX_8888:
+      return true;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/image_factory.h b/gpu/command_buffer/service/image_factory.h
index 40dd15a..b581342 100644
--- a/gpu/command_buffer/service/image_factory.h
+++ b/gpu/command_buffer/service/image_factory.h
@@ -15,6 +15,7 @@
 }
 
 namespace gpu {
+struct Capabilities;
 
 class GPU_EXPORT ImageFactory {
  public:
@@ -35,6 +36,16 @@
       unsigned internalformat,
       gfx::GpuMemoryBuffer::Format format);
 
+  // Returns true if |format| is supported by |capabilities|.
+  static bool IsGpuMemoryBufferFormatSupported(
+      gfx::GpuMemoryBuffer::Format format,
+      const Capabilities& capabilities);
+
+  // Returns true if |size| is valid for |format|.
+  static bool IsImageSizeValidForGpuMemoryBufferFormat(
+      const gfx::Size& size,
+      gfx::GpuMemoryBuffer::Format format);
+
   // Creates a GLImage instance for GPU memory buffer identified by |handle|.
   // |client_id| should be set to the client requesting the creation of instance
   // and can be used by factory implementation to verify access rights.
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc
index 98d738d..c0904c7 100644
--- a/gpu/command_buffer/service/shader_translator.cc
+++ b/gpu/command_buffer/service/shader_translator.cc
@@ -110,13 +110,19 @@
   // Make sure Init is called only once.
   DCHECK(compiler_ == NULL);
   DCHECK(shader_type == GL_FRAGMENT_SHADER || shader_type == GL_VERTEX_SHADER);
-  DCHECK(shader_spec == SH_GLES2_SPEC || shader_spec == SH_WEBGL_SPEC);
+  DCHECK(shader_spec == SH_GLES2_SPEC || shader_spec == SH_WEBGL_SPEC ||
+         shader_spec == SH_GLES3_SPEC || shader_spec == SH_WEBGL2_SPEC);
   DCHECK(resources != NULL);
 
   g_translator_initializer.Get();
 
-  ShShaderOutput shader_output =
-      (glsl_implementation_type == kGlslES ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT);
+  ShShaderOutput shader_output;
+  if (glsl_implementation_type == kGlslES) {
+    shader_output = SH_ESSL_OUTPUT;
+  } else {
+    shader_output = (shader_spec == SH_WEBGL2_SPEC) ? SH_GLSL_CORE_OUTPUT :
+        SH_GLSL_COMPATIBILITY_OUTPUT;
+  }
 
   {
     TRACE_EVENT0("gpu", "ShConstructCompiler");
diff --git a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
index 2c44e1a..ff15241 100644
--- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
@@ -17,8 +17,18 @@
 
 namespace gpu {
 
+namespace {
+enum CopyType { TexImage, TexSubImage };
+const CopyType kCopyTypes[] = {
+    TexImage,
+    TexSubImage,
+};
+}
+
 // A collection of tests that exercise the GL_CHROMIUM_copy_texture extension.
-class GLCopyTextureCHROMIUMTest : public testing::Test {
+class GLCopyTextureCHROMIUMTest
+    : public testing::Test,
+      public ::testing::WithParamInterface<CopyType> {
  protected:
   void SetUp() override {
     gl_.Initialize(GLManager::Options());
@@ -50,16 +60,29 @@
   GLuint framebuffer_id_;
 };
 
+INSTANTIATE_TEST_CASE_P(CopyType,
+                        GLCopyTextureCHROMIUMTest,
+                        ::testing::ValuesIn(kCopyTypes));
+
 // Test to ensure that the basic functionality of the extension works.
-TEST_F(GLCopyTextureCHROMIUMTest, Basic) {
+TEST_P(GLCopyTextureCHROMIUMTest, Basic) {
+  CopyType copy_type = GetParam();
   uint8 pixels[1 * 4] = { 255u, 0u, 0u, 255u };
 
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                pixels);
 
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                        GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(glGetError() == GL_NO_ERROR);
 
   // Check the FB is still bound.
@@ -76,7 +99,51 @@
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 }
 
-TEST_F(GLCopyTextureCHROMIUMTest, InternalFormat) {
+TEST_P(GLCopyTextureCHROMIUMTest, ImmutableTexture) {
+  if (!GLTestHelper::HasExtension("GL_EXT_texture_storage")) {
+    LOG(INFO) << "GL_EXT_texture_storage not supported. Skipping test...";
+    return;
+  }
+  CopyType copy_type = GetParam();
+
+  uint8 pixels[1 * 4] = {255u, 0u, 0u, 255u};
+
+  glBindTexture(GL_TEXTURE_2D, textures_[0]);
+  glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1);
+  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+                  pixels);
+
+  glBindTexture(GL_TEXTURE_2D, textures_[1]);
+  glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1);
+  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                         textures_[1], 0);
+  EXPECT_TRUE(glGetError() == GL_NO_ERROR);
+
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+    EXPECT_TRUE(glGetError() == GL_INVALID_OPERATION);
+  } else {
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+    EXPECT_TRUE(glGetError() == GL_NO_ERROR);
+
+    // Check the FB is still bound.
+    GLint value = 0;
+    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
+    GLuint fb_id = value;
+    EXPECT_EQ(framebuffer_id_, fb_id);
+
+    // Check that FB is complete.
+    EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+              glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    GLTestHelper::CheckPixels(0, 0, 1, 1, 0, pixels);
+    EXPECT_TRUE(GL_NO_ERROR == glGetError());
+  }
+}
+
+TEST_P(GLCopyTextureCHROMIUMTest, InternalFormat) {
+  CopyType copy_type = GetParam();
   GLint src_formats[] = {GL_ALPHA,     GL_RGB,             GL_RGBA,
                          GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGRA_EXT};
   GLint dest_formats[] = {GL_RGB, GL_RGBA};
@@ -85,33 +152,34 @@
     for (size_t dest_index = 0; dest_index < arraysize(dest_formats);
          dest_index++) {
       glBindTexture(GL_TEXTURE_2D, textures_[0]);
-      glTexImage2D(GL_TEXTURE_2D,
-                   0,
-                   src_formats[src_index],
-                   1,
-                   1,
-                   0,
-                   src_formats[src_index],
-                   GL_UNSIGNED_BYTE,
-                   NULL);
+      glTexImage2D(GL_TEXTURE_2D, 0, src_formats[src_index], 1, 1, 0,
+                   src_formats[src_index], GL_UNSIGNED_BYTE, nullptr);
       EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
-      glCopyTextureCHROMIUM(GL_TEXTURE_2D,
-                            textures_[0],
-                            textures_[1],
-                            0,
-                            dest_formats[dest_index],
-                            GL_UNSIGNED_BYTE);
+      if (copy_type == TexImage) {
+        glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1],
+                              dest_formats[dest_index], GL_UNSIGNED_BYTE);
+      } else {
+        glBindTexture(GL_TEXTURE_2D, textures_[1]);
+        glTexImage2D(GL_TEXTURE_2D, 0, dest_formats[dest_index], 1, 1, 0,
+                     dest_formats[dest_index], GL_UNSIGNED_BYTE, nullptr);
+        EXPECT_TRUE(GL_NO_ERROR == glGetError());
+
+        glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0,
+                                 0);
+      }
+
       EXPECT_TRUE(GL_NO_ERROR == glGetError()) << "src_index:" << src_index
                                                << " dest_index:" << dest_index;
     }
   }
 }
 
-TEST_F(GLCopyTextureCHROMIUMTest, InternalFormatNotSupported) {
+TEST_P(GLCopyTextureCHROMIUMTest, InternalFormatNotSupported) {
+  CopyType copy_type = GetParam();
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
-  glTexImage2D(
-      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+               nullptr);
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   // Check unsupported format reports error.
@@ -119,12 +187,17 @@
                                       GL_LUMINANCE_ALPHA};
   for (size_t dest_index = 0; dest_index < arraysize(unsupported_dest_formats);
        dest_index++) {
-    glCopyTextureCHROMIUM(GL_TEXTURE_2D,
-                          textures_[0],
-                          textures_[1],
-                          0,
-                          unsupported_dest_formats[dest_index],
-                          GL_UNSIGNED_BYTE);
+    if (copy_type == TexImage) {
+      glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1],
+                            unsupported_dest_formats[dest_index],
+                            GL_UNSIGNED_BYTE);
+    } else {
+      glBindTexture(GL_TEXTURE_2D, textures_[1]);
+      glTexImage2D(GL_TEXTURE_2D, 0, unsupported_dest_formats[dest_index], 1, 1,
+                   0, unsupported_dest_formats[dest_index], GL_UNSIGNED_BYTE,
+                   nullptr);
+      glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+    }
     EXPECT_TRUE(GL_INVALID_OPERATION == glGetError())
         << "dest_index:" << dest_index;
   }
@@ -163,8 +236,8 @@
 
   // If the dest texture has different properties, glCopyTextureCHROMIUM()
   // redefines them.
-  glCopyTextureCHROMIUM(
-      GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA, GL_UNSIGNED_BYTE);
+  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                        GL_UNSIGNED_BYTE);
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   // glTexSubImage2D() succeeds because textures_[1] is redefined into 2x2
@@ -189,7 +262,8 @@
 }
 
 // Test that the extension respects the flip-y pixel storage setting.
-TEST_F(GLCopyTextureCHROMIUMTest, FlipY) {
+TEST_P(GLCopyTextureCHROMIUMTest, FlipY) {
+  CopyType copy_type = GetParam();
   uint8 pixels[2][2][4];
   for (int x = 0; x < 2; ++x) {
     for (int y = 0; y < 2; ++y) {
@@ -205,8 +279,16 @@
                pixels);
 
   glPixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                        GL_UNSIGNED_BYTE);
+
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   uint8 copied_pixels[2][2][4] = {{{0}}};
@@ -225,7 +307,8 @@
 
 // Test that the extension respects the GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
 // storage setting.
-TEST_F(GLCopyTextureCHROMIUMTest, PremultiplyAlpha) {
+TEST_P(GLCopyTextureCHROMIUMTest, PremultiplyAlpha) {
+  CopyType copy_type = GetParam();
   uint8 pixels[1 * 4] = { 2, 2, 2, 128 };
 
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
@@ -233,8 +316,15 @@
                pixels);
 
   glPixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, GL_TRUE);
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                       GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   uint8 copied_pixels[1 * 4] = {0};
@@ -249,7 +339,8 @@
 
 // Test that the extension respects the GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
 // storage setting.
-TEST_F(GLCopyTextureCHROMIUMTest, UnpremultiplyAlpha) {
+TEST_P(GLCopyTextureCHROMIUMTest, UnpremultiplyAlpha) {
+  CopyType copy_type = GetParam();
   uint8 pixels[1 * 4] = { 16, 16, 16, 128 };
 
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
@@ -257,8 +348,15 @@
                pixels);
 
   glPixelStorei(GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, GL_TRUE);
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                        GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   uint8 copied_pixels[1 * 4] = {0};
@@ -271,7 +369,8 @@
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 }
 
-TEST_F(GLCopyTextureCHROMIUMTest, FlipYAndPremultiplyAlpha) {
+TEST_P(GLCopyTextureCHROMIUMTest, FlipYAndPremultiplyAlpha) {
+  CopyType copy_type = GetParam();
   uint8 pixels[2][2][4];
   for (int x = 0; x < 2; ++x) {
     for (int y = 0; y < 2; ++y) {
@@ -289,8 +388,15 @@
 
   glPixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
   glPixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, GL_TRUE);
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                        GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   uint8 copied_pixels[2][2][4] = {{{0}}};
@@ -307,7 +413,8 @@
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 }
 
-TEST_F(GLCopyTextureCHROMIUMTest, FlipYAndUnpremultiplyAlpha) {
+TEST_P(GLCopyTextureCHROMIUMTest, FlipYAndUnpremultiplyAlpha) {
+  CopyType copy_type = GetParam();
   uint8 pixels[2][2][4];
   for (int x = 0; x < 2; ++x) {
     for (int y = 0; y < 2; ++y) {
@@ -325,8 +432,15 @@
 
   glPixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
   glPixelStorei(GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, GL_TRUE);
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                        GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   uint8 copied_pixels[2][2][4] = {{{0}}};
@@ -356,7 +470,8 @@
 
 // Validate that some basic GL state is not touched upon execution of
 // the extension.
-TEST_F(GLCopyTextureCHROMIUMTest, BasicStatePreservation) {
+TEST_P(GLCopyTextureCHROMIUMTest, BasicStatePreservation) {
+  CopyType copy_type = GetParam();
   uint8 pixels[1 * 4] = { 255u, 0u, 0u, 255u };
 
   glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -365,6 +480,12 @@
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                pixels);
 
+  if (copy_type == TexSubImage) {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+  }
+
   GLboolean reference_settings[2] = { GL_TRUE, GL_FALSE };
   for (int x = 0; x < 2; ++x) {
     GLboolean setting = reference_settings[x];
@@ -378,8 +499,12 @@
 
     glActiveTexture(GL_TEXTURE1 + x);
 
-    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0,
-                          GL_RGBA, GL_UNSIGNED_BYTE);
+    if (copy_type == TexImage) {
+      glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                            GL_UNSIGNED_BYTE);
+    } else {
+      glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+    }
     EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
     EXPECT_EQ(setting, glIsEnabled(GL_DEPTH_TEST));
@@ -409,13 +534,20 @@
 
 // Verify that invocation of the extension does not modify the bound
 // texture state.
-TEST_F(GLCopyTextureCHROMIUMTest, TextureStatePreserved) {
+TEST_P(GLCopyTextureCHROMIUMTest, TextureStatePreserved) {
+  CopyType copy_type = GetParam();
   // Setup the texture used for the extension invocation.
   uint8 pixels[1 * 4] = { 255u, 0u, 0u, 255u };
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                pixels);
 
+  if (copy_type == TexSubImage) {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+  }
+
   GLuint texture_ids[2];
   glGenTextures(2, texture_ids);
 
@@ -425,8 +557,12 @@
   glActiveTexture(GL_TEXTURE1);
   glBindTexture(GL_TEXTURE_2D, texture_ids[1]);
 
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0,
-                        GL_RGBA, GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   GLint active_texture = 0;
@@ -451,13 +587,20 @@
 
 // Verify that invocation of the extension does not perturb the currently
 // bound FBO state.
-TEST_F(GLCopyTextureCHROMIUMTest, FBOStatePreserved) {
+TEST_P(GLCopyTextureCHROMIUMTest, FBOStatePreserved) {
+  CopyType copy_type = GetParam();
   // Setup the texture used for the extension invocation.
   uint8 pixels[1 * 4] = { 255u, 0u, 0u, 255u };
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                pixels);
 
+  if (copy_type == TexSubImage) {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+  }
+
   GLuint texture_id;
   glGenTextures(1, &texture_id);
   glBindTexture(GL_TEXTURE_2D, texture_id);
@@ -485,8 +628,12 @@
   glClear(GL_COLOR_BUFFER_BIT);
   GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_color);
 
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0,
-                        GL_RGBA, GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   EXPECT_TRUE(glIsFramebuffer(framebuffer_id));
@@ -534,7 +681,8 @@
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 }
 
-TEST_F(GLCopyTextureCHROMIUMTest, ProgramStatePreservation) {
+TEST_P(GLCopyTextureCHROMIUMTest, ProgramStatePreservation) {
+  CopyType copy_type = GetParam();
   // unbind the one created in setup.
   glBindFramebuffer(GL_FRAMEBUFFER, 0);
   glBindTexture(GL_TEXTURE_2D, 0);
@@ -588,8 +736,15 @@
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                pixels);
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                        GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
 
   // test using program after
   glClear(GL_COLOR_BUFFER_BIT);
@@ -605,14 +760,22 @@
 }
 
 // Test that glCopyTextureCHROMIUM doesn't leak uninitialized textures.
-TEST_F(GLCopyTextureCHROMIUMTest, UninitializedSource) {
+TEST_P(GLCopyTextureCHROMIUMTest, UninitializedSource) {
+  CopyType copy_type = GetParam();
   const GLsizei kWidth = 64, kHeight = 64;
   glBindTexture(GL_TEXTURE_2D, textures_[0]);
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight,
-               0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
+               GL_UNSIGNED_BYTE, nullptr);
 
-  glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA,
-                        GL_UNSIGNED_BYTE);
+  if (copy_type == TexImage) {
+    glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], GL_RGBA,
+                          GL_UNSIGNED_BYTE);
+  } else {
+    glBindTexture(GL_TEXTURE_2D, textures_[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, nullptr);
+    glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, 0);
+  }
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 
   uint8 pixels[kHeight][kWidth][4] = {{{1}}};
@@ -629,4 +792,56 @@
   EXPECT_TRUE(GL_NO_ERROR == glGetError());
 }
 
+TEST_F(GLCopyTextureCHROMIUMTest, CopySubTextureDimension) {
+  glBindTexture(GL_TEXTURE_2D, textures_[0]);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+               nullptr);
+
+  glBindTexture(GL_TEXTURE_2D, textures_[1]);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+               nullptr);
+
+  glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 1, 1);
+  EXPECT_TRUE(GL_NO_ERROR == glGetError());
+
+  // xoffset < 0
+  glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], -1, 1);
+  EXPECT_TRUE(glGetError() == GL_INVALID_VALUE);
+
+  // xoffset + source_width > dest_width
+  glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 2, 2);
+  EXPECT_TRUE(glGetError() == GL_INVALID_VALUE);
+}
+
+TEST_F(GLCopyTextureCHROMIUMTest, CopySubTextureOffset) {
+  uint8 red[1 * 4] = {255u, 0u, 0u, 255u};
+  glBindTexture(GL_TEXTURE_2D, textures_[0]);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+               red);
+
+  uint8 transparent_pixel[4 * 4] = {
+      0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u};
+  glBindTexture(GL_TEXTURE_2D, textures_[1]);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+               transparent_pixel);
+
+  glCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 1, 1);
+  EXPECT_TRUE(glGetError() == GL_NO_ERROR);
+
+  // Check the FB is still bound.
+  GLint value = 0;
+  glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
+  GLuint fb_id = value;
+  EXPECT_EQ(framebuffer_id_, fb_id);
+
+  // Check that FB is complete.
+  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+            glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+  uint8 transparent[1 * 4] = {0u, 0u, 0u, 0u};
+  GLTestHelper::CheckPixels(0, 0, 1, 1, 0, transparent);
+  GLTestHelper::CheckPixels(1, 1, 1, 1, 0, red);
+  EXPECT_TRUE(GL_NO_ERROR == glGetError());
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
index 8430dfb..9e37d55 100644
--- a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
+++ b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
@@ -109,7 +109,6 @@
   glCopyTextureCHROMIUM(GL_TEXTURE_2D,
                         texture_ids_[0],
                         texture_ids_[1],
-                        0,
                         GL_RGBA,
                         GL_UNSIGNED_BYTE);
   EXPECT_TRUE(glGetError() == GL_NO_ERROR);
diff --git a/gpu/gpu_unittests.isolate b/gpu/gpu_unittests.isolate
index e64633c..a718aac 100644
--- a/gpu/gpu_unittests.isolate
+++ b/gpu/gpu_unittests.isolate
@@ -20,7 +20,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
@@ -38,7 +37,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
@@ -52,7 +50,6 @@
           '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=<(asan)',
-          '--lsan=<(lsan)',
           '--msan=<(msan)',
           '--tsan=<(tsan)',
         ],
diff --git a/gpu/perftests/run_all_tests.cc b/gpu/perftests/run_all_tests.cc
index ed0df88..60a6b03 100644
--- a/gpu/perftests/run_all_tests.cc
+++ b/gpu/perftests/run_all_tests.cc
@@ -9,7 +9,10 @@
 int main(int argc, char** argv) {
   base::TestSuite test_suite(argc, argv);
 
+  // Always run the perf tests serially, to avoid distorting
+  // perf measurements with randomness resulting from running
+  // in parallel.
   const auto& run_test_suite =
       base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite));
-  return base::LaunchUnitTests(argc, argv, run_test_suite);
+  return base::LaunchUnitTestsSerially(argc, argv, run_test_suite);
 }
diff --git a/gpu/perftests/texture_upload_perftest.cc b/gpu/perftests/texture_upload_perftest.cc
index 495ef86..5f76746 100644
--- a/gpu/perftests/texture_upload_perftest.cc
+++ b/gpu/perftests/texture_upload_perftest.cc
@@ -193,6 +193,7 @@
     glDeleteTextures(1, &color_texture_);
     CheckNoGlError();
 
+    gpu_timing_client_ = nullptr;
     gl_context_ = nullptr;
     surface_ = nullptr;
   }
diff --git a/mojo/application/content_handler_factory.h b/mojo/application/content_handler_factory.h
index 271655e..8b59bd9 100644
--- a/mojo/application/content_handler_factory.h
+++ b/mojo/application/content_handler_factory.h
@@ -32,7 +32,7 @@
 
   class ManagedDelegate : public Delegate {
    public:
-    virtual ~ManagedDelegate() {}
+    ~ManagedDelegate() override {}
     // Implement this method to create the Application for the given content.
     // This method will be called on a new thread. The application will be run
     // on this new thread, and the returned value will be kept alive until the
@@ -47,7 +47,7 @@
   };
 
   explicit ContentHandlerFactory(Delegate* delegate);
-  virtual ~ContentHandlerFactory();
+  ~ContentHandlerFactory() override;
 
  private:
   // From InterfaceFactory:
diff --git a/mojo/edk/system/data_pipe.h b/mojo/edk/system/data_pipe.h
index 8096e01..c539f1b 100644
--- a/mojo/edk/system/data_pipe.h
+++ b/mojo/edk/system/data_pipe.h
@@ -230,7 +230,7 @@
            bool has_local_consumer,
            const MojoCreateDataPipeOptions& validated_options,
            scoped_ptr<DataPipeImpl> impl);
-  virtual ~DataPipe();
+  ~DataPipe() override;
 
   // |ChannelEndpointClient| implementation:
   bool OnReadMessage(unsigned port, MessageInTransit* message) override;
diff --git a/mojo/nacl/BUILD.gn b/mojo/nacl/BUILD.gn
index d7d1a99..c4aea69 100644
--- a/mojo/nacl/BUILD.gn
+++ b/mojo/nacl/BUILD.gn
@@ -17,7 +17,7 @@
       "//nacl_bindings:monacl_sel",
     ]
 
-    data_deps = [ "//nacl_bindings:irt_mojo(//native_client/build/toolchain/nacl:irt_${cpu_arch})" ]
+    data_deps = [ "//nacl_bindings:irt_mojo(//native_client/build/toolchain/nacl:irt_${target_cpu})" ]
   }
 }
 
@@ -49,7 +49,7 @@
 group("mojo_nacl_tests") {
   testonly = true
   nacl_toolchain =
-      "//native_client/build/toolchain/nacl:clang_newlib_${cpu_arch}"
+      "//native_client/build/toolchain/nacl:clang_newlib_${target_cpu}"
   deps = [
     ":monacl_shell",
     ":monacl_test($nacl_toolchain)",
diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni
index 0cf7bff..ce8cf9e 100644
--- a/mojo/public/mojo_application.gni
+++ b/mojo/public/mojo_application.gni
@@ -155,7 +155,7 @@
     nexe_target_name = base_target_name + "_nexe"
     nexe_name = base_target_name + ".nexe"
 
-    output = "${base_target_name}_${cpu_arch}.nexe.mojo"
+    output = "${base_target_name}_${target_cpu}.nexe.mojo"
 
     executable(nexe_target_name) {
       output_name = base_target_name
diff --git a/mojo/public/python/src/common.h b/mojo/public/python/src/common.h
index 2ada2a4..70dddc7 100644
--- a/mojo/public/python/src/common.h
+++ b/mojo/public/python/src/common.h
@@ -56,7 +56,7 @@
 class PythonClosure : public mojo::Closure::Runnable {
  public:
   PythonClosure(PyObject* callable, const mojo::Closure& quit);
-  ~PythonClosure();
+  ~PythonClosure() override;
 
   void Run() const override;
 
diff --git a/mojo/services/view_manager/public/cpp/tests/view_unittest.cc b/mojo/services/view_manager/public/cpp/tests/view_unittest.cc
index abbd712..09d1bde 100644
--- a/mojo/services/view_manager/public/cpp/tests/view_unittest.cc
+++ b/mojo/services/view_manager/public/cpp/tests/view_unittest.cc
@@ -742,7 +742,7 @@
   explicit SharedPropertyChangeObserver(View* view) : view_(view) {
     view_->AddObserver(this);
   }
-  virtual ~SharedPropertyChangeObserver() { view_->RemoveObserver(this); }
+  ~SharedPropertyChangeObserver() override { view_->RemoveObserver(this); }
 
   Changes GetAndClearChanges() {
     Changes changes;
@@ -835,7 +835,7 @@
         old_property_value_(-1) {
     view_->AddObserver(this);
   }
-  virtual ~LocalPropertyChangeObserver() { view_->RemoveObserver(this); }
+  ~LocalPropertyChangeObserver() override { view_->RemoveObserver(this); }
 
   PropertyChangeInfo PropertyChangeInfoAndClear() {
     PropertyChangeInfo result(property_key_, old_property_value_);
diff --git a/mojo/services/view_manager/public/cpp/view_tracker.h b/mojo/services/view_manager/public/cpp/view_tracker.h
index 1d6bf14..cfc2b9d 100644
--- a/mojo/services/view_manager/public/cpp/view_tracker.h
+++ b/mojo/services/view_manager/public/cpp/view_tracker.h
@@ -34,7 +34,7 @@
   bool Contains(View* view);
 
   // ViewObserver overrides:
-  virtual void OnViewDestroying(View* view) override;
+  void OnViewDestroying(View* view) override;
 
  private:
   Views views_;
diff --git a/mojo/skia/ganesh_context.h b/mojo/skia/ganesh_context.h
index 1bbc20c..460ea4f 100644
--- a/mojo/skia/ganesh_context.h
+++ b/mojo/skia/ganesh_context.h
@@ -31,7 +31,7 @@
   };
 
   explicit GaneshContext(base::WeakPtr<GLContext> gl_context);
-  ~GaneshContext();
+  ~GaneshContext() override;
 
   // Note: You must be in a GaneshContext::Scope to use GrContext.
   GrContext* gr() const {
diff --git a/mojo/tools/package_manager/package_manager_application.h b/mojo/tools/package_manager/package_manager_application.h
index af23710..d50e11c 100644
--- a/mojo/tools/package_manager/package_manager_application.h
+++ b/mojo/tools/package_manager/package_manager_application.h
@@ -23,7 +23,7 @@
       public PackageFetcherDelegate {
  public:
   PackageManagerApplication();
-  virtual ~PackageManagerApplication();
+  ~PackageManagerApplication() override;
 
  private:
   struct PendingLoad {
@@ -43,12 +43,12 @@
   void PendingLoadComplete(const GURL& url);
 
   // ApplicationDelegate implementation.
-  virtual void Initialize(ApplicationImpl* app) override;
+  void Initialize(ApplicationImpl* app) override;
 
   // PackageFetcher.
-  virtual void FetchSucceeded(const GURL& url,
-                              const base::FilePath& name) override;
-  virtual void FetchFailed(const GURL& url) override;
+  void FetchSucceeded(const GURL& url,
+                      const base::FilePath& name) override;
+  void FetchFailed(const GURL& url) override;
 
   mojo::NetworkServicePtr network_service_;
 
diff --git a/mojo/tools/roll/cc_strip_video.patch b/mojo/tools/roll/cc_strip_video.patch
index 827171b..a992d5d 100644
--- a/mojo/tools/roll/cc_strip_video.patch
+++ b/mojo/tools/roll/cc_strip_video.patch
@@ -1,5 +1,5 @@
 diff --git a/cc/BUILD.gn b/cc/BUILD.gn
-index 6fe0694..803b0f9 100644
+index 9c4752d..e217b12 100644
 --- a/cc/BUILD.gn
 +++ b/cc/BUILD.gn
 @@ -222,13 +222,6 @@ component("cc") {
@@ -34,30 +34,22 @@
      "test/geometry_test_utils.cc",
      "test/geometry_test_utils.h",
      "test/impl_side_painting_settings.h",
-@@ -783,7 +772,6 @@ if (!is_win || link_chrome_on_windows) {
-       "layers/tiled_layer_unittest.cc",
-       "layers/ui_resource_layer_impl_unittest.cc",
-       "layers/ui_resource_layer_unittest.cc",
--      "layers/video_layer_impl_unittest.cc",
-       "output/begin_frame_args_unittest.cc",
-       "output/delegating_renderer_unittest.cc",
-       "output/filter_operations_unittest.cc",
-@@ -816,7 +804,6 @@ if (!is_win || link_chrome_on_windows) {
-       "resources/tile_manager_unittest.cc",
-       "resources/tile_priority_unittest.cc",
-       "resources/tile_task_worker_pool_unittest.cc",
--      "resources/video_resource_updater_unittest.cc",
-       "scheduler/begin_frame_source_unittest.cc",
-       "scheduler/delay_based_time_source_unittest.cc",
-       "scheduler/scheduler_state_machine_unittest.cc",
-@@ -844,7 +831,6 @@ if (!is_win || link_chrome_on_windows) {
-       "trees/layer_tree_host_unittest_picture.cc",
-       "trees/layer_tree_host_unittest_proxy.cc",
-       "trees/layer_tree_host_unittest_scroll.cc",
--      "trees/layer_tree_host_unittest_video.cc",
-       "trees/layer_tree_impl_unittest.cc",
-       "trees/occlusion_tracker_unittest.cc",
-       "trees/occlusion_unittest.cc",
+@@ -782,7 +771,6 @@ test("cc_unittests") {
+     "layers/tiled_layer_unittest.cc",
+     "layers/ui_resource_layer_impl_unittest.cc",
+     "layers/ui_resource_layer_unittest.cc",
+-    "layers/video_layer_impl_unittest.cc",
+     "output/begin_frame_args_unittest.cc",
+     "output/delegating_renderer_unittest.cc",
+     "output/filter_operations_unittest.cc",
+@@ -843,7 +831,6 @@ test("cc_unittests") {
+     "trees/layer_tree_host_unittest_picture.cc",
+     "trees/layer_tree_host_unittest_proxy.cc",
+     "trees/layer_tree_host_unittest_scroll.cc",
+-    "trees/layer_tree_host_unittest_video.cc",
+     "trees/layer_tree_impl_unittest.cc",
+     "trees/occlusion_tracker_unittest.cc",
+     "trees/occlusion_unittest.cc",
 diff --git a/cc/layers/video_frame_provider.h b/cc/layers/video_frame_provider.h
 deleted file mode 100644
 index 784d951..0000000
@@ -250,7 +242,7 @@
 -
 -}  // namespace cc
 diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
-index 6142d96..5c560dc 100644
+index 2016447..578faa9 100644
 --- a/cc/output/gl_renderer.cc
 +++ b/cc/output/gl_renderer.cc
 @@ -13,7 +13,6 @@
@@ -262,7 +254,7 @@
  #include "cc/output/compositor_frame_metadata.h"
  #include "cc/output/context_provider.h"
 diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
-index 743e1cf..9e9175e 100644
+index b30b0a5..81ad842 100644
 --- a/cc/output/renderer_pixeltest.cc
 +++ b/cc/output/renderer_pixeltest.cc
 @@ -12,7 +12,6 @@
@@ -276,7 +268,7 @@
 @@ -388,453 +387,6 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) {
        FuzzyPixelOffByOneComparator(true)));
  }
- 
+
 -class VideoGLRendererPixelTest : public GLRendererPixelTest {
 - protected:
 -  void CreateTestYUVVideoDrawQuad_Striped(const SharedQuadState* shared_state,
@@ -726,7 +718,7 @@
 -
  TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
    gfx::Rect viewport_rect(this->device_viewport_size_);
- 
+
 diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
 index 358929e..15bce98 100644
 --- a/cc/quads/yuv_video_draw_quad.h
@@ -737,22 +729,22 @@
  #include "cc/base/cc_export.h"
 -#include "cc/layers/video_layer_impl.h"
  #include "cc/quads/draw_quad.h"
- 
+
  namespace cc {
 diff --git a/cc/resources/drawing_display_item.cc b/cc/resources/drawing_display_item.cc
 index 648f9de..6dffad9 100644
 --- a/cc/resources/drawing_display_item.cc
 +++ b/cc/resources/drawing_display_item.cc
 @@ -6,6 +6,7 @@
- 
+
  #include <string>
- 
+
 +#include "base/logging.h"
  #include "base/strings/stringprintf.h"
  #include "base/trace_event/trace_event_argument.h"
  #include "cc/debug/picture_debug_util.h"
 diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
-index 70fa92b..38b2d66 100644
+index 4b2bc75..7ffa683 100644
 --- a/cc/trees/layer_tree_host_impl_unittest.cc
 +++ b/cc/trees/layer_tree_host_impl_unittest.cc
 @@ -27,7 +27,6 @@
@@ -784,7 +776,7 @@
  using ::testing::AtLeast;
  using ::testing::_;
 -using media::VideoFrame;
- 
+
  namespace cc {
  namespace {
 @@ -96,7 +92,6 @@ class LayerTreeHostImplTest : public testing::Test,
@@ -793,12 +785,12 @@
          current_priority_cutoff_value_(0) {
 -    media::InitializeMediaLibraryForTesting();
    }
- 
+
    LayerTreeSettings DefaultSettings() {
-@@ -5463,18 +5458,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
+@@ -5486,18 +5481,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
    root_layer->SetBounds(gfx::Size(10, 10));
    root_layer->SetHasRenderSurface(true);
- 
+
 -  scoped_refptr<VideoFrame> softwareFrame =
 -      media::VideoFrame::CreateColorFrame(
 -          gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
@@ -814,10 +806,10 @@
    scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
        IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
    io_surface_layer->SetBounds(gfx::Size(10, 10));
-@@ -6555,16 +6538,6 @@ TEST_F(LayerTreeHostImplTest,
+@@ -6578,16 +6561,6 @@ TEST_F(LayerTreeHostImplTest,
    scoped_ptr<SolidColorLayerImpl> root_layer =
        SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
- 
+
 -  // VideoLayerImpl will not be drawn.
 -  FakeVideoFrameProvider provider;
 -  scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
@@ -832,7 +824,7 @@
    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
 diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
-index 48be5b8..f9b690d 100644
+index c52132e..1be61a5 100644
 --- a/cc/trees/layer_tree_host_unittest.cc
 +++ b/cc/trees/layer_tree_host_unittest.cc
 @@ -18,7 +18,6 @@
@@ -851,10 +843,10 @@
  #include "cc/test/geometry_test_utils.h"
  #include "cc/test/impl_side_painting_settings.h"
  #include "cc/test/layer_tree_test.h"
-@@ -4167,28 +4165,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest {
+@@ -4163,28 +4161,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest {
    int num_draws_;
  };
- 
+
 -// VideoLayer must support being invalidated and then passing that along
 -// to the compositor thread, even though no resources are updated in
 -// response to that invalidation.
@@ -908,7 +900,7 @@
 -#include "media/base/media.h"
 -
 -using media::VideoFrame;
- 
+
  namespace cc {
  namespace {
 @@ -66,7 +60,6 @@ class LayerTreeHostContextTest : public LayerTreeTest {
@@ -917,12 +909,12 @@
          async_output_surface_creation_(false) {
 -    media::InitializeMediaLibraryForTesting();
    }
- 
+
    void LoseContext() {
 @@ -1055,41 +1048,6 @@ class LayerTreeHostContextTestDontUseLostResources
      layer_with_mask->SetMaskLayer(mask.get());
      root->AddChild(layer_with_mask);
- 
+
 -    scoped_refptr<VideoLayer> video_color =
 -        VideoLayer::Create(&color_frame_provider_, media::VIDEO_ROTATION_0);
 -    video_color->SetBounds(gfx::Size(10, 10));
@@ -962,7 +954,7 @@
        // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
        scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
 @@ -1119,14 +1077,6 @@ class LayerTreeHostContextTestDontUseLostResources
- 
+
    void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
      LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
 -
@@ -974,7 +966,7 @@
 -      scaled_hw_frame_provider_.set_frame(NULL);
 -    }
    }
- 
+
    DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
 @@ -1175,14 +1125,6 @@ class LayerTreeHostContextTestDontUseLostResources
    scoped_refptr<DelegatedFrameResourceCollection>
@@ -989,5 +981,5 @@
 -  FakeVideoFrameProvider hw_frame_provider_;
 -  FakeVideoFrameProvider scaled_hw_frame_provider_;
  };
- 
+
  SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
diff --git a/mojo/tools/roll/disable_find_bad_constructs.patch b/mojo/tools/roll/disable_find_bad_constructs.patch
new file mode 100644
index 0000000..4549e5b
--- /dev/null
+++ b/mojo/tools/roll/disable_find_bad_constructs.patch
@@ -0,0 +1,18 @@
+diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
+index 39fe251..721e87c 100644
+--- a/build/config/clang/BUILD.gn
++++ b/build/config/clang/BUILD.gn
+@@ -21,13 +21,6 @@ config("find_bad_constructs") {
+               "//third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so",
+               root_build_dir) ]
+     }
+-
+-    cflags += [
+-      "-Xclang",
+-      "-add-plugin",
+-      "-Xclang",
+-      "find-bad-constructs",
+-    ]
+   }
+ }
+ 
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index c4ce4fc..ccb186a 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -314,12 +314,12 @@
 if (compile_suid_client) {
   component("suid_sandbox_client") {
     sources = [
-      "suid/common/sandbox.h",
-      "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",
+      "suid/common/sandbox.h",
+      "suid/common/suid_unsafe_environment_variables.h",
     ]
     defines = [ "SANDBOX_IMPLEMENTATION" ]
 
diff --git a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
index 2d337c6..8e7e144 100644
--- a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
+++ b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
@@ -651,6 +651,10 @@
   return UnsafeTrap(AllowRedirectedSyscall, NULL);
 }
 
+#if !defined(ADDRESS_SANITIZER)
+// ASan does not allow changing the signal handler for SIGBUS, and treats it as
+// a fatal signal.
+
 int bus_handler_fd_ = -1;
 
 void SigBusHandler(int, siginfo_t* info, void* void_context) {
@@ -679,6 +683,7 @@
   BPF_ASSERT(close(fds[1]) == 0);
   BPF_ASSERT(c == 0x55);
 }
+#endif  // !defined(ADDRESS_SANITIZER)
 
 BPF_TEST_C(SandboxBPF, SigMask, RedirectAllSyscallsPolicy) {
   // Signal masks are potentially tricky to handle. For instance, if we
diff --git a/services/http_server/http_server_app.cc b/services/http_server/http_server_app.cc
index e4486fe..98e4dd7 100644
--- a/services/http_server/http_server_app.cc
+++ b/services/http_server/http_server_app.cc
@@ -18,9 +18,9 @@
                       public mojo::InterfaceFactory<HttpServerFactory> {
  public:
   HttpServerApp() {}
-  ~HttpServerApp() {}
+  ~HttpServerApp() override {}
 
-  virtual void Initialize(mojo::ApplicationImpl* app) override { app_ = app; }
+  void Initialize(mojo::ApplicationImpl* app) override { app_ = app; }
 
  private:
   // ApplicationDelegate:
diff --git a/services/js/js_app.h b/services/js/js_app.h
index 8e7e793..adcf45e 100644
--- a/services/js/js_app.h
+++ b/services/js/js_app.h
@@ -27,7 +27,7 @@
  public:
   JSApp(mojo::InterfaceRequest<mojo::Application> application_request,
         mojo::URLResponsePtr response);
-  virtual ~JSApp();
+  ~JSApp() override;
 
  private:
   static const char kMainModuleName[];
diff --git a/services/kiosk_wm/kiosk_wm.h b/services/kiosk_wm/kiosk_wm.h
index 309f50e..c5814cc 100644
--- a/services/kiosk_wm/kiosk_wm.h
+++ b/services/kiosk_wm/kiosk_wm.h
@@ -30,7 +30,7 @@
                 public ui::AcceleratorTarget {
  public:
   KioskWM();
-  virtual ~KioskWM();
+  ~KioskWM() override;
 
   base::WeakPtr<KioskWM> GetWeakPtr();
 
diff --git a/services/kiosk_wm/navigator_host_impl.h b/services/kiosk_wm/navigator_host_impl.h
index 7ff7355..f258e4f 100644
--- a/services/kiosk_wm/navigator_host_impl.h
+++ b/services/kiosk_wm/navigator_host_impl.h
@@ -16,7 +16,7 @@
 class NavigatorHostImpl : public mojo::NavigatorHost {
  public:
   NavigatorHostImpl(KioskWM* kiosk_wm);
-  ~NavigatorHostImpl();
+  ~NavigatorHostImpl() override;
 
   void Bind(mojo::InterfaceRequest<mojo::NavigatorHost> request);
 
diff --git a/services/nacl/BUILD.gn b/services/nacl/BUILD.gn
index a30fe86..51ef84c 100644
--- a/services/nacl/BUILD.gn
+++ b/services/nacl/BUILD.gn
@@ -21,6 +21,6 @@
       "//url",
     ]
 
-    data_deps = [ "//nacl_bindings:irt_mojo(//native_client/build/toolchain/nacl:irt_${cpu_arch})" ]
+    data_deps = [ "//nacl_bindings:irt_mojo(//native_client/build/toolchain/nacl:irt_${target_cpu})" ]
   }
 }
diff --git a/services/reaper/reaper_impl.h b/services/reaper/reaper_impl.h
index b0ae2a4..760841d 100644
--- a/services/reaper/reaper_impl.h
+++ b/services/reaper/reaper_impl.h
@@ -33,7 +33,7 @@
   typedef uint64 AppSecret;
 
   ReaperImpl();
-  ~ReaperImpl();
+  ~ReaperImpl() override;
 
   void GetApplicationSecret(const GURL& caller_app,
                             const mojo::Callback<void(AppSecret)>&);
diff --git a/services/surfaces/surfaces_scheduler.cc b/services/surfaces/surfaces_scheduler.cc
index 500ef97..b5edb05 100644
--- a/services/surfaces/surfaces_scheduler.cc
+++ b/services/surfaces/surfaces_scheduler.cc
@@ -11,8 +11,7 @@
 SurfacesScheduler::SurfacesScheduler() {
   cc::SchedulerSettings settings;
   scheduler_ = cc::Scheduler::Create(
-      this, settings, 0, base::MessageLoop::current()->task_runner(), nullptr,
-      nullptr);
+      this, settings, 0, base::MessageLoop::current()->task_runner(), nullptr);
   scheduler_->SetCanStart();
   scheduler_->SetVisible(true);
   scheduler_->SetCanDraw(true);
diff --git a/services/surfaces/surfaces_scheduler.h b/services/surfaces/surfaces_scheduler.h
index 5e2e5c4..1c98af1 100644
--- a/services/surfaces/surfaces_scheduler.h
+++ b/services/surfaces/surfaces_scheduler.h
@@ -18,7 +18,7 @@
 class SurfacesScheduler : public cc::SchedulerClient {
  public:
   SurfacesScheduler();
-  ~SurfacesScheduler();
+  ~SurfacesScheduler() override;
 
   void SetNeedsDraw();
 
diff --git a/services/window_manager/focus_controller.h b/services/window_manager/focus_controller.h
index 20f966e..6837c68 100644
--- a/services/window_manager/focus_controller.h
+++ b/services/window_manager/focus_controller.h
@@ -25,7 +25,7 @@
  public:
   // |rules| cannot be null.
   explicit FocusController(scoped_ptr<FocusRules> rules);
-  virtual ~FocusController();
+  ~FocusController() override;
 
   void AddObserver(FocusControllerObserver* observer);
   void RemoveObserver(FocusControllerObserver* observer);
diff --git a/services/window_manager/focus_controller_unittest.cc b/services/window_manager/focus_controller_unittest.cc
index a657e36..ba47c73 100644
--- a/services/window_manager/focus_controller_unittest.cc
+++ b/services/window_manager/focus_controller_unittest.cc
@@ -1071,7 +1071,7 @@
     disposition_view->parent()->RemoveChild(disposition_view);
     window_to_destroy_ = disposition_view;
   }
-  virtual void TearDown() override {
+  void TearDown() override {
     if (window_to_destroy_)
       window_to_destroy_->Destroy();
 
diff --git a/services/window_manager/window_manager_apptest.cc b/services/window_manager/window_manager_apptest.cc
index 818999f..1f8519e 100644
--- a/services/window_manager/window_manager_apptest.cc
+++ b/services/window_manager/window_manager_apptest.cc
@@ -31,7 +31,7 @@
 
  private:
   // ApplicationDelegate:
-  virtual void Initialize(ApplicationImpl* app) override {
+  void Initialize(ApplicationImpl* app) override {
     view_manager_client_factory_.reset(
         new ViewManagerClientFactory(app->shell(), this));
   }
diff --git a/shell/app_child_process.cc b/shell/app_child_process.cc
index 0054037..387aa5f 100644
--- a/shell/app_child_process.cc
+++ b/shell/app_child_process.cc
@@ -84,7 +84,7 @@
  public:
   AppContext()
       : io_thread_("io_thread"), controller_thread_("controller_thread") {}
-  ~AppContext() {}
+  ~AppContext() override {}
 
   void Init() {
     // Initialize Mojo before starting any threads.
diff --git a/shell/application_manager/application_manager.h b/shell/application_manager/application_manager.h
index fee8cdf..05a4fc9 100644
--- a/shell/application_manager/application_manager.h
+++ b/shell/application_manager/application_manager.h
@@ -215,13 +215,12 @@
   // Note: The keys are URLs after mapping and resolving.
   URLToNativeOptionsMap url_to_native_options_;
 
-  base::WeakPtrFactory<ApplicationManager> weak_ptr_factory_;
-
   base::SequencedWorkerPool* blocking_pool_;
   NetworkServicePtr network_service_;
   MimeTypeToURLMap mime_type_to_url_;
   ScopedVector<NativeRunner> native_runners_;
   bool disable_cache_;
+  base::WeakPtrFactory<ApplicationManager> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ApplicationManager);
 };
diff --git a/shell/launcher_main.cc b/shell/launcher_main.cc
index 410417b..4a95d53 100644
--- a/shell/launcher_main.cc
+++ b/shell/launcher_main.cc
@@ -46,7 +46,7 @@
                                      &app_args_);
   }
 
-  ~Launcher() {
+  ~Launcher() override {
     // TODO(vtl): We need to destroy this before calling
     // ShutdownIPCSupportOnIOThread(). This is all quite sketchy, and we really
     // should convert all of this to running the application on the main thread,
diff --git a/shell/test/pingable_app.cc b/shell/test/pingable_app.cc
index a22ddbe..b864098 100644
--- a/shell/test/pingable_app.cc
+++ b/shell/test/pingable_app.cc
@@ -40,7 +40,7 @@
                     public mojo::InterfaceFactory<Pingable> {
  public:
   PingableApp() {}
-  ~PingableApp() {}
+  ~PingableApp() override {}
 
  private:
   // ApplicationDelegate:
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index aede7dc..472a8cf 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -251,6 +251,9 @@
   sources = [
     # Chrome sources.
     "config/SkUserConfig.h",
+    "ext/SkDiscardableMemory_chrome.cc",
+    "ext/SkDiscardableMemory_chrome.h",
+    "ext/SkMemory_new_handler.cpp",
     "ext/analysis_canvas.cc",
     "ext/analysis_canvas.h",
     "ext/benchmarking_canvas.cc",
@@ -279,15 +282,12 @@
     "ext/recursive_gaussian_convolution.cc",
     "ext/recursive_gaussian_convolution.h",
     "ext/refptr.h",
-    "ext/SkDiscardableMemory_chrome.h",
-    "ext/SkDiscardableMemory_chrome.cc",
-    "ext/SkMemory_new_handler.cpp",
     "ext/skia_utils_base.cc",
     "ext/skia_utils_base.h",
-    "ext/skia_utils_ios.mm",
     "ext/skia_utils_ios.h",
-    "ext/skia_utils_mac.mm",
+    "ext/skia_utils_ios.mm",
     "ext/skia_utils_mac.h",
+    "ext/skia_utils_mac.mm",
     "ext/skia_utils_win.cc",
     "ext/skia_utils_win.h",
   ]
@@ -317,7 +317,6 @@
   # Remove unused util files include in utils.gypi
   sources -= [
     "//third_party/skia/include/utils/SkBoundaryPatch.h",
-    "//third_party/skia/include/utils/SkFrontBufferedStream.h",
     "//third_party/skia/include/utils/SkCamera.h",
     "//third_party/skia/include/utils/SkCanvasStateUtils.h",
     "//third_party/skia/include/utils/SkCubicInterval.h",
@@ -325,24 +324,24 @@
     "//third_party/skia/include/utils/SkDebugUtils.h",
     "//third_party/skia/include/utils/SkDumpCanvas.h",
     "//third_party/skia/include/utils/SkEventTracer.h",
+    "//third_party/skia/include/utils/SkFrontBufferedStream.h",
     "//third_party/skia/include/utils/SkInterpolator.h",
     "//third_party/skia/include/utils/SkLayer.h",
     "//third_party/skia/include/utils/SkMeshUtils.h",
     "//third_party/skia/include/utils/SkNinePatch.h",
-    "//third_party/skia/include/utils/SkParse.h",
     "//third_party/skia/include/utils/SkParsePaint.h",
     "//third_party/skia/include/utils/SkParsePath.h",
     "//third_party/skia/include/utils/SkRandom.h",
     "//third_party/skia/src/utils/SkBitmapHasher.cpp",
     "//third_party/skia/src/utils/SkBitmapHasher.h",
     "//third_party/skia/src/utils/SkBoundaryPatch.cpp",
-    "//third_party/skia/src/utils/SkFrontBufferedStream.cpp",
     "//third_party/skia/src/utils/SkCamera.cpp",
     "//third_party/skia/src/utils/SkCanvasStack.h",
     "//third_party/skia/src/utils/SkCubicInterval.cpp",
     "//third_party/skia/src/utils/SkCullPoints.cpp",
     "//third_party/skia/src/utils/SkDumpCanvas.cpp",
     "//third_party/skia/src/utils/SkFloatUtils.h",
+    "//third_party/skia/src/utils/SkFrontBufferedStream.cpp",
     "//third_party/skia/src/utils/SkInterpolator.cpp",
     "//third_party/skia/src/utils/SkLayer.cpp",
     "//third_party/skia/src/utils/SkMD5.cpp",
@@ -350,8 +349,6 @@
     "//third_party/skia/src/utils/SkMeshUtils.cpp",
     "//third_party/skia/src/utils/SkNinePatch.cpp",
     "//third_party/skia/src/utils/SkOSFile.cpp",
-    "//third_party/skia/src/utils/SkParse.cpp",
-    "//third_party/skia/src/utils/SkParseColor.cpp",
     "//third_party/skia/src/utils/SkParsePath.cpp",
     "//third_party/skia/src/utils/SkPathUtils.cpp",
     "//third_party/skia/src/utils/SkSHA1.cpp",
@@ -360,8 +357,8 @@
     "//third_party/skia/src/utils/SkTLogic.h",
 
     # We don't currently need to change thread affinity, so leave out this complexity for now.
-    "//third_party/skia/src/utils/SkThreadUtils_pthread_mach.cpp",
     "//third_party/skia/src/utils/SkThreadUtils_pthread_linux.cpp",
+    "//third_party/skia/src/utils/SkThreadUtils_pthread_mach.cpp",
 
     #testing
     "//third_party/skia/src/fonts/SkGScalerContext.cpp",
@@ -404,8 +401,8 @@
   if (is_win) {
     sources -= [
       "//third_party/skia/src/ports/SkOSFile_posix.cpp",
-      "//third_party/skia/src/ports/SkTime_Unix.cpp",
       "//third_party/skia/src/ports/SkTLS_pthread.cpp",
+      "//third_party/skia/src/ports/SkTime_Unix.cpp",
     ]
   } else {
     sources -= [
@@ -432,16 +429,16 @@
 
   if (!is_linux) {
     sources -= [
-      "//third_party/skia/src/ports/SkFontHost_fontconfig.cpp",
       "//third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp",
       "//third_party/skia/src/ports/SkFontConfigInterface_direct.cpp",
+      "//third_party/skia/src/ports/SkFontHost_fontconfig.cpp",
     ]
   }
 
   if (!is_linux && !is_android) {
     sources -= [
-      "//third_party/skia/src/ports/SkFontHost_FreeType_common.cpp",
       "//third_party/skia/src/ports/SkFontHost_FreeType.cpp",
+      "//third_party/skia/src/ports/SkFontHost_FreeType_common.cpp",
     ]
   }
 
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 37ca466..d9b6297 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -79,6 +79,10 @@
 //#define SK_DEBUG
 //#define SK_RELEASE
 
+#ifdef DCHECK_ALWAYS_ON
+    #undef SK_RELEASE
+    #define SK_DEBUG
+#endif
 
 /*  If, in debugging mode, Skia needs to stop (presumably to invoke a debugger)
     it will call SK_CRASH(). If this is not defined it, it is defined in
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc
index 409d56b..0dd6949 100644
--- a/skia/ext/benchmarking_canvas.cc
+++ b/skia/ext/benchmarking_canvas.cc
@@ -2,250 +2,760 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/containers/hash_tables.h"
 #include "base/logging.h"
+#include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "skia/ext/benchmarking_canvas.h"
-#include "third_party/skia/include/core/SkSurface.h"
-#include "third_party/skia/include/utils/SkNWayCanvas.h"
+#include "third_party/skia/include/core/SkColorFilter.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkRegion.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
+#include "third_party/skia/include/core/SkXfermode.h"
+
+namespace {
+
+class FlagsBuilder {
+public:
+  FlagsBuilder(char separator)
+      : separator_(separator) {}
+
+  void addFlag(bool flag_val, const char flag_name[]) {
+    if (!flag_val)
+      return;
+    if (!oss_.str().empty())
+      oss_ << separator_;
+
+    oss_ << flag_name;
+  }
+
+  std::string str() const {
+    return oss_.str();
+  }
+
+private:
+  char separator_;
+  std::ostringstream oss_;
+};
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(bool b) {
+  scoped_ptr<base::FundamentalValue> val(new base::FundamentalValue(b));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkScalar scalar) {
+  scoped_ptr<base::FundamentalValue> val(new base::FundamentalValue(scalar));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkSize& size) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("width",  AsValue(size.width()));
+  val->Set("height", AsValue(size.height()));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPoint& point) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("x", AsValue(point.x()));
+  val->Set("y", AsValue(point.y()));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkRect& rect) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("left", AsValue(rect.fLeft));
+  val->Set("top", AsValue(rect.fTop));
+  val->Set("right", AsValue(rect.fRight));
+  val->Set("bottom", AsValue(rect.fBottom));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkRRect& rrect) {
+  scoped_ptr<base::DictionaryValue> radii_val(new base::DictionaryValue());
+  radii_val->Set("upper-left", AsValue(rrect.radii(SkRRect::kUpperLeft_Corner)));
+  radii_val->Set("upper-right", AsValue(rrect.radii(SkRRect::kUpperRight_Corner)));
+  radii_val->Set("lower-right", AsValue(rrect.radii(SkRRect::kLowerRight_Corner)));
+  radii_val->Set("lower-left", AsValue(rrect.radii(SkRRect::kLowerLeft_Corner)));
+
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("rect", AsValue(rrect.rect()));
+  val->Set("radii", radii_val.Pass());
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkMatrix& matrix) {
+  scoped_ptr<base::ListValue> val(new base::ListValue());
+  for (int i = 0; i < 9; ++i)
+    val->Append(AsValue(matrix[i]).release()); // no scoped_ptr-aware Append() variant
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkColor color) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->SetInteger("a", SkColorGetA(color));
+  val->SetInteger("r", SkColorGetR(color));
+  val->SetInteger("g", SkColorGetG(color));
+  val->SetInteger("b", SkColorGetB(color));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkXfermode::Mode mode) {
+  scoped_ptr<base::StringValue> val(
+      new base::StringValue(SkXfermode::ModeName(mode)));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkCanvas::PointMode mode) {
+  static const char* gModeStrings[] = { "Points", "Lines", "Polygon" };
+  DCHECK_LT(static_cast<size_t>(mode), SK_ARRAY_COUNT(gModeStrings));
+
+  scoped_ptr<base::StringValue> val(new base::StringValue(gModeStrings[mode]));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkXfermode& xfermode) {
+  SkXfermode::Mode mode;
+  if (xfermode.asMode(&mode))
+    return AsValue(mode);
+
+  scoped_ptr<base::StringValue> val(new base::StringValue("unknown"));
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkColorFilter& filter) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+
+  if (unsigned flags = filter.getFlags()) {
+    FlagsBuilder builder('|');
+    builder.addFlag(flags & SkColorFilter::kAlphaUnchanged_Flag,
+                    "kAlphaUnchanged_Flag");
+    builder.addFlag(flags & SkColorFilter::kHasFilter16_Flag,
+                    "kHasFilter16_Flag");
+
+    val->SetString("flags", builder.str());
+  }
+
+  SkScalar color_matrix[20];
+  if (filter.asColorMatrix(color_matrix)) {
+    scoped_ptr<base::ListValue> color_matrix_val(new base::ListValue());
+    for (unsigned i = 0; i < 20; ++i)
+      color_matrix_val->Append(AsValue(color_matrix[i]).release());
+
+    val->Set("color_matrix", color_matrix_val.Pass());
+  }
+
+  SkColor color;
+  SkXfermode::Mode mode;
+  if (filter.asColorMode(&color, &mode)) {
+    scoped_ptr<base::DictionaryValue> color_mode_val(
+        new base::DictionaryValue());
+    color_mode_val->Set("color", AsValue(color));
+    color_mode_val->Set("mode", AsValue(mode));
+
+    val->Set("color_mode", color_mode_val.Pass());
+  }
+
+  if (filter.asComponentTable(nullptr)) {
+    scoped_ptr<base::DictionaryValue> component_table_val(
+        new base::DictionaryValue());
+    // use this as a marker for now
+    val->Set("component_table", component_table_val.Pass());
+  }
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkImageFilter& filter) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->SetInteger("inputs", filter.countInputs());
+
+  SkColorFilter* color_filter;
+  if (filter.asColorFilter(&color_filter)) {
+    val->Set("color_filter", AsValue(*color_filter));
+    SkSafeUnref(color_filter); // ref'd in asColorFilter
+  }
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPaint& paint) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  SkPaint default_paint;
+
+  if (paint.getColor() != default_paint.getColor())
+    val->Set("Color", AsValue(paint.getColor()));
+
+  if (paint.getStyle() != default_paint.getStyle()) {
+    static const char* gStyleStrings[] = { "Fill", "Stroke", "StrokeFill" };
+    DCHECK_LT(static_cast<size_t>(paint.getStyle()),
+              SK_ARRAY_COUNT(gStyleStrings));
+    val->SetString("Style", gStyleStrings[paint.getStyle()]);
+  }
+
+  if (paint.getXfermode() != default_paint.getXfermode()) {
+    DCHECK(paint.getXfermode());
+    val->Set("Xfermode", AsValue(*paint.getXfermode()));
+  }
+
+  if (paint.getFlags()) {
+    FlagsBuilder builder('|');
+    builder.addFlag(paint.isAntiAlias(), "AntiAlias");
+    builder.addFlag(paint.isDither(), "Dither");
+    builder.addFlag(paint.isUnderlineText(), "UnderlineText");
+    builder.addFlag(paint.isStrikeThruText(), "StrikeThruText");
+    builder.addFlag(paint.isFakeBoldText(), "FakeBoldText");
+    builder.addFlag(paint.isLinearText(), "LinearText");
+    builder.addFlag(paint.isSubpixelText(), "SubpixelText");
+    builder.addFlag(paint.isDevKernText(), "DevKernText");
+    builder.addFlag(paint.isLCDRenderText(), "LCDRenderText");
+    builder.addFlag(paint.isEmbeddedBitmapText(), "EmbeddedBitmapText");
+    builder.addFlag(paint.isAutohinted(), "Autohinted");
+    builder.addFlag(paint.isVerticalText(), "VerticalText");
+    builder.addFlag(paint.getFlags() & SkPaint::kGenA8FromLCD_Flag,
+                    "GenA8FromLCD");
+
+    val->SetString("Flags", builder.str());
+  }
+
+  if (paint.getFilterLevel() != default_paint.getFilterLevel()) {
+    static const char* gFilterLevelStrings[] =
+        { "None", "Low", "Medium", "High" };
+    DCHECK_LT(static_cast<size_t>(paint.getFilterLevel()),
+              SK_ARRAY_COUNT(gFilterLevelStrings));
+    val->SetString("FilterLevel", gFilterLevelStrings[paint.getFilterLevel()]);
+  }
+
+  if (paint.getTextSize() != default_paint.getTextSize())
+    val->SetDouble("TextSize", paint.getTextSize());
+
+  if (paint.getTextScaleX() != default_paint.getTextScaleX())
+    val->SetDouble("TextScaleX", paint.getTextScaleX());
+
+  if (paint.getTextSkewX() != default_paint.getTextSkewX())
+    val->SetDouble("TextSkewX", paint.getTextSkewX());
+
+  if (paint.getColorFilter())
+    val->Set("ColorFilter", AsValue(*paint.getColorFilter()));
+
+  if (paint.getImageFilter())
+    val->Set("ImageFilter", AsValue(*paint.getImageFilter()));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkCanvas::SaveFlags flags) {
+  FlagsBuilder builder('|');
+  builder.addFlag(flags & SkCanvas::kHasAlphaLayer_SaveFlag,
+                  "kHasAlphaLayer");
+  builder.addFlag(flags & SkCanvas::kFullColorLayer_SaveFlag,
+                  "kFullColorLayer");
+  builder.addFlag(flags & SkCanvas::kClipToLayer_SaveFlag,
+                  "kClipToLayer");
+
+  scoped_ptr<base::StringValue> val(new base::StringValue(builder.str()));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkRegion::Op op) {
+  static const char* gOpStrings[] = { "Difference",
+                                      "Intersect",
+                                      "Union",
+                                      "XOR",
+                                      "ReverseDifference",
+                                      "Replace"
+                                    };
+  DCHECK_LT(static_cast<size_t>(op), SK_ARRAY_COUNT(gOpStrings));
+  scoped_ptr<base::StringValue> val(new base::StringValue(gOpStrings[op]));
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkRegion& region) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("bounds", AsValue(SkRect::Make(region.getBounds())));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPicture& picture) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("cull-rect", AsValue(picture.cullRect()));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkBitmap& bitmap) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("size", AsValue(SkSize::Make(bitmap.width(), bitmap.height())));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkImage& image) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("size", AsValue(SkSize::Make(image.width(), image.height())));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkTextBlob& blob) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+  val->Set("bounds", AsValue(blob.bounds()));
+
+  return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPath& path) {
+  scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+
+  static const char* gFillStrings[] =
+      { "winding", "even-odd", "inverse-winding", "inverse-even-odd" };
+  DCHECK_LT(static_cast<size_t>(path.getFillType()),
+      SK_ARRAY_COUNT(gFillStrings));
+  val->SetString("fill-type", gFillStrings[path.getFillType()]);
+
+  static const char* gConvexityStrings[] = { "Unknown", "Convex", "Concave" };
+  DCHECK_LT(static_cast<size_t>(path.getConvexity()),
+      SK_ARRAY_COUNT(gConvexityStrings));
+  val->SetString("convexity", gConvexityStrings[path.getConvexity()]);
+
+  val->SetBoolean("is-rect", path.isRect(nullptr));
+  val->Set("bounds", AsValue(path.getBounds()));
+
+  static const char* gVerbStrings[] =
+      { "move", "line", "quad", "conic", "cubic", "close", "done" };
+  static const int gPtsPerVerb[] = { 1, 1, 2, 2, 3, 0, 0 };
+  static const int gPtOffsetPerVerb[] = { 0, 1, 1, 1, 1, 0, 0 };
+  SK_COMPILE_ASSERT(
+      SK_ARRAY_COUNT(gVerbStrings) == static_cast<size_t>(SkPath::kDone_Verb + 1),
+      gVerbStrings_size_mismatch);
+  SK_COMPILE_ASSERT(
+      SK_ARRAY_COUNT(gVerbStrings) == SK_ARRAY_COUNT(gPtsPerVerb),
+      gPtsPerVerb_size_mismatch);
+  SK_COMPILE_ASSERT(
+      SK_ARRAY_COUNT(gVerbStrings) == SK_ARRAY_COUNT(gPtOffsetPerVerb),
+      gPtOffsetPerVerb_size_mismatch);
+
+  scoped_ptr<base::ListValue> verbs_val(new base::ListValue());
+  SkPath::Iter iter(const_cast<SkPath&>(path), false);
+  SkPoint points[4];
+
+  for(SkPath::Verb verb = iter.next(points, false);
+      verb != SkPath::kDone_Verb; verb = iter.next(points, false)) {
+      DCHECK_LT(static_cast<size_t>(verb), SK_ARRAY_COUNT(gVerbStrings));
+
+      scoped_ptr<base::DictionaryValue> verb_val(new base::DictionaryValue());
+      scoped_ptr<base::ListValue> pts_val(new base::ListValue());
+
+      for (int i = 0; i < gPtsPerVerb[verb]; ++i)
+        pts_val->Append(AsValue(points[i + gPtOffsetPerVerb[verb]]).release());
+
+      verb_val->Set(gVerbStrings[verb], pts_val.Pass());
+
+      if (SkPath::kConic_Verb == verb)
+        verb_val->Set("weight", AsValue(iter.conicWeight()));
+
+      verbs_val->Append(verb_val.release());
+  }
+  val->Set("verbs", verbs_val.Pass());
+
+  return val.Pass();
+}
+
+template<typename T>
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsListValue(const T array[], size_t count) {
+  scoped_ptr<base::ListValue> val(new base::ListValue());
+
+  for (size_t i = 0; i < count; ++i)
+    val->Append(AsValue(array[i]).release());
+
+  return val.Pass();
+}
+
+} // namespace
 
 namespace skia {
 
-class AutoStamper {
+class BenchmarkingCanvas::AutoOp {
 public:
-  AutoStamper(TimingCanvas* timing_canvas);
-  ~AutoStamper();
+  AutoOp(BenchmarkingCanvas* canvas, const char op_name[],
+         const SkPaint* paint = nullptr)
+      : canvas_(canvas)
+      , op_record_(new base::DictionaryValue())
+      , op_params_(new base::ListValue()) {
+
+    DCHECK(canvas);
+    DCHECK(op_name);
+
+    op_record_->SetString("cmd_string", op_name);
+    op_record_->Set("info", op_params_);
+
+    if (paint)
+      this->addParam("paint", AsValue(*paint));
+
+    start_ticks_ = base::TimeTicks::Now();
+  }
+
+  ~AutoOp() {
+    base::TimeDelta ticks = base::TimeTicks::Now() - start_ticks_;
+    op_record_->SetDouble("cmd_time", ticks.InMillisecondsF());
+
+    canvas_->op_records_.Append(op_record_);
+  }
+
+  void addParam(const char name[], scoped_ptr<base::Value> value) {
+    scoped_ptr<base::DictionaryValue> param(new base::DictionaryValue());
+    param->Set(name, value.Pass());
+
+    op_params_->Append(param.release());
+  }
 
 private:
-  TimingCanvas* timing_canvas_;
+  BenchmarkingCanvas* canvas_;
+  base::DictionaryValue* op_record_;
+  base::ListValue* op_params_;
   base::TimeTicks start_ticks_;
 };
 
-class TimingCanvas : public SkNWayCanvas {
-public:
-  TimingCanvas(int width, int height, const BenchmarkingCanvas* track_canvas)
-      : SkNWayCanvas(width, height)
-      , tracking_canvas_(track_canvas) {
-    surface_ = skia::AdoptRef(SkSurface::NewRasterN32Premul(width, height));
-
-    addCanvas(surface_->getCanvas());
-  }
-
-  ~TimingCanvas() override {}
-
-  double GetTime(size_t index) {
-    TimingsMap::const_iterator timing_info = timings_map_.find(index);
-    return timing_info != timings_map_.end()
-        ? timing_info->second.InMillisecondsF()
-        : 0.0;
-  }
-
-  // SkCanvas overrides.
-  void willSave() override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::willSave();
-  }
-
-  SaveLayerStrategy willSaveLayer(const SkRect* bounds,
-                                  const SkPaint* paint,
-                                  SaveFlags flags) override {
-    AutoStamper stamper(this);
-    return SkNWayCanvas::willSaveLayer(bounds, paint, flags);
-  }
-
-  void willRestore() override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::willRestore();
-  }
-
-  void onDrawPaint(const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawPaint(paint);
-  }
-
-  void onDrawPoints(PointMode mode,
-                    size_t count,
-                    const SkPoint pts[],
-                    const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawPoints(mode, count, pts, paint);
-  }
-
-  void onDrawOval(const SkRect& rect, const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawOval(rect, paint);
-  }
-
-  void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawRect(rect, paint);
-  }
-
-  void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawRRect(rrect, paint);
-  }
-
-  void onDrawPath(const SkPath& path, const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawPath(path, paint);
-  }
-
-  void onDrawBitmap(const SkBitmap& bitmap,
-                    SkScalar left,
-                    SkScalar top,
-                    const SkPaint* paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawBitmap(bitmap, left, top, paint);
-  }
-
-  void onDrawBitmapRect(const SkBitmap& bitmap,
-                        const SkRect* src,
-                        const SkRect& dst,
-                        const SkPaint* paint,
-                        DrawBitmapRectFlags flags) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawBitmapRect(bitmap, src, dst, paint, flags);
-  }
-
-  void onDrawSprite(const SkBitmap& bitmap,
-                    int left,
-                    int top,
-                    const SkPaint* paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawSprite(bitmap, left, top, paint);
-  }
-
-  void onDrawVertices(VertexMode vmode,
-                      int vertexCount,
-                      const SkPoint vertices[],
-                      const SkPoint texs[],
-                      const SkColor colors[],
-                      SkXfermode* xmode,
-                      const uint16_t indices[],
-                      int indexCount,
-                      const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawVertices(vmode, vertexCount, vertices, texs, colors,
-                                  xmode, indices, indexCount, paint);
-  }
-
-protected:
- void onDrawText(const void* text,
-                 size_t byteLength,
-                 SkScalar x,
-                 SkScalar y,
-                 const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawText(text, byteLength, x, y, paint);
-  }
-
-  void onDrawPosText(const void* text,
-                     size_t byteLength,
-                     const SkPoint pos[],
-                     const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawPosText(text, byteLength, pos, paint);
-  }
-
-  void onDrawPosTextH(const void* text,
-                      size_t byteLength,
-                      const SkScalar xpos[],
-                      SkScalar constY,
-                      const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawPosTextH(text, byteLength, xpos, constY, paint);
-  }
-
-  void onDrawTextOnPath(const void* text,
-                        size_t byteLength,
-                        const SkPath& path,
-                        const SkMatrix* matrix,
-                        const SkPaint& paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawTextOnPath(text, byteLength, path, matrix, paint);
-  }
-
-  void onClipRect(const SkRect& rect,
-                  SkRegion::Op op,
-                  ClipEdgeStyle edge_style) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onClipRect(rect, op, edge_style);
-  }
-
-  void onClipRRect(const SkRRect& rrect,
-                   SkRegion::Op op,
-                   ClipEdgeStyle edge_style) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onClipRRect(rrect, op, edge_style);
-  }
-
-  void onClipPath(const SkPath& path,
-                  SkRegion::Op op,
-                  ClipEdgeStyle edge_style) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onClipPath(path, op, edge_style);
-  }
-
-  void onClipRegion(const SkRegion& region, SkRegion::Op op) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onClipRegion(region, op);
-  }
-
-  void onDrawPicture(const SkPicture* picture,
-                     const SkMatrix* matrix,
-                     const SkPaint* paint) override {
-    AutoStamper stamper(this);
-    SkNWayCanvas::onDrawPicture(picture, matrix, paint);
-  }
-
-private:
-  typedef base::hash_map<size_t, base::TimeDelta> TimingsMap;
-  TimingsMap timings_map_;
-
-  skia::RefPtr<SkSurface> surface_;
-
-  friend class AutoStamper;
-  const BenchmarkingCanvas* tracking_canvas_;
-};
-
-AutoStamper::AutoStamper(TimingCanvas *timing_canvas)
-    : timing_canvas_(timing_canvas) {
-  start_ticks_ = base::TimeTicks::Now();
-}
-
-AutoStamper::~AutoStamper() {
-  base::TimeDelta delta = base::TimeTicks::Now() - start_ticks_;
-  int command_index = timing_canvas_->tracking_canvas_->CommandCount() - 1;
-  DCHECK_GE(command_index, 0);
-  timing_canvas_->timings_map_[command_index] = delta;
-}
-
-BenchmarkingCanvas::BenchmarkingCanvas(int width, int height)
-    : SkNWayCanvas(width, height) {
-  debug_canvas_ = skia::AdoptRef(SkNEW_ARGS(SkDebugCanvas, (width, height)));
-  timing_canvas_ = skia::AdoptRef(SkNEW_ARGS(TimingCanvas, (width, height, this)));
-
-  addCanvas(debug_canvas_.get());
-  addCanvas(timing_canvas_.get());
+BenchmarkingCanvas::BenchmarkingCanvas(SkCanvas* canvas, unsigned flags)
+    : INHERITED(canvas->imageInfo().width(),
+                canvas->imageInfo().height())
+    , flags_(flags) {
+  addCanvas(canvas);
 }
 
 BenchmarkingCanvas::~BenchmarkingCanvas() {
-  removeAll();
 }
 
 size_t BenchmarkingCanvas::CommandCount() const {
-  return debug_canvas_->getSize();
+  return op_records_.GetSize();
 }
 
-SkDrawCommand* BenchmarkingCanvas::GetCommand(size_t index) {
-  DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize()));
-  return debug_canvas_->getDrawCommandAt(index);
+const base::ListValue& BenchmarkingCanvas::Commands() const {
+  return op_records_;
 }
 
 double BenchmarkingCanvas::GetTime(size_t index) {
-  DCHECK_LT(index,  static_cast<size_t>(debug_canvas_->getSize()));
-  return timing_canvas_->GetTime(index);
+  const base::DictionaryValue* op;
+  if (!op_records_.GetDictionary(index, &op))
+    return 0;
+
+  double t;
+  if (!op->GetDouble("cmd_time", &t))
+    return 0;
+
+  return t;
+}
+
+void BenchmarkingCanvas::willSave() {
+  AutoOp op(this, "Save");
+
+  INHERITED::willSave();
+}
+
+SkCanvas::SaveLayerStrategy BenchmarkingCanvas::willSaveLayer(const SkRect* rect,
+                                                              const SkPaint* paint,
+                                                              SaveFlags flags) {
+  AutoOp op(this, "SaveLayer", paint);
+  if (rect)
+    op.addParam("bounds", AsValue(*rect));
+  if (paint)
+    op.addParam("paint", AsValue(*paint));
+  if (flags)
+    op.addParam("flags", AsValue(flags));
+
+  return INHERITED::willSaveLayer(rect, paint, flags);
+}
+
+void BenchmarkingCanvas::willRestore() {
+  AutoOp op(this, "Restore");
+
+  INHERITED::willRestore();
+}
+
+void BenchmarkingCanvas::didConcat(const SkMatrix& m) {
+  AutoOp op(this, "Concat");
+  op.addParam("matrix", AsValue(m));
+
+  INHERITED::didConcat(m);
+}
+
+void BenchmarkingCanvas::didSetMatrix(const SkMatrix& m) {
+  AutoOp op(this, "SetMatrix");
+  op.addParam("matrix", AsValue(m));
+
+  INHERITED::didSetMatrix(m);
+}
+
+void BenchmarkingCanvas::onClipRect(const SkRect& rect,
+                                    SkRegion::Op region_op,
+                                    SkCanvas::ClipEdgeStyle style) {
+  AutoOp op(this, "ClipRect");
+  op.addParam("rect", AsValue(rect));
+  op.addParam("op", AsValue(region_op));
+  op.addParam("anti-alias", AsValue(style == kSoft_ClipEdgeStyle));
+
+  INHERITED::onClipRect(rect, region_op, style);
+}
+
+void BenchmarkingCanvas::onClipRRect(const SkRRect& rrect,
+                                     SkRegion::Op region_op,
+                                     SkCanvas::ClipEdgeStyle style) {
+  AutoOp op(this, "ClipRRect");
+  op.addParam("rrect", AsValue(rrect));
+  op.addParam("op", AsValue(region_op));
+  op.addParam("anti-alias", AsValue(style == kSoft_ClipEdgeStyle));
+
+  INHERITED::onClipRRect(rrect, region_op, style);
+}
+
+void BenchmarkingCanvas::onClipPath(const SkPath& path,
+                                    SkRegion::Op region_op,
+                                    SkCanvas::ClipEdgeStyle style) {
+  AutoOp op(this, "ClipPath");
+  op.addParam("path", AsValue(path));
+  op.addParam("op", AsValue(region_op));
+  op.addParam("anti-alias", AsValue(style == kSoft_ClipEdgeStyle));
+
+  INHERITED::onClipPath(path, region_op, style);
+}
+
+void BenchmarkingCanvas::onClipRegion(const SkRegion& region,
+                                      SkRegion::Op region_op) {
+  AutoOp op(this, "ClipRegion");
+  op.addParam("region", AsValue(region));
+  op.addParam("op", AsValue(region_op));
+
+  INHERITED::onClipRegion(region, region_op);
+}
+
+void BenchmarkingCanvas::onDrawPaint(const SkPaint& paint) {
+  AutoOp op(this, "DrawPaint", &paint);
+
+  INHERITED::onDrawPaint(paint);
+}
+
+void BenchmarkingCanvas::onDrawPoints(PointMode mode, size_t count,
+                                      const SkPoint pts[], const SkPaint& paint) {
+  AutoOp op(this, "DrawPoints", &paint);
+  op.addParam("mode", AsValue(mode));
+  op.addParam("points", AsListValue(pts, count));
+
+  INHERITED::onDrawPoints(mode, count, pts, paint);
+}
+
+void BenchmarkingCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
+  AutoOp op(this, "DrawRect", &paint);
+  op.addParam("rect", AsValue(rect));
+
+  INHERITED::onDrawRect(rect, paint);
+}
+
+void BenchmarkingCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
+  AutoOp op(this, "DrawOval", &paint);
+  op.addParam("rect", AsValue(rect));
+
+  INHERITED::onDrawOval(rect, paint);
+}
+
+void BenchmarkingCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
+  AutoOp op(this, "DrawRRect", &paint);
+  op.addParam("rrect", AsValue(rrect));
+
+  INHERITED::onDrawRRect(rrect, paint);
+}
+
+void BenchmarkingCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+                                      const SkPaint& paint) {
+  AutoOp op(this, "DrawDRRect", &paint);
+  op.addParam("outer", AsValue(outer));
+  op.addParam("inner", AsValue(inner));
+
+  INHERITED::onDrawDRRect(outer, inner, paint);
+}
+
+void BenchmarkingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
+  AutoOp op(this, "DrawPath", &paint);
+  op.addParam("path", AsValue(path));
+
+  INHERITED::onDrawPath(path, paint);
+}
+
+void BenchmarkingCanvas::onDrawPicture(const SkPicture* picture,
+                                       const SkMatrix* matrix,
+                                       const SkPaint* paint) {
+  DCHECK(picture);
+  AutoOp op(this, "DrawPicture", paint);
+  op.addParam("picture", AsValue(picture));
+  if (matrix)
+    op.addParam("matrix", AsValue(*matrix));
+
+  INHERITED::drawPicture(picture, matrix, paint);
+}
+
+void BenchmarkingCanvas::onDrawBitmap(const SkBitmap& bitmap,
+                                      SkScalar left,
+                                      SkScalar top,
+                                      const SkPaint* paint) {
+  AutoOp op(this, "DrawBitmap", paint);
+  op.addParam("bitmap", AsValue(bitmap));
+  op.addParam("left", AsValue(left));
+  op.addParam("top", AsValue(top));
+
+  INHERITED::onDrawBitmap(bitmap, left, top, paint);
+}
+
+void BenchmarkingCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
+                                          const SkRect* src,
+                                          const SkRect& dst,
+                                          const SkPaint* paint,
+                                          DrawBitmapRectFlags flags) {
+  AutoOp op(this, "DrawBitmapRect", paint);
+  op.addParam("bitmap", AsValue(bitmap));
+  if (src)
+    op.addParam("src", AsValue(*src));
+  op.addParam("dst", AsValue(dst));
+
+  INHERITED::onDrawBitmapRect(bitmap, src, dst, paint, flags);
+}
+
+void BenchmarkingCanvas::onDrawImage(const SkImage* image,
+                                     SkScalar left,
+                                     SkScalar top,
+                                     const SkPaint* paint) {
+  DCHECK(image);
+  AutoOp op(this, "DrawImage", paint);
+  op.addParam("image", AsValue(*image));
+  op.addParam("left", AsValue(left));
+  op.addParam("top", AsValue(top));
+
+  INHERITED::onDrawImage(image, left, top, paint);
+}
+
+void BenchmarkingCanvas::onDrawImageRect(const SkImage* image, const SkRect* src,
+                                         const SkRect& dst, const SkPaint* paint) {
+  DCHECK(image);
+  AutoOp op(this, "DrawImageRect", paint);
+  op.addParam("image", AsValue(*image));
+  if (src)
+    op.addParam("src", AsValue(*src));
+  op.addParam("dst", AsValue(dst));
+
+  INHERITED::onDrawImageRect(image, src, dst, paint);
+}
+
+void BenchmarkingCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
+                                          const SkIRect& center,
+                                          const SkRect& dst,
+                                          const SkPaint* paint) {
+  AutoOp op(this, "DrawBitmapNine", paint);
+  op.addParam("bitmap", AsValue(bitmap));
+  op.addParam("center", AsValue(SkRect::Make(center)));
+  op.addParam("dst", AsValue(dst));
+
+  INHERITED::onDrawBitmapNine(bitmap, center, dst, paint);
+}
+
+void BenchmarkingCanvas::onDrawSprite(const SkBitmap& bitmap, int left, int top,
+                                      const SkPaint* paint)  {
+  AutoOp op(this, "DrawSprite", paint);
+  op.addParam("bitmap", AsValue(bitmap));
+  op.addParam("left", AsValue(SkIntToScalar(left)));
+  op.addParam("top", AsValue(SkIntToScalar(top)));
+
+  INHERITED::onDrawSprite(bitmap, left, top, paint);
+}
+
+void BenchmarkingCanvas::onDrawText(const void* text, size_t byteLength,
+                                    SkScalar x, SkScalar y,
+                                    const SkPaint& paint) {
+  AutoOp op(this, "DrawText", &paint);
+  op.addParam("count", AsValue(SkIntToScalar(paint.countText(text, byteLength))));
+  op.addParam("x", AsValue(x));
+  op.addParam("y", AsValue(y));
+
+  INHERITED::onDrawText(text, byteLength, x, y, paint);
+}
+
+void BenchmarkingCanvas::onDrawPosText(const void* text, size_t byteLength,
+                                       const SkPoint pos[], const SkPaint& paint) {
+  AutoOp op(this, "DrawPosText", &paint);
+
+  int count = paint.countText(text, byteLength);
+  op.addParam("count", AsValue(SkIntToScalar(count)));
+  op.addParam("pos", AsListValue(pos, count));
+
+  INHERITED::onDrawPosText(text, byteLength, pos, paint);
+}
+
+void BenchmarkingCanvas::onDrawPosTextH(const void* text, size_t byteLength,
+                                        const SkScalar xpos[], SkScalar constY,
+                                        const SkPaint& paint)  {
+  AutoOp op(this, "DrawPosTextH", &paint);
+  op.addParam("constY", AsValue(constY));
+
+  int count = paint.countText(text, byteLength);
+  op.addParam("count", AsValue(SkIntToScalar(count)));
+  op.addParam("pos", AsListValue(xpos, count));
+
+  INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, paint);
+}
+
+void BenchmarkingCanvas::onDrawTextOnPath(const void* text, size_t byteLength,
+                                          const SkPath& path, const SkMatrix* matrix,
+                                          const SkPaint& paint) {
+  AutoOp op(this, "DrawTextOnPath", &paint);
+  op.addParam("count", AsValue(SkIntToScalar(paint.countText(text, byteLength))));
+  op.addParam("path", AsValue(path));
+  if (matrix)
+    op.addParam("matrix", AsValue(*matrix));
+
+  INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint);
+}
+
+void BenchmarkingCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+                                        const SkPaint& paint) {
+  DCHECK(blob);
+  AutoOp op(this, "DrawTextBlob", &paint);
+  op.addParam("blob", AsValue(*blob));
+  op.addParam("x", AsValue(x));
+  op.addParam("y", AsValue(y));
+
+  INHERITED::onDrawTextBlob(blob, x, y, paint);
 }
 
 } // namespace skia
diff --git a/skia/ext/benchmarking_canvas.h b/skia/ext/benchmarking_canvas.h
index 50289a5..4f2e257 100644
--- a/skia/ext/benchmarking_canvas.h
+++ b/skia/ext/benchmarking_canvas.h
@@ -5,45 +5,86 @@
 #ifndef SKIA_EXT_BENCHMARKING_CANVAS_H_
 #define SKIA_EXT_BENCHMARKING_CANVAS_H_
 
-#include "base/compiler_specific.h"
-#include "skia/ext/refptr.h"
+#include "base/values.h"
 #include "third_party/skia/include/utils/SkNWayCanvas.h"
-#include "third_party/skia/src/utils/debugger/SkDebugCanvas.h"
 
 namespace skia {
 
-class TimingCanvas;
-
 class SK_API BenchmarkingCanvas : public SkNWayCanvas {
 public:
-  BenchmarkingCanvas(int width, int height);
+  BenchmarkingCanvas(SkCanvas* canvas, unsigned flags = 0);
   ~BenchmarkingCanvas() override;
 
+  enum Flags {
+      // TODO(fmalita): add overdraw visualization support
+      // (http://crbug.com/461534)
+      kOverdrawVisualization_Flag = 0x01,
+  };
+
   // Returns the number of draw commands executed on this canvas.
   size_t CommandCount() const;
 
-  // Get draw command info for a given index.
-  SkDrawCommand* GetCommand(size_t index);
+  // Returns the list of executed draw commands.
+  const base::ListValue& Commands() const;
 
   // Return the recorded render time (milliseconds) for a draw command index.
   double GetTime(size_t index);
 
-private:
-  // In order to avoid introducing a Skia version dependency, this
-  // implementation dispatches draw commands in lock-step to two distinct
-  // canvases:
-  //   * a SkDebugCanvas used for gathering command info and tracking
-  //     the current command index
-  //   * a SkiaTimingCanvas used for measuring raster paint times (and relying
-  //     on the former for tracking the current command index).
-  //
-  // This way, if the SkCanvas API is extended, we don't need to worry about
-  // updating content::SkiaTimingCanvas to accurately override all new methods
-  // (to avoid timing info indices from getting out of sync), as SkDebugCanvas
-  // already does that for us.
+protected:
+  // SkCanvas overrides
+  void willSave() override;
+  SaveLayerStrategy willSaveLayer(const SkRect*,
+                                  const SkPaint*,
+                                  SaveFlags) override;
+  void willRestore() override;
 
-  skia::RefPtr<SkDebugCanvas> debug_canvas_;
-  skia::RefPtr<TimingCanvas> timing_canvas_;
+  void didConcat(const SkMatrix&) override;
+  void didSetMatrix(const SkMatrix&) override;
+
+  void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
+  void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
+  void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
+  void onClipRegion(const SkRegion&, SkRegion::Op) override;
+
+  void onDrawPaint(const SkPaint&) override;
+  void onDrawPoints(PointMode, size_t count, const SkPoint pts[],
+                    const SkPaint&) override;
+  void onDrawRect(const SkRect&, const SkPaint&) override;
+  void onDrawOval(const SkRect&, const SkPaint&) override;
+  void onDrawRRect(const SkRRect&, const SkPaint&) override;
+  void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
+  void onDrawPath(const SkPath&, const SkPaint&) override;
+
+  void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+
+  void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
+  void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst,
+                        const SkPaint*, DrawBitmapRectFlags flags) override;
+  void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
+  void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
+                       const SkPaint*) override;
+  void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
+                        const SkPaint*) override;
+  void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override;
+
+  void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+                  const SkPaint&) override;
+  void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+                     const SkPaint&) override;
+  void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+                      SkScalar constY, const SkPaint&) override;
+  void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+                        const SkMatrix* matrix, const SkPaint&) override;
+  void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+                      const SkPaint& paint) override;
+
+private:
+  typedef SkNWayCanvas INHERITED;
+
+  class AutoOp;
+
+  base::ListValue op_records_;
+  unsigned flags_;
 };
 
 }
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi
index 2163a79..04e428a 100644
--- a/skia/skia_library.gypi
+++ b/skia/skia_library.gypi
@@ -102,7 +102,6 @@
   '../third_party/skia/include/utils/SkLayer.h',
   '../third_party/skia/include/utils/SkMeshUtils.h',
   '../third_party/skia/include/utils/SkNinePatch.h',
-  '../third_party/skia/include/utils/SkParse.h',
   '../third_party/skia/include/utils/SkParsePaint.h',
   '../third_party/skia/include/utils/SkParsePath.h',
   '../third_party/skia/include/utils/SkRandom.h',
@@ -124,8 +123,6 @@
   '../third_party/skia/src/utils/SkMeshUtils.cpp',
   '../third_party/skia/src/utils/SkNinePatch.cpp',
   '../third_party/skia/src/utils/SkOSFile.cpp',
-  '../third_party/skia/src/utils/SkParse.cpp',
-  '../third_party/skia/src/utils/SkParseColor.cpp',
   '../third_party/skia/src/utils/SkParsePath.cpp',
   '../third_party/skia/src/utils/SkPathUtils.cpp',
   '../third_party/skia/src/utils/SkSHA1.cpp',
diff --git a/skia/skia_test_expectations.txt b/skia/skia_test_expectations.txt
index c8fd3a4..5927d5c 100644
--- a/skia/skia_test_expectations.txt
+++ b/skia/skia_test_expectations.txt
@@ -51,66 +51,4 @@
 # We fixed a blending bug.
 crbug.com/459579 virtual/gpu/fast/canvas/canvas-composite-transformclip.html [ ImageOnlyFailure ]
 
-# http://crrev/928853003 (SK_SUPPORT_LEGACY_ARCTO_QUADS)
-crbug.com/458898 accessibility/svg-bounds.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/arc360.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-arc-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-arc-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-composite.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-composite-transformclip.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-ellipse-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-ellipse-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-ellipse-connecting-line.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/canvas-scroll-path-into-view.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 fast/canvas/image-object-in-canvas.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/animations/animateMotion-accumulate-2b.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/batik/text/smallFonts.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/batik/text/textFeatures.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/batik/text/textProperties.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/animate-path-discrete.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/circular-marker-reference-1.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/circular-marker-reference-2.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/circular-marker-reference-3.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/circular-marker-reference-4.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/marker-opacity.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/non-circular-marker-reference.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/custom/use-css-no-effect-on-shadow-tree.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.1/animate-elem-37-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.1/animate-elem-41-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.1/animate-elem-78-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.1/animate-elem-80-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.1/painting-stroke-03-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.1/paths-data-10-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.1/struct-group-03-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t.svg [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/arc360.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-arc-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-arc-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-composite.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-composite-transformclip.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-ellipse-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-ellipse-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-ellipse-connecting-line.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/canvas-scroll-path-into-view.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/arc360.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/canvas-arc-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/canvas-arc-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/canvas-composite.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/canvas-ellipse-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/canvas-ellipse-connecting-line.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/gpu/fast/canvas/canvas-scroll-path-into-view.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/arc360.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-arc-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-arc-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-composite.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-composite-transformclip.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-ellipse-circumference-fill.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-ellipse-circumference.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-ellipse-connecting-line.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/canvas-scroll-path-into-view.html [ ImageOnlyFailure Failure Pass ]
-crbug.com/458898 virtual/slimmingpaint/fast/canvas/image-object-in-canvas.html [ ImageOnlyFailure Failure Pass ]
-
 # END OVERRIDES HERE (this line ensures that the file is newline-terminated)
diff --git a/sky/compositor/layer_host.h b/sky/compositor/layer_host.h
index 1e4fcc7..36bf2df 100644
--- a/sky/compositor/layer_host.h
+++ b/sky/compositor/layer_host.h
@@ -22,7 +22,7 @@
 class LayerHost : public SurfaceHolder::Client {
  public:
   explicit LayerHost(LayerHostClient* client);
-  ~LayerHost();
+  ~LayerHost() override;
 
   LayerHostClient* client() const { return client_; }
 
diff --git a/sky/engine/BUILD.gn b/sky/engine/BUILD.gn
index cc9d406..b94f7d5 100644
--- a/sky/engine/BUILD.gn
+++ b/sky/engine/BUILD.gn
@@ -46,7 +46,7 @@
   # nullptr) conflict with upcoming c++0x types.
   cflags_cc = [ "-Wno-c++0x-compat" ]
 
-  if (is_linux && cpu_arch == "arm") {
+  if (is_linux && target_cpu == "arm") {
     # Due to a bug in gcc arm, we get warnings about uninitialized
     # timesNewRoman.unstatic.3258 and colorTransparent.unstatic.4879.
     cflags += [ "-Wno-uninitialized" ]
diff --git a/sky/engine/config.gni b/sky/engine/config.gni
index 9575923..d6214be 100644
--- a/sky/engine/config.gni
+++ b/sky/engine/config.gni
@@ -8,7 +8,7 @@
   import("//build/config/android/config.gni")
 }
 
-if (cpu_arch == "arm") {
+if (target_cpu == "arm") {
   import("//build/config/arm.gni")
 } else {
   # TODO(brettw) remove this once && early-out is checked in.
diff --git a/sky/engine/platform/BUILD.gn b/sky/engine/platform/BUILD.gn
index da61f25..c0bae3b 100644
--- a/sky/engine/platform/BUILD.gn
+++ b/sky/engine/platform/BUILD.gn
@@ -640,7 +640,7 @@
     direct_dependent_configs = [ "//build/config/linux:fontconfig" ]
   }
 
-  if (cpu_arch == "arm") {
+  if (target_cpu == "arm") {
     deps += [ ":sky_arm_neon" ]
   }
 }
@@ -713,7 +713,7 @@
   include_dirs = [ "$root_build_dir" ]
 }
 
-if (cpu_arch == "arm") {
+if (target_cpu == "arm") {
   source_set("sky_arm_neon") {
     sources = [
       "graphics/cpu/arm/WebGLImageConversionNEON.h",
diff --git a/sky/engine/platform/graphics/ImageDecodingStoreTest.cpp b/sky/engine/platform/graphics/ImageDecodingStoreTest.cpp
index c0650fc..0e153c8 100644
--- a/sky/engine/platform/graphics/ImageDecodingStoreTest.cpp
+++ b/sky/engine/platform/graphics/ImageDecodingStoreTest.cpp
@@ -38,7 +38,7 @@
 
 class ImageDecodingStoreTest : public ::testing::Test, public MockImageDecoderClient {
 public:
-    virtual void SetUp()
+    void SetUp() override
     {
         ImageDecodingStore::instance()->setCacheLimitInBytes(1024 * 1024);
         m_data = SharedBuffer::create();
@@ -46,17 +46,17 @@
         m_decodersDestroyed = 0;
     }
 
-    virtual void TearDown()
+    void TearDown() override
     {
         ImageDecodingStore::instance()->clear();
     }
 
-    virtual void decoderBeingDestroyed()
+    void decoderBeingDestroyed() override
     {
         ++m_decodersDestroyed;
     }
 
-    virtual void frameBufferRequested()
+    void frameBufferRequested() override
     {
         // Decoder is never used by ImageDecodingStore.
         ASSERT_TRUE(false);
diff --git a/sky/engine/platform/graphics/gpu/DrawingBufferTest.cpp b/sky/engine/platform/graphics/gpu/DrawingBufferTest.cpp
index bc9794b..cbc4074 100644
--- a/sky/engine/platform/graphics/gpu/DrawingBufferTest.cpp
+++ b/sky/engine/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -205,7 +205,7 @@
 
 class DrawingBufferTest : public Test {
 protected:
-    virtual void SetUp()
+    void SetUp() override
     {
         RefPtr<FakeContextEvictionManager> contextEvictionManager = adoptRef(new FakeContextEvictionManager());
         OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests);
@@ -443,7 +443,7 @@
 
 class DrawingBufferImageChromiumTest : public DrawingBufferTest {
 protected:
-    virtual void SetUp()
+    void SetUp() override
     {
         RefPtr<FakeContextEvictionManager> contextEvictionManager = adoptRef(new FakeContextEvictionManager());
         OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests);
@@ -456,7 +456,7 @@
         testing::Mock::VerifyAndClearExpectations(webContext());
     }
 
-    virtual void TearDown()
+    void TearDown() override
     {
         RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(false);
     }
diff --git a/sky/engine/platform/text/LineEnding.cpp b/sky/engine/platform/text/LineEnding.cpp
index 80ee70a..ac71b2e 100644
--- a/sky/engine/platform/text/LineEnding.cpp
+++ b/sky/engine/platform/text/LineEnding.cpp
@@ -50,16 +50,16 @@
         : m_buffer(buffer)
     {
     }
-    virtual ~CStringBuffer() { }
+    ~CStringBuffer() override { }
 
-    virtual char* allocate(size_t size) override
+    char* allocate(size_t size) override
     {
         char* ptr;
         m_buffer = CString::newUninitialized(size, ptr);
         return ptr;
     }
 
-    virtual void copy(const CString& source) override
+    void copy(const CString& source) override
     {
         m_buffer = source;
     }
@@ -76,16 +76,16 @@
         : m_buffer(buffer)
     {
     }
-    virtual ~VectorCharAppendBuffer() { }
+    ~VectorCharAppendBuffer() override { }
 
-    virtual char* allocate(size_t size) override
+    char* allocate(size_t size) override
     {
         size_t oldSize = m_buffer.size();
         m_buffer.grow(oldSize + size);
         return m_buffer.data() + oldSize;
     }
 
-    virtual void copy(const CString& source) override
+    void copy(const CString& source) override
     {
         m_buffer.append(source.data(), source.length());
     }
diff --git a/sky/tools/debugger/debugger.cc b/sky/tools/debugger/debugger.cc
index ed17436..7ba8c5f 100644
--- a/sky/tools/debugger/debugger.cc
+++ b/sky/tools/debugger/debugger.cc
@@ -29,7 +29,7 @@
                     public http_server::HttpHandler {
  public:
   SkyDebugger() : is_tracing_(false), handler_binding_(this) {}
-  virtual ~SkyDebugger() {}
+  ~SkyDebugger() override {}
 
  private:
   // mojo::ApplicationDelegate:
diff --git a/sky/tools/debugger/trace_collector.h b/sky/tools/debugger/trace_collector.h
index ce8db02..8c6c322 100644
--- a/sky/tools/debugger/trace_collector.h
+++ b/sky/tools/debugger/trace_collector.h
@@ -18,7 +18,7 @@
   typedef base::Callback<void(std::string)> TraceCallback;
 
   explicit TraceCollector(mojo::ScopedDataPipeConsumerHandle source);
-  ~TraceCollector();
+  ~TraceCollector() override;
 
   void GetTrace(TraceCallback callback);
 
diff --git a/sky/tools/tester/test_harness_impl.h b/sky/tools/tester/test_harness_impl.h
index 3067b52..18f8696 100644
--- a/sky/tools/tester/test_harness_impl.h
+++ b/sky/tools/tester/test_harness_impl.h
@@ -19,7 +19,7 @@
  public:
   TestHarnessImpl(TestRunner* runner,
                   mojo::InterfaceRequest<TestHarness> request);
-  virtual ~TestHarnessImpl();
+  ~TestHarnessImpl() override;
 
  private:
   // TestHarness implementation.
diff --git a/sky/tools/tester/test_runner.cc b/sky/tools/tester/test_runner.cc
index c726989..5982382 100644
--- a/sky/tools/tester/test_runner.cc
+++ b/sky/tools/tester/test_runner.cc
@@ -20,8 +20,8 @@
                        const std::string& url,
                        bool enable_pixel_dumping)
     : client_(client),
-      weak_ptr_factory_(this),
-      enable_pixel_dumping_(enable_pixel_dumping) {
+      enable_pixel_dumping_(enable_pixel_dumping),
+      weak_ptr_factory_(this) {
   CHECK(client);
 
   mojo::ServiceProviderPtr test_harness_provider;
diff --git a/sky/tools/tester/test_runner.h b/sky/tools/tester/test_runner.h
index 57bfab2..8810240 100644
--- a/sky/tools/tester/test_runner.h
+++ b/sky/tools/tester/test_runner.h
@@ -45,8 +45,8 @@
 
   mojo::ServiceProviderImpl test_harness_provider_impl_;
   TestRunnerClient* client_;
-  base::WeakPtrFactory<TestRunner> weak_ptr_factory_;
   bool enable_pixel_dumping_;
+  base::WeakPtrFactory<TestRunner> weak_ptr_factory_;
 
   MOJO_DISALLOW_COPY_AND_ASSIGN(TestRunner);
 };
diff --git a/sky/tools/tester/tester.cc b/sky/tools/tester/tester.cc
index 631ca4e..f0af25c 100644
--- a/sky/tools/tester/tester.cc
+++ b/sky/tools/tester/tester.cc
@@ -64,17 +64,17 @@
         root_(NULL),
         content_(NULL),
         weak_ptr_factory_(this) {}
-  virtual ~SkyTester() {}
+  ~SkyTester() override {}
 
  private:
   // Overridden from mojo::ApplicationDelegate:
-  virtual void Initialize(mojo::ApplicationImpl* impl) override {
+  void Initialize(mojo::ApplicationImpl* impl) override {
     window_manager_app_->Initialize(impl);
 
     if (impl->args().size() >= 2)
       url_from_args_ = impl->args()[1];
   }
-  virtual bool ConfigureIncomingConnection(
+  bool ConfigureIncomingConnection(
       mojo::ApplicationConnection* connection) override {
     window_manager_app_->ConfigureIncomingConnection(connection);
     if (test_runner_)
@@ -83,9 +83,9 @@
   }
 
   // Overridden from mojo::ViewManagerDelegate:
-  virtual void OnEmbed(mojo::View* root,
-                       mojo::InterfaceRequest<mojo::ServiceProvider> services,
-                       mojo::ServiceProviderPtr exposed_services) override {
+  void OnEmbed(mojo::View* root,
+               mojo::InterfaceRequest<mojo::ServiceProvider> services,
+               mojo::ServiceProviderPtr exposed_services) override {
     root_ = root;
     root_->AddObserver(this);
 
@@ -100,22 +100,21 @@
   }
 
   // Overridden from window_manager::WindowManagerDelegate:
-  virtual void Embed(const mojo::String& url,
-                     mojo::InterfaceRequest<mojo::ServiceProvider> services,
-                     mojo::ServiceProviderPtr exposed_services) override {}
+  void Embed(const mojo::String& url,
+             mojo::InterfaceRequest<mojo::ServiceProvider> services,
+             mojo::ServiceProviderPtr exposed_services) override {}
 
-  virtual void OnViewManagerDisconnected(
-      mojo::ViewManager* view_manager) override {
+  void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override {
     root_ = NULL;
   }
 
-  virtual void OnViewDestroyed(mojo::View* view) override {
+  void OnViewDestroyed(mojo::View* view) override {
     view->RemoveObserver(this);
   }
 
-  virtual void OnViewBoundsChanged(mojo::View* view,
-                                   const mojo::Rect& old_bounds,
-                                   const mojo::Rect& new_bounds) override {
+  void OnViewBoundsChanged(mojo::View* view,
+                           const mojo::Rect& old_bounds,
+                           const mojo::Rect& new_bounds) override {
     content_->SetBounds(new_bounds);
   }
 
diff --git a/sky/viewer/internals.h b/sky/viewer/internals.h
index fc76d36..f94f268 100644
--- a/sky/viewer/internals.h
+++ b/sky/viewer/internals.h
@@ -17,7 +17,7 @@
 class Internals : public base::SupportsUserData::Data,
                   public mojo::Shell {
  public:
-  virtual ~Internals();
+  ~Internals() override;
 
   static void Create(Dart_Isolate isolate, DocumentView* document_view);
 
diff --git a/sky/viewer/viewer.cc b/sky/viewer/viewer.cc
index 61c92da..7f043b3 100644
--- a/sky/viewer/viewer.cc
+++ b/sky/viewer/viewer.cc
@@ -27,11 +27,11 @@
  public:
   Viewer() {}
 
-  virtual ~Viewer() { blink::shutdown(); }
+  ~Viewer() override { blink::shutdown(); }
 
  private:
   // Overridden from ApplicationDelegate:
-  virtual void Initialize(mojo::ApplicationImpl* app) override {
+  void Initialize(mojo::ApplicationImpl* app) override {
     RuntimeFlags::Initialize(app);
 
     mojo::NetworkServicePtr network_service;
@@ -43,15 +43,15 @@
     tracing_.Initialize(app);
   }
 
-  virtual bool ConfigureIncomingConnection(
+  bool ConfigureIncomingConnection(
       mojo::ApplicationConnection* connection) override {
     connection->AddService<mojo::ContentHandler>(this);
     return true;
   }
 
   // Overridden from InterfaceFactory<ContentHandler>
-  virtual void Create(mojo::ApplicationConnection* connection,
-                      mojo::InterfaceRequest<mojo::ContentHandler> request) override {
+  void Create(mojo::ApplicationConnection* connection,
+              mojo::InterfaceRequest<mojo::ContentHandler> request) override {
     new ContentHandlerImpl(request.Pass());
   }
 
diff --git a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java b/testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
index cc89268..4e1a067 100644
--- a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
+++ b/testing/android/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
@@ -12,17 +12,13 @@
 import android.os.Environment;
 import android.util.Log;
 
-import org.chromium.net.test.TestServerSpawner;
-
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Matcher;
@@ -36,15 +32,11 @@
     public static final String EXTRA_ONLY_OUTPUT_FAILURES =
             "org.chromium.native_test.ChromeNativeTestInstrumentationTestRunner."
                     + "OnlyOutputFailures";
-    public static final String EXTRA_ENABLE_TEST_SERVER_SPAWNER =
-            "org.chromium.native_test.ChromeNativeTestInstrumentationTestRunner."
-                    + "EnableTestServerSpawner";
 
     private static final String TAG = "ChromeNativeTestInstrumentationTestRunner";
 
     private static final int ACCEPT_TIMEOUT_MS = 5000;
     private static final Pattern RE_TEST_OUTPUT = Pattern.compile("\\[ *([^ ]*) *\\] ?([^ ]+) .*");
-    private static final int SERVER_SPAWNER_PORT = 0;
 
     private static interface ResultsBundleGenerator {
         public Bundle generate(Map<String, TestResult> rawResults);
@@ -57,10 +49,6 @@
     private ResultsBundleGenerator mBundleGenerator;
     private boolean mOnlyOutputFailures;
 
-    private boolean mEnableTestServerSpawner;
-    private TestServerSpawner mTestServerSpawner;
-    private Thread mTestServerSpawnerThread;
-
     @Override
     public void onCreate(Bundle arguments) {
         mCommandLineFile = arguments.getString(ChromeNativeTestActivity.EXTRA_COMMAND_LINE_FILE);
@@ -77,55 +65,16 @@
         mLogBundle = new Bundle();
         mBundleGenerator = new RobotiumBundleGenerator();
         mOnlyOutputFailures = arguments.containsKey(EXTRA_ONLY_OUTPUT_FAILURES);
-        mEnableTestServerSpawner = arguments.containsKey(EXTRA_ENABLE_TEST_SERVER_SPAWNER);
-        mTestServerSpawner = null;
-        mTestServerSpawnerThread = null;
         start();
     }
 
     @Override
     public void onStart() {
         super.onStart();
-
-        setUp();
         Bundle results = runTests();
-        tearDown();
-
         finish(Activity.RESULT_OK, results);
     }
 
-    private void setUp() {
-        if (mEnableTestServerSpawner) {
-            Log.i(TAG, "Test server spawner enabled.");
-            try {
-                mTestServerSpawner = new TestServerSpawner(SERVER_SPAWNER_PORT, ACCEPT_TIMEOUT_MS);
-
-                File portFile = new File(
-                        Environment.getExternalStorageDirectory(), "net-test-server-ports");
-                OutputStreamWriter writer =
-                        new OutputStreamWriter(new FileOutputStream(portFile));
-                writer.write(Integer.toString(mTestServerSpawner.getServerPort()) + ":0");
-                writer.close();
-
-                mTestServerSpawnerThread = new Thread(mTestServerSpawner);
-                mTestServerSpawnerThread.start();
-            } catch (IOException e) {
-                Log.e(TAG, "Error creating TestServerSpawner: " + e.toString());
-            }
-        }
-    }
-
-    private void tearDown() {
-        if (mTestServerSpawnerThread != null) {
-            try {
-                mTestServerSpawner.stop();
-                mTestServerSpawnerThread.join();
-            } catch (InterruptedException e) {
-                Log.e(TAG, "Interrupted while shutting down test server spawner: " + e.toString());
-            }
-        }
-    }
-
     /** Runs the tests in the ChromeNativeTestActivity and returns a Bundle containing the results.
      */
     private Bundle runTests() {
diff --git a/testing/buildbot/OWNERS b/testing/buildbot/OWNERS
index 8b86544..c3c145a 100644
--- a/testing/buildbot/OWNERS
+++ b/testing/buildbot/OWNERS
@@ -12,3 +12,8 @@
 phajdan.jr@chromium.org
 sky@chromium.org
 thakis@chromium.org
+
+per-file chromium.perf.json=eakuefner@chromium.org
+per-file chromium.perf.json=fmeawad@chromium.org
+per-file chromium.perf.json=simonhatch@chromium.org
+per-file chromium.perf.json=sullivan@chromium.org
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 2c63c08..6e748c7 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1,2 +1,60 @@
 {
+  "Android Nexus4 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      }
+    ]
+  },
+  "Android Nexus5 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      }
+    ]
+  },
+  "Android Nexus7v2 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      }
+    ]
+  },
+  "Android Nexus10 Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      }
+    ]
+  },
+  "Android MotoE Perf": {
+    "scripts": [
+      {
+        "name": "host_info",
+        "script": "host_info.py"
+      }
+    ]
+  },
+  "Mac 10.8 Perf (1)": {
+    "scripts": [
+      {
+	"name": "gpu_perftests",
+	"script": "gtest_perf_test.py",
+	"args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
+      }
+    ]
+  },
+  "Mac 10.9 Perf (1)": {
+    "scripts": [
+      {
+	"name": "gpu_perftests",
+	"script": "gtest_perf_test.py",
+	"args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
+      }
+    ]
+  }
 }
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json
index ae8f0b4..9933e3b 100644
--- a/testing/buildbot/chromium.webkit.json
+++ b/testing/buildbot/chromium.webkit.json
@@ -1,4 +1,238 @@
 {
+  "WebKit XP": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Win7": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Win7 (dbg)": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.6": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.7": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.8": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.8 (retina)": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.9": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.6 (dbg)": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Mac10.7 (dbg)": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Linux": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Linux 32": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
+  "WebKit Linux (dbg)": {
+    "gtest_tests": [
+      "blink_heap_unittests",
+      "blink_platform_unittests",
+      "webkit_unit_tests",
+      "wtf_unittests"
+    ],
+    "scripts": [
+      {
+        "name": "webkit_lint",
+        "script": "webkit_lint.py"
+      },
+      {
+        "name": "webkit_python_tests",
+        "script": "webkit_python_tests.py"
+      }
+    ]
+  },
   "Linux ChromiumOS Tests (1)": {
     "gtest_tests": [
       "accessibility_unittests",
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json
index 7921d66..a469ddd 100644
--- a/testing/buildbot/trybot_analyze_config.json
+++ b/testing/buildbot/trybot_analyze_config.json
@@ -34,12 +34,17 @@
       "third_party/accessibility-audit/axs_testing.js",
       "third_party/hunspell_dictionaries/.*",
       "third_party/zlib/google/test/data/.*",
-      "tools/clang/scripts/plugin_flags.sh",
+      "tools/clang/scripts/plugin_flags.py",
       "tools/clang/scripts/update.py",
       "tools/clang/scripts/update.sh",
       "tools/metrics/histograms/histograms.xml",
       "tools/perf/.*",
       "tools/telemetry/.*"
     ]
+  },
+  "ios": {
+    "exclusions": [
+      "ios/build/bots/.*"
+    ]
   }
 }
diff --git a/testing/chromoting/chromoting_integration_tests.isolate b/testing/chromoting/chromoting_integration_tests.isolate
index be04bd6..82bf5f1 100644
--- a/testing/chromoting/chromoting_integration_tests.isolate
+++ b/testing/chromoting/chromoting_integration_tests.isolate
@@ -30,6 +30,7 @@
           '../../remoting/tools/internal/test-account-host-config.json',
           '<(PRODUCT_DIR)/remoting/com.google.chrome.remote_desktop.json',
           '<(PRODUCT_DIR)/remoting/com.google.chrome.remote_assistance.json',
+          '<(PRODUCT_DIR)/remoting-me2me-host.deb',
         ],
       },
     }],
@@ -79,20 +80,7 @@
         ],
       },
     }],
-    ['OS=="mac"', {
-      'variables': {
-        'command': [
-          '../test_env.py',
-          '<(PRODUCT_DIR)/browser_tests<(EXECUTABLE_SUFFIX)',
-          '--gtest_filter=RemoteDesktopBrowserTest.MANUAL_Launch',
-          '--run-manual',
-          '--ui-test-action-timeout=100000',
-          '--webapp-unpacked=<(PRODUCT_DIR)/remoting/remoting.webapp',
-          '--extension-name=Chromoting',
-        ],
-      },
-    }],
-    ['OS=="win"', {
+    ['OS=="win" or OS=="mac"', {
       'variables': {
         'command': [
           '../test_env.py',
@@ -100,7 +88,7 @@
           '--gtest_filter=RemoteDesktopBrowserTest.MANUAL_Launch:RemoteDesktopBrowserTest.MANUAL_Auth',
           '--run-manual',
           '--ui-test-action-timeout=100000',
-          '--webapp-unpacked=<(PRODUCT_DIR)/remoting/remoting.webapp',
+          '--webapp-unpacked=<(PRODUCT_DIR)/remoting/remoting.webapp.v2',
           '--extension-name=Chromoting',
           '--accounts-file=../../remoting/tools/internal/test_accounts.json',
           '--account-type=gmail',
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json
index 8ae6e31..a335f78 100644
--- a/testing/commit_queue/config.json
+++ b/testing/commit_queue/config.json
@@ -5,6 +5,7 @@
             "trybots": {
                 "launched": {
                     "tryserver.chromium.linux": {
+                        "android_amp_rel_tests_recipe": ["defaulttests"],
                         "cast_shell": ["defaulttests"],
                         "cast_shell_apk": ["defaulttests"],
                         "linux_android_rel_ng": ["defaulttests"],
diff --git a/testing/scripts/webkit_lint.py b/testing/scripts/webkit_lint.py
new file mode 100755
index 0000000..eeb9367
--- /dev/null
+++ b/testing/scripts/webkit_lint.py
@@ -0,0 +1,43 @@
+#!/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 json
+import os
+import sys
+
+
+import common
+
+
+def main_run(args):
+  with common.temporary_file() as tempfile_path:
+    rc = common.run_command([
+        sys.executable,
+        os.path.join(common.SRC_DIR, 'third_party', 'WebKit',
+                     'Tools', 'Scripts', 'lint-test-expectations'),
+        '--json', tempfile_path
+    ])
+
+    with open(tempfile_path) as f:
+      failures = json.load(f)
+
+  json.dump({
+      'valid': True,
+      'failures': failures,
+  }, args.output)
+
+  return rc
+
+
+def main_compile_targets(args):
+  json.dump([], args.output)
+
+
+if __name__ == '__main__':
+  funcs = {
+    'run': main_run,
+    'compile_targets': main_compile_targets,
+  }
+  sys.exit(common.run_script(sys.argv[1:], funcs))
diff --git a/testing/scripts/webkit_python_tests.py b/testing/scripts/webkit_python_tests.py
new file mode 100755
index 0000000..b0c2fbc
--- /dev/null
+++ b/testing/scripts/webkit_python_tests.py
@@ -0,0 +1,47 @@
+#!/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 json
+import os
+import sys
+
+
+import common
+
+
+def main_run(args):
+  with common.temporary_file() as tempfile_path:
+    rc = common.run_command([
+        sys.executable,
+        os.path.join(common.SRC_DIR, 'third_party', 'WebKit',
+                     'Tools', 'Scripts', 'test-webkitpy'),
+        '--write-full-results-to', tempfile_path,
+    ])
+
+    with open(tempfile_path) as f:
+      results = json.load(f)
+
+  parsed_results = common.parse_common_test_results(results)
+  failures = parsed_results['unexpected_failures']
+
+  json.dump({
+      'valid': bool(rc <= common.MAX_FAILURES_EXIT_STATUS and
+                   ((rc == 0) or failures)),
+      'failures': failures.keys(),
+  }, args.output)
+
+  return rc
+
+
+def main_compile_targets(args):
+  json.dump([], args.output)
+
+
+if __name__ == '__main__':
+  funcs = {
+    'run': main_run,
+    'compile_targets': main_compile_targets,
+  }
+  sys.exit(common.run_script(sys.argv[1:], funcs))
diff --git a/third_party/ashmem/BUILD.gn b/third_party/ashmem/BUILD.gn
index a3f7e6a..5e92b37 100644
--- a/third_party/ashmem/BUILD.gn
+++ b/third_party/ashmem/BUILD.gn
@@ -6,7 +6,7 @@
 
 source_set("ashmem") {
   sources = [
-    "ashmem.h",
     "ashmem-dev.c",
+    "ashmem.h",
   ]
 }
diff --git a/third_party/fontconfig/BUILD.gn b/third_party/fontconfig/BUILD.gn
index 21f42ce..9af485f 100644
--- a/third_party/fontconfig/BUILD.gn
+++ b/third_party/fontconfig/BUILD.gn
@@ -36,8 +36,8 @@
     "src/src/fcstat.c",
     "src/src/fcstr.c",
     "src/src/fcxml.c",
-    "src/src/ftglue.h",
     "src/src/ftglue.c",
+    "src/src/ftglue.h",
   ]
 
   include_dirs = [
diff --git a/third_party/harfbuzz-ng/BUILD.gn b/third_party/harfbuzz-ng/BUILD.gn
index 90b200f..b370348 100644
--- a/third_party/harfbuzz-ng/BUILD.gn
+++ b/third_party/harfbuzz-ng/BUILD.gn
@@ -47,91 +47,91 @@
       "src/hb-atomic-private.hh",
       "src/hb-blob.cc",
       "src/hb-blob.h",
-      "src/hb-buffer.cc",
       "src/hb-buffer-deserialize-json.hh",
       "src/hb-buffer-deserialize-text.hh",
-      "src/hb-buffer.h",
       "src/hb-buffer-private.hh",
       "src/hb-buffer-serialize.cc",
+      "src/hb-buffer.cc",
+      "src/hb-buffer.h",
       "src/hb-cache-private.hh",
       "src/hb-common.cc",
       "src/hb-common.h",
       "src/hb-deprecated.h",
+      "src/hb-face-private.hh",
       "src/hb-face.cc",
       "src/hb-face.h",
-      "src/hb-face-private.hh",
       "src/hb-fallback-shape.cc",
+      "src/hb-font-private.hh",
       "src/hb-font.cc",
       "src/hb-font.h",
-      "src/hb-font-private.hh",
-      "src/hb.h",
       "src/hb-icu.cc",
       "src/hb-icu.h",
       "src/hb-mutex-private.hh",
       "src/hb-object-private.hh",
       "src/hb-open-file-private.hh",
       "src/hb-open-type-private.hh",
-      "src/hb-ot.h",
       "src/hb-ot-head-table.hh",
       "src/hb-ot-hhea-table.hh",
       "src/hb-ot-hmtx-table.hh",
-      "src/hb-ot-layout.cc",
       "src/hb-ot-layout-common-private.hh",
       "src/hb-ot-layout-gdef-table.hh",
       "src/hb-ot-layout-gpos-table.hh",
-      "src/hb-ot-layout-gsubgpos-private.hh",
       "src/hb-ot-layout-gsub-table.hh",
-      "src/hb-ot-layout.h",
+      "src/hb-ot-layout-gsubgpos-private.hh",
       "src/hb-ot-layout-private.hh",
-      "src/hb-ot-map.cc",
+      "src/hb-ot-layout.cc",
+      "src/hb-ot-layout.h",
       "src/hb-ot-map-private.hh",
+      "src/hb-ot-map.cc",
       "src/hb-ot-maxp-table.hh",
       "src/hb-ot-name-table.hh",
-      "src/hb-ot-shape.cc",
-      "src/hb-ot-shape-complex-arabic.cc",
       "src/hb-ot-shape-complex-arabic-fallback.hh",
       "src/hb-ot-shape-complex-arabic-table.hh",
+      "src/hb-ot-shape-complex-arabic.cc",
       "src/hb-ot-shape-complex-default.cc",
       "src/hb-ot-shape-complex-hangul.cc",
       "src/hb-ot-shape-complex-hebrew.cc",
-      "src/hb-ot-shape-complex-indic.cc",
       "src/hb-ot-shape-complex-indic-machine.hh",
       "src/hb-ot-shape-complex-indic-private.hh",
       "src/hb-ot-shape-complex-indic-table.cc",
-      "src/hb-ot-shape-complex-myanmar.cc",
+      "src/hb-ot-shape-complex-indic.cc",
       "src/hb-ot-shape-complex-myanmar-machine.hh",
+      "src/hb-ot-shape-complex-myanmar.cc",
       "src/hb-ot-shape-complex-private.hh",
-      "src/hb-ot-shape-complex-sea.cc",
       "src/hb-ot-shape-complex-sea-machine.hh",
+      "src/hb-ot-shape-complex-sea.cc",
       "src/hb-ot-shape-complex-thai.cc",
       "src/hb-ot-shape-complex-tibetan.cc",
-      "src/hb-ot-shape-fallback.cc",
       "src/hb-ot-shape-fallback-private.hh",
-      "src/hb-ot-shape.h",
-      "src/hb-ot-shape-normalize.cc",
+      "src/hb-ot-shape-fallback.cc",
       "src/hb-ot-shape-normalize-private.hh",
+      "src/hb-ot-shape-normalize.cc",
       "src/hb-ot-shape-private.hh",
+      "src/hb-ot-shape.cc",
+      "src/hb-ot-shape.h",
       "src/hb-ot-tag.cc",
       "src/hb-ot-tag.h",
+      "src/hb-ot.h",
       "src/hb-private.hh",
+      "src/hb-set-private.hh",
       "src/hb-set.cc",
       "src/hb-set.h",
-      "src/hb-set-private.hh",
-      "src/hb-shape.cc",
-      "src/hb-shape.h",
+      "src/hb-shape-plan-private.hh",
       "src/hb-shape-plan.cc",
       "src/hb-shape-plan.h",
-      "src/hb-shape-plan-private.hh",
-      "src/hb-shaper.cc",
+      "src/hb-shape.cc",
+      "src/hb-shape.h",
       "src/hb-shaper-impl-private.hh",
       "src/hb-shaper-list.hh",
       "src/hb-shaper-private.hh",
+      "src/hb-shaper.cc",
+      "src/hb-unicode-private.hh",
       "src/hb-unicode.cc",
       "src/hb-unicode.h",
-      "src/hb-unicode-private.hh",
       "src/hb-utf-private.hh",
       "src/hb-version.h",
       "src/hb-warning.cc",
+      "src/hb.h",
     ]
 
     defines = [
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc
index 0500aa2..942177c 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.cc
+++ b/third_party/harfbuzz-ng/src/hb-buffer.cc
@@ -454,7 +454,7 @@
     info[j] = t;
   }
 
-  if (pos) {
+  if (have_positions) {
     for (i = start, j = end - 1; i < j; i++, j--) {
       hb_glyph_position_t t;
 
diff --git a/third_party/libxml/BUILD.gn b/third_party/libxml/BUILD.gn
index 992e92a..299a110 100644
--- a/third_party/libxml/BUILD.gn
+++ b/third_party/libxml/BUILD.gn
@@ -27,24 +27,43 @@
 static_library("libxml") {
   output_name = "libxml2"
   sources = [
-    "chromium/libxml_utils.h",
     "chromium/libxml_utils.cc",
+    "chromium/libxml_utils.h",
     "linux/config.h",
     "linux/include/libxml/xmlversion.h",
     "mac/config.h",
     "mac/include/libxml/xmlversion.h",
+    "src/DOCBparser.c",
+    "src/HTMLparser.c",
+    "src/HTMLtree.c",
+    "src/SAX.c",
+    "src/SAX2.c",
+    "src/acconfig.h",
+    "src/c14n.c",
+    "src/catalog.c",
+    "src/chvalid.c",
+    "src/debugXML.c",
+    "src/dict.c",
+    "src/elfgcchack.h",
+    "src/encoding.c",
+    "src/entities.c",
+    "src/error.c",
+    "src/globals.c",
+    "src/hash.c",
+    "src/include/libxml/DOCBparser.h",
+    "src/include/libxml/HTMLparser.h",
+    "src/include/libxml/HTMLtree.h",
+    "src/include/libxml/SAX.h",
+    "src/include/libxml/SAX2.h",
     "src/include/libxml/c14n.h",
     "src/include/libxml/catalog.h",
     "src/include/libxml/chvalid.h",
     "src/include/libxml/debugXML.h",
     "src/include/libxml/dict.h",
-    "src/include/libxml/DOCBparser.h",
     "src/include/libxml/encoding.h",
     "src/include/libxml/entities.h",
     "src/include/libxml/globals.h",
     "src/include/libxml/hash.h",
-    "src/include/libxml/HTMLparser.h",
-    "src/include/libxml/HTMLtree.h",
     "src/include/libxml/list.h",
     "src/include/libxml/nanoftp.h",
     "src/include/libxml/nanohttp.h",
@@ -52,8 +71,6 @@
     "src/include/libxml/parserInternals.h",
     "src/include/libxml/pattern.h",
     "src/include/libxml/relaxng.h",
-    "src/include/libxml/SAX.h",
-    "src/include/libxml/SAX2.h",
     "src/include/libxml/schemasInternals.h",
     "src/include/libxml/schematron.h",
     "src/include/libxml/threads.h",
@@ -62,10 +79,10 @@
     "src/include/libxml/valid.h",
     "src/include/libxml/xinclude.h",
     "src/include/libxml/xlink.h",
+    "src/include/libxml/xmlIO.h",
     "src/include/libxml/xmlautomata.h",
     "src/include/libxml/xmlerror.h",
     "src/include/libxml/xmlexports.h",
-    "src/include/libxml/xmlIO.h",
     "src/include/libxml/xmlmemory.h",
     "src/include/libxml/xmlmodule.h",
     "src/include/libxml/xmlreader.h",
@@ -81,21 +98,6 @@
     "src/include/libxml/xpointer.h",
     "src/include/win32config.h",
     "src/include/wsockcompat.h",
-    "src/acconfig.h",
-    "src/c14n.c",
-    "src/catalog.c",
-    "src/chvalid.c",
-    "src/debugXML.c",
-    "src/dict.c",
-    "src/DOCBparser.c",
-    "src/elfgcchack.h",
-    "src/encoding.c",
-    "src/entities.c",
-    "src/error.c",
-    "src/globals.c",
-    "src/hash.c",
-    "src/HTMLparser.c",
-    "src/HTMLtree.c",
     "src/legacy.c",
     "src/libxml.h",
     "src/list.c",
@@ -105,8 +107,6 @@
     "src/parserInternals.c",
     "src/pattern.c",
     "src/relaxng.c",
-    "src/SAX.c",
-    "src/SAX2.c",
     "src/schematron.c",
     "src/threads.c",
     "src/tree.c",
diff --git a/third_party/mesa/BUILD.gn b/third_party/mesa/BUILD.gn
index 468a7e6..acdca86 100644
--- a/third_party/mesa/BUILD.gn
+++ b/third_party/mesa/BUILD.gn
@@ -149,19 +149,19 @@
     "src/src/glsl/glsl_types.cpp",
     "src/src/glsl/glsl_types.h",
     "src/src/glsl/hir_field_selection.cpp",
+    "src/src/glsl/ir.cpp",
+    "src/src/glsl/ir.h",
     "src/src/glsl/ir_basic_block.cpp",
     "src/src/glsl/ir_basic_block.h",
     "src/src/glsl/ir_builder.cpp",
     "src/src/glsl/ir_builder.h",
     "src/src/glsl/ir_clone.cpp",
     "src/src/glsl/ir_constant_expression.cpp",
-    "src/src/glsl/ir.cpp",
     "src/src/glsl/ir_expression_flattening.cpp",
     "src/src/glsl/ir_expression_flattening.h",
-    "src/src/glsl/ir_function_can_inline.cpp",
     "src/src/glsl/ir_function.cpp",
+    "src/src/glsl/ir_function_can_inline.cpp",
     "src/src/glsl/ir_function_detect_recursion.cpp",
-    "src/src/glsl/ir.h",
     "src/src/glsl/ir_hierarchical_visitor.cpp",
     "src/src/glsl/ir_hierarchical_visitor.h",
     "src/src/glsl/ir_hv_accept.cpp",
@@ -176,11 +176,11 @@
     "src/src/glsl/ir_validate.cpp",
     "src/src/glsl/ir_variable_refcount.cpp",
     "src/src/glsl/ir_variable_refcount.h",
-    "src/src/glsl/linker.cpp",
-    "src/src/glsl/linker.h",
     "src/src/glsl/link_functions.cpp",
     "src/src/glsl/link_uniform_initializers.cpp",
     "src/src/glsl/link_uniforms.cpp",
+    "src/src/glsl/linker.cpp",
+    "src/src/glsl/linker.h",
     "src/src/glsl/loop_analysis.cpp",
     "src/src/glsl/loop_analysis.h",
     "src/src/glsl/loop_controls.cpp",
@@ -250,7 +250,11 @@
 static_library("mesa") {
   sources = [
     "$generated_src_dir/mesa/builtin_function.cpp",
+    "$generated_src_dir/mesa/enums.c",
     "$generated_src_dir/mesa/glapi_mapi_tmp_shared.h",
+    "$generated_src_dir/mesa/lex.yy.c",
+    "$generated_src_dir/mesa/program/program_parse.tab.c",
+    "$generated_src_dir/mesa/program/program_parse.tab.h",
     "src/src/mapi/mapi/entry.c",
     "src/src/mapi/mapi/entry.h",
     "src/src/mapi/mapi/mapi_glapi.c",
@@ -312,7 +316,6 @@
     "src/src/mesa/main/drawtex.h",
     "src/src/mesa/main/enable.c",
     "src/src/mesa/main/enable.h",
-    "$generated_src_dir/mesa/enums.c",
     "src/src/mesa/main/enums.h",
     "src/src/mesa/main/errors.c",
     "src/src/mesa/main/errors.h",
@@ -474,7 +477,6 @@
     "src/src/mesa/program/hash_table.h",
     "src/src/mesa/program/ir_to_mesa.cpp",
     "src/src/mesa/program/ir_to_mesa.h",
-    "$generated_src_dir/mesa/lex.yy.c",
     "src/src/mesa/program/nvfragparse.c",
     "src/src/mesa/program/nvfragparse.h",
     "src/src/mesa/program/nvvertparse.c",
@@ -500,8 +502,6 @@
     "src/src/mesa/program/prog_statevars.h",
     "src/src/mesa/program/program.c",
     "src/src/mesa/program/program.h",
-    "$generated_src_dir/mesa/program/program_parse.tab.c",
-    "$generated_src_dir/mesa/program/program_parse.tab.h",
     "src/src/mesa/program/program_parse_extra.c",
     "src/src/mesa/program/programopt.c",
     "src/src/mesa/program/programopt.h",
diff --git a/third_party/mesa/mesa.gyp b/third_party/mesa/mesa.gyp
index bf2afcd..82027b3 100644
--- a/third_party/mesa/mesa.gyp
+++ b/third_party/mesa/mesa.gyp
@@ -80,6 +80,7 @@
           # which is used by gallium/auxiliary/Makefile.
           '-fsanitize=null',
           '-fsanitize=vptr',
+          '-fsanitize-coverage=<(sanitizer_coverage)',
         ],
       }],
     ],
diff --git a/third_party/ots/BUILD.gn b/third_party/ots/BUILD.gn
index 513dce6..c9d339a 100644
--- a/third_party/ots/BUILD.gn
+++ b/third_party/ots/BUILD.gn
@@ -8,8 +8,8 @@
 
 source_set("ots") {
   sources = [
-    "include/ots-memory-stream.h",
     "include/opentype-sanitiser.h",
+    "include/ots-memory-stream.h",
     "src/cff.cc",
     "src/cff.h",
     "src/cff_type2_charstring.cc",
@@ -46,10 +46,10 @@
     "src/loca.h",
     "src/ltsh.cc",
     "src/ltsh.h",
-    "src/maxp.cc",
-    "src/maxp.h",
     "src/math.cc",
     "src/math_.h",
+    "src/maxp.cc",
+    "src/maxp.h",
     "src/metrics.cc",
     "src/metrics.h",
     "src/name.cc",
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index 6825f1e..d94a4cb 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -95,6 +95,7 @@
   }
   public_configs = [
     ":protobuf_config",
+
     # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
     "//build/config/compiler:no_size_t_to_int_warning",
   ]
@@ -118,57 +119,57 @@
 
   sources = protobuf_lite_sources
   sources += [
-    "src/google/protobuf/descriptor.h",
-    "src/google/protobuf/descriptor.pb.h",
-    "src/google/protobuf/descriptor_database.h",
-    "src/google/protobuf/dynamic_message.h",
-    "src/google/protobuf/generated_enum_reflection.h",
-    "src/google/protobuf/generated_message_reflection.h",
-    "src/google/protobuf/message.h",
-    "src/google/protobuf/reflection_ops.h",
-    "src/google/protobuf/service.h",
-    "src/google/protobuf/text_format.h",
-    "src/google/protobuf/wire_format.h",
-    "src/google/protobuf/io/gzip_stream.h",
-    "src/google/protobuf/io/printer.h",
-    "src/google/protobuf/io/tokenizer.h",
-    "src/google/protobuf/io/zero_copy_stream_impl.h",
     "src/google/protobuf/compiler/code_generator.h",
     "src/google/protobuf/compiler/command_line_interface.h",
     "src/google/protobuf/compiler/importer.h",
     "src/google/protobuf/compiler/java/java_doc_comment.cc",
     "src/google/protobuf/compiler/java/java_doc_comment.h",
     "src/google/protobuf/compiler/parser.h",
-    "src/google/protobuf/stubs/strutil.cc",
-    "src/google/protobuf/stubs/strutil.h",
-    "src/google/protobuf/stubs/substitute.cc",
-    "src/google/protobuf/stubs/substitute.h",
+    "src/google/protobuf/descriptor.cc",
+    "src/google/protobuf/descriptor.h",
+    "src/google/protobuf/descriptor.pb.cc",
+    "src/google/protobuf/descriptor.pb.h",
+    "src/google/protobuf/descriptor_database.cc",
+    "src/google/protobuf/descriptor_database.h",
+    "src/google/protobuf/dynamic_message.cc",
+    "src/google/protobuf/dynamic_message.h",
+    "src/google/protobuf/extension_set_heavy.cc",
+    "src/google/protobuf/generated_enum_reflection.h",
+    "src/google/protobuf/generated_message_reflection.cc",
+    "src/google/protobuf/generated_message_reflection.h",
+    "src/google/protobuf/io/gzip_stream.h",
+    "src/google/protobuf/io/printer.h",
+    "src/google/protobuf/io/tokenizer.h",
+    "src/google/protobuf/io/zero_copy_stream_impl.h",
+    "src/google/protobuf/message.cc",
+    "src/google/protobuf/message.h",
+    "src/google/protobuf/reflection_ops.cc",
+    "src/google/protobuf/reflection_ops.h",
+    "src/google/protobuf/service.cc",
+    "src/google/protobuf/service.h",
     "src/google/protobuf/stubs/stl_util.h",
     "src/google/protobuf/stubs/stringprintf.cc",
     "src/google/protobuf/stubs/stringprintf.h",
     "src/google/protobuf/stubs/structurally_valid.cc",
+    "src/google/protobuf/stubs/strutil.cc",
+    "src/google/protobuf/stubs/strutil.h",
+    "src/google/protobuf/stubs/substitute.cc",
+    "src/google/protobuf/stubs/substitute.h",
     "src/google/protobuf/stubs/template_util.h",
     "src/google/protobuf/stubs/type_traits.h",
-    "src/google/protobuf/descriptor.cc",
-    "src/google/protobuf/descriptor.pb.cc",
-    "src/google/protobuf/descriptor_database.cc",
-    "src/google/protobuf/dynamic_message.cc",
-    "src/google/protobuf/extension_set_heavy.cc",
-    "src/google/protobuf/generated_message_reflection.cc",
-    "src/google/protobuf/message.cc",
-    "src/google/protobuf/reflection_ops.cc",
-    "src/google/protobuf/service.cc",
     "src/google/protobuf/text_format.cc",
+    "src/google/protobuf/text_format.h",
     "src/google/protobuf/wire_format.cc",
+    "src/google/protobuf/wire_format.h",
 
     # This file pulls in zlib, but it's not actually used by protoc, so
     # instead of compiling zlib for the host, let's just exclude this.
     # "src/src/google/protobuf/io/gzip_stream.cc",
+    "src/google/protobuf/compiler/importer.cc",
+    "src/google/protobuf/compiler/parser.cc",
     "src/google/protobuf/io/printer.cc",
     "src/google/protobuf/io/tokenizer.cc",
     "src/google/protobuf/io/zero_copy_stream_impl.cc",
-    "src/google/protobuf/compiler/importer.cc",
-    "src/google/protobuf/compiler/parser.cc",
   ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
@@ -178,6 +179,7 @@
   }
   public_configs = [
     ":protobuf_config",
+
     # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
     "//build/config/compiler:no_size_t_to_int_warning",
   ]
@@ -191,12 +193,6 @@
     sources = [
       "src/google/protobuf/compiler/code_generator.cc",
       "src/google/protobuf/compiler/command_line_interface.cc",
-      "src/google/protobuf/compiler/plugin.cc",
-      "src/google/protobuf/compiler/plugin.pb.cc",
-      "src/google/protobuf/compiler/subprocess.cc",
-      "src/google/protobuf/compiler/subprocess.h",
-      "src/google/protobuf/compiler/zip_writer.cc",
-      "src/google/protobuf/compiler/zip_writer.h",
       "src/google/protobuf/compiler/cpp/cpp_enum.cc",
       "src/google/protobuf/compiler/cpp/cpp_enum.h",
       "src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
@@ -243,8 +239,14 @@
       "src/google/protobuf/compiler/java/java_service.h",
       "src/google/protobuf/compiler/java/java_string_field.cc",
       "src/google/protobuf/compiler/java/java_string_field.h",
-      "src/google/protobuf/compiler/python/python_generator.cc",
       "src/google/protobuf/compiler/main.cc",
+      "src/google/protobuf/compiler/plugin.cc",
+      "src/google/protobuf/compiler/plugin.pb.cc",
+      "src/google/protobuf/compiler/python/python_generator.cc",
+      "src/google/protobuf/compiler/subprocess.cc",
+      "src/google/protobuf/compiler/subprocess.h",
+      "src/google/protobuf/compiler/zip_writer.cc",
+      "src/google/protobuf/compiler/zip_writer.h",
     ]
 
     configs -= [ "//build/config/compiler:chromium_code" ]
@@ -262,3 +264,68 @@
     deps += [ "//build/config/sanitizers:deps" ]
   }
 }
+
+copy("copy_google") {
+  sources = [
+    "__init__.py",
+  ]
+  outputs = [
+    "$root_gen_dir/google/{{source_file_part}}",
+  ]
+}
+
+copy("copy_google_protobuf") {
+  sources = [
+    "python/google/protobuf/__init__.py",
+    "python/google/protobuf/descriptor.py",
+    "python/google/protobuf/descriptor_database.py",
+    "python/google/protobuf/descriptor_pool.py",
+    "python/google/protobuf/message.py",
+    "python/google/protobuf/message_factory.py",
+    "python/google/protobuf/reflection.py",
+    "python/google/protobuf/service.py",
+    "python/google/protobuf/service_reflection.py",
+    "python/google/protobuf/text_format.py",
+
+    # TODO(ncarter): protoc"s python generator treats
+    # descriptor.proto specially, but it's not possible to trigger
+    # the special treatment unless you run protoc from ./src/src
+    # (the treatment is based on the path to the .proto file
+    # matching a constant exactly). I'm not sure how to convince
+    # gyp to execute a rule from a different directory.  Until this
+    # is resolved, use a copy of descriptor_pb2.py that I manually
+    # generated.
+    "descriptor_pb2.py",
+  ]
+  outputs = [
+    "$root_gen_dir/google/protobuf/{{source_file_part}}",
+  ]
+}
+
+copy("copy_google_protobuf_internal") {
+  sources = [
+    "python/google/protobuf/internal/__init__.py",
+    "python/google/protobuf/internal/api_implementation.py",
+    "python/google/protobuf/internal/containers.py",
+    "python/google/protobuf/internal/cpp_message.py",
+    "python/google/protobuf/internal/decoder.py",
+    "python/google/protobuf/internal/encoder.py",
+    "python/google/protobuf/internal/enum_type_wrapper.py",
+    "python/google/protobuf/internal/generator_test.py",
+    "python/google/protobuf/internal/message_listener.py",
+    "python/google/protobuf/internal/python_message.py",
+    "python/google/protobuf/internal/type_checkers.py",
+    "python/google/protobuf/internal/wire_format.py",
+  ]
+  outputs = [
+    "$root_gen_dir/google/protobuf/internal/{{source_file_part}}",
+  ]
+}
+
+group("py_proto") {
+  public_deps = [
+    ":copy_google",
+    ":copy_google_protobuf",
+    ":copy_google_protobuf_internal",
+  ]
+}
diff --git a/third_party/yasm/BUILD.gn b/third_party/yasm/BUILD.gn
index a09a495..9ed8e46 100644
--- a/third_party/yasm/BUILD.gn
+++ b/third_party/yasm/BUILD.gn
@@ -124,13 +124,13 @@
 
   executable("re2c") {
     sources = [
-      "source/patched-yasm/tools/re2c/main.c",
+      "source/patched-yasm/tools/re2c/actions.c",
       "source/patched-yasm/tools/re2c/code.c",
       "source/patched-yasm/tools/re2c/dfa.c",
-      "source/patched-yasm/tools/re2c/parser.c",
-      "source/patched-yasm/tools/re2c/actions.c",
-      "source/patched-yasm/tools/re2c/scanner.c",
+      "source/patched-yasm/tools/re2c/main.c",
       "source/patched-yasm/tools/re2c/mbo_getopt.c",
+      "source/patched-yasm/tools/re2c/parser.c",
+      "source/patched-yasm/tools/re2c/scanner.c",
       "source/patched-yasm/tools/re2c/substr.c",
       "source/patched-yasm/tools/re2c/translate.c",
     ]
@@ -203,8 +203,8 @@
       "source/patched-yasm/modules/objfmts/macho/macho-objfmt.c",
       "source/patched-yasm/modules/objfmts/rdf/rdf-objfmt.c",
       "source/patched-yasm/modules/objfmts/xdf/xdf-objfmt.c",
-      "source/patched-yasm/modules/parsers/gas/gas-parse.c",
       "source/patched-yasm/modules/parsers/gas/gas-parse-intel.c",
+      "source/patched-yasm/modules/parsers/gas/gas-parse.c",
       "source/patched-yasm/modules/parsers/gas/gas-parser.c",
       "source/patched-yasm/modules/parsers/nasm/nasm-parse.c",
       "source/patched-yasm/modules/parsers/nasm/nasm-parser.c",
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index 85cf086..2d221d7 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -315,6 +315,20 @@
     return true;
   }
 
+  bool VisitUnresolvedMemberExpr(UnresolvedMemberExpr* member) {
+    for (Decl* decl : member->decls()) {
+      if (CXXMethodDecl* method = dyn_cast<CXXMethodDecl>(decl)) {
+        if (method->getParent() == receiver_->record() &&
+            Config::GetTraceMethodType(method) ==
+            Config::TRACE_AFTER_DISPATCH_METHOD) {
+          dispatched_to_receiver_ = true;
+          return true;
+        }
+      }
+    }
+    return true;
+  }
+
  private:
   RecordInfo* receiver_;
   bool dispatched_to_receiver_;
@@ -325,8 +339,12 @@
 // - A base is traced if a base-qualified call to a trace method is found.
 class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
  public:
-  CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info)
-      : trace_(trace), info_(info), delegates_to_traceimpl_(false) {}
+  CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info, RecordCache* cache)
+      : trace_(trace),
+        info_(info),
+        cache_(cache),
+        delegates_to_traceimpl_(false) {
+  }
 
   bool delegates_to_traceimpl() const { return delegates_to_traceimpl_; }
 
@@ -370,17 +388,8 @@
       if (CheckTraceBaseCall(call))
         return true;
 
-      // If we find a call to registerWeakMembers which is unresolved we
-      // unsoundly consider all weak members as traced.
-      // TODO: Find out how to validate weak member tracing for unresolved call.
-      if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) {
-        for (RecordInfo::Fields::iterator it = info_->GetFields().begin();
-             it != info_->GetFields().end();
-             ++it) {
-          if (it->second.edge()->IsWeakMember())
-            it->second.MarkTraced();
-        }
-      }
+      if (expr->getMemberName().getAsString() == kRegisterWeakMembersName)
+        MarkAllWeakMembersTraced();
 
       QualType base = expr->getBaseType();
       if (!base->isPointerType())
@@ -408,6 +417,18 @@
   }
 
  private:
+  bool IsTraceCallName(const std::string& name) {
+    if (trace_->getName() == kTraceImplName)
+      return name == kTraceName;
+    if (trace_->getName() == kTraceAfterDispatchImplName)
+      return name == kTraceAfterDispatchName;
+    // Currently, a manually dispatched class cannot have mixin bases (having
+    // one would add a vtable which we explicitly check against). This means
+    // that we can only make calls to a trace method of the same name. Revisit
+    // this if our mixin/vtable assumption changes.
+    return name == trace_->getName();
+  }
+
   CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) {
     NestedNameSpecifier* qual = expr->getQualifier();
     if (!qual)
@@ -424,18 +445,23 @@
                                         CXXDependentScopeMemberExpr* expr) {
     string fn_name = expr->getMember().getAsString();
 
-    // Check for VisitorDispatcher::trace(field)
+    // Check for VisitorDispatcher::trace(field) and
+    // VisitorDispatcher::registerWeakMembers.
     if (!expr->isImplicitAccess()) {
       if (clang::DeclRefExpr* base_decl =
               clang::dyn_cast<clang::DeclRefExpr>(expr->getBase())) {
-        if (Config::IsVisitorDispatcherType(base_decl->getType()) &&
-            call->getNumArgs() == 1 && fn_name == kTraceName) {
-          FindFieldVisitor finder;
-          finder.TraverseStmt(call->getArg(0));
-          if (finder.field())
-            FoundField(finder.field());
+        if (Config::IsVisitorDispatcherType(base_decl->getType())) {
+          if (call->getNumArgs() == 1 && fn_name == kTraceName) {
+            FindFieldVisitor finder;
+            finder.TraverseStmt(call->getArg(0));
+            if (finder.field())
+              FoundField(finder.field());
 
-          return;
+            return;
+          } else if (call->getNumArgs() == 1 &&
+                     fn_name == kRegisterWeakMembersName) {
+            MarkAllWeakMembersTraced();
+          }
         }
       }
     }
@@ -445,13 +471,12 @@
       return;
 
     // Check for Super<T>::trace(visitor)
-    if (call->getNumArgs() == 1 && fn_name == trace_->getName()) {
+    if (call->getNumArgs() == 1 && IsTraceCallName(fn_name)) {
       RecordInfo::Bases::iterator it = info_->GetBases().begin();
       for (; it != info_->GetBases().end(); ++it) {
         if (it->first->getName() == tmpl->getName())
           it->second.MarkTraced();
       }
-      return;
     }
 
     // Check for TraceIfNeeded<T>::trace(visitor, &field)
@@ -524,29 +549,54 @@
       func_name = callee->getMemberName().getAsString();
     }
 
-    if (trace_->getName() == kTraceImplName) {
-      if (func_name != kTraceName)
-        return false;
-    } else if (trace_->getName() == kTraceAfterDispatchImplName) {
-      if (func_name != kTraceAfterDispatchName)
-        return false;
-    } else {
-      // Currently, a manually dispatched class cannot have mixin bases (having
-      // one would add a vtable which we explicitly check against). This means
-      // that we can only make calls to a trace method of the same name. Revisit
-      // this if our mixin/vtable assumption changes.
-      if (func_name != trace_->getName())
-        return false;
-    }
-
     if (!callee_record)
       return false;
-    RecordInfo::Bases::iterator iter = info_->GetBases().find(callee_record);
-    if (iter == info_->GetBases().end())
+
+    if (!IsTraceCallName(func_name))
       return false;
 
-    iter->second.MarkTraced();
-    return true;
+    for (auto& base : info_->GetBases()) {
+      // We want to deal with omitted trace() function in an intermediary
+      // class in the class hierarchy, e.g.:
+      //     class A : public GarbageCollected<A> { trace() { ... } };
+      //     class B : public A { /* No trace(); have nothing to trace. */ };
+      //     class C : public B { trace() { B::trace(visitor); } }
+      // where, B::trace() is actually A::trace(), and in some cases we get
+      // A as |callee_record| instead of B. We somehow need to mark B as
+      // traced if we find A::trace() call.
+      //
+      // To solve this, here we keep going up the class hierarchy as long as
+      // they are not required to have a trace method. The implementation is
+      // a simple DFS, where |base_records| represents the set of base classes
+      // we need to visit.
+
+      std::vector<CXXRecordDecl*> base_records;
+      base_records.push_back(base.first);
+
+      while (!base_records.empty()) {
+        CXXRecordDecl* base_record = base_records.back();
+        base_records.pop_back();
+
+        if (base_record == callee_record) {
+          // If we find a matching trace method, pretend the user has written
+          // a correct trace() method of the base; in the example above, we
+          // find A::trace() here and mark B as correctly traced.
+          base.second.MarkTraced();
+          return true;
+        }
+
+        if (RecordInfo* base_info = cache_->Lookup(base_record)) {
+          if (!base_info->RequiresTraceMethod()) {
+            // If this base class is not required to have a trace method, then
+            // the actual trace method may be defined in an ancestor.
+            for (auto& inner_base : base_info->GetBases())
+              base_records.push_back(inner_base.first);
+          }
+        }
+      }
+    }
+
+    return false;
   }
 
   bool CheckTraceFieldCall(CXXMemberCallExpr* call) {
@@ -609,7 +659,8 @@
   };
 
   // Nested checking for weak callbacks.
-  CheckTraceVisitor(RecordInfo* info) : trace_(0), info_(info) {}
+  CheckTraceVisitor(RecordInfo* info)
+      : trace_(nullptr), info_(info), cache_(nullptr) {}
 
   bool IsWeakCallback() { return !trace_; }
 
@@ -641,8 +692,19 @@
     }
   }
 
+  void MarkAllWeakMembersTraced() {
+    // If we find a call to registerWeakMembers which is unresolved we
+    // unsoundly consider all weak members as traced.
+    // TODO: Find out how to validate weak member tracing for unresolved call.
+    for (auto& field : info_->GetFields()) {
+      if (field.second.edge()->IsWeakMember())
+        field.second.MarkTraced();
+    }
+  }
+
   CXXMethodDecl* trace_;
   RecordInfo* info_;
+  RecordCache* cache_;
   bool delegates_to_traceimpl_;
 };
 
@@ -1069,7 +1131,8 @@
         CheckLeftMostDerived(info);
         CheckDispatch(info);
         if (CXXMethodDecl* newop = info->DeclaresNewOperator())
-          ReportClassOverridesNew(info, newop);
+          if (!Config::IsIgnoreAnnotated(newop))
+            ReportClassOverridesNew(info, newop);
         if (info->IsGCMixinInstance()) {
           // Require that declared GCMixin implementations
           // also provide a trace() override.
@@ -1365,7 +1428,8 @@
   // Determine what type of tracing method this is (dispatch or trace).
   void CheckTraceOrDispatchMethod(RecordInfo* parent, CXXMethodDecl* method) {
     Config::TraceMethodType trace_type = Config::GetTraceMethodType(method);
-    if (trace_type != Config::TRACE_METHOD ||
+    if (trace_type == Config::TRACE_AFTER_DISPATCH_METHOD ||
+        trace_type == Config::TRACE_AFTER_DISPATCH_IMPL_METHOD ||
         !parent->GetTraceDispatchMethod()) {
       CheckTraceMethod(parent, method, trace_type);
     }
@@ -1387,7 +1451,7 @@
       }
     }
 
-    CheckTraceVisitor visitor(trace, parent);
+    CheckTraceVisitor visitor(trace, parent, &cache_);
     visitor.TraverseCXXMethodDecl(trace);
 
     // Skip reporting if this trace method is a just delegate to
diff --git a/tools/clang/blink_gc_plugin/CMakeLists.txt b/tools/clang/blink_gc_plugin/CMakeLists.txt
index c511edf..7f1dee3 100644
--- a/tools/clang/blink_gc_plugin/CMakeLists.txt
+++ b/tools/clang/blink_gc_plugin/CMakeLists.txt
@@ -1,6 +1,6 @@
 # This line is read by update.sh and other scripts in tools/clang/scripts
 # Note: The spaces are significant.
-set(LIBRARYNAME BlinkGCPlugin_14)
+set(LIBRARYNAME BlinkGCPlugin)
 
 add_llvm_loadable_module("lib${LIBRARYNAME}"
                          BlinkGCPlugin.cpp
diff --git a/tools/clang/blink_gc_plugin/Config.h b/tools/clang/blink_gc_plugin/Config.h
index c2d39b7..02cbee9 100644
--- a/tools/clang/blink_gc_plugin/Config.h
+++ b/tools/clang/blink_gc_plugin/Config.h
@@ -236,7 +236,7 @@
     if (name == kTraceAfterDispatchName)
       return TRACE_AFTER_DISPATCH_METHOD;
     if (name == kTraceImplName)
-      return TRACE_AFTER_DISPATCH_METHOD;
+      return TRACE_IMPL_METHOD;
     if (name == kTraceAfterDispatchImplName)
       return TRACE_AFTER_DISPATCH_IMPL_METHOD;
 
diff --git a/tools/clang/blink_gc_plugin/Edge.h b/tools/clang/blink_gc_plugin/Edge.h
index d0b78b5..7659968 100644
--- a/tools/clang/blink_gc_plugin/Edge.h
+++ b/tools/clang/blink_gc_plugin/Edge.h
@@ -24,6 +24,7 @@
 // Bare-bones visitor.
 class EdgeVisitor {
  public:
+  virtual ~EdgeVisitor() {}
   virtual void VisitValue(Value*) {}
   virtual void VisitRawPtr(RawPtr*) {}
   virtual void VisitRefPtr(RefPtr*) {}
diff --git a/tools/clang/blink_gc_plugin/RecordInfo.cpp b/tools/clang/blink_gc_plugin/RecordInfo.cpp
index 0257415..bda33fa 100644
--- a/tools/clang/blink_gc_plugin/RecordInfo.cpp
+++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp
@@ -427,39 +427,50 @@
   if (Config::IsGCBase(name_))
     return;
   CXXMethodDecl* trace = nullptr;
+  CXXMethodDecl* trace_impl = nullptr;
   CXXMethodDecl* trace_after_dispatch = nullptr;
   bool has_adjust_and_mark = false;
   bool has_is_heap_object_alive = false;
-  for (CXXRecordDecl::method_iterator it = record_->method_begin();
-       it != record_->method_end();
-       ++it) {
-    switch (Config::GetTraceMethodType(*it)) {
+  for (Decl* decl : record_->decls()) {
+    CXXMethodDecl* method = dyn_cast<CXXMethodDecl>(decl);
+    if (!method) {
+      if (FunctionTemplateDecl* func_template =
+          dyn_cast<FunctionTemplateDecl>(decl))
+        method = dyn_cast<CXXMethodDecl>(func_template->getTemplatedDecl());
+    }
+    if (!method)
+      continue;
+
+    switch (Config::GetTraceMethodType(method)) {
       case Config::TRACE_METHOD:
-        trace = *it;
+        trace = method;
         break;
       case Config::TRACE_AFTER_DISPATCH_METHOD:
-        trace_after_dispatch = *it;
+        trace_after_dispatch = method;
         break;
       case Config::TRACE_IMPL_METHOD:
+        trace_impl = method;
+        break;
       case Config::TRACE_AFTER_DISPATCH_IMPL_METHOD:
         break;
       case Config::NOT_TRACE_METHOD:
-        if (it->getNameAsString() == kFinalizeName) {
-          finalize_dispatch_method_ = *it;
-        } else if (it->getNameAsString() == kAdjustAndMarkName) {
+        if (method->getNameAsString() == kFinalizeName) {
+          finalize_dispatch_method_ = method;
+        } else if (method->getNameAsString() == kAdjustAndMarkName) {
           has_adjust_and_mark = true;
-        } else if (it->getNameAsString() == kIsHeapObjectAliveName) {
+        } else if (method->getNameAsString() == kIsHeapObjectAliveName) {
           has_is_heap_object_alive = true;
         }
         break;
     }
   }
+
   // Record if class defines the two GCMixin methods.
   has_gc_mixin_methods_ =
       has_adjust_and_mark && has_is_heap_object_alive ? kTrue : kFalse;
   if (trace_after_dispatch) {
     trace_method_ = trace_after_dispatch;
-    trace_dispatch_method_ = trace;
+    trace_dispatch_method_ = trace_impl ? trace_impl : trace;
   } else {
     // TODO: Can we never have a dispatch method called trace without the same
     // class defining a traceAfterDispatch method?
diff --git a/tools/clang/blink_gc_plugin/RecordInfo.h b/tools/clang/blink_gc_plugin/RecordInfo.h
index 82fb604..da2f415 100644
--- a/tools/clang/blink_gc_plugin/RecordInfo.h
+++ b/tools/clang/blink_gc_plugin/RecordInfo.h
@@ -23,6 +23,7 @@
 class GraphPoint {
  public:
   GraphPoint() : traced_(false) {}
+  virtual ~GraphPoint() {}
   void MarkTraced() { traced_ = true; }
   bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); }
   virtual const TracingStatus NeedsTracing() = 0;
diff --git a/tools/clang/blink_gc_plugin/tests/heap/stubs.h b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
index 3220178..e8ff1b3 100644
--- a/tools/clang/blink_gc_plugin/tests/heap/stubs.h
+++ b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
@@ -220,7 +220,10 @@
 class InlinedGlobalMarkingVisitor
     : public VisitorHelper<InlinedGlobalMarkingVisitor> {
 public:
-     InlinedGlobalMarkingVisitor* operator->() { return this; }
+    InlinedGlobalMarkingVisitor* operator->() { return this; }
+
+    template<typename T, void (T::*method)(Visitor*)>
+    void registerWeakMembers(const T* obj);
 };
 
 class GarbageCollectedMixin {
diff --git a/tools/clang/blink_gc_plugin/tests/register_weak_members_template.cpp b/tools/clang/blink_gc_plugin/tests/register_weak_members_template.cpp
new file mode 100644
index 0000000..6742c22
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/register_weak_members_template.cpp
@@ -0,0 +1,7 @@
+// 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 "register_weak_members_template.h"
+
+// Nothing to define here.
diff --git a/tools/clang/blink_gc_plugin/tests/register_weak_members_template.h b/tools/clang/blink_gc_plugin/tests/register_weak_members_template.h
new file mode 100644
index 0000000..7d3905a
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/register_weak_members_template.h
@@ -0,0 +1,43 @@
+// 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 REGISTER_WEAK_MEMBERS_TEMPLATE_H_
+#define REGISTER_WEAK_MEMBERS_TEMPLATE_H_
+
+#include "heap/stubs.h"
+
+namespace blink {
+
+class X : public GarbageCollected<X> {
+ public:
+  void trace(Visitor* visitor) { traceImpl(visitor); }
+  void trace(InlinedGlobalMarkingVisitor visitor) { traceImpl(visitor); }
+
+ private:
+  template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor) {}
+};
+
+class HasUntracedWeakMembers : public GarbageCollected<HasUntracedWeakMembers> {
+ public:
+  void trace(Visitor* visitor) { traceImpl(visitor); }
+  void trace(InlinedGlobalMarkingVisitor visitor) { traceImpl(visitor); }
+
+  // Don't have to be defined for the purpose of this test.
+  void clearWeakMembers(Visitor* visitor);
+
+ private:
+  template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor) {
+    visitor->template registerWeakMembers<
+        HasUntracedWeakMembers,
+        &HasUntracedWeakMembers::clearWeakMembers>(this);
+  }
+
+  WeakMember<X> x_;
+};
+
+}
+
+#endif  // REGISTER_WEAK_MEMBERS_TEMPLATE_H_
diff --git a/tools/clang/blink_gc_plugin/tests/register_weak_members_template.txt b/tools/clang/blink_gc_plugin/tests/register_weak_members_template.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/register_weak_members_template.txt
@@ -0,0 +1 @@
+
diff --git a/tools/clang/blink_gc_plugin/tests/test.sh b/tools/clang/blink_gc_plugin/tests/test.sh
index 02c7477..95bb261 100755
--- a/tools/clang/blink_gc_plugin/tests/test.sh
+++ b/tools/clang/blink_gc_plugin/tests/test.sh
@@ -29,6 +29,7 @@
     flags="$(cat "${3}")"
   fi
   local output="$("${CLANG_PATH}" -c -Wno-c++11-extensions \
+      -Wno-inaccessible-base \
       -Xclang -load -Xclang "${PLUGIN_PATH}" \
       -Xclang -add-plugin -Xclang blink-gc-plugin ${flags} ${1} 2>&1)"
   local json="${input%cpp}graph.json"
diff --git a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.cpp b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.cpp
index 706624d..53a6855 100644
--- a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.cpp
+++ b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.cpp
@@ -6,9 +6,11 @@
 
 namespace blink {
 
-void TraceAfterDispatchInlinedBase::trace(Visitor* visitor) {
-  // Implement a simple form of manual dispatching, because BlinkGCPlugin gets
-  // angry if dispatching statements are missing.
+template <typename VisitorDispatcher>
+inline void TraceAfterDispatchInlinedBase::traceImpl(
+    VisitorDispatcher visitor) {
+  // Implement a simple form of manual dispatching, because BlinkGCPlugin
+  // checks if the tracing is dispatched to all derived classes.
   //
   // This function has to be implemented out-of-line, since we need to know the
   // definition of derived classes here.
@@ -21,6 +23,15 @@
 }
 
 void TraceAfterDispatchExternBase::trace(Visitor* visitor) {
+  traceImpl(visitor);
+}
+
+void TraceAfterDispatchExternBase::trace(InlinedGlobalMarkingVisitor visitor) {
+  traceImpl(visitor);
+}
+
+template <typename VisitorDispatcher>
+inline void TraceAfterDispatchExternBase::traceImpl(VisitorDispatcher visitor) {
   if (tag_ == DERIVED) {
     static_cast<TraceAfterDispatchExternDerived*>(this)->traceAfterDispatch(
         visitor);
@@ -33,6 +44,11 @@
   traceAfterDispatchImpl(visitor);
 }
 
+void TraceAfterDispatchExternBase::traceAfterDispatch(
+    InlinedGlobalMarkingVisitor visitor) {
+  traceAfterDispatchImpl(visitor);
+}
+
 template <typename VisitorDispatcher>
 inline void TraceAfterDispatchExternBase::traceAfterDispatchImpl(
     VisitorDispatcher visitor) {
@@ -43,6 +59,11 @@
   traceAfterDispatchImpl(visitor);
 }
 
+void TraceAfterDispatchExternDerived::traceAfterDispatch(
+    InlinedGlobalMarkingVisitor visitor) {
+  traceAfterDispatchImpl(visitor);
+}
+
 template <typename VisitorDispatcher>
 inline void TraceAfterDispatchExternDerived::traceAfterDispatchImpl(
     VisitorDispatcher visitor) {
diff --git a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.h b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.h
index e55c06e..fe25279 100644
--- a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.h
+++ b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl.h
@@ -23,12 +23,19 @@
  public:
   explicit TraceAfterDispatchInlinedBase(ClassTag tag) : tag_(tag) {}
 
-  void trace(Visitor* visitor);
+  void trace(Visitor* visitor) { traceImpl(visitor); }
+  void trace(InlinedGlobalMarkingVisitor visitor) { traceImpl(visitor); }
 
   void traceAfterDispatch(Visitor* visitor) { traceAfterDispatchImpl(visitor); }
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor) {
+    traceAfterDispatchImpl(visitor);
+  }
 
  private:
   template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor);
+
+  template <typename VisitorDispatcher>
   void traceAfterDispatchImpl(VisitorDispatcher visitor) {
     visitor->trace(x_base_);
   }
@@ -42,6 +49,9 @@
   TraceAfterDispatchInlinedDerived() : TraceAfterDispatchInlinedBase(DERIVED) {}
 
   void traceAfterDispatch(Visitor* visitor) { traceAfterDispatchImpl(visitor); }
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor) {
+    traceAfterDispatchImpl(visitor);
+  }
 
  private:
   template <typename VisitorDispatcher>
@@ -59,11 +69,16 @@
   explicit TraceAfterDispatchExternBase(ClassTag tag) : tag_(tag) {}
 
   void trace(Visitor* visitor);
+  void trace(InlinedGlobalMarkingVisitor visitor);
 
   void traceAfterDispatch(Visitor* visitor);
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor);
 
  private:
   template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor);
+
+  template <typename VisitorDispatcher>
   void traceAfterDispatchImpl(VisitorDispatcher visitor);
 
   ClassTag tag_;
@@ -75,6 +90,7 @@
   TraceAfterDispatchExternDerived() : TraceAfterDispatchExternBase(DERIVED) {}
 
   void traceAfterDispatch(Visitor* visitor);
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor);
 
  private:
   template <typename VisitorDispatcher>
diff --git a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.cpp b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.cpp
index 1ea1936..23798f7 100644
--- a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.cpp
+++ b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.cpp
@@ -6,24 +6,37 @@
 
 namespace blink {
 
-void TraceAfterDispatchInlinedBase::trace(Visitor* visitor) {
-  // Implement a simple form of manual dispatching, because BlinkGCPlugin gets
-  // angry if dispatching statements are missing.
+template <typename VisitorDispatcher>
+inline void TraceAfterDispatchInlinedBase::traceImpl(
+    VisitorDispatcher visitor) {
+  // Implement a simple form of manual dispatching, because BlinkGCPlugin
+  // checks if the tracing is dispatched to all derived classes.
   //
   // This function has to be implemented out-of-line, since we need to know the
   // definition of derived classes here.
   if (tag_ == DERIVED) {
-    static_cast<TraceAfterDispatchInlinedDerived*>(this)->traceAfterDispatch(
-        visitor);
+    // Missing dispatch call:
+    // static_cast<TraceAfterDispatchInlinedDerived*>(this)->traceAfterDispatch(
+    //     visitor);
   } else {
     traceAfterDispatch(visitor);
   }
 }
 
 void TraceAfterDispatchExternBase::trace(Visitor* visitor) {
+  traceImpl(visitor);
+}
+
+void TraceAfterDispatchExternBase::trace(InlinedGlobalMarkingVisitor visitor) {
+  traceImpl(visitor);
+}
+
+template <typename VisitorDispatcher>
+inline void TraceAfterDispatchExternBase::traceImpl(VisitorDispatcher visitor) {
   if (tag_ == DERIVED) {
-    static_cast<TraceAfterDispatchExternDerived*>(this)->traceAfterDispatch(
-        visitor);
+    // Missing dispatch call:
+    // static_cast<TraceAfterDispatchExternDerived*>(this)->traceAfterDispatch(
+    //     visitor);
   } else {
     traceAfterDispatch(visitor);
   }
@@ -33,6 +46,11 @@
   traceAfterDispatchImpl(visitor);
 }
 
+void TraceAfterDispatchExternBase::traceAfterDispatch(
+    InlinedGlobalMarkingVisitor visitor) {
+  traceAfterDispatchImpl(visitor);
+}
+
 template <typename VisitorDispatcher>
 inline void TraceAfterDispatchExternBase::traceAfterDispatchImpl(
     VisitorDispatcher visitor) {
@@ -43,6 +61,11 @@
   traceAfterDispatchImpl(visitor);
 }
 
+void TraceAfterDispatchExternDerived::traceAfterDispatch(
+    InlinedGlobalMarkingVisitor visitor) {
+  traceAfterDispatchImpl(visitor);
+}
+
 template <typename VisitorDispatcher>
 inline void TraceAfterDispatchExternDerived::traceAfterDispatchImpl(
     VisitorDispatcher visitor) {
diff --git a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.h b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.h
index 441ef32..b480e39 100644
--- a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.h
+++ b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.h
@@ -23,12 +23,19 @@
  public:
   explicit TraceAfterDispatchInlinedBase(ClassTag tag) : tag_(tag) {}
 
-  void trace(Visitor* visitor);
+  void trace(Visitor* visitor) { traceImpl(visitor); }
+  void trace(InlinedGlobalMarkingVisitor visitor) { traceImpl(visitor); }
 
   void traceAfterDispatch(Visitor* visitor) { traceAfterDispatchImpl(visitor); }
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor) {
+    traceAfterDispatchImpl(visitor);
+  }
 
  private:
   template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor);
+
+  template <typename VisitorDispatcher>
   void traceAfterDispatchImpl(VisitorDispatcher visitor) {
     // No trace call; should get a warning.
   }
@@ -42,6 +49,9 @@
   TraceAfterDispatchInlinedDerived() : TraceAfterDispatchInlinedBase(DERIVED) {}
 
   void traceAfterDispatch(Visitor* visitor) { traceAfterDispatchImpl(visitor); }
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor) {
+    traceAfterDispatchImpl(visitor);
+  }
 
  private:
   template <typename VisitorDispatcher>
@@ -58,11 +68,16 @@
   explicit TraceAfterDispatchExternBase(ClassTag tag) : tag_(tag) {}
 
   void trace(Visitor* visitor);
+  void trace(InlinedGlobalMarkingVisitor visitor);
 
   void traceAfterDispatch(Visitor* visitor);
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor);
 
  private:
   template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor);
+
+  template <typename VisitorDispatcher>
   void traceAfterDispatchImpl(VisitorDispatcher visitor);
 
   ClassTag tag_;
@@ -74,6 +89,7 @@
   TraceAfterDispatchExternDerived() : TraceAfterDispatchExternBase(DERIVED) {}
 
   void traceAfterDispatch(Visitor* visitor);
+  void traceAfterDispatch(InlinedGlobalMarkingVisitor visitor);
 
  private:
   template <typename VisitorDispatcher>
diff --git a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.txt b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.txt
index 68b5a72..058fccb 100644
--- a/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.txt
+++ b/tools/clang/blink_gc_plugin/tests/trace_after_dispatch_impl_error.txt
@@ -1,28 +1,34 @@
+trace_after_dispatch_impl_error.cpp:10:1: warning: [blink-gc] Missing dispatch to class 'TraceAfterDispatchInlinedDerived' in manual trace dispatch.
+inline void TraceAfterDispatchInlinedBase::traceImpl(
+^
+trace_after_dispatch_impl_error.cpp:35:1: warning: [blink-gc] Missing dispatch to class 'TraceAfterDispatchExternDerived' in manual trace dispatch.
+inline void TraceAfterDispatchExternBase::traceImpl(VisitorDispatcher visitor) {
+^
 In file included from trace_after_dispatch_impl_error.cpp:5:
-./trace_after_dispatch_impl_error.h:32:3: warning: [blink-gc] Class 'TraceAfterDispatchInlinedBase' has untraced fields that require tracing.
+./trace_after_dispatch_impl_error.h:39:3: warning: [blink-gc] Class 'TraceAfterDispatchInlinedBase' has untraced fields that require tracing.
   void traceAfterDispatchImpl(VisitorDispatcher visitor) {
   ^
-./trace_after_dispatch_impl_error.h:37:3: note: [blink-gc] Untraced field 'x_base_' declared here:
+./trace_after_dispatch_impl_error.h:44:3: note: [blink-gc] Untraced field 'x_base_' declared here:
   Member<X> x_base_;
   ^
-./trace_after_dispatch_impl_error.h:48:3: warning: [blink-gc] Base class 'TraceAfterDispatchInlinedBase' of derived class 'TraceAfterDispatchInlinedDerived' requires tracing.
+./trace_after_dispatch_impl_error.h:58:3: warning: [blink-gc] Base class 'TraceAfterDispatchInlinedBase' of derived class 'TraceAfterDispatchInlinedDerived' requires tracing.
   void traceAfterDispatchImpl(VisitorDispatcher visitor) {
   ^
-./trace_after_dispatch_impl_error.h:48:3: warning: [blink-gc] Class 'TraceAfterDispatchInlinedDerived' has untraced fields that require tracing.
-./trace_after_dispatch_impl_error.h:52:3: note: [blink-gc] Untraced field 'x_derived_' declared here:
+./trace_after_dispatch_impl_error.h:58:3: warning: [blink-gc] Class 'TraceAfterDispatchInlinedDerived' has untraced fields that require tracing.
+./trace_after_dispatch_impl_error.h:62:3: note: [blink-gc] Untraced field 'x_derived_' declared here:
   Member<X> x_derived_;
   ^
-trace_after_dispatch_impl_error.cpp:37:1: warning: [blink-gc] Class 'TraceAfterDispatchExternBase' has untraced fields that require tracing.
+trace_after_dispatch_impl_error.cpp:55:1: warning: [blink-gc] Class 'TraceAfterDispatchExternBase' has untraced fields that require tracing.
 inline void TraceAfterDispatchExternBase::traceAfterDispatchImpl(
 ^
-./trace_after_dispatch_impl_error.h:69:3: note: [blink-gc] Untraced field 'x_base_' declared here:
+./trace_after_dispatch_impl_error.h:84:3: note: [blink-gc] Untraced field 'x_base_' declared here:
   Member<X> x_base_;
   ^
-trace_after_dispatch_impl_error.cpp:47:1: warning: [blink-gc] Base class 'TraceAfterDispatchExternBase' of derived class 'TraceAfterDispatchExternDerived' requires tracing.
+trace_after_dispatch_impl_error.cpp:70:1: warning: [blink-gc] Base class 'TraceAfterDispatchExternBase' of derived class 'TraceAfterDispatchExternDerived' requires tracing.
 inline void TraceAfterDispatchExternDerived::traceAfterDispatchImpl(
 ^
-trace_after_dispatch_impl_error.cpp:47:1: warning: [blink-gc] Class 'TraceAfterDispatchExternDerived' has untraced fields that require tracing.
-./trace_after_dispatch_impl_error.h:82:3: note: [blink-gc] Untraced field 'x_derived_' declared here:
+trace_after_dispatch_impl_error.cpp:70:1: warning: [blink-gc] Class 'TraceAfterDispatchExternDerived' has untraced fields that require tracing.
+./trace_after_dispatch_impl_error.h:98:3: note: [blink-gc] Untraced field 'x_derived_' declared here:
   Member<X> x_derived_;
   ^
-6 warnings generated.
+8 warnings generated.
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.cpp b/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.cpp
new file mode 100644
index 0000000..11b576c
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.cpp
@@ -0,0 +1,13 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "traceimpl_dependent_scope.h"
+
+namespace blink {
+
+// Template instantiation.
+template class Derived<int>;
+template class DerivedMissingTrace<int>;
+
+}
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.h b/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.h
new file mode 100644
index 0000000..0d079f6
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.h
@@ -0,0 +1,62 @@
+// 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 TRACEIMPL_DEPENDENT_SCOPE_H_
+#define TRACEIMPL_DEPENDENT_SCOPE_H_
+
+#include "heap/stubs.h"
+
+namespace blink {
+
+class X : public GarbageCollected<X> {
+ public:
+  virtual void trace(Visitor*) {}
+};
+
+template <typename T>
+class Base : public GarbageCollected<Base<T> > {
+ public:
+  virtual void trace(Visitor* visitor) { traceImpl(visitor); }
+  virtual void trace(InlinedGlobalMarkingVisitor visitor) {
+    traceImpl(visitor);
+  }
+
+ private:
+  template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor) {}
+};
+
+template <typename T>
+class Derived : public Base<T> {
+ public:
+  void trace(Visitor* visitor) override { traceImpl(visitor); }
+  void trace(InlinedGlobalMarkingVisitor visitor) override {
+    traceImpl(visitor);
+  }
+
+ private:
+  template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor) {
+    Base<T>::trace(visitor);
+  }
+};
+
+template <typename T>
+class DerivedMissingTrace : public Base<T> {
+ public:
+  void trace(Visitor* visitor) override { traceImpl(visitor); }
+  void trace(InlinedGlobalMarkingVisitor visitor) override {
+    traceImpl(visitor);
+  }
+
+ private:
+  template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor) {
+    // Missing Base<T>::trace(visitor).
+  }
+};
+
+}
+
+#endif  // TRACEIMPL_DEPENDENT_SCOPE_H_
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.txt b/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.txt
new file mode 100644
index 0000000..e1aab33
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_dependent_scope.txt
@@ -0,0 +1,5 @@
+In file included from traceimpl_dependent_scope.cpp:5:
+./traceimpl_dependent_scope.h:55:3: warning: [blink-gc] Base class 'Base<int>' of derived class 'DerivedMissingTrace<int>' requires tracing.
+  void traceImpl(VisitorDispatcher visitor) {
+  ^
+1 warning generated.
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.cpp b/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.cpp
new file mode 100644
index 0000000..b6dc2df
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.cpp
@@ -0,0 +1,7 @@
+// 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 "traceimpl_omitted_trace.h"
+
+// Nothing to define here.
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.h b/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.h
new file mode 100644
index 0000000..3c5e955
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.h
@@ -0,0 +1,47 @@
+// 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 TRACEIMPL_OMITTED_TRACE_H_
+#define TRACEIMPL_OMITTED_TRACE_H_
+
+#include "heap/stubs.h"
+
+namespace blink {
+
+class A : public GarbageCollected<A> {
+ public:
+  virtual void trace(Visitor* visitor) { traceImpl(visitor); }
+  virtual void trace(InlinedGlobalMarkingVisitor visitor) {
+    traceImpl(visitor);
+  }
+
+ private:
+  template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor) {}
+};
+
+class B : public A {
+  // trace() isn't necessary because we've got nothing to trace here.
+};
+
+class C : public B {
+ public:
+  void trace(Visitor* visitor) override { traceImpl(visitor); }
+  void trace(InlinedGlobalMarkingVisitor visitor) override {
+    traceImpl(visitor);
+  }
+
+ private:
+  template <typename VisitorDispatcher>
+  void traceImpl(VisitorDispatcher visitor) {
+    // B::trace() is actually A::trace(), and in certain cases we only get
+    // limited information like "there is a function call that will be resolved
+    // to A::trace()". We still want to mark B as traced.
+    B::trace(visitor);
+  }
+};
+
+}
+
+#endif  // TRACEIMPL_OMITTED_TRACE_H_
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.txt b/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_omitted_trace.txt
@@ -0,0 +1 @@
+
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index 9cbc84a..48d6a73 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -149,7 +149,10 @@
   banned_directories_.push_back("/courgette/");
   banned_directories_.push_back("/pdf/");
   banned_directories_.push_back("/ppapi/");
-  banned_directories_.push_back("/usr/");
+  banned_directories_.push_back("/usr/include/");
+  banned_directories_.push_back("/usr/lib/");
+  banned_directories_.push_back("/usr/local/include/");
+  banned_directories_.push_back("/usr/local/lib/");
   banned_directories_.push_back("/testing/");
   banned_directories_.push_back("/v8/");
   banned_directories_.push_back("/dart/");
@@ -263,11 +266,6 @@
     filename = resolvedPath;
   }
 
-  // On linux, chrome is often checked out to /usr/local/google. Due to the
-  // "usr" rule in banned_directories_, all diagnostics would be suppressed
-  // in that case. As a workaround, strip that prefix.
-  filename = lstrip(filename, "/usr/local/google");
-
   for (size_t i = 0; i < banned_directories_.size(); ++i) {
     // If any of the banned directories occur as a component in filename,
     // this file is rejected.
diff --git a/tools/clang/scripts/blink_gc_plugin_flags.sh b/tools/clang/scripts/blink_gc_plugin_flags.sh
index 3654808..38ea72d 100755
--- a/tools/clang/scripts/blink_gc_plugin_flags.sh
+++ b/tools/clang/scripts/blink_gc_plugin_flags.sh
@@ -13,9 +13,6 @@
 else
   LIBSUFFIX=so
 fi
-LIBNAME=\
-$(grep 'set(LIBRARYNAME' "$SRC_DIR"/tools/clang/blink_gc_plugin/CMakeLists.txt \
-    | cut -d ' ' -f 2 | tr -d ')')
 
 FLAGS=""
 PREFIX="-Xclang -plugin-arg-blink-gc-plugin -Xclang"
@@ -31,5 +28,5 @@
   fi
 done
 
-echo -Xclang -load -Xclang $CLANG_LIB_PATH/lib$LIBNAME.$LIBSUFFIX \
+echo -Xclang -load -Xclang $CLANG_LIB_PATH/libBlinkGCPlugin.$LIBSUFFIX \
   -Xclang -add-plugin -Xclang blink-gc-plugin $FLAGS
diff --git a/tools/clang/scripts/package.sh b/tools/clang/scripts/package.sh
index e0c0fcc..25cd6f0 100755
--- a/tools/clang/scripts/package.sh
+++ b/tools/clang/scripts/package.sh
@@ -52,6 +52,7 @@
 LLVM_BUILD_DIR="${THIS_DIR}/../../../third_party/llvm-build"
 LLVM_BIN_DIR="${LLVM_BUILD_DIR}/Release+Asserts/bin"
 LLVM_LIB_DIR="${LLVM_BUILD_DIR}/Release+Asserts/lib"
+STAMP_FILE="${LLVM_DIR}/../llvm-build/cr_build_revision"
 
 echo "Diff in llvm:" | tee buildlog.txt
 svn stat "${LLVM_DIR}" 2>&1 | tee -a buildlog.txt
@@ -86,8 +87,7 @@
 "${THIS_DIR}"/update.sh --bootstrap --force-local-build --run-tests \
     ${extra_flags} 2>&1 | tee -a buildlog.txt
 
-R=$("${LLVM_BIN_DIR}/clang" --version | \
-     sed -ne 's/clang version .*(trunk \([0-9]*\))/\1/p')
+R=$(cat "${STAMP_FILE}")
 
 PDIR=clang-$R
 rm -rf $PDIR
@@ -95,6 +95,11 @@
 mkdir $PDIR/bin
 mkdir $PDIR/lib
 
+GOLDDIR=llvmgold-$R
+if [ "$(uname -s)" = "Linux" ]; then
+  mkdir -p $GOLDDIR/lib
+fi
+
 if [ "$(uname -s)" = "Darwin" ]; then
   SO_EXT="dylib"
 else
@@ -122,11 +127,12 @@
 # Copy plugins. Some of the dylibs are pretty big, so copy only the ones we
 # care about.
 cp "${LLVM_LIB_DIR}/libFindBadConstructs.${SO_EXT}" $PDIR/lib
+cp "${LLVM_LIB_DIR}/libBlinkGCPlugin.${SO_EXT}" $PDIR/lib
 
-BLINKGCPLUGIN_LIBNAME=\
-$(grep 'set(LIBRARYNAME' "$THIS_DIR"/../blink_gc_plugin/CMakeLists.txt \
-    | cut -d ' ' -f 2 | tr -d ')')
-cp "${LLVM_LIB_DIR}/lib${BLINKGCPLUGIN_LIBNAME}.${SO_EXT}" $PDIR/lib
+# Copy gold plugin on Linux.
+if [ "$(uname -s)" = "Linux" ]; then
+  cp "${LLVM_LIB_DIR}/LLVMgold.${SO_EXT}" $GOLDDIR/lib
+fi
 
 if [[ -n "${gcc_toolchain}" ]]; then
   # Copy the stdlibc++.so.6 we linked Clang against so it can run.
@@ -173,6 +179,10 @@
   tar zcf $PDIR.tgz -C $PDIR bin lib buildlog.txt
 fi
 
+if [ "$(uname -s)" = "Linux" ]; then
+  tar zcf $GOLDDIR.tgz -C $GOLDDIR lib
+fi
+
 if [ "$(uname -s)" = "Darwin" ]; then
   PLATFORM=Mac
 else
@@ -182,3 +192,9 @@
 echo To upload, run:
 echo gsutil cp -a public-read $PDIR.tgz \
      gs://chromium-browser-clang/$PLATFORM/$PDIR.tgz
+if [ "$(uname -s)" = "Linux" ]; then
+  echo gsutil cp -a public-read $GOLDDIR.tgz \
+       gs://chromium-browser-clang/$PLATFORM/$GOLDDIR.tgz
+fi
+
+# FIXME: Warn if the file already exists on the server.
diff --git a/tools/clang/scripts/plugin_flags.py b/tools/clang/scripts/plugin_flags.py
new file mode 100755
index 0000000..3f61d6b
--- /dev/null
+++ b/tools/clang/scripts/plugin_flags.py
@@ -0,0 +1,29 @@
+#!/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.
+
+# This script returns the flags that should be used when GYP_DEFINES contains
+# clang_use_chrome_plugins. The flags are stored in a script so that they can
+# be changed on the bots without requiring a master restart.
+
+import os
+import sys
+
+# Path constants. (All of these should be absolute paths.)
+THIS_DIR = os.path.abspath(os.path.dirname(__file__))
+CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
+CLANG_LIB_PATH = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build',
+                              'Release+Asserts', 'lib')
+
+if sys.platform == 'darwin':
+  LIBSUFFIX = 'dylib'
+else:
+  LIBSUFFIX = 'so'
+
+LIB_PATH = os.path.join(
+    CLANG_LIB_PATH,
+    'libFindBadConstructs.' + LIBSUFFIX)
+
+print ('-Xclang -load -Xclang %s'
+       ' -Xclang -add-plugin -Xclang find-bad-constructs') % LIB_PATH
diff --git a/tools/clang/scripts/plugin_flags.sh b/tools/clang/scripts/plugin_flags.sh
deleted file mode 100755
index 81fe0f1..0000000
--- a/tools/clang/scripts/plugin_flags.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env bash
-# 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.
-
-# This script returns the flags that should be used when GYP_DEFINES contains
-# clang_use_chrome_plugins. The flags are stored in a script so that they can
-# be changed on the bots without requiring a master restart.
-
-SRC_ABS_DIR=$(cd $(dirname $0)/../../.. && echo $PWD)
-CLANG_LIB_PATH=$SRC_ABS_DIR/third_party/llvm-build/Release+Asserts/lib
-
-if uname -s | grep -q Darwin; then
-  LIBSUFFIX=dylib
-else
-  LIBSUFFIX=so
-fi
-
-echo -Xclang -load -Xclang $CLANG_LIB_PATH/libFindBadConstructs.$LIBSUFFIX \
-  -Xclang -add-plugin -Xclang find-bad-constructs \
-  -Xclang -plugin-arg-find-bad-constructs -Xclang check-weak-ptr-factory-order \
-  -Xclang -plugin-arg-find-bad-constructs -Xclang strict-virtual-specifiers
diff --git a/tools/clang/scripts/repackage.sh b/tools/clang/scripts/repackage.sh
deleted file mode 100755
index e19ab7e..0000000
--- a/tools/clang/scripts/repackage.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script will check out llvm and clang, build a full package
-# with the latest plugin revisions and then repackage an existing
-# clang-package with the new plugin revisions.
-
-# The new package can be uploaded to replace the existing clang
-# package at the same clang revision.
-
-THIS_DIR="$(dirname "${0}")"
-LLVM_BUILD_DIR="${THIS_DIR}/../../../third_party/llvm-build"
-LLVM_TAR_DIR="${LLVM_BUILD_DIR}/Release+Asserts"
-LLVM_BIN_DIR="${LLVM_TAR_DIR}/bin"
-LLVM_LIB_DIR="${LLVM_TAR_DIR}/lib"
-
-set -eu
-
-if [ "$(uname -s)" = "Darwin" ]; then
-  PLATFORM=Mac
-  SO_EXT="dylib"
-else
-  PLATFORM=Linux_x64
-  SO_EXT="so"
-fi
-
-# Build clang with the new plugin revisions.
-"$THIS_DIR"/package.sh $@
-
-R=$("${LLVM_BIN_DIR}/clang" --version | \
-     sed -ne 's/clang version .*(trunk \([0-9]*\))/\1/p')
-PDIR=clang-$R
-
-if [ ! -f "$PDIR.tgz" ]; then
-    echo "Could not find package archive $PDIR.tgz generated by package.sh"
-    exit 1
-fi
-
-# We don't want to change the clang binary, so fetch the current clang
-# package and add the plugin shared-libraries to the existing package.
-rm -rf $LLVM_BUILD_DIR
-"$THIS_DIR"/update.sh
-
-LIBNAME=\
-$(grep 'set(LIBRARYNAME' "$THIS_DIR"/../blink_gc_plugin/CMakeLists.txt \
-    | cut -d ' ' -f 2 | tr -d ')')
-LIBFILE=lib$LIBNAME.$SO_EXT
-
-# Check that we are actually creating the plugin at a new revision.
-if [ -f "$LLVM_LIB_DIR/$LIBFILE" ]; then
-    echo "The plugin revision $LIBNAME is already in the existing package."
-    exit 1
-fi
-
-cp $PDIR/lib/$LIBFILE "$LLVM_LIB_DIR/"
-if [ "$(uname -s)" = "Darwin" ]; then
-  tar zcf ${PDIR}_repack.tgz -C "$LLVM_TAR_DIR" bin include lib buildlog.txt
-else
-  tar zcf ${PDIR}_repack.tgz -C "$LLVM_TAR_DIR" bin lib buildlog.txt
-fi
-
-echo The clang package has been repackaged with $LIBNAME
-echo To upload, run:
-echo gsutil cp -a public-read ${PDIR}_repack.tgz \
-     gs://chromium-browser-clang/$PLATFORM/$PDIR.tgz
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 6e55d0c..cb0878d 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -24,7 +24,7 @@
 # in bringup. Use a pinned revision to make it slightly more stable.
 if (re.search(r'\b(asan)=1', os.environ.get('GYP_DEFINES', '')) and
     not 'LLVM_FORCE_HEAD_REVISION' in os.environ):
-  LLVM_WIN_REVISION = '228702'
+  LLVM_WIN_REVISION = '229860'
 
 # Path constants. (All of these should be absolute paths.)
 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index 7c60472..ae90743 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -8,7 +8,12 @@
 # Do NOT CHANGE this if you don't know what you're doing -- see
 # https://code.google.com/p/chromium/wiki/UpdatingClang
 # Reverting problematic clang rolls is safe, though.
-CLANG_REVISION=223108
+CLANG_REVISION=231191
+
+# This is incremented when pushing a new build of Clang at the same revision.
+CLANG_SUB_REVISION=1
+
+PACKAGE_VERSION="${CLANG_REVISION}-${CLANG_SUB_REVISION}"
 
 THIS_DIR="$(dirname "${0}")"
 LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
@@ -23,6 +28,7 @@
 ANDROID_NDK_DIR="${THIS_DIR}/../../../third_party/android_tools/ndk"
 STAMP_FILE="${LLVM_DIR}/../llvm-build/cr_build_revision"
 CHROMIUM_TOOLS_DIR="${THIS_DIR}/.."
+BINUTILS_DIR="${THIS_DIR}/../../../third_party/binutils"
 
 ABS_CHROMIUM_TOOLS_DIR="${PWD}/${CHROMIUM_TOOLS_DIR}"
 ABS_LIBCXX_DIR="${PWD}/${LIBCXX_DIR}"
@@ -30,10 +36,13 @@
 ABS_LLVM_DIR="${PWD}/${LLVM_DIR}"
 ABS_LLVM_BUILD_DIR="${PWD}/${LLVM_BUILD_DIR}"
 ABS_COMPILER_RT_DIR="${PWD}/${COMPILER_RT_DIR}"
+ABS_BINUTILS_DIR="${PWD}/${BINUTILS_DIR}"
 
 # ${A:-a} returns $A if it's set, a else.
 LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
 
+CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang
+
 if [[ -z "$GYP_DEFINES" ]]; then
   GYP_DEFINES=
 fi
@@ -51,6 +60,7 @@
   # --print-revision, stamp file logic, etc. all works naturally.
   CLANG_REVISION=$(svn info "$LLVM_REPO_URL" \
       | grep 'Last Changed Rev' | awk '{ printf $4; }')
+  PACKAGE_VERSION="${CLANG_REVISION}-0"
 fi
 
 # Use both the clang revision and the plugin revisions to test for updates.
@@ -88,7 +98,7 @@
       force_local_build=yes
       ;;
     --print-revision)
-      echo $CLANG_REVISION
+      echo $PACKAGE_VERSION
       exit 0
       ;;
     --run-tests)
@@ -161,6 +171,40 @@
     with_android=
   fi
 
+  LLVM_BUILD_TOOLS_DIR="${ABS_LLVM_DIR}/../llvm-build-tools"
+
+  if [[ "${OS}" == "Linux" ]] && [[ -z "${gcc_toolchain}" ]]; then
+    if [[ $(gcc -dumpversion) < "4.7.0" ]]; then
+      # We need a newer GCC version.
+      if [[ ! -e "${LLVM_BUILD_TOOLS_DIR}/gcc482" ]]; then
+        echo "Downloading pre-built GCC 4.8.2..."
+        mkdir -p "${LLVM_BUILD_TOOLS_DIR}"
+        curl --fail -L "${CDS_URL}/tools/gcc482.tgz" | \
+          tar zxf - -C "${LLVM_BUILD_TOOLS_DIR}"
+        echo Done
+      fi
+      gcc_toolchain="${LLVM_BUILD_TOOLS_DIR}/gcc482"
+    else
+      # Always set gcc_toolchain; llvm-symbolizer needs the bundled libstdc++.
+      gcc_toolchain="$(dirname $(dirname $(which gcc)))"
+    fi
+  fi
+
+  if [[ "${OS}" == "Linux" ]]; then
+    # TODO(hans): Might need to make this work on Mac eventually.
+    if [[ $(cmake --version | grep -Eo '[0-9.]+') < "3.0" ]]; then
+      # We need a newer CMake version.
+      if [[ ! -e "${LLVM_BUILD_TOOLS_DIR}/cmake310" ]]; then
+        echo "Downloading pre-built CMake 3.10..."
+        mkdir -p "${LLVM_BUILD_TOOLS_DIR}"
+        curl --fail -L "${CDS_URL}/tools/cmake310.tgz" | \
+          tar zxf - -C "${LLVM_BUILD_TOOLS_DIR}"
+        echo Done
+      fi
+      export PATH="${LLVM_BUILD_TOOLS_DIR}/cmake310/bin:${PATH}"
+    fi
+  fi
+
   echo "LLVM_FORCE_HEAD_REVISION was set; using r${CLANG_REVISION}"
 fi
 
@@ -193,8 +237,8 @@
   PREVIOUSLY_BUILT_REVISON=$(cat "${STAMP_FILE}")
   if [[ -z "$force_local_build" ]] && \
        [[ "${PREVIOUSLY_BUILT_REVISON}" = \
-          "${CLANG_AND_PLUGINS_REVISION}" ]]; then
-    echo "Clang already at ${CLANG_AND_PLUGINS_REVISION}"
+          "${PACKAGE_VERSION}" ]]; then
+    echo "Clang already at ${PACKAGE_VERSION}"
     exit 0
   fi
 fi
@@ -205,8 +249,7 @@
 if [[ -z "$force_local_build" ]]; then
   # Check if there's a prebuilt binary and if so just fetch that. That's faster,
   # and goma relies on having matching binary hashes on client and server too.
-  CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang
-  CDS_FILE="clang-${CLANG_REVISION}.tgz"
+  CDS_FILE="clang-${PACKAGE_VERSION}.tgz"
   CDS_OUT_DIR=$(mktemp -d -t clang_download.XXXXXX)
   CDS_OUTPUT="${CDS_OUT_DIR}/${CDS_FILE}"
   if [ "${OS}" = "Linux" ]; then
@@ -228,12 +271,12 @@
     rm -rf "${LLVM_BUILD_DIR}"
     mkdir -p "${LLVM_BUILD_DIR}"
     tar -xzf "${CDS_OUTPUT}" -C "${LLVM_BUILD_DIR}"
-    echo clang "${CLANG_REVISION}" unpacked
-    echo "${CLANG_AND_PLUGINS_REVISION}" > "${STAMP_FILE}"
+    echo clang "${PACKAGE_VERSION}" unpacked
+    echo "${PACKAGE_VERSION}" > "${STAMP_FILE}"
     rm -rf "${CDS_OUT_DIR}"
     exit 0
   else
-    echo Did not find prebuilt clang at r"${CLANG_REVISION}", building
+    echo Did not find prebuilt clang "${PACKAGE_VERSION}", building
   fi
 fi
 
@@ -277,6 +320,8 @@
       "${CLANG_DIR}/lib/Sema/SemaExprCXX.cpp" \
       "${CLANG_DIR}/test/SemaCXX/default2.cpp" \
       "${CLANG_DIR}/test/SemaCXX/typo-correction-delayed.cpp" \
+      "${COMPILER_RT_DIR}/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc" \
+      "${COMPILER_RT_DIR}/test/tsan/signal_segv_handler.cc" \
       ; do
   if [[ -e "${i}" ]]; then
     rm -f "${i}"  # For unversioned files.
@@ -359,349 +404,6 @@
   patch -p0
   popd
 
-  # Apply r223211: "Revert r222997."
-  pushd "${LLVM_DIR}"
-  cat << 'EOF' |
---- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp
-+++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp
-@@ -921,8 +921,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
-             Value *OriginPtr =
-                 getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset);
-             setOrigin(A, EntryIRB.CreateLoad(OriginPtr));
--          } else {
--            setOrigin(A, getCleanOrigin());
-           }
-         }
-         ArgOffset += RoundUpToAlignment(Size, kShadowTLSAlignment);
-@@ -942,13 +940,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
-   /// \brief Get the origin for a value.
-   Value *getOrigin(Value *V) {
-     if (!MS.TrackOrigins) return nullptr;
--    if (!PropagateShadow) return getCleanOrigin();
--    if (isa<Constant>(V)) return getCleanOrigin();
--    assert((isa<Instruction>(V) || isa<Argument>(V)) &&
--           "Unexpected value type in getOrigin()");
--    Value *Origin = OriginMap[V];
--    assert(Origin && "Missing origin");
--    return Origin;
-+    if (isa<Instruction>(V) || isa<Argument>(V)) {
-+      Value *Origin = OriginMap[V];
-+      if (!Origin) {
-+        DEBUG(dbgs() << "NO ORIGIN: " << *V << "\n");
-+        Origin = getCleanOrigin();
-+      }
-+      return Origin;
-+    }
-+    return getCleanOrigin();
-   }
- 
-   /// \brief Get the origin for i-th argument of the instruction I.
-@@ -1088,7 +1088,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
-     IRB.CreateStore(getCleanShadow(&I), ShadowPtr);
- 
-     setShadow(&I, getCleanShadow(&I));
--    setOrigin(&I, getCleanOrigin());
-   }
- 
-   void visitAtomicRMWInst(AtomicRMWInst &I) {
-EOF
-  patch -p1
-  popd
-
-  # Apply r223219: "Preserve LD_LIBRARY_PATH when using the 'env' command"
-  pushd "${CLANG_DIR}"
-  cat << 'EOF' |
---- a/test/Driver/env.c
-+++ b/test/Driver/env.c
-@@ -5,12 +5,14 @@
- // REQUIRES: shell
- //
- // The PATH variable is heavily used when trying to find a linker.
--// RUN: env -i LC_ALL=C %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-+// RUN: env -i LC_ALL=C LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
-+// RUN:   %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
- // RUN:     --target=i386-unknown-linux \
- // RUN:     --sysroot=%S/Inputs/basic_linux_tree \
- // RUN:   | FileCheck --check-prefix=CHECK-LD-32 %s
- //
--// RUN: env -i LC_ALL=C PATH="" %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-+// RUN: env -i LC_ALL=C PATH="" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
-+// RUN:   %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
- // RUN:     --target=i386-unknown-linux \
- // RUN:     --sysroot=%S/Inputs/basic_linux_tree \
- // RUN:   | FileCheck --check-prefix=CHECK-LD-32 %s
-EOF
-  patch -p1
-  popd
-
-  # Revert r220714: "Frontend: Define __EXCEPTIONS if -fexceptions is passed"
-  pushd "${CLANG_DIR}"
-  cat << 'EOF' |
---- a/lib/Frontend/InitPreprocessor.cpp
-+++ b/lib/Frontend/InitPreprocessor.cpp
-@@ -566,7 +566,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
-     Builder.defineMacro("__BLOCKS__");
-   }
- 
--  if (!LangOpts.MSVCCompat && LangOpts.Exceptions)
-+  if (!LangOpts.MSVCCompat && LangOpts.CXXExceptions)
-     Builder.defineMacro("__EXCEPTIONS");
-   if (!LangOpts.MSVCCompat && LangOpts.RTTI)
-     Builder.defineMacro("__GXX_RTTI");
-diff --git a/test/Frontend/exceptions.c b/test/Frontend/exceptions.c
-index 981b5b9..4bbaaa3 100644
---- a/test/Frontend/exceptions.c
-+++ b/test/Frontend/exceptions.c
-@@ -1,9 +1,6 @@
--// RUN: %clang_cc1 -fms-compatibility -fexceptions -fcxx-exceptions -DMS_MODE -verify %s
-+// RUN: %clang_cc1 -fms-compatibility -fexceptions -fcxx-exceptions -verify %s
- // expected-no-diagnostics
- 
--// RUN: %clang_cc1 -fms-compatibility -fexceptions -verify %s
--// expected-no-diagnostics
--
--#if defined(MS_MODE) && defined(__EXCEPTIONS)
-+#if defined(__EXCEPTIONS)
- #error __EXCEPTIONS should not be defined.
- #endif
-diff --git a/test/Preprocessor/predefined-exceptions.m b/test/Preprocessor/predefined-exceptions.m
-index 0791075..c13f429 100644
---- a/test/Preprocessor/predefined-exceptions.m
-+++ b/test/Preprocessor/predefined-exceptions.m
-@@ -1,6 +1,6 @@
- // RUN: %clang_cc1 -x objective-c -fobjc-exceptions -fexceptions -E -dM %s | FileCheck -check-prefix=CHECK-OBJC-NOCXX %s 
- // CHECK-OBJC-NOCXX: #define OBJC_ZEROCOST_EXCEPTIONS 1
--// CHECK-OBJC-NOCXX: #define __EXCEPTIONS 1
-+// CHECK-OBJC-NOCXX-NOT: #define __EXCEPTIONS 1
- 
- // RUN: %clang_cc1 -x objective-c++ -fobjc-exceptions -fexceptions -fcxx-exceptions -E -dM %s | FileCheck -check-prefix=CHECK-OBJC-CXX %s 
- // CHECK-OBJC-CXX: #define OBJC_ZEROCOST_EXCEPTIONS 1
-EOF
-  patch -p1
-  popd
-
-  # Apply r223177: "Ensure typos in the default values of template parameters get diagnosed."
-  pushd "${CLANG_DIR}"
-  cat << 'EOF' |
---- a/lib/Parse/ParseTemplate.cpp
-+++ b/lib/Parse/ParseTemplate.cpp
-@@ -676,7 +676,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
-     GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
-     EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
- 
--    DefaultArg = ParseAssignmentExpression();
-+    DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
-     if (DefaultArg.isInvalid())
-       SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
-   }
-diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp
-index 1626044..c4d40b4 100644
---- a/test/SemaCXX/default2.cpp
-+++ b/test/SemaCXX/default2.cpp
-@@ -122,3 +122,9 @@ class XX {
-   void A(int length = -1 ) {  } 
-   void B() { A(); }
- };
-+
-+template <int I = (1 * I)> struct S {};  // expected-error-re {{use of undeclared identifier 'I'{{$}}}}
-+S<1> s;
-+
-+template <int I1 = I2, int I2 = 1> struct T {};  // expected-error-re {{use of undeclared identifier 'I2'{{$}}}}
-+T<0, 1> t;
-diff --git a/test/SemaCXX/typo-correction-delayed.cpp b/test/SemaCXX/typo-correction-delayed.cpp
-index bff1d76..7bf9258 100644
---- a/test/SemaCXX/typo-correction-delayed.cpp
-+++ b/test/SemaCXX/typo-correction-delayed.cpp
-@@ -102,3 +102,7 @@ void f(int *i) {
-   __atomic_load(i, i, something_something);  // expected-error-re {{use of undeclared identifier 'something_something'{{$}}}}
- }
- }
-+
-+const int DefaultArg = 9;  // expected-note {{'DefaultArg' declared here}}
-+template <int I = defaultArg> struct S {};  // expected-error {{use of undeclared identifier 'defaultArg'; did you mean 'DefaultArg'?}}
-+S<1> s;
-EOF
-  patch -p1
-  popd
-
-  # Apply r223209: "Handle delayed corrections in a couple more error paths in ParsePostfixExpressionSuffix."
-  pushd "${CLANG_DIR}"
-  cat << 'EOF' |
---- a/lib/Parse/ParseExpr.cpp
-+++ b/lib/Parse/ParseExpr.cpp
-@@ -1390,6 +1390,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
-         SourceLocation OpenLoc = ConsumeToken();
- 
-         if (ParseSimpleExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) {
-+          (void)Actions.CorrectDelayedTyposInExpr(LHS);
-           LHS = ExprError();
-         }
- 
-@@ -1440,6 +1441,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
-         if (Tok.isNot(tok::r_paren)) {
-           if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
-                                   LHS.get())) {
-+            (void)Actions.CorrectDelayedTyposInExpr(LHS);
-             LHS = ExprError();
-           }
-         }
-diff --git a/test/SemaCXX/typo-correction-delayed.cpp b/test/SemaCXX/typo-correction-delayed.cpp
-index 7bf9258..f7ef015 100644
---- a/test/SemaCXX/typo-correction-delayed.cpp
-+++ b/test/SemaCXX/typo-correction-delayed.cpp
-@@ -106,3 +106,9 @@ void f(int *i) {
- const int DefaultArg = 9;  // expected-note {{'DefaultArg' declared here}}
- template <int I = defaultArg> struct S {};  // expected-error {{use of undeclared identifier 'defaultArg'; did you mean 'DefaultArg'?}}
- S<1> s;
-+
-+namespace foo {}
-+void test_paren_suffix() {
-+  foo::bar({5, 6});  // expected-error-re {{no member named 'bar' in namespace 'foo'{{$}}}} \
-+                     // expected-error {{expected expression}}
-+}
-EOF
-  patch -p1
-  popd
-
-  # Apply r223705: "Handle possible TypoExprs in member initializers."
-  pushd "${CLANG_DIR}"
-  cat << 'EOF' |
---- a/lib/Sema/SemaDeclCXX.cpp
-+++ b/lib/Sema/SemaDeclCXX.cpp
-@@ -2813,6 +2813,11 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
-                           SourceLocation IdLoc,
-                           Expr *Init,
-                           SourceLocation EllipsisLoc) {
-+  ExprResult Res = CorrectDelayedTyposInExpr(Init);
-+  if (!Res.isUsable())
-+    return true;
-+  Init = Res.get();
-+
-   if (!ConstructorD)
-     return true;
- 
-diff --git a/test/SemaCXX/typo-correction-delayed.cpp b/test/SemaCXX/typo-correction-delayed.cpp
-index f7ef015..d303b58 100644
---- a/test/SemaCXX/typo-correction-delayed.cpp
-+++ b/test/SemaCXX/typo-correction-delayed.cpp
-@@ -112,3 +112,10 @@ void test_paren_suffix() {
-   foo::bar({5, 6});  // expected-error-re {{no member named 'bar' in namespace 'foo'{{$}}}} \
-                      // expected-error {{expected expression}}
- }
-+
-+const int kNum = 10;  // expected-note {{'kNum' declared here}}
-+class SomeClass {
-+  int Kind;
-+public:
-+  explicit SomeClass() : Kind(kSum) {}  // expected-error {{use of undeclared identifier 'kSum'; did you mean 'kNum'?}}
-+};
-EOF
-  patch -p1
-  popd
-
-  # Apply r224172: "Typo correction: Ignore temporary binding exprs after overload resolution"
-  pushd "${CLANG_DIR}"
-  cat << 'EOF' |
---- a/lib/Sema/SemaExprCXX.cpp
-+++ b/lib/Sema/SemaExprCXX.cpp
-@@ -6105,8 +6105,13 @@ public:
-     auto Result = BaseTransform::RebuildCallExpr(Callee, LParenLoc, Args,
-                                                  RParenLoc, ExecConfig);
-     if (auto *OE = dyn_cast<OverloadExpr>(Callee)) {
--      if (!Result.isInvalid() && Result.get())
--        OverloadResolution[OE] = cast<CallExpr>(Result.get())->getCallee();
-+      if (!Result.isInvalid() && Result.get()) {
-+        Expr *ResultCall = Result.get();
-+        if (auto *BE = dyn_cast<CXXBindTemporaryExpr>(ResultCall))
-+          ResultCall = BE->getSubExpr();
-+        if (auto *CE = dyn_cast<CallExpr>(ResultCall))
-+          OverloadResolution[OE] = CE->getCallee();
-+      }
-     }
-     return Result;
-   }
-diff --git a/test/SemaCXX/typo-correction-delayed.cpp b/test/SemaCXX/typo-correction-delayed.cpp
-index d303b58..d42888f 100644
---- a/test/SemaCXX/typo-correction-delayed.cpp
-+++ b/test/SemaCXX/typo-correction-delayed.cpp
-@@ -119,3 +119,23 @@ class SomeClass {
- public:
-   explicit SomeClass() : Kind(kSum) {}  // expected-error {{use of undeclared identifier 'kSum'; did you mean 'kNum'?}}
- };
-+
-+extern "C" int printf(const char *, ...);
-+
-+// There used to be an issue with typo resolution inside overloads.
-+struct AssertionResult {
-+  ~AssertionResult();
-+  operator bool();
-+  int val;
-+};
-+AssertionResult Compare(const char *a, const char *b);
-+AssertionResult Compare(int a, int b);
-+int main() {
-+  // expected-note@+1 {{'result' declared here}}
-+  const char *result;
-+  // expected-error@+1 {{use of undeclared identifier 'resulta'; did you mean 'result'?}}
-+  if (AssertionResult ar = (Compare("value1", resulta)))
-+    ;
-+  else
-+    printf("ar: %d\n", ar.val);
-+}
-EOF
-  patch -p1
-  popd
-
-  # Apply r224173: "Implement feedback on r224172 in PR21899"
-  pushd "${CLANG_DIR}"
-  cat << 'EOF' |
---- a/lib/Sema/SemaExprCXX.cpp
-+++ b/lib/Sema/SemaExprCXX.cpp
-@@ -6105,7 +6105,7 @@ public:
-     auto Result = BaseTransform::RebuildCallExpr(Callee, LParenLoc, Args,
-                                                  RParenLoc, ExecConfig);
-     if (auto *OE = dyn_cast<OverloadExpr>(Callee)) {
--      if (!Result.isInvalid() && Result.get()) {
-+      if (Result.isUsable()) {
-         Expr *ResultCall = Result.get();
-         if (auto *BE = dyn_cast<CXXBindTemporaryExpr>(ResultCall))
-           ResultCall = BE->getSubExpr();
-diff --git a/test/SemaCXX/typo-correction-delayed.cpp b/test/SemaCXX/typo-correction-delayed.cpp
-index d42888f..7879d29 100644
---- a/test/SemaCXX/typo-correction-delayed.cpp
-+++ b/test/SemaCXX/typo-correction-delayed.cpp
-@@ -120,22 +120,13 @@ public:
-   explicit SomeClass() : Kind(kSum) {}  // expected-error {{use of undeclared identifier 'kSum'; did you mean 'kNum'?}}
- };
- 
--extern "C" int printf(const char *, ...);
--
- // There used to be an issue with typo resolution inside overloads.
--struct AssertionResult {
--  ~AssertionResult();
--  operator bool();
--  int val;
--};
--AssertionResult Compare(const char *a, const char *b);
--AssertionResult Compare(int a, int b);
--int main() {
-+struct AssertionResult { ~AssertionResult(); };
-+AssertionResult Overload(const char *a);
-+AssertionResult Overload(int a);
-+void UseOverload() {
-   // expected-note@+1 {{'result' declared here}}
-   const char *result;
-   // expected-error@+1 {{use of undeclared identifier 'resulta'; did you mean 'result'?}}
--  if (AssertionResult ar = (Compare("value1", resulta)))
--    ;
--  else
--    printf("ar: %d\n", ar.val);
-+  Overload(resulta);
- }
-EOF
-  patch -p1
-  popd
-
   # This Go bindings test doesn't work after the bootstrap build on Linux. (PR21552)
   pushd "${LLVM_DIR}"
   cat << 'EOF' |
@@ -718,6 +420,7 @@
   patch -p0
   popd
 
+
 fi
 
 # Echo all commands.
@@ -842,6 +545,12 @@
   LDFLAGS+="-stdlib=libc++ -L${PWD}/libcxxbuild"
 fi
 
+# Find the binutils include dir for the gold plugin.
+BINUTILS_INCDIR=""
+if [ "${OS}" = "Linux" ]; then
+  BINUTILS_INCDIR="${ABS_BINUTILS_DIR}/Linux_x64/Release/include"
+fi
+
 # Hook the Chromium tools into the LLVM build. Several Chromium tools have
 # dependencies on LLVM/Clang libraries. The LLVM build detects implicit tools
 # in the tools subdirectory, so install a shim CMakeLists.txt that forwards to
@@ -861,6 +570,7 @@
     -DCMAKE_BUILD_TYPE=Release \
     -DLLVM_ENABLE_ASSERTIONS=ON \
     -DLLVM_ENABLE_THREADS=OFF \
+    -DLLVM_BINUTILS_INCDIR="${BINUTILS_INCDIR}" \
     -DCMAKE_C_COMPILER="${CC}" \
     -DCMAKE_CXX_COMPILER="${CXX}" \
     -DCMAKE_C_FLAGS="${CFLAGS}" \
@@ -970,4 +680,4 @@
 fi
 
 # After everything is done, log success for this revision.
-echo "${CLANG_AND_PLUGINS_REVISION}" > "${STAMP_FILE}"
+echo "${PACKAGE_VERSION}" > "${STAMP_FILE}"
diff --git a/tools/generate_library_loader/generate_library_loader.gni b/tools/generate_library_loader/generate_library_loader.gni
index 2b6874a..24f753b 100644
--- a/tools/generate_library_loader/generate_library_loader.gni
+++ b/tools/generate_library_loader/generate_library_loader.gni
@@ -60,8 +60,8 @@
       public_configs = [ invoker.config ]
     }
     sources = [
-      output_h,
       output_cc,
+      output_h,
     ]
     deps = [
       ":${target_name}_loader",
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index efd5760..d2b3ede 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -215,6 +215,9 @@
   "ui/login/login_resources.grd": {
     "includes": [28300],
   },
+  "ui/oobe/oobe_resources.grd": {
+    "includes": [28310],
+  },
   "chrome/browser/resources/translate_internals_resources.grd": {
     "includes": [28500],
   },
diff --git a/tools/relocation_packer/BUILD.gn b/tools/relocation_packer/BUILD.gn
index e95dbcf..563a64d 100644
--- a/tools/relocation_packer/BUILD.gn
+++ b/tools/relocation_packer/BUILD.gn
@@ -28,8 +28,8 @@
       "src/elf_file.cc",
       "src/leb128.cc",
       "src/packer.cc",
-      "src/sleb128.cc",
       "src/run_length_encoder.cc",
+      "src/sleb128.cc",
     ]
   }
 
@@ -53,9 +53,9 @@
       "src/elf_file_unittest.cc",
       "src/leb128_unittest.cc",
       "src/packer_unittest.cc",
-      "src/sleb128_unittest.cc",
-      "src/run_length_encoder_unittest.cc",
       "src/run_all_unittests.cc",
+      "src/run_length_encoder_unittest.cc",
+      "src/sleb128_unittest.cc",
     ]
     rebased_test_data = rebase_path("test_data", root_build_dir)
     data = [
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt
index d6f6096..c429a9f 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -742,3 +742,20 @@
 *!content::ContentMainRunnerImpl::Run
 *!content::ContentMain
 *!content::LaunchTests
+
+UNINITIALIZED READ
+name=http://crbug.com/463204
+skia.dll!_ltod3
+skia.dll!SkPaint::measure_text
+skia.dll!SkPaint::measureText
+content.dll!content::DoPreSandboxWarmupForTypeface
+content.dll!content::`anonymous namespace'::WarmupDirectWrite
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/463261
+...
+blink_web.dll!blink::WebFrameWidgetImpl::selectionBounds
+content.dll!content::RenderWidget::GetSelectionBounds
+content.dll!content::RenderWidget::UpdateSelectionBounds
+content.dll!content::RenderWidget::willBeginCompositorFrame
+cc.dll!base::internal::InvokeHelper<>::MakeItSo
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
index 72a2478..cc442bc 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
@@ -36,5 +36,3 @@
 # so we can avoid excluding this for light mode.
 MessageLoopTestTypeUI.RecursiveDenial3
 
-# crbug/461816
-PEImageTest.EnumeratesPE
diff --git a/tools/valgrind/gtest_exclude/components_unittests.gtest.txt b/tools/valgrind/gtest_exclude/components_unittests.gtest.txt
index ab9ecfc..e6a2b3f 100644
--- a/tools/valgrind/gtest_exclude/components_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/components_unittests.gtest.txt
@@ -3,3 +3,6 @@
 
 # Fails under valgrind, see http://crbug.com/444516
 AudioDirectiveListTest.*
+
+# http://crbug.com/462352
+FeedbackUploaderChromeTest.VariationHeaders
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
index 6d9febd..2ec3183 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -1,3 +1,6 @@
+# http://crbug.com/293125
+WebRtcBrowserTest.CanMakeEmptyCallThenAddStreamsAndRenegotiate
+
 # crbug.com/395172
 WebRtcBrowserTest.CanForwardRemoteStream
 WebRtcBrowserTest.CanForwardRemoteStream720p
@@ -23,8 +26,12 @@
 # crbug.com/461489
 ServiceWorkerVersionBrowserTest.TimeoutStartingWorker
 
-# http://crbug.com/293125
-WebRtcBrowserTest.CanMakeEmptyCallThenAddStreamsAndRenegotiate
-
 # http://crbug.com/456131
 BrowserSideNavigationBrowserTest.BrowserInitiatedNavigations
+
+# http://crbug.com/464029
+WebRtcBrowserTest.CallAndModifyStream
+
+# http://crbug.com/464033
+RenderFrameHostImplBrowserTest.IsFocused_AtLoad
+RenderFrameHostImplBrowserTest.IsFocused_Widget
diff --git a/tools/valgrind/gtest_exclude/gfx_unittests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/gfx_unittests.gtest-memcheck.txt
deleted file mode 100644
index 3aaaafc..0000000
--- a/tools/valgrind/gtest_exclude/gfx_unittests.gtest-memcheck.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# http://crbug.com/402209
-FontRenderParamsTest.Default
diff --git a/tools/valgrind/gtest_exclude/media_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/media_unittests.gtest_mac.txt
index 7f60330..44a4117 100644
--- a/tools/valgrind/gtest_exclude/media_unittests.gtest_mac.txt
+++ b/tools/valgrind/gtest_exclude/media_unittests.gtest_mac.txt
@@ -7,3 +7,6 @@
 
 # Times out under Valgrind, http://crbug.com/444578
 PipelineIntegrationTest.*
+
+# Hangs the whole Mac Valgrind bot: http://crbug.com/462483
+MidiManagerMacTest.*
diff --git a/tools/valgrind/gtest_exclude/mojo_system_unittests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/mojo_system_unittests.gtest-drmemory.txt
index 24fd314..5149d6c 100644
--- a/tools/valgrind/gtest_exclude/mojo_system_unittests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/mojo_system_unittests.gtest-drmemory.txt
@@ -2,3 +2,5 @@
 RemoteMessagePipeTest.HandlePassing
 # crbug.com/440828
 EmbedderTest.MultiprocessChannels
+# crbug.com/464019
+DataPipeImplTest*.TwoPhaseAllOrNone
diff --git a/tools/valgrind/gtest_exclude/ui_base_unittests.gtest.txt b/tools/valgrind/gtest_exclude/ui_base_unittests.gtest.txt
deleted file mode 100644
index 59ec948..0000000
--- a/tools/valgrind/gtest_exclude/ui_base_unittests.gtest.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# Hangs, fails on cros valgrind. crbug.com/427818
-TouchExplorationTest.*
diff --git a/tools/valgrind/locate_valgrind.sh b/tools/valgrind/locate_valgrind.sh
index 5d0a06b..11d4d83 100755
--- a/tools/valgrind/locate_valgrind.sh
+++ b/tools/valgrind/locate_valgrind.sh
@@ -36,32 +36,24 @@
     PLATFORM="mac_10.7"
     ;;
   *)
-    echo "Unknown platform:" >&2
-    uname -a >&2
-    echo "We'll try to search for valgrind binaries installed in /usr/local" >&2
-    PLATFORM=
+    (echo "Sorry, your platform is not supported:" &&
+     uname -a
+     echo
+     echo "If you're on Mac OS X, please see http://crbug.com/441425") >&2
+    exit 42
   esac
 
-  if [ "$PLATFORM" != "" ]
+  # The binaries should be in third_party/valgrind
+  # (checked out from deps/third_party/valgrind/binaries).
+  CHROME_VALGRIND="$THISDIR/../../third_party/valgrind/$PLATFORM"
+
+  # TODO(timurrrr): readlink -f is not present on Mac...
+  if [ "$PLATFORM" != "mac" ] && \
+    [ "$PLATFORM" != "mac_10.6" ] && \
+    [ "$PLATFORM" != "mac_10.7" ]
   then
-    # The binaries should be in third_party/valgrind
-    # (checked out from deps/third_party/valgrind/binaries).
-    CHROME_VALGRIND="$THISDIR/../../third_party/valgrind/$PLATFORM"
-
-    # TODO(timurrrr): readlink -f is not present on Mac...
-    if [ "$PLATFORM" != "mac" ] && \
-      [ "$PLATFORM" != "mac_10.6" ] && \
-      [ "$PLATFORM" != "mac_10.7" ]
-    then
-      # Get rid of all "../" dirs
-      CHROME_VALGRIND=`readlink -f $CHROME_VALGRIND`
-    fi
-
-    if ! test -x $CHROME_VALGRIND/bin/valgrind
-    then
-      # We couldn't find the binaries in third_party/valgrind
-      CHROME_VALGRIND=""
-    fi
+    # Get rid of all "../" dirs
+    CHROME_VALGRIND=$(readlink -f $CHROME_VALGRIND)
   fi
 fi
 
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 9ea9570..121f26b 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -501,6 +501,16 @@
    fun:_ZN10extensions19ExtensionManagement7RefreshEv
    fun:_ZN10extensions19ExtensionManagement22OnExtensionPrefChangedEv
 }
+{
+   bug_464462
+   Memcheck:Uninitialized
+   fun:_ZN7content14ManifestParser16ParseIconDensityERKN4base15DictionaryValueE
+   fun:_ZN7content14ManifestParser10ParseIconsERKN4base15DictionaryValueE
+   fun:_ZN7content14ManifestParser5ParseEv
+   fun:_ZN7content18ManifestParserTest21ParseManifestWithURLsERKN4base16BasicStringPieceISsEERK4GURLS8_
+   fun:_ZN7content18ManifestParserTest13ParseManifestERKN4base16BasicStringPieceISsEE
+   fun:_ZN7content45ManifestParserTest_IconDensityParseRules_Test8TestBodyEv
+}
 
 #-----------------------------------------------------------------------
 # 3. Suppressions for real chromium bugs that are not yet fixed.
diff --git a/ui/android/java/src/org/chromium/ui/base/Clipboard.java b/ui/android/java/src/org/chromium/ui/base/Clipboard.java
index aaa500e..67aaca2 100644
--- a/ui/android/java/src/org/chromium/ui/base/Clipboard.java
+++ b/ui/android/java/src/org/chromium/ui/base/Clipboard.java
@@ -4,12 +4,13 @@
 
 package org.chromium.ui.base;
 
+import android.annotation.TargetApi;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
+import android.os.Build;
 import android.widget.Toast;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
 import org.chromium.ui.R;
@@ -20,6 +21,10 @@
  */
 @JNINamespace("ui")
 public class Clipboard {
+
+    private static final boolean IS_HTML_CLIPBOARD_SUPPORTED =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
+
     // Necessary for coercing clipboard contents to text if they require
     // access to network resources, etceteras (e.g., URI in clipboard)
     private final Context mContext;
@@ -83,9 +88,10 @@
      * @return a Java string with the html text if any, or null if there is no html
      *         text or no entries on the primary clip.
      */
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     @CalledByNative
     private String getHTMLText() {
-        if (isHTMLClipboardSupported()) {
+        if (IS_HTML_CLIPBOARD_SUPPORTED) {
             final ClipData clip = mClipboardManager.getPrimaryClip();
             if (clip != null && clip.getItemCount() > 0) {
                 return clip.getItemAt(0).getHtmlText();
@@ -129,8 +135,9 @@
      * @param label The Plain-text label for the HTML content.
      * @param text  Plain-text representation of the HTML content.
      */
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     public void setHTMLText(final String html, final String label, final String text) {
-        if (isHTMLClipboardSupported()) {
+        if (IS_HTML_CLIPBOARD_SUPPORTED) {
             setPrimaryClipNoException(ClipData.newHtmlText(label, text, html));
         }
     }
@@ -150,7 +157,7 @@
 
     @CalledByNative
     private static boolean isHTMLClipboardSupported() {
-        return ApiCompatibilityUtils.isHTMLClipboardSupported();
+        return IS_HTML_CLIPBOARD_SUPPORTED;
     }
 
     private void setPrimaryClipNoException(ClipData clip) {
diff --git a/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java b/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java
index 5f4c598..e785af6 100644
--- a/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java
+++ b/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java
@@ -60,12 +60,6 @@
     }
 
     @CalledByNative
-    private static void setDefaultBufferSize(SurfaceTexture surfaceTexture, int width,
-            int height) {
-        surfaceTexture.setDefaultBufferSize(width, height);
-    }
-
-    @CalledByNative
     private static void getTransformMatrix(SurfaceTexture surfaceTexture, float[] matrix) {
         surfaceTexture.getTransformMatrix(matrix);
     }
diff --git a/ui/events/event_dispatcher_unittest.cc b/ui/events/event_dispatcher_unittest.cc
index ad00122..d6caf00 100644
--- a/ui/events/event_dispatcher_unittest.cc
+++ b/ui/events/event_dispatcher_unittest.cc
@@ -18,7 +18,7 @@
 class TestTarget : public EventTarget {
  public:
   TestTarget() : parent_(NULL), valid_(true) {}
-  virtual ~TestTarget() {}
+  ~TestTarget() override {}
 
   void set_parent(TestTarget* parent) { parent_ = parent; }
 
@@ -38,19 +38,19 @@
 
  private:
   // Overridden from EventTarget:
-  virtual bool CanAcceptEvent(const ui::Event& event) override {
+  bool CanAcceptEvent(const ui::Event& event) override {
     return true;
   }
 
-  virtual EventTarget* GetParentTarget() override {
+  EventTarget* GetParentTarget() override {
     return parent_;
   }
 
-  virtual scoped_ptr<EventTargetIterator> GetChildIterator() override {
+  scoped_ptr<EventTargetIterator> GetChildIterator() override {
     return scoped_ptr<EventTargetIterator>();
   }
 
-  virtual EventTargeter* GetEventTargeter() override {
+  EventTargeter* GetEventTargeter() override {
     return NULL;
   }
 
@@ -71,7 +71,7 @@
         received_pre_target_(false) {
   }
 
-  virtual ~TestEventHandler() {}
+  ~TestEventHandler() override {}
 
   virtual void ReceivedEvent(Event* event) {
     static_cast<TestTarget*>(event->target())->AddHandlerId(id_);
@@ -94,7 +94,7 @@
 
  private:
   // Overridden from EventHandler:
-  virtual void OnEvent(Event* event) override {
+  void OnEvent(Event* event) override {
     ui::EventHandler::OnEvent(event);
     ReceivedEvent(event);
     SetStatusOnEvent(event);
@@ -123,7 +123,7 @@
     set_cancelable(false);
   }
 
-  virtual ~NonCancelableEvent() {}
+  ~NonCancelableEvent() override {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NonCancelableEvent);
@@ -138,10 +138,10 @@
         dispatcher_delegate_(delegate) {
   }
 
-  virtual ~EventHandlerDestroyDispatcherDelegate() {}
+  ~EventHandlerDestroyDispatcherDelegate() override {}
 
  private:
-  virtual void ReceivedEvent(Event* event) override {
+  void ReceivedEvent(Event* event) override {
     TestEventHandler::ReceivedEvent(event);
     delete dispatcher_delegate_;
   }
@@ -155,10 +155,10 @@
 class InvalidateTargetEventHandler : public TestEventHandler {
  public:
   explicit InvalidateTargetEventHandler(int id) : TestEventHandler(id) {}
-  virtual ~InvalidateTargetEventHandler() {}
+  ~InvalidateTargetEventHandler() override {}
 
  private:
-  virtual void ReceivedEvent(Event* event) override {
+  void ReceivedEvent(Event* event) override {
    TestEventHandler::ReceivedEvent(event);
    TestTarget* target = static_cast<TestTarget*>(event->target());
    target->set_valid(false);
@@ -177,7 +177,7 @@
         dispatcher_delegate_(NULL) {
   }
 
-  virtual ~EventHandlerDestroyer() {
+  ~EventHandlerDestroyer() override {
     CHECK(!to_destroy_);
   }
 
@@ -186,7 +186,7 @@
   }
 
  private:
-  virtual void ReceivedEvent(Event* event) override {
+  void ReceivedEvent(Event* event) override {
     TestEventHandler::ReceivedEvent(event);
     delete to_destroy_;
     to_destroy_ = NULL;
@@ -207,7 +207,7 @@
  public:
   TestEventDispatcher() {}
 
-  virtual ~TestEventDispatcher() {}
+  ~TestEventDispatcher() override {}
 
   EventDispatchDetails ProcessEvent(EventTarget* target, Event* event) {
     return DispatchEvent(target, event);
@@ -215,7 +215,7 @@
 
  private:
   // Overridden from EventDispatcherDelegate:
-  virtual bool CanDispatchToTarget(EventTarget* target) override {
+  bool CanDispatchToTarget(EventTarget* target) override {
     TestTarget* test_target = static_cast<TestTarget*>(target);
     return test_target->valid();
   }
diff --git a/ui/events/event_processor_unittest.cc b/ui/events/event_processor_unittest.cc
index 33a8162..90b2ad9 100644
--- a/ui/events/event_processor_unittest.cc
+++ b/ui/events/event_processor_unittest.cc
@@ -20,10 +20,10 @@
 class EventProcessorTest : public testing::Test {
  public:
   EventProcessorTest() {}
-  virtual ~EventProcessorTest() {}
+  ~EventProcessorTest() override {}
 
   // testing::Test:
-  virtual void SetUp() override {
+  void SetUp() override {
     processor_.SetRoot(scoped_ptr<EventTarget>(new TestEventTarget()));
     processor_.Reset();
     root()->SetEventTargeter(make_scoped_ptr(new EventTargeter()));
@@ -78,7 +78,7 @@
 class BoundsTestTarget : public TestEventTarget {
  public:
   BoundsTestTarget() {}
-  virtual ~BoundsTestTarget() {}
+  ~BoundsTestTarget() override {}
 
   void set_bounds(gfx::Rect rect) { bounds_ = rect; }
   gfx::Rect bounds() const { return bounds_; }
@@ -106,8 +106,8 @@
 
  private:
   // EventTarget:
-  virtual void ConvertEventToTarget(EventTarget* target,
-                                    LocatedEvent* event) override {
+  void ConvertEventToTarget(EventTarget* target,
+                            LocatedEvent* event) override {
     event->ConvertLocationToTarget(this,
                                    static_cast<BoundsTestTarget*>(target));
   }
@@ -182,10 +182,10 @@
  public:
   ReDispatchEventHandler(EventProcessor* processor, EventTarget* target)
       : processor_(processor), expected_target_(target) {}
-  virtual ~ReDispatchEventHandler() {}
+  ~ReDispatchEventHandler() override {}
 
   // TestEventHandler:
-  virtual void OnMouseEvent(MouseEvent* event) override {
+  void OnMouseEvent(MouseEvent* event) override {
     TestEventHandler::OnMouseEvent(event);
 
     EXPECT_EQ(expected_target_, event->target());
@@ -322,11 +322,11 @@
 class IgnoreEventTargeter : public EventTargeter {
  public:
   IgnoreEventTargeter() {}
-  virtual ~IgnoreEventTargeter() {}
+  ~IgnoreEventTargeter() override {}
 
  private:
   // EventTargeter:
-  virtual bool SubtreeShouldBeExploredForEvent(
+  bool SubtreeShouldBeExploredForEvent(
       EventTarget* target, const LocatedEvent& event) override {
     return false;
   }
@@ -364,16 +364,16 @@
  public:
   explicit BubblingEventTargeter(TestEventTarget* initial_target)
     : initial_target_(initial_target) {}
-  virtual ~BubblingEventTargeter() {}
+  ~BubblingEventTargeter() override {}
 
  private:
   // EventTargeter:
-  virtual EventTarget* FindTargetForEvent(EventTarget* root,
+  EventTarget* FindTargetForEvent(EventTarget* root,
                                           Event* event) override {
     return initial_target_;
   }
 
-  virtual EventTarget* FindNextBestTarget(EventTarget* previous_target,
+  EventTarget* FindNextBestTarget(EventTarget* previous_target,
                                           Event* event) override {
     return previous_target->GetParentTarget();
   }
diff --git a/ui/events/event_rewriter_unittest.cc b/ui/events/event_rewriter_unittest.cc
index 08e592f..3129ae3 100644
--- a/ui/events/event_rewriter_unittest.cc
+++ b/ui/events/event_rewriter_unittest.cc
@@ -22,7 +22,7 @@
  public:
   explicit TestEvent(EventType type)
       : Event(type, base::TimeDelta(), 0), unique_id_(next_unique_id_++) {}
-  virtual ~TestEvent() {}
+  ~TestEvent() override {}
   int unique_id() const { return unique_id_; }
 
  private:
@@ -38,14 +38,14 @@
 class TestEventRewriteProcessor : public test::TestEventProcessor {
  public:
   TestEventRewriteProcessor() {}
-  virtual ~TestEventRewriteProcessor() { CheckAllReceived(); }
+  ~TestEventRewriteProcessor() override { CheckAllReceived(); }
 
   void AddExpectedEvent(EventType type) { expected_events_.push_back(type); }
   // Test that all expected events have been received.
   void CheckAllReceived() { EXPECT_TRUE(expected_events_.empty()); }
 
   // EventProcessor:
-  virtual EventDispatchDetails OnEventFromSource(Event* event) override {
+  EventDispatchDetails OnEventFromSource(Event* event) override {
     EXPECT_FALSE(expected_events_.empty());
     EXPECT_EQ(expected_events_.front(), event->type());
     expected_events_.pop_front();
@@ -62,7 +62,7 @@
  public:
   explicit TestEventRewriteSource(EventProcessor* processor)
       : processor_(processor) {}
-  virtual EventProcessor* GetEventProcessor() override { return processor_; }
+  EventProcessor* GetEventProcessor() override { return processor_; }
   void Send(EventType type) {
     scoped_ptr<Event> event(new TestEvent(type));
     (void)SendEventToProcessor(event.get());
@@ -83,16 +83,15 @@
     CHECK_NE(EVENT_REWRITE_DISPATCH_ANOTHER, status);
   }
 
-  virtual EventRewriteStatus RewriteEvent(const Event& event,
-                                          scoped_ptr<Event>* rewritten_event)
+  EventRewriteStatus RewriteEvent(const Event& event,
+                                  scoped_ptr<Event>* rewritten_event)
       override {
     if (status_ == EVENT_REWRITE_REWRITTEN)
       rewritten_event->reset(new TestEvent(type_));
     return status_;
   }
-  virtual EventRewriteStatus NextDispatchEvent(const Event& last_event,
-                                               scoped_ptr<Event>* new_event)
-      override {
+  EventRewriteStatus NextDispatchEvent(const Event& last_event,
+                                       scoped_ptr<Event>* new_event) override {
     NOTREACHED();
     return status_;
   }
@@ -113,9 +112,8 @@
     rules_.insert(std::pair<RewriteCase, RewriteResult>(
         RewriteCase(from_state, from_type), r));
   }
-  virtual EventRewriteStatus RewriteEvent(const Event& event,
-                                          scoped_ptr<Event>* rewritten_event)
-      override {
+  EventRewriteStatus RewriteEvent(const Event& event,
+                                  scoped_ptr<Event>* rewritten_event) override {
     RewriteRules::iterator find =
         rules_.find(RewriteCase(state_, event.type()));
     if (find == rules_.end())
@@ -130,9 +128,8 @@
     state_ = find->second.state;
     return find->second.status;
   }
-  virtual EventRewriteStatus NextDispatchEvent(const Event& last_event,
-                                               scoped_ptr<Event>* new_event)
-      override {
+  EventRewriteStatus NextDispatchEvent(const Event& last_event,
+                                       scoped_ptr<Event>* new_event) override {
     EXPECT_TRUE(last_rewritten_event_);
     const TestEvent* arg_last = static_cast<const TestEvent*>(&last_event);
     EXPECT_EQ(last_rewritten_event_->unique_id(), arg_last->unique_id());
diff --git a/ui/events/gesture_detection/gesture_provider_unittest.cc b/ui/events/gesture_detection/gesture_provider_unittest.cc
index da305ff..bf483ef 100644
--- a/ui/events/gesture_detection/gesture_provider_unittest.cc
+++ b/ui/events/gesture_detection/gesture_provider_unittest.cc
@@ -58,7 +58,7 @@
 class GestureProviderTest : public testing::Test, public GestureProviderClient {
  public:
   GestureProviderTest() {}
-  virtual ~GestureProviderTest() {}
+  ~GestureProviderTest() override {}
 
   static MockMotionEvent ObtainMotionEvent(base::TimeTicks event_time,
                                            MotionEvent::Action action,
@@ -123,15 +123,15 @@
   }
 
   // Test
-  virtual void SetUp() override { SetUpWithConfig(GetDefaultConfig()); }
+  void SetUp() override { SetUpWithConfig(GetDefaultConfig()); }
 
-  virtual void TearDown() override {
+  void TearDown() override {
     gestures_.clear();
     gesture_provider_.reset();
   }
 
   // GestureProviderClient
-  virtual void OnGestureEvent(const GestureEventData& gesture) override {
+  void OnGestureEvent(const GestureEventData& gesture) override {
     if (gesture.type() == ET_GESTURE_SCROLL_BEGIN)
       active_scroll_begin_event_.reset(new GestureEventData(gesture));
     gestures_.push_back(gesture);
diff --git a/ui/events/gesture_detection/motion_event_buffer_unittest.cc b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
index badbd98..0b77dfe 100644
--- a/ui/events/gesture_detection/motion_event_buffer_unittest.cc
+++ b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
@@ -41,14 +41,14 @@
                               public MotionEventBufferClient {
  public:
   MotionEventBufferTest() : needs_flush_(false) {}
-  virtual ~MotionEventBufferTest() {}
+  ~MotionEventBufferTest() override {}
 
   // MotionEventBufferClient implementation.
-  virtual void ForwardMotionEvent(const MotionEvent& event) override {
+  void ForwardMotionEvent(const MotionEvent& event) override {
     forwarded_events_.push_back(event.Clone().release());
   }
 
-  virtual void SetNeedsFlush() override { needs_flush_ = true; }
+  void SetNeedsFlush() override { needs_flush_ = true; }
 
   bool GetAndResetNeedsFlush() {
     bool needs_flush = needs_flush_;
diff --git a/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc b/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
index d8a2551..fa31056 100644
--- a/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
+++ b/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
@@ -23,20 +23,20 @@
  public:
   TouchDispositionGestureFilterTest()
       : cancel_after_next_gesture_(false), sent_gesture_count_(0) {}
-  virtual ~TouchDispositionGestureFilterTest() {}
+  ~TouchDispositionGestureFilterTest() override {}
 
   // testing::Test
-  virtual void SetUp() override {
+  void SetUp() override {
     queue_.reset(new TouchDispositionGestureFilter(this));
     touch_event_.set_flags(kDefaultEventFlags);
   }
 
-  virtual void TearDown() override {
+  void TearDown() override {
     queue_.reset();
   }
 
   // TouchDispositionGestureFilterClient
-  virtual void ForwardGestureEvent(const GestureEventData& event) override {
+  void ForwardGestureEvent(const GestureEventData& event) override {
     ++sent_gesture_count_;
     last_sent_gesture_.reset(new GestureEventData(event));
     sent_gestures_.push_back(event.type());
diff --git a/ui/events/gesture_detection/velocity_tracker_unittest.cc b/ui/events/gesture_detection/velocity_tracker_unittest.cc
index 9b45053..c5cf15c 100644
--- a/ui/events/gesture_detection/velocity_tracker_unittest.cc
+++ b/ui/events/gesture_detection/velocity_tracker_unittest.cc
@@ -43,7 +43,7 @@
 class VelocityTrackerTest : public testing::Test {
  public:
   VelocityTrackerTest() {}
-  virtual ~VelocityTrackerTest() {}
+  ~VelocityTrackerTest() override {}
 
  protected:
   static MockMotionEvent Sample(MotionEvent::Action action,
diff --git a/ui/events/gestures/gesture_provider_impl.h b/ui/events/gestures/gesture_provider_impl.h
index 118c78b..fd907e1 100644
--- a/ui/events/gestures/gesture_provider_impl.h
+++ b/ui/events/gestures/gesture_provider_impl.h
@@ -27,7 +27,7 @@
 class EVENTS_EXPORT GestureProviderImpl : public GestureProviderClient {
  public:
   GestureProviderImpl(GestureProviderImplClient* client);
-  virtual ~GestureProviderImpl();
+  ~GestureProviderImpl() override;
 
   bool OnTouchEvent(const TouchEvent& event);
   void OnTouchEventAck(bool event_consumed);
@@ -35,7 +35,7 @@
   ScopedVector<GestureEvent>* GetAndResetPendingGestures();
 
   // GestureProviderClient implementation
-  virtual void OnGestureEvent(const GestureEventData& gesture) override;
+  void OnGestureEvent(const GestureEventData& gesture) override;
 
  private:
   bool IsConsideredDoubleTap(const GestureEventData& previous_tap,
diff --git a/ui/events/gestures/gesture_provider_impl_unittest.cc b/ui/events/gestures/gesture_provider_impl_unittest.cc
index 66cc808..fadedc1 100644
--- a/ui/events/gestures/gesture_provider_impl_unittest.cc
+++ b/ui/events/gestures/gesture_provider_impl_unittest.cc
@@ -15,15 +15,15 @@
  public:
   GestureProviderImplTest() {}
 
-  virtual ~GestureProviderImplTest() {}
+  ~GestureProviderImplTest() override {}
 
-  virtual void OnGestureEvent(GestureEvent* event) override {}
+  void OnGestureEvent(GestureEvent* event) override {}
 
-  virtual void SetUp() override {
+  void SetUp() override {
     provider_.reset(new GestureProviderImpl(this));
   }
 
-  virtual void TearDown() override { provider_.reset(); }
+  void TearDown() override { provider_.reset(); }
 
   GestureProviderImpl* provider() { return provider_.get(); }
 
diff --git a/ui/events/gestures/gesture_recognizer_impl.h b/ui/events/gestures/gesture_recognizer_impl.h
index d87045a..9957356 100644
--- a/ui/events/gestures/gesture_recognizer_impl.h
+++ b/ui/events/gestures/gesture_recognizer_impl.h
@@ -31,22 +31,22 @@
   typedef std::map<int, GestureConsumer*> TouchIdToConsumerMap;
 
   GestureRecognizerImpl();
-  virtual ~GestureRecognizerImpl();
+  ~GestureRecognizerImpl() override;
 
   std::vector<GestureEventHelper*>& helpers() { return helpers_; }
 
   // Overridden from GestureRecognizer
-  virtual GestureConsumer* GetTouchLockedTarget(
+  GestureConsumer* GetTouchLockedTarget(
       const TouchEvent& event) override;
-  virtual GestureConsumer* GetTargetForGestureEvent(
+  GestureConsumer* GetTargetForGestureEvent(
       const GestureEvent& event) override;
-  virtual GestureConsumer* GetTargetForLocation(
+  GestureConsumer* GetTargetForLocation(
       const gfx::PointF& location, int source_device_id) override;
-  virtual void TransferEventsTo(GestureConsumer* current_consumer,
-                                GestureConsumer* new_consumer) override;
-  virtual bool GetLastTouchPointForTarget(GestureConsumer* consumer,
-                                          gfx::PointF* point) override;
-  virtual bool CancelActiveTouches(GestureConsumer* consumer) override;
+  void TransferEventsTo(GestureConsumer* current_consumer,
+                        GestureConsumer* new_consumer) override;
+  bool GetLastTouchPointForTarget(GestureConsumer* consumer,
+                                  gfx::PointF* point) override;
+  bool CancelActiveTouches(GestureConsumer* consumer) override;
 
  protected:
   virtual GestureProviderImpl* GetGestureProviderForConsumer(
@@ -59,26 +59,25 @@
   void DispatchGestureEvent(GestureEvent* event);
 
   // Overridden from GestureRecognizer
-  virtual bool ProcessTouchEventPreDispatch(const TouchEvent& event,
-                                            GestureConsumer* consumer) override;
+  bool ProcessTouchEventPreDispatch(const TouchEvent& event,
+                                    GestureConsumer* consumer) override;
 
-  virtual Gestures* ProcessTouchEventPostDispatch(
+  Gestures* ProcessTouchEventPostDispatch(
       const TouchEvent& event,
       ui::EventResult result,
       GestureConsumer* consumer) override;
 
-  virtual Gestures* ProcessTouchEventOnAsyncAck(
+  Gestures* ProcessTouchEventOnAsyncAck(
       const TouchEvent& event,
       ui::EventResult result,
       GestureConsumer* consumer) override;
 
-  virtual bool CleanupStateForConsumer(GestureConsumer* consumer)
-      override;
-  virtual void AddGestureEventHelper(GestureEventHelper* helper) override;
-  virtual void RemoveGestureEventHelper(GestureEventHelper* helper) override;
+  bool CleanupStateForConsumer(GestureConsumer* consumer) override;
+  void AddGestureEventHelper(GestureEventHelper* helper) override;
+  void RemoveGestureEventHelper(GestureEventHelper* helper) override;
 
   // Overridden from GestureProviderImplClient
-  virtual void OnGestureEvent(GestureEvent* event) override;
+  void OnGestureEvent(GestureEvent* event) override;
 
   // Convenience method to find the GestureEventHelper that can dispatch events
   // to a specific |consumer|.
diff --git a/ui/events/gestures/motion_event_impl.h b/ui/events/gestures/motion_event_impl.h
index cac09e8..e2b90a2 100644
--- a/ui/events/gestures/motion_event_impl.h
+++ b/ui/events/gestures/motion_event_impl.h
@@ -19,31 +19,31 @@
 class EVENTS_EXPORT MotionEventImpl : public MotionEvent {
  public:
   MotionEventImpl();
-  virtual ~MotionEventImpl();
+  ~MotionEventImpl() override;
 
   void OnTouch(const TouchEvent& touch);
 
   // MotionEvent implementation.
-  virtual int GetId() const override;
-  virtual Action GetAction() const override;
-  virtual int GetActionIndex() const override;
-  virtual size_t GetPointerCount() const override;
-  virtual int GetPointerId(size_t pointer_index) const override;
-  virtual float GetX(size_t pointer_index) const override;
-  virtual float GetY(size_t pointer_index) const override;
-  virtual float GetRawX(size_t pointer_index) const override;
-  virtual float GetRawY(size_t pointer_index) const override;
-  virtual float GetTouchMajor(size_t pointer_index) const override;
-  virtual float GetTouchMinor(size_t pointer_index) const override;
-  virtual float GetOrientation(size_t pointer_index) const override;
-  virtual float GetPressure(size_t pointer_index) const override;
-  virtual ToolType GetToolType(size_t pointer_index) const override;
-  virtual int GetButtonState() const override;
-  virtual int GetFlags() const override;
-  virtual base::TimeTicks GetEventTime() const override;
+  int GetId() const override;
+  Action GetAction() const override;
+  int GetActionIndex() const override;
+  size_t GetPointerCount() const override;
+  int GetPointerId(size_t pointer_index) const override;
+  float GetX(size_t pointer_index) const override;
+  float GetY(size_t pointer_index) const override;
+  float GetRawX(size_t pointer_index) const override;
+  float GetRawY(size_t pointer_index) const override;
+  float GetTouchMajor(size_t pointer_index) const override;
+  float GetTouchMinor(size_t pointer_index) const override;
+  float GetOrientation(size_t pointer_index) const override;
+  float GetPressure(size_t pointer_index) const override;
+  ToolType GetToolType(size_t pointer_index) const override;
+  int GetButtonState() const override;
+  int GetFlags() const override;
+  base::TimeTicks GetEventTime() const override;
 
-  virtual scoped_ptr<MotionEvent> Clone() const override;
-  virtual scoped_ptr<MotionEvent> Cancel() const override;
+  scoped_ptr<MotionEvent> Clone() const override;
+  scoped_ptr<MotionEvent> Cancel() const override;
 
   int GetSourceDeviceId(size_t pointer_index) const;
 
diff --git a/ui/events/platform/platform_event_builder_x_unittest.cc b/ui/events/platform/platform_event_builder_x_unittest.cc
index ad0d438..40b4f40 100644
--- a/ui/events/platform/platform_event_builder_x_unittest.cc
+++ b/ui/events/platform/platform_event_builder_x_unittest.cc
@@ -16,7 +16,7 @@
 class PlatformEventBuilderXTest : public testing::Test {
  public:
   PlatformEventBuilderXTest() {}
-  virtual ~PlatformEventBuilderXTest() {}
+  ~PlatformEventBuilderXTest() override {}
 
   void SetUp() override {
     DeviceDataManagerX11::CreateInstance();
diff --git a/ui/events/platform/platform_event_source_unittest.cc b/ui/events/platform/platform_event_source_unittest.cc
index cc34960..cc305cb 100644
--- a/ui/events/platform/platform_event_source_unittest.cc
+++ b/ui/events/platform/platform_event_source_unittest.cc
@@ -48,7 +48,7 @@
   TestPlatformEventSource()
       : stop_stream_(false) {
   }
-  virtual ~TestPlatformEventSource() {}
+  ~TestPlatformEventSource() override {}
 
   uint32_t Dispatch(const PlatformEvent& event) { return DispatchEvent(event); }
 
@@ -65,7 +65,7 @@
   }
 
   // PlatformEventSource:
-  virtual void StopCurrentEventStream() override {
+  void StopCurrentEventStream() override {
     stop_stream_ = true;
   }
 
@@ -83,7 +83,7 @@
         stop_stream_(false) {
     PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
   }
-  virtual ~TestPlatformEventDispatcher() {
+  ~TestPlatformEventDispatcher() override {
     PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
   }
 
@@ -93,11 +93,11 @@
 
  protected:
   // PlatformEventDispatcher:
-  virtual bool CanDispatchEvent(const PlatformEvent& event) override {
+  bool CanDispatchEvent(const PlatformEvent& event) override {
     return true;
   }
 
-  virtual uint32_t DispatchEvent(const PlatformEvent& event) override {
+  uint32_t DispatchEvent(const PlatformEvent& event) override {
     list_->push_back(id_);
     return post_dispatch_action_;
   }
@@ -117,17 +117,17 @@
       : id_(id), list_(list) {
     PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
   }
-  virtual ~TestPlatformEventObserver() {
+  ~TestPlatformEventObserver() override {
     PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
   }
 
  protected:
   // PlatformEventObserver:
-  virtual void WillProcessEvent(const PlatformEvent& event) override {
+  void WillProcessEvent(const PlatformEvent& event) override {
     list_->push_back(id_);
   }
 
-  virtual void DidProcessEvent(const PlatformEvent& event) override {}
+  void DidProcessEvent(const PlatformEvent& event) override {}
 
  private:
   int id_;
@@ -139,13 +139,13 @@
 class PlatformEventTest : public testing::Test {
  public:
   PlatformEventTest() {}
-  virtual ~PlatformEventTest() {}
+  ~PlatformEventTest() override {}
 
   TestPlatformEventSource* source() { return source_.get(); }
 
  protected:
   // testing::Test:
-  virtual void SetUp() override {
+  void SetUp() override {
     source_.reset(new TestPlatformEventSource());
   }
 
@@ -334,7 +334,7 @@
  public:
   RunCallbackDuringDispatch(int id, std::vector<int>* list)
       : TestPlatformEventDispatcher(id, list) {}
-  virtual ~RunCallbackDuringDispatch() {}
+  ~RunCallbackDuringDispatch() override {}
 
   void set_callback(const base::Closure& callback) {
     callback_ = callback;
@@ -342,7 +342,7 @@
 
  protected:
   // PlatformEventDispatcher:
-  virtual uint32_t DispatchEvent(const PlatformEvent& event) override {
+  uint32_t DispatchEvent(const PlatformEvent& event) override {
     if (!callback_.is_null())
       callback_.Run();
     return TestPlatformEventDispatcher::DispatchEvent(event);
@@ -497,7 +497,7 @@
 class PlatformEventTestWithMessageLoop : public PlatformEventTest {
  public:
   PlatformEventTestWithMessageLoop() {}
-  virtual ~PlatformEventTestWithMessageLoop() {}
+  ~PlatformEventTestWithMessageLoop() override {}
 
   void Run() {
     message_loop_.PostTask(
@@ -530,7 +530,7 @@
     : public PlatformEventTestWithMessageLoop {
  public:
   // PlatformEventTestWithMessageLoop:
-  virtual void RunTestImpl() override {
+  void RunTestImpl() override {
     std::vector<int> list;
     TestPlatformEventDispatcher dispatcher(10, &list);
     TestPlatformEventObserver observer(15, &list);
@@ -569,7 +569,7 @@
  public:
   DestroyScopedHandleDispatcher(int id, std::vector<int>* list)
       : TestPlatformEventDispatcher(id, list) {}
-  virtual ~DestroyScopedHandleDispatcher() {}
+  ~DestroyScopedHandleDispatcher() override {}
 
   void SetScopedHandle(scoped_ptr<ScopedEventDispatcher> handler) {
     handler_ = handler.Pass();
@@ -581,11 +581,11 @@
 
  private:
   // PlatformEventDispatcher:
-  virtual bool CanDispatchEvent(const PlatformEvent& event) override {
+  bool CanDispatchEvent(const PlatformEvent& event) override {
     return true;
   }
 
-  virtual uint32_t DispatchEvent(const PlatformEvent& event) override {
+  uint32_t DispatchEvent(const PlatformEvent& event) override {
     handler_.reset();
     uint32_t action = TestPlatformEventDispatcher::DispatchEvent(event);
     if (!callback_.is_null()) {
@@ -640,7 +640,7 @@
   }
 
   // PlatformEventTestWithMessageLoop:
-  virtual void RunTestImpl() override {
+  void RunTestImpl() override {
     std::vector<int> list;
     TestPlatformEventDispatcher dispatcher(10, &list);
     TestPlatformEventObserver observer(15, &list);
@@ -740,7 +740,7 @@
   }
 
   // PlatformEventTestWithMessageLoop:
-  virtual void RunTestImpl() override {
+  void RunTestImpl() override {
     std::vector<int> list;
     TestPlatformEventDispatcher dispatcher(10, &list);
     TestPlatformEventObserver observer(15, &list);
diff --git a/ui/events/platform/x11/device_data_manager_x11.h b/ui/events/platform/x11/device_data_manager_x11.h
index 9f064f2..801b1c5 100644
--- a/ui/events/platform/x11/device_data_manager_x11.h
+++ b/ui/events/platform/x11/device_data_manager_x11.h
@@ -238,7 +238,7 @@
 
  private:
   DeviceDataManagerX11();
-  virtual ~DeviceDataManagerX11();
+  ~DeviceDataManagerX11() override;
 
   // Initialize the XInput related system information.
   bool InitializeXInputInternal();
diff --git a/ui/events/platform/x11/platform_event_utils_x_unittest.cc b/ui/events/platform/x11/platform_event_utils_x_unittest.cc
index 1d89404..cba2844 100644
--- a/ui/events/platform/x11/platform_event_utils_x_unittest.cc
+++ b/ui/events/platform/x11/platform_event_utils_x_unittest.cc
@@ -85,9 +85,9 @@
 class PlatformEventUtilsXTest : public testing::Test {
  public:
   PlatformEventUtilsXTest() {}
-  virtual ~PlatformEventUtilsXTest() {}
+  ~PlatformEventUtilsXTest() override {}
 
-  virtual void SetUp() override {
+  void SetUp() override {
     DeviceDataManagerX11::CreateInstance();
     ui::TouchFactory::GetInstance()->ResetForTest();
   }
diff --git a/ui/events/platform/x11/x11_event_source.h b/ui/events/platform/x11/x11_event_source.h
index 206ca5a..6501eb7 100644
--- a/ui/events/platform/x11/x11_event_source.h
+++ b/ui/events/platform/x11/x11_event_source.h
@@ -24,7 +24,7 @@
 class EVENTS_EXPORT X11EventSource : public PlatformEventSource {
  public:
   explicit X11EventSource(XDisplay* display);
-  virtual ~X11EventSource();
+  ~X11EventSource() override;
 
   static X11EventSource* GetInstance();
 
@@ -48,8 +48,8 @@
 
  private:
   // PlatformEventSource:
-  virtual uint32_t DispatchEvent(XEvent* xevent) override;
-  virtual void StopCurrentEventStream() override;
+  uint32_t DispatchEvent(XEvent* xevent) override;
+  void StopCurrentEventStream() override;
 
   // The connection to the X11 server used to receive the events.
   XDisplay* display_;
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc
index 8ad7931..0df1977 100644
--- a/ui/events/platform/x11/x11_event_source_libevent.cc
+++ b/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -22,7 +22,7 @@
     AddEventWatcher();
   }
 
-  virtual ~X11EventSourceLibevent() {
+  ~X11EventSourceLibevent() override {
   }
 
  private:
@@ -39,16 +39,16 @@
   }
 
   // PlatformEventSource:
-  virtual void OnDispatcherListChanged() override {
+  void OnDispatcherListChanged() override {
     AddEventWatcher();
   }
 
   // base::MessagePumpLibevent::Watcher:
-  virtual void OnFileCanReadWithoutBlocking(int fd) override {
+  void OnFileCanReadWithoutBlocking(int fd) override {
     DispatchXEvents();
   }
 
-  virtual void OnFileCanWriteWithoutBlocking(int fd) override {
+  void OnFileCanWriteWithoutBlocking(int fd) override {
     NOTREACHED();
   }
 
diff --git a/ui/gfx/animation/animation.h b/ui/gfx/animation/animation.h
index 81e8e2b..d7d7d3a 100644
--- a/ui/gfx/animation/animation.h
+++ b/ui/gfx/animation/animation.h
@@ -82,7 +82,7 @@
 
   // AnimationContainer::Element overrides
   void SetStartTime(base::TimeTicks start_time) override;
-  virtual void Step(base::TimeTicks time_now) = 0;
+  void Step(base::TimeTicks time_now) override = 0;
   base::TimeDelta GetTimerInterval() const override;
 
  private:
diff --git a/ui/gl/android/surface_texture.cc b/ui/gl/android/surface_texture.cc
index bf9012a..a9f52dc 100644
--- a/ui/gl/android/surface_texture.cc
+++ b/ui/gl/android/surface_texture.cc
@@ -87,19 +87,6 @@
   env->ReleaseFloatArrayElements(jmatrix.obj(), elements, JNI_ABORT);
 }
 
-void SurfaceTexture::SetDefaultBufferSize(int width, int height) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-
-  if (width > 0 && height > 0) {
-    Java_SurfaceTexturePlatformWrapper_setDefaultBufferSize(
-        env, j_surface_texture_.obj(), static_cast<jint>(width),
-        static_cast<jint>(height));
-  } else {
-    LOG(WARNING) << "Not setting surface texture buffer size - "
-                    "width or height is 0";
-  }
-}
-
 void SurfaceTexture::AttachToGLContext() {
   if (GlContextMethodsAvailable()) {
     int texture_id;
diff --git a/ui/gl/android/surface_texture.h b/ui/gl/android/surface_texture.h
index 05bc5a3..b22e5c4 100644
--- a/ui/gl/android/surface_texture.h
+++ b/ui/gl/android/surface_texture.h
@@ -46,9 +46,6 @@
   // texture image set by the most recent call to updateTexImage.
   void GetTransformMatrix(float mtx[16]);
 
-  // Set the default size of the image buffers.
-  void SetDefaultBufferSize(int width, int height);
-
   // Attach the SurfaceTexture to the texture currently bound to
   // GL_TEXTURE_EXTERNAL_OES.
   void AttachToGLContext();
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc
index 5fa2c44..950558b 100644
--- a/ui/gl/gl_context_egl.cc
+++ b/ui/gl/gl_context_egl.cc
@@ -4,6 +4,7 @@
 
 #include "ui/gl/gl_context_egl.h"
 
+#include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/trace_event/trace_event.h"
@@ -38,12 +39,18 @@
   DCHECK(compatible_surface);
   DCHECK(!context_);
 
-  static const EGLint kContextAttributes[] = {
-    EGL_CONTEXT_CLIENT_VERSION, 2,
+  EGLint context_client_version = 2;
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableUnsafeES3APIs)) {
+    context_client_version = 3;
+  }
+
+  const EGLint kContextAttributes[] = {
+    EGL_CONTEXT_CLIENT_VERSION, context_client_version,
     EGL_NONE
   };
-  static const EGLint kContextRobustnessAttributes[] = {
-    EGL_CONTEXT_CLIENT_VERSION, 2,
+  const EGLint kContextRobustnessAttributes[] = {
+    EGL_CONTEXT_CLIENT_VERSION, context_client_version,
     EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
     EGL_LOSE_CONTEXT_ON_RESET_EXT,
     EGL_NONE
diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc
index 6b9a519..ca106b7 100644
--- a/ui/gl/gl_image_memory.cc
+++ b/ui/gl/gl_image_memory.cc
@@ -183,30 +183,6 @@
   return false;
 }
 
-// static
-bool GLImageMemory::ValidSize(const gfx::Size& size,
-                              gfx::GpuMemoryBuffer::Format format) {
-  switch (format) {
-    case gfx::GpuMemoryBuffer::ATC:
-    case gfx::GpuMemoryBuffer::ATCIA:
-    case gfx::GpuMemoryBuffer::DXT1:
-    case gfx::GpuMemoryBuffer::DXT5:
-    case gfx::GpuMemoryBuffer::ETC1:
-      // Compressed images must have a width and height that's evenly divisible
-      // by the block size.
-      return size.width() % 4 == 0 && size.height() % 4 == 0;
-    case gfx::GpuMemoryBuffer::RGBA_8888:
-    case gfx::GpuMemoryBuffer::BGRA_8888:
-      return true;
-    case gfx::GpuMemoryBuffer::RGBX_8888:
-      NOTREACHED();
-      return false;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
 bool GLImageMemory::Initialize(const unsigned char* memory,
                                gfx::GpuMemoryBuffer::Format format) {
   if (!ValidInternalFormat(internalformat_)) {
@@ -221,6 +197,8 @@
 
   DCHECK(memory);
   DCHECK(!memory_);
+  DCHECK_IMPLIES(IsCompressedFormat(format), size_.width() % 4 == 0);
+  DCHECK_IMPLIES(IsCompressedFormat(format), size_.height() % 4 == 0);
   memory_ = memory;
   format_ = format;
   return true;
diff --git a/ui/gl/gl_image_memory.h b/ui/gl/gl_image_memory.h
index befc3a8..a50a380 100644
--- a/ui/gl/gl_image_memory.h
+++ b/ui/gl/gl_image_memory.h
@@ -26,9 +26,6 @@
                             gfx::GpuMemoryBuffer::Format format,
                             size_t* stride_in_bytes);
 
-  static bool ValidSize(const gfx::Size& size,
-                        gfx::GpuMemoryBuffer::Format format);
-
   bool Initialize(const unsigned char* memory,
                   gfx::GpuMemoryBuffer::Format format);
 
diff --git a/ui/gl/gl_image_shared_memory.cc b/ui/gl/gl_image_shared_memory.cc
index 363ebf5..d9e31a7 100644
--- a/ui/gl/gl_image_shared_memory.cc
+++ b/ui/gl/gl_image_shared_memory.cc
@@ -18,9 +18,6 @@
   if (size.IsEmpty())
     return false;
 
-  if (!GLImageMemory::ValidSize(size, format))
-    return false;
-
   size_t stride_in_bytes = 0;
   if (!GLImageMemory::StrideInBytes(size.width(), format, &stride_in_bytes))
     return false;
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index 48d7cd2..da70422 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -156,6 +156,15 @@
   static scoped_refptr<GLSurface> CreateViewGLSurface(
       gfx::AcceleratedWidget window);
 
+#if defined(USE_OZONE)
+  // Create a GL surface that renders directly into a window with surfaceless
+  // semantics - there is no default framebuffer and the primary surface must
+  // be presented as an overlay. If surfaceless mode is not supported or
+  // enabled it will return a null pointer.
+  static scoped_refptr<GLSurface> CreateSurfacelessViewGLSurface(
+      gfx::AcceleratedWidget window);
+#endif  // defined(USE_OZONE)
+
   // Create a GL surface used for offscreen rendering.
   static scoped_refptr<GLSurface> CreateOffscreenGLSurface(
       const gfx::Size& size);
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 2dcdc88..61c3c05 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -37,6 +37,10 @@
 #define EGL_FIXED_SIZE_ANGLE 0x3201
 #endif
 
+#if !defined(EGL_OPENGL_ES3_BIT)
+#define EGL_OPENGL_ES3_BIT 0x00000040
+#endif
+
 #if defined(OS_WIN)
 // From ANGLE's egl/eglext.h.
 
@@ -172,13 +176,18 @@
 
   // Choose an EGL configuration.
   // On X this is only used for PBuffer surfaces.
-  static const EGLint kConfigAttribs[] = {
+  EGLint renderable_type = EGL_OPENGL_ES2_BIT;
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableUnsafeES3APIs)) {
+    renderable_type = EGL_OPENGL_ES3_BIT;
+  }
+  const EGLint kConfigAttribs[] = {
     EGL_BUFFER_SIZE, 32,
     EGL_ALPHA_SIZE, 8,
     EGL_BLUE_SIZE, 8,
     EGL_GREEN_SIZE, 8,
     EGL_RED_SIZE, 8,
-    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+    EGL_RENDERABLE_TYPE, renderable_type,
     EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
     EGL_NONE
   };
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc
index cba706b..47ea8d6 100644
--- a/ui/gl/gl_surface_ozone.cc
+++ b/ui/gl/gl_surface_ozone.cc
@@ -4,16 +4,20 @@
 
 #include "ui/gl/gl_surface.h"
 
+#include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_linux_dma_buffer.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/gl_surface_osmesa.h"
 #include "ui/gl/gl_surface_stub.h"
+#include "ui/gl/scoped_binders.h"
 #include "ui/gl/scoped_make_current.h"
+#include "ui/ozone/public/native_pixmap.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 #include "ui/ozone/public/surface_ozone_egl.h"
 
@@ -157,15 +161,15 @@
     return SwapBuffersAsync(callback);
   }
 
- private:
+ protected:
   ~GLSurfaceOzoneSurfaceless() override {
     Destroy();  // EGL surface must be destroyed before SurfaceOzone
   }
 
   bool Flush() {
     glFlush();
-    // TODO: the following should be replaced by a per surface flush as it gets
-    // implemented in GL drivers.
+    // TODO: crbug.com/462360 the following should be replaced by a per surface
+    // flush as it gets implemented in GL drivers.
     if (has_implicit_external_sync_) {
       const EGLint attrib_list[] = {
           EGL_SYNC_CONDITION_KHR,
@@ -182,6 +186,8 @@
       } else {
         return false;
       }
+    } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
+      glFinish();
     }
     return true;
   }
@@ -194,6 +200,157 @@
   DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
 };
 
+// This provides surface-like semantics implemented through surfaceless.
+// A framebuffer is bound automatically.
+class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
+    : public GLSurfaceOzoneSurfaceless {
+ public:
+  GLSurfaceOzoneSurfacelessSurfaceImpl(
+      scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
+      AcceleratedWidget widget)
+      : GLSurfaceOzoneSurfaceless(ozone_surface.Pass(), widget),
+        fbo_(0),
+        current_surface_(0) {
+    for (auto& texture : textures_)
+      texture = 0;
+  }
+
+  unsigned int GetBackingFrameBufferObject() override { return fbo_; }
+
+  bool OnMakeCurrent(GLContext* context) override {
+    if (!fbo_) {
+      glGenFramebuffersEXT(1, &fbo_);
+      if (!fbo_)
+        return false;
+      glGenTextures(arraysize(textures_), textures_);
+      if (!CreatePixmaps())
+        return false;
+    }
+    BindFramebuffer();
+    glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
+    return SurfacelessEGL::OnMakeCurrent(context);
+  }
+
+  bool Resize(const gfx::Size& size) override {
+    if (size == GetSize())
+      return true;
+    return GLSurfaceOzoneSurfaceless::Resize(size) && CreatePixmaps();
+  }
+
+  bool SupportsPostSubBuffer() override { return false; }
+
+  bool SwapBuffers() override {
+    if (!images_[current_surface_]->ScheduleOverlayPlane(
+            widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
+            gfx::Rect(GetSize()), gfx::RectF(1, 1)))
+      return false;
+    if (!GLSurfaceOzoneSurfaceless::SwapBuffers())
+      return false;
+    current_surface_ ^= 1;
+    BindFramebuffer();
+    return true;
+  }
+
+  bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
+    if (!images_[current_surface_]->ScheduleOverlayPlane(
+            widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
+            gfx::Rect(GetSize()), gfx::RectF(1, 1)))
+      return false;
+    if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback))
+      return false;
+    current_surface_ ^= 1;
+    BindFramebuffer();
+    return true;
+  }
+
+  void Destroy() override {
+    GLContext* current_context = GLContext::GetCurrent();
+    DCHECK(current_context && current_context->IsCurrent(this));
+    glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
+    if (fbo_) {
+      glDeleteTextures(arraysize(textures_), textures_);
+      for (auto& texture : textures_)
+        texture = 0;
+      glDeleteFramebuffersEXT(1, &fbo_);
+      fbo_ = 0;
+    }
+    for (auto image : images_) {
+      if (image)
+        image->Destroy(true);
+    }
+  }
+
+ private:
+  class SurfaceImage : public GLImageLinuxDMABuffer {
+   public:
+    SurfaceImage(const gfx::Size& size, unsigned internalformat)
+        : GLImageLinuxDMABuffer(size, internalformat) {}
+
+    bool Initialize(scoped_refptr<ui::NativePixmap> pixmap,
+                    gfx::GpuMemoryBuffer::Format format) {
+      base::FileDescriptor handle(pixmap->GetDmaBufFd(), false);
+      if (!GLImageLinuxDMABuffer::Initialize(handle, format,
+                                             pixmap->GetDmaBufPitch()))
+        return false;
+      pixmap_ = pixmap;
+      return true;
+    }
+    bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+                              int z_order,
+                              gfx::OverlayTransform transform,
+                              const gfx::Rect& bounds_rect,
+                              const gfx::RectF& crop_rect) override {
+      return ui::SurfaceFactoryOzone::GetInstance()->ScheduleOverlayPlane(
+          widget, z_order, transform, pixmap_, bounds_rect, crop_rect);
+    }
+
+   private:
+    ~SurfaceImage() override {}
+
+    scoped_refptr<ui::NativePixmap> pixmap_;
+  };
+
+  ~GLSurfaceOzoneSurfacelessSurfaceImpl() override {
+    DCHECK(!fbo_);
+    for (size_t i = 0; i < arraysize(textures_); i++)
+      DCHECK(!textures_[i]) << "texture " << i << " not released";
+  }
+
+  void BindFramebuffer() {
+    ScopedFrameBufferBinder fb(fbo_);
+    glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                              GL_TEXTURE_2D, textures_[current_surface_], 0);
+  }
+
+  bool CreatePixmaps() {
+    if (!fbo_)
+      return true;
+    for (size_t i = 0; i < arraysize(textures_); i++) {
+      scoped_refptr<ui::NativePixmap> pixmap =
+          ui::SurfaceFactoryOzone::GetInstance()->CreateNativePixmap(
+              widget_, GetSize(), ui::SurfaceFactoryOzone::RGBA_8888,
+              ui::SurfaceFactoryOzone::SCANOUT);
+      if (!pixmap)
+        return false;
+      scoped_refptr<SurfaceImage> image = new SurfaceImage(GetSize(), GL_RGBA);
+      if (!image->Initialize(pixmap, gfx::GpuMemoryBuffer::Format::BGRA_8888))
+        return false;
+      images_[i] = image;
+      // Bind image to texture.
+      ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
+      if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
+        return false;
+    }
+    return true;
+  }
+
+  GLuint fbo_;
+  GLuint textures_[2];
+  scoped_refptr<GLImage> images_[2];
+  int current_surface_;
+  DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
+};
+
 }  // namespace
 
 // static
@@ -215,6 +372,27 @@
 }
 
 // static
+scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
+    gfx::AcceleratedWidget window) {
+  if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
+      window != kNullAcceleratedWidget &&
+      GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
+      ui::SurfaceFactoryOzone::GetInstance()->CanShowPrimaryPlaneAsOverlay()) {
+    scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
+        ui::SurfaceFactoryOzone::GetInstance()
+            ->CreateSurfacelessEGLSurfaceForWidget(window);
+    if (!surface_ozone)
+      return nullptr;
+    scoped_refptr<GLSurface> surface;
+    surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
+    if (surface->Initialize())
+      return surface;
+  }
+
+  return nullptr;
+}
+
+// static
 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
     gfx::AcceleratedWidget window) {
   if (GetGLImplementation() == kGLImplementationOSMesaGL) {
@@ -234,7 +412,8 @@
               ->CreateSurfacelessEGLSurfaceForWidget(window);
       if (!surface_ozone)
         return NULL;
-      surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
+      surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(surface_ozone.Pass(),
+                                                         window);
     } else {
       scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
           ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index 479ff69..8817156 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -58,6 +58,9 @@
 // On Windows only: use the WARP software rasterizer in the GPU process.
 const char kUseWarp[] = "use-warp";
 
+// Enable OpenGL ES 3 APIs without proper service side validation.
+const char kEnableUnsafeES3APIs[] = "enable-unsafe-es3-apis";
+
 // Disables GL drawing operations which produce pixel output. With this
 // the GL output will not be correct but tests will run faster.
 const char kDisableGLDrawingForTests[] = "disable-gl-drawing-for-tests";
@@ -74,6 +77,7 @@
   kDisableD3D11,
   kEnableGPUServiceLogging,
   kEnableGPUServiceTracing,
+  kEnableUnsafeES3APIs,
   kGpuNoContextLost,
   kDisableGLDrawingForTests,
   kOverrideUseGLWithOSMesaForTests,
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h
index ce27df0..0715ad9 100644
--- a/ui/gl/gl_switches.h
+++ b/ui/gl/gl_switches.h
@@ -36,6 +36,7 @@
 GL_EXPORT extern const char kTestGLLib[];
 GL_EXPORT extern const char kUseGpuInTests[];
 GL_EXPORT extern const char kUseWarp[];
+GL_EXPORT extern const char kEnableUnsafeES3APIs[];
 
 // These flags are used by the test harness code, not passed in by users.
 GL_EXPORT extern const char kDisableGLDrawingForTests[];
diff --git a/ui/gl/gpu_timing.cc b/ui/gl/gpu_timing.cc
index 22a4a64..a3b697f 100644
--- a/ui/gl/gpu_timing.cc
+++ b/ui/gl/gpu_timing.cc
@@ -30,6 +30,17 @@
   return new GPUTimingClient(this);
 }
 
+uint32_t GPUTiming::GetDisjointCount() {
+  if (timer_type_ == kTimerTypeDisjoint) {
+    GLint disjoint_value = 0;
+    glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
+    if (disjoint_value) {
+      disjoint_counter_++;
+    }
+  }
+  return disjoint_counter_;
+}
+
 GPUTimer::~GPUTimer() {
   glDeleteQueriesARB(2, queries_);
 }
@@ -87,6 +98,7 @@
     : gpu_timing_(gpu_timing) {
   if (gpu_timing) {
     timer_type_ = gpu_timing->GetTimerType();
+    disjoint_counter_ = gpu_timing_->GetDisjointCount();
   }
 }
 
@@ -111,12 +123,13 @@
 
 bool GPUTimingClient::CheckAndResetTimerErrors() {
   if (timer_type_ == GPUTiming::kTimerTypeDisjoint) {
-    GLint disjoint_value = 0;
-    glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
-    return disjoint_value != 0;
-  } else {
-    return false;
+    DCHECK(gpu_timing_ != nullptr);
+    const uint32_t total_disjoint_count = gpu_timing_->GetDisjointCount();
+    const bool disjoint_triggered = total_disjoint_count != disjoint_counter_;
+    disjoint_counter_ = total_disjoint_count;
+    return disjoint_triggered;
   }
+  return false;
 }
 
 int64 GPUTimingClient::CalculateTimerOffset() {
diff --git a/ui/gl/gpu_timing.h b/ui/gl/gpu_timing.h
index 9702fe1..1c8f8cf 100644
--- a/ui/gl/gpu_timing.h
+++ b/ui/gl/gpu_timing.h
@@ -52,6 +52,7 @@
   };
 
   TimerType GetTimerType() const { return timer_type_; }
+  uint32_t GetDisjointCount();
 
  private:
   friend struct base::DefaultDeleter<GPUTiming>;
@@ -62,6 +63,7 @@
   scoped_refptr<GPUTimingClient> CreateGPUTimingClient();
 
   TimerType timer_type_ = kTimerTypeInvalid;
+  uint32_t disjoint_counter_ = 0;
   DISALLOW_COPY_AND_ASSIGN(GPUTiming);
 };
 
@@ -125,6 +127,7 @@
   GPUTiming* gpu_timing_;
   GPUTiming::TimerType timer_type_ = GPUTiming::kTimerTypeInvalid;
   int64 offset_ = 0;  // offset cache when timer_type_ == kTimerTypeARB
+  uint32_t disjoint_counter_ = 0;
   bool offset_valid_ = false;
   base::Callback<int64(void)> cpu_time_for_testing_;
 
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h
index 6e1184c..eb75912 100644
--- a/ui/platform_window/x11/x11_window.h
+++ b/ui/platform_window/x11/x11_window.h
@@ -21,7 +21,7 @@
                                     public PlatformEventDispatcher {
  public:
   explicit X11Window(PlatformWindowDelegate* delegate);
-  virtual ~X11Window();
+  ~X11Window() override;
 
  private:
   void Destroy();
@@ -29,23 +29,23 @@
   void ProcessXInput2Event(XEvent* xevent);
 
   // PlatformWindow:
-  virtual void Show() override;
-  virtual void Hide() override;
-  virtual void Close() override;
-  virtual void SetBounds(const gfx::Rect& bounds) override;
-  virtual gfx::Rect GetBounds() override;
-  virtual void SetCapture() override;
-  virtual void ReleaseCapture() override;
-  virtual void ToggleFullscreen() override;
-  virtual void Maximize() override;
-  virtual void Minimize() override;
-  virtual void Restore() override;
-  virtual void SetCursor(PlatformCursor cursor) override;
-  virtual void MoveCursorTo(const gfx::Point& location) override;
+  void Show() override;
+  void Hide() override;
+  void Close() override;
+  void SetBounds(const gfx::Rect& bounds) override;
+  gfx::Rect GetBounds() override;
+  void SetCapture() override;
+  void ReleaseCapture() override;
+  void ToggleFullscreen() override;
+  void Maximize() override;
+  void Minimize() override;
+  void Restore() override;
+  void SetCursor(PlatformCursor cursor) override;
+  void MoveCursorTo(const gfx::Point& location) override;
 
   // PlatformEventDispatcher:
-  virtual bool CanDispatchEvent(const PlatformEvent& event) override;
-  virtual uint32_t DispatchEvent(const PlatformEvent& event) override;
+  bool CanDispatchEvent(const PlatformEvent& event) override;
+  uint32_t DispatchEvent(const PlatformEvent& event) override;
 
   PlatformWindowDelegate* delegate_;