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/BUILD.gn b/BUILD.gn
index 9dbc41c..402b19a 100644
--- a/BUILD.gn
+++ b/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/android/animation_frame_time_histogram.cc b/android/animation_frame_time_histogram.cc
new file mode 100644
index 0000000..0d79619
--- /dev/null
+++ b/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/android/animation_frame_time_histogram.h b/android/animation_frame_time_histogram.h
new file mode 100644
index 0000000..63f938b
--- /dev/null
+++ b/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/android/base_jni_registrar.cc b/android/base_jni_registrar.cc
index 4dda482..7439d3c 100644
--- a/android/base_jni_registrar.cc
+++ b/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/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
new file mode 100644
index 0000000..ad5cdd8
--- /dev/null
+++ b/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/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index c03cad2..4198853 100644
--- a/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/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.gyp b/base.gyp
index 30de275..3888ad9 100644
--- a/base.gyp
+++ b/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.gypi b/base.gypi
index 148246f..0f8fff2 100644
--- a/base.gypi
+++ b/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_nacl.gyp b/base_nacl.gyp
index 63e1ed4..90a2893 100644
--- a/base_nacl.gyp
+++ b/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_unittests.isolate b/base_unittests.isolate
index e5495e3..5126fb3 100644
--- a/base_unittests.isolate
+++ b/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/files/file_path_watcher_win.cc b/files/file_path_watcher_win.cc
index 63e5480..f6d0029 100644
--- a/files/file_path_watcher_win.cc
+++ b/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/files/important_file_writer.cc b/files/important_file_writer.cc
index d256236..47b0b09 100644
--- a/files/important_file_writer.cc
+++ b/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/json/json_file_value_serializer.cc b/json/json_file_value_serializer.cc
index 71033f6..72a0970 100644
--- a/json/json_file_value_serializer.cc
+++ b/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/json/json_file_value_serializer.h b/json/json_file_value_serializer.h
index 6cfcbe8..aab47ee 100644
--- a/json/json_file_value_serializer.h
+++ b/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/json/json_string_value_serializer.cc b/json/json_string_value_serializer.cc
index b626640..debf9f0 100644
--- a/json/json_string_value_serializer.cc
+++ b/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/json/json_string_value_serializer.h b/json/json_string_value_serializer.h
index 7f99bc9..bc0e66d 100644
--- a/json/json_string_value_serializer.h
+++ b/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/json/json_value_serializer_unittest.cc b/json/json_value_serializer_unittest.cc
index d2a84de..225ee67 100644
--- a/json/json_value_serializer_unittest.cc
+++ b/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/mac/foundation_util.h b/mac/foundation_util.h
index accc0d9..353ed7c 100644
--- a/mac/foundation_util.h
+++ b/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/mac/foundation_util.mm b/mac/foundation_util.mm
index 2895b66..27d6e7c 100644
--- a/mac/foundation_util.mm
+++ b/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/mac/sdk_forward_declarations.h b/mac/sdk_forward_declarations.h
index 2795b19..25d937e 100644
--- a/mac/sdk_forward_declarations.h
+++ b/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/memory/discardable_memory_android.cc b/memory/discardable_memory_android.cc
index 5dcdfdc..2b35587 100644
--- a/memory/discardable_memory_android.cc
+++ b/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/memory/discardable_memory_mac.cc b/memory/discardable_memory_mac.cc
index e0096e5..2881f5e 100644
--- a/memory/discardable_memory_mac.cc
+++ b/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/memory/discardable_shared_memory.h b/memory/discardable_shared_memory.h
index 59c5d5b..e3b437c 100644
--- a/memory/discardable_shared_memory.h
+++ b/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/prefs/base_prefs_switches.cc b/prefs/base_prefs_switches.cc
new file mode 100644
index 0000000..304248b
--- /dev/null
+++ b/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/prefs/base_prefs_switches.h b/prefs/base_prefs_switches.h
new file mode 100644
index 0000000..7a6b665
--- /dev/null
+++ b/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/prefs/json_pref_store.cc b/prefs/json_pref_store.cc
index c52a95c..2e34b50 100644
--- a/prefs/json_pref_store.cc
+++ b/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/process/kill.cc b/process/kill.cc
index caca348..a647d96 100644
--- a/process/kill.cc
+++ b/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/process/kill.h b/process/kill.h
index 8c0a213..df0d95e 100644
--- a/process/kill.h
+++ b/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/process/kill_posix.cc b/process/kill_posix.cc
index 77705ee..298486b 100644
--- a/process/kill_posix.cc
+++ b/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/process/kill_win.cc b/process/kill_win.cc
index 7daf5f8..3c93047 100644
--- a/process/kill_win.cc
+++ b/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/process/launch_posix.cc b/process/launch_posix.cc
index 203b7c8..f9963fa 100644
--- a/process/launch_posix.cc
+++ b/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/process/process_posix.cc b/process/process_posix.cc
index bc2f3f8..a36bf77 100644
--- a/process/process_posix.cc
+++ b/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/process/process_win.cc b/process/process_win.cc
index 8e5360b..b62fdb4 100644
--- a/process/process_win.cc
+++ b/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/synchronization/waitable_event.h b/synchronization/waitable_event.h
index 5adc1ec..c35af54 100644
--- a/synchronization/waitable_event.h
+++ b/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/synchronization/waitable_event_watcher_win.cc b/synchronization/waitable_event_watcher_win.cc
index a04a435..46d47ac 100644
--- a/synchronization/waitable_event_watcher_win.cc
+++ b/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/test/BUILD.gn b/test/BUILD.gn
index 05a3dc3..120159e 100644
--- a/test/BUILD.gn
+++ b/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/test/data/pe_image/pe_image_test_32.dll b/test/data/pe_image/pe_image_test_32.dll
new file mode 100755
index 0000000..118ce11
--- /dev/null
+++ b/test/data/pe_image/pe_image_test_32.dll
Binary files differ
diff --git a/test/data/pe_image/pe_image_test_64.dll b/test/data/pe_image/pe_image_test_64.dll
new file mode 100755
index 0000000..70f8ea4
--- /dev/null
+++ b/test/data/pe_image/pe_image_test_64.dll
Binary files differ
diff --git a/test/data/prefs/write.golden.json b/test/data/prefs/write.golden.json
index 9a5523c..fb1fff1 100644
--- a/test/data/prefs/write.golden.json
+++ b/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/test/gtest_util.cc b/test/gtest_util.cc
index c0bc04a..b811194 100644
--- a/test/gtest_util.cc
+++ b/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/test/mock_log.cc b/test/mock_log.cc
new file mode 100644
index 0000000..fa511d4
--- /dev/null
+++ b/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/test/mock_log.h b/test/mock_log.h
new file mode 100644
index 0000000..315ef1f
--- /dev/null
+++ b/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/test/test_mock_time_task_runner.cc b/test/test_mock_time_task_runner.cc
index a878280..8e65ccf 100644
--- a/test/test_mock_time_task_runner.cc
+++ b/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/test/test_mock_time_task_runner.h b/test/test_mock_time_task_runner.h
index 1a651f6..5f06013 100644
--- a/test/test_mock_time_task_runner.h
+++ b/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/third_party/nspr/BUILD.gn b/third_party/nspr/BUILD.gn
index c0b2ec2..a67e168 100644
--- a/third_party/nspr/BUILD.gn
+++ b/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/threading/sequenced_worker_pool.cc b/threading/sequenced_worker_pool.cc
index 89224f7..19b81b7 100644
--- a/threading/sequenced_worker_pool.cc
+++ b/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/threading/sequenced_worker_pool_unittest.cc b/threading/sequenced_worker_pool_unittest.cc
index ed5f896..9d0f607 100644
--- a/threading/sequenced_worker_pool_unittest.cc
+++ b/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/threading/thread_restrictions.h b/threading/thread_restrictions.h
index 7c46fd2..1e5f510 100644
--- a/threading/thread_restrictions.h
+++ b/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/timer/timer.cc b/timer/timer.cc
index 11f73ca..fa6b8cd 100644
--- a/timer/timer.cc
+++ b/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/timer/timer.h b/timer/timer.h
index ea34a9f..1ef58a3 100644
--- a/timer/timer.h
+++ b/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/trace_event/memory_dump_manager.cc b/trace_event/memory_dump_manager.cc
index c8be8f8..cbed238 100644
--- a/trace_event/memory_dump_manager.cc
+++ b/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/trace_event/memory_dump_manager.h b/trace_event/memory_dump_manager.h
index 1a22e61..8a9b3b7 100644
--- a/trace_event/memory_dump_manager.h
+++ b/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/trace_event/memory_dump_manager_unittest.cc b/trace_event/memory_dump_manager_unittest.cc
index 1ba73e6..78be377 100644
--- a/trace_event/memory_dump_manager_unittest.cc
+++ b/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/trace_event/memory_dump_provider.h b/trace_event/memory_dump_provider.h
index 18363c5..1c5bbb1 100644
--- a/trace_event/memory_dump_provider.h
+++ b/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/trace_event/process_memory_maps_dump_provider.cc b/trace_event/process_memory_maps_dump_provider.cc
index e1cefc3..93feded 100644
--- a/trace_event/process_memory_maps_dump_provider.cc
+++ b/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/trace_event/process_memory_maps_dump_provider.h b/trace_event/process_memory_maps_dump_provider.h
index 543f7fd..0d30db2 100644
--- a/trace_event/process_memory_maps_dump_provider.h
+++ b/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/trace_event/process_memory_totals_dump_provider.cc b/trace_event/process_memory_totals_dump_provider.cc
index cda0ff1..125be38 100644
--- a/trace_event/process_memory_totals_dump_provider.cc
+++ b/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/trace_event/process_memory_totals_dump_provider.h b/trace_event/process_memory_totals_dump_provider.h
index 45917a8..8dae966 100644
--- a/trace_event/process_memory_totals_dump_provider.h
+++ b/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/trace_event/trace_event.h b/trace_event/trace_event.h
index e12d8f4..c30a84a 100644
--- a/trace_event/trace_event.h
+++ b/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/values.cc b/values.cc
index 061b7a1..52876cf 100644
--- a/values.cc
+++ b/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/values.h b/values.h
index 4648283..1e1cae3 100644
--- a/values.h
+++ b/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/win/pe_image_unittest.cc b/win/pe_image_unittest.cc
index 4134741..28b65a4 100644
--- a/win/pe_image_unittest.cc
+++ b/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/win/scoped_process_information_unittest.cc b/win/scoped_process_information_unittest.cc
index ccfa729..614504d 100644
--- a/win/scoped_process_information_unittest.cc
+++ b/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/win/win_util.cc b/win/win_util.cc
index a3c9ece..957f937 100644
--- a/win/win_util.cc
+++ b/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