Update from https://crrev.com/316786

List of manually-modified files:
gpu/command_buffer/service/in_process_command_buffer.cc
examples/sample_app/BUILD.gn
examples/sample_app/spinning_cube.cc
mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java
mojo/cc/context_provider_mojo.cc
mojo/cc/context_provider_mojo.h
mojo/common/trace_controller_impl.cc
mojo/gles2/command_buffer_client_impl.cc
mojo/gles2/command_buffer_client_impl.h
services/gles2/gpu_impl.cc
shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
sky/engine/core/dom/Node.cpp
sky/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java
ui/events/latency_info.cc
ui/gfx/transform.cc
ui/gfx/transform.h
ui/gfx/transform_util.cc
ui/gfx/transform_util.h

Review URL: https://codereview.chromium.org/935333002
diff --git a/BUILD.gn b/BUILD.gn
index 44e656c..e417681 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -11,12 +11,6 @@
 
 component("base") {
   sources = [
-    "third_party/dmg_fp/dmg_fp.h",
-    "third_party/dmg_fp/g_fmt.cc",
-    "third_party/dmg_fp/dtoa_wrapper.cc",
-    "third_party/icu/icu_utf.cc",
-    "third_party/icu/icu_utf.h",
-    "third_party/superfasthash/superfasthash.c",
     "allocator/allocator_extension.cc",
     "allocator/allocator_extension.h",
     "allocator/type_profiler_control.cc",
@@ -94,6 +88,8 @@
     "auto_reset.h",
     "barrier_closure.cc",
     "barrier_closure.h",
+    "base64.cc",
+    "base64.h",
     "base_export.h",
     "base_paths.cc",
     "base_paths.h",
@@ -106,8 +102,6 @@
     "base_paths_win.cc",
     "base_paths_win.h",
     "base_switches.h",
-    "base64.cc",
-    "base64.h",
     "basictypes.h",
     "big_endian.cc",
     "big_endian.h",
@@ -125,10 +119,10 @@
     "callback_internal.cc",
     "callback_internal.h",
     "cancelable_callback.h",
-    "command_line.cc",
-    "command_line.h",
     "chromeos/memory_pressure_observer_chromeos.cc",
     "chromeos/memory_pressure_observer_chromeos.h",
+    "command_line.cc",
+    "command_line.h",
     "compiler_specific.h",
     "containers/adapters.h",
     "containers/hash_tables.h",
@@ -154,6 +148,12 @@
     "debug/dump_without_crashing.h",
     "debug/gdi_debug_util_win.cc",
     "debug/gdi_debug_util_win.h",
+    "third_party/dmg_fp/dmg_fp.h",
+    "third_party/dmg_fp/dtoa_wrapper.cc",
+    "third_party/dmg_fp/g_fmt.cc",
+    "third_party/icu/icu_utf.cc",
+    "third_party/icu/icu_utf.h",
+    "third_party/superfasthash/superfasthash.c",
 
     # This file depends on files from the "allocator" target,
     # but this target does not depend on "allocator" (see
@@ -185,8 +185,6 @@
     "files/dir_reader_linux.h",
     "files/dir_reader_posix.h",
     "files/file.cc",
-    "files/file_posix.cc",
-    "files/file_win.cc",
     "files/file_enumerator.cc",
     "files/file_enumerator.h",
     "files/file_enumerator_posix.cc",
@@ -203,6 +201,7 @@
     "files/file_path_watcher_linux.cc",
     "files/file_path_watcher_mac.cc",
     "files/file_path_watcher_win.cc",
+    "files/file_posix.cc",
     "files/file_proxy.cc",
     "files/file_proxy.h",
     "files/file_util.cc",
@@ -214,6 +213,7 @@
     "files/file_util_proxy.cc",
     "files/file_util_proxy.h",
     "files/file_util_win.cc",
+    "files/file_win.cc",
     "files/important_file_writer.cc",
     "files/important_file_writer.h",
     "files/memory_mapped_file.cc",
@@ -280,8 +280,8 @@
     "mac/launchd.h",
     "mac/libdispatch_task_runner.cc",
     "mac/libdispatch_task_runner.h",
-    "mac/mac_logging.h",
     "mac/mac_logging.cc",
+    "mac/mac_logging.h",
     "mac/mac_util.h",
     "mac/mac_util.mm",
     "mac/mach_logging.cc",
@@ -378,19 +378,19 @@
     "message_loop/message_pump_mac.mm",
     "message_loop/message_pump_win.cc",
     "message_loop/message_pump_win.h",
-    "metrics/field_trial.cc",
-    "metrics/field_trial.h",
-    "metrics/sample_map.cc",
-    "metrics/sample_map.h",
-    "metrics/sample_vector.cc",
-    "metrics/sample_vector.h",
     "metrics/bucket_ranges.cc",
     "metrics/bucket_ranges.h",
+    "metrics/field_trial.cc",
+    "metrics/field_trial.h",
     "metrics/histogram.cc",
     "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_flattener.h",
     "metrics/histogram_macros.h",
@@ -402,10 +402,6 @@
     "metrics/sparse_histogram.h",
     "metrics/statistics_recorder.cc",
     "metrics/statistics_recorder.h",
-    "metrics/stats_counters.cc",
-    "metrics/stats_counters.h",
-    "metrics/stats_table.cc",
-    "metrics/stats_table.h",
     "metrics/user_metrics.cc",
     "metrics/user_metrics.h",
     "metrics/user_metrics_action.h",
@@ -414,14 +410,14 @@
     "native_library_mac.mm",
     "native_library_posix.cc",
     "native_library_win.cc",
-    "numerics/safe_conversions.h",
-    "numerics/safe_conversions_impl.h",
-    "numerics/safe_math.h",
-    "numerics/safe_math_impl.h",
     "nix/mime_util_xdg.cc",
     "nix/mime_util_xdg.h",
     "nix/xdg_util.cc",
     "nix/xdg_util.h",
+    "numerics/safe_conversions.h",
+    "numerics/safe_conversions_impl.h",
+    "numerics/safe_math.h",
+    "numerics/safe_math_impl.h",
     "observer_list.h",
     "observer_list_threadsafe.h",
     "os_compat_android.cc",
@@ -544,11 +540,11 @@
     "strings/string16.cc",
     "strings/string16.h",
     "strings/string_number_conversions.cc",
-    "strings/string_split.cc",
-    "strings/string_split.h",
     "strings/string_number_conversions.h",
     "strings/string_piece.cc",
     "strings/string_piece.h",
+    "strings/string_split.cc",
+    "strings/string_split.h",
     "strings/string_tokenizer.h",
     "strings/string_util.cc",
     "strings/string_util.h",
@@ -590,8 +586,6 @@
     "synchronization/waitable_event_watcher_posix.cc",
     "synchronization/waitable_event_watcher_win.cc",
     "synchronization/waitable_event_win.cc",
-    "system_monitor/system_monitor.cc",
-    "system_monitor/system_monitor.h",
     "sys_byteorder.h",
     "sys_info.cc",
     "sys_info.h",
@@ -604,6 +598,8 @@
     "sys_info_openbsd.cc",
     "sys_info_posix.cc",
     "sys_info_win.cc",
+    "system_monitor/system_monitor.cc",
+    "system_monitor/system_monitor.h",
     "task/cancelable_task_tracker.cc",
     "task/cancelable_task_tracker.h",
     "task_runner.cc",
@@ -644,12 +640,12 @@
     "threading/thread_local_storage_posix.cc",
     "threading/thread_local_storage_win.cc",
     "threading/thread_local_win.cc",
-    "threading/thread_restrictions.h",
     "threading/thread_restrictions.cc",
+    "threading/thread_restrictions.h",
     "threading/watchdog.cc",
     "threading/watchdog.h",
-    "threading/worker_pool.h",
     "threading/worker_pool.cc",
+    "threading/worker_pool.h",
     "threading/worker_pool_posix.cc",
     "threading/worker_pool_posix.h",
     "threading/worker_pool_win.cc",
@@ -675,6 +671,11 @@
     "timer/mock_timer.h",
     "timer/timer.cc",
     "timer/timer.h",
+    "trace_event/memory_dump_manager.cc",
+    "trace_event/memory_dump_manager.h",
+    "trace_event/memory_dump_provider.h",
+    "trace_event/process_memory_dump.cc",
+    "trace_event/process_memory_dump.h",
     "trace_event/trace_event.h",
     "trace_event/trace_event_android.cc",
     "trace_event/trace_event_argument.cc",
@@ -695,10 +696,10 @@
     "tracking_info.cc",
     "tracking_info.h",
     "tuple.h",
-    "values.cc",
-    "values.h",
     "value_conversions.cc",
     "value_conversions.h",
+    "values.cc",
+    "values.h",
     "version.cc",
     "version.h",
     "vlog.cc",
@@ -787,10 +788,10 @@
 
   if (is_android) {
     sources += [
-      "memory/discardable_memory_ashmem_allocator.cc",
-      "memory/discardable_memory_ashmem_allocator.h",
       "memory/discardable_memory_ashmem.cc",
       "memory/discardable_memory_ashmem.h",
+      "memory/discardable_memory_ashmem_allocator.cc",
+      "memory/discardable_memory_ashmem_allocator.h",
     ]
     sources -= [
       "base_paths_posix.cc",
@@ -802,12 +803,12 @@
     sources += [
       "debug/proc_maps_linux.cc",
       "files/file_path_watcher_linux.cc",
-      "process/memory_linux.cc",
+      "posix/unix_domain_socket_linux.cc",
       "process/internal_linux.cc",
+      "process/memory_linux.cc",
       "process/process_handle_linux.cc",
       "process/process_iterator_linux.cc",
       "process/process_metrics_linux.cc",
-      "posix/unix_domain_socket_linux.cc",
       "sys_info_linux.cc",
     ]
     set_sources_assignment_filter(sources_assignment_filter)
@@ -835,24 +836,24 @@
       "debug/stack_trace_posix.cc",
       "files/file_enumerator_posix.cc",
       "files/file_util_posix.cc",
+      "memory/shared_memory_posix.cc",
       "message_loop/message_pump_libevent.cc",
+      "metrics/field_trial.cc",
+      "native_library_posix.cc",
       "process/kill_posix.cc",
       "process/launch_posix.cc",
       "process/process_metrics_posix.cc",
       "process/process_posix.cc",
-      "metrics/field_trial.cc",
-      "native_library_posix.cc",
-      "memory/shared_memory_posix.cc",
       "sync_socket_posix.cc",
       "sys_info_posix.cc",
     ]
   } else {
     # Remove nacl stuff.
     sources -= [
+      "memory/shared_memory_nacl.cc",
       "os_compat_nacl.cc",
       "os_compat_nacl.h",
       "rand_util_nacl.cc",
-      "memory/shared_memory_nacl.cc",
     ]
   }
 
@@ -1126,6 +1127,10 @@
   sources = [
     "files/protect_file_posix.cc",
   ]
+
+  deps = [
+    "//base",
+  ]
 }
 
 test("base_unittests") {
@@ -1183,10 +1188,9 @@
     "gmock_unittest.cc",
     "guid_unittest.cc",
     "hash_unittest.cc",
-    "id_map_unittest.cc",
     "i18n/break_iterator_unittest.cc",
-    "i18n/char_iterator_unittest.cc",
     "i18n/case_conversion_unittest.cc",
+    "i18n/char_iterator_unittest.cc",
     "i18n/file_util_icu_unittest.cc",
     "i18n/icu_string_conversions_unittest.cc",
     "i18n/number_formatting_unittest.cc",
@@ -1195,6 +1199,7 @@
     "i18n/string_search_unittest.cc",
     "i18n/time_formatting_unittest.cc",
     "i18n/timezone_unittest.cc",
+    "id_map_unittest.cc",
     "ios/device_util_unittest.mm",
     "ios/weak_nsobject_unittest.mm",
     "json/json_parser_unittest.cc",
@@ -1233,17 +1238,17 @@
     "message_loop/message_loop_unittest.cc",
     "message_loop/message_pump_glib_unittest.cc",
     "message_loop/message_pump_io_ios_unittest.cc",
-    "metrics/sample_map_unittest.cc",
-    "metrics/sample_vector_unittest.cc",
     "metrics/bucket_ranges_unittest.cc",
     "metrics/field_trial_unittest.cc",
     "metrics/histogram_base_unittest.cc",
     "metrics/histogram_delta_serialization_unittest.cc",
     "metrics/histogram_snapshot_manager_unittest.cc",
     "metrics/histogram_unittest.cc",
+    "metrics/sample_map_unittest.cc",
+    "metrics/sample_vector_unittest.cc",
     "metrics/sparse_histogram_unittest.cc",
-    "metrics/stats_table_unittest.cc",
     "metrics/statistics_recorder_unittest.cc",
+    "numerics/safe_numerics_unittest.cc",
     "observer_list_unittest.cc",
     "os_compat_android_unittest.cc",
     "path_service_unittest.cc",
@@ -1271,7 +1276,6 @@
     "process/process_util_unittest_ios.cc",
     "profiler/tracked_time_unittest.cc",
     "rand_util_unittest.cc",
-    "numerics/safe_numerics_unittest.cc",
     "scoped_clear_errno_unittest.cc",
     "scoped_generic_unittest.cc",
     "scoped_native_library_unittest.cc",
@@ -1282,13 +1286,13 @@
     "strings/nullable_string16_unittest.cc",
     "strings/safe_sprintf_unittest.cc",
     "strings/string16_unittest.cc",
-    "strings/stringprintf_unittest.cc",
     "strings/string_number_conversions_unittest.cc",
     "strings/string_piece_unittest.cc",
     "strings/string_split_unittest.cc",
     "strings/string_tokenizer_unittest.cc",
     "strings/string_util_unittest.cc",
     "strings/stringize_macros_unittest.cc",
+    "strings/stringprintf_unittest.cc",
     "strings/sys_string_conversions_mac_unittest.mm",
     "strings/sys_string_conversions_unittest.cc",
     "strings/utf_offset_string_conversions_unittest.cc",
@@ -1330,6 +1334,7 @@
     "timer/mock_timer_unittest.cc",
     "timer/timer_unittest.cc",
     "tools_sanity_unittest.cc",
+    "trace_event/memory_dump_manager_unittest.cc",
     "trace_event/trace_event_argument_unittest.cc",
     "trace_event/trace_event_memory_unittest.cc",
     "trace_event/trace_event_synthetic_delay_unittest.cc",
@@ -1372,6 +1377,7 @@
     "//base/test:run_all_unittests",
     "//base/test:test_support",
     "//base/third_party/dynamic_annotations",
+    "//base/third_party/nspr",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/icu",
@@ -1386,7 +1392,6 @@
 
   if (is_ios) {
     sources -= [
-      "metrics/stats_table_uinittest.cc",  # Requires spawning a process.
       "process/memory_unittest.cc",
       "process/memory_unittest_mac.h",
       "process/memory_unittest_mac.mm",
@@ -1509,16 +1514,19 @@
 
   # GYP: //base.gyp:base_java_application_state
   # GYP: //base.gyp:base_java_library_load_from_apk_status_codes
+  # GYP: //base.gyp:base_java_library_process_type
   # GYP: //base.gyp:base_java_memory_pressure_level
   java_cpp_enum("base_android_java_enums_srcjar") {
     sources = [
       "android/application_status_listener.h",
       "android/library_loader/library_load_from_apk_status_codes.h",
+      "android/library_loader/library_loader_hooks.h",
       "memory/memory_pressure_listener.h",
     ]
     outputs = [
       "org/chromium/base/ApplicationState.java",
       "org/chromium/base/library_loader/LibraryLoadFromApkStatusCodes.java",
+      "org/chromium/base/library_loader/LibraryProcessType.java",
       "org/chromium/base/MemoryPressureLevel.java",
     ]
   }
diff --git a/allocator/BUILD.gn b/allocator/BUILD.gn
index 8d96317..e931b1c 100644
--- a/allocator/BUILD.gn
+++ b/allocator/BUILD.gn
@@ -46,6 +46,11 @@
   source_set("tcmalloc") {
     tcmalloc_dir = "//third_party/tcmalloc/chromium"
 
+    # Don't check tcmalloc's includes. These files include various files like
+    # base/foo.h and they actually refer to tcmalloc's forked copy of base
+    # rather than the regular one, which confuses the header checker.
+    check_includes = false
+
     sources = [
       # Generated for our configuration from tcmalloc"s build
       # and checked in.
@@ -134,7 +139,6 @@
       "$tcmalloc_dir/src/windows/port.cc",
       "$tcmalloc_dir/src/windows/port.h",
       "allocator_shim.cc",
-      "allocator_shim.h",
       "debugallocation_shim.cc",
 
       # These are both #included by allocator_shim for maximal linking.
@@ -176,10 +180,10 @@
         # cpuprofiler
         "$tcmalloc_dir/src/base/thread_lister.c",
         "$tcmalloc_dir/src/base/thread_lister.h",
-        "$tcmalloc_dir/src/profiledata.cc",
-        "$tcmalloc_dir/src/profiledata.h",
         "$tcmalloc_dir/src/profile-handler.cc",
         "$tcmalloc_dir/src/profile-handler.h",
+        "$tcmalloc_dir/src/profiledata.cc",
+        "$tcmalloc_dir/src/profiledata.h",
         "$tcmalloc_dir/src/profiler.cc",
       ]
       defines += [ "PERFTOOLS_DLL_DECL=" ]
diff --git a/allocator/allocator.gyp b/allocator/allocator.gyp
index c20325d..d426c9c 100644
--- a/allocator/allocator.gyp
+++ b/allocator/allocator.gyp
@@ -106,9 +106,9 @@
             '<(tcmalloc_dir)/src/base/abort.cc',
             '<(tcmalloc_dir)/src/base/abort.h',
             '<(tcmalloc_dir)/src/base/arm_instruction_set_select.h',
-            '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
             '<(tcmalloc_dir)/src/base/atomicops-internals-arm-generic.h',
             '<(tcmalloc_dir)/src/base/atomicops-internals-arm-v6plus.h',
+            '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
             '<(tcmalloc_dir)/src/base/atomicops-internals-macosx.h',
             '<(tcmalloc_dir)/src/base/atomicops-internals-windows.h',
             '<(tcmalloc_dir)/src/base/atomicops-internals-x86.cc',
@@ -322,10 +322,10 @@
             # cpuprofiler
             '<(tcmalloc_dir)/src/base/thread_lister.c',
             '<(tcmalloc_dir)/src/base/thread_lister.h',
-            '<(tcmalloc_dir)/src/profiledata.cc',
-            '<(tcmalloc_dir)/src/profiledata.h',
             '<(tcmalloc_dir)/src/profile-handler.cc',
             '<(tcmalloc_dir)/src/profile-handler.h',
+            '<(tcmalloc_dir)/src/profiledata.cc',
+            '<(tcmalloc_dir)/src/profiledata.h',
             '<(tcmalloc_dir)/src/profiler.cc',
           ],
         }],
@@ -434,9 +434,9 @@
             '../..',
           ],
           'sources': [
-            'allocator_unittest.cc',
             '../profiler/alternate_timer.cc',
             '../profiler/alternate_timer.h',
+            'allocator_unittest.cc',
           ],
         },
       ],
@@ -499,10 +499,10 @@
             '../..',
           ],
           'sources': [
-            'type_profiler_tcmalloc.cc',
-            'type_profiler_tcmalloc.h',
             '<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
             '<(tcmalloc_dir)/src/type_profiler_map.cc',
+            'type_profiler_tcmalloc.cc',
+            'type_profiler_tcmalloc.h',
           ],
         },
         {
@@ -542,9 +542,9 @@
             '../..',
           ],
           'sources': [
-            'type_profiler_map_unittest.cc',
             '<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
             '<(tcmalloc_dir)/src/type_profiler_map.cc',
+            'type_profiler_map_unittest.cc',
           ],
         },
       ],
diff --git a/allocator/allocator_unittest.cc b/allocator/allocator_unittest.cc
index 9471e95..a1d1ef0 100644
--- a/allocator/allocator_unittest.cc
+++ b/allocator/allocator_unittest.cc
@@ -6,7 +6,7 @@
 #include <stdlib.h>
 #include <algorithm>   // for min()
 
-#include "base/atomicops.h"
+#include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 // Number of bits in a size_t.
@@ -15,10 +15,6 @@
 static const size_t kMaxSize = ~static_cast<size_t>(0);
 // Maximum positive size of a size_t if it were signed.
 static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1);
-// An allocation size which is not too big to be reasonable.
-static const size_t kNotTooBig = 100000;
-// An allocation size which is just too big.
-static const size_t kTooBig = ~static_cast<size_t>(0);
 
 namespace {
 
@@ -82,197 +78,6 @@
   }
 }
 
-template <class AtomicType>
-static void TestAtomicIncrement() {
-  // For now, we just test single threaded execution
-
-  // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
-  // outside the expected address bounds.  This is in particular to
-  // test that some future change to the asm code doesn't cause the
-  // 32-bit NoBarrier_AtomicIncrement to do the wrong thing on 64-bit machines.
-  struct {
-    AtomicType prev_word;
-    AtomicType count;
-    AtomicType next_word;
-  } s;
-
-  AtomicType prev_word_value, next_word_value;
-  memset(&prev_word_value, 0xFF, sizeof(AtomicType));
-  memset(&next_word_value, 0xEE, sizeof(AtomicType));
-
-  s.prev_word = prev_word_value;
-  s.count = 0;
-  s.next_word = next_word_value;
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
-  EXPECT_EQ(s.count, 1);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
-  EXPECT_EQ(s.count, 3);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
-  EXPECT_EQ(s.count, 6);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
-  EXPECT_EQ(s.count, 3);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
-  EXPECT_EQ(s.count, 1);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
-  EXPECT_EQ(s.count, 0);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
-  EXPECT_EQ(s.count, -1);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
-  EXPECT_EQ(s.count, -5);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-
-  EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
-  EXPECT_EQ(s.count, 0);
-  EXPECT_EQ(s.prev_word, prev_word_value);
-  EXPECT_EQ(s.next_word, next_word_value);
-}
-
-
-#define NUM_BITS(T) (sizeof(T) * 8)
-
-
-template <class AtomicType>
-static void TestCompareAndSwap() {
-  AtomicType value = 0;
-  AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
-  EXPECT_EQ(1, value);
-  EXPECT_EQ(0, prev);
-
-  // Use test value that has non-zero bits in both halves, more for testing
-  // 64-bit implementation on 32-bit platforms.
-  const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
-                                 (NUM_BITS(AtomicType) - 2)) + 11;
-  value = k_test_val;
-  prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
-  EXPECT_EQ(k_test_val, value);
-  EXPECT_EQ(k_test_val, prev);
-
-  value = k_test_val;
-  prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
-  EXPECT_EQ(5, value);
-  EXPECT_EQ(k_test_val, prev);
-}
-
-
-template <class AtomicType>
-static void TestAtomicExchange() {
-  AtomicType value = 0;
-  AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
-  EXPECT_EQ(1, value);
-  EXPECT_EQ(0, new_value);
-
-  // Use test value that has non-zero bits in both halves, more for testing
-  // 64-bit implementation on 32-bit platforms.
-  const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
-                                 (NUM_BITS(AtomicType) - 2)) + 11;
-  value = k_test_val;
-  new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
-  EXPECT_EQ(k_test_val, value);
-  EXPECT_EQ(k_test_val, new_value);
-
-  value = k_test_val;
-  new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
-  EXPECT_EQ(5, value);
-  EXPECT_EQ(k_test_val, new_value);
-}
-
-
-template <class AtomicType>
-static void TestAtomicIncrementBounds() {
-  // Test increment at the half-width boundary of the atomic type.
-  // It is primarily for testing at the 32-bit boundary for 64-bit atomic type.
-  AtomicType test_val = static_cast<uint64_t>(1) << (NUM_BITS(AtomicType) / 2);
-  AtomicType value = test_val - 1;
-  AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
-  EXPECT_EQ(test_val, value);
-  EXPECT_EQ(value, new_value);
-
-  base::subtle::NoBarrier_AtomicIncrement(&value, -1);
-  EXPECT_EQ(test_val - 1, value);
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestStore() {
-  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
-  const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
-  AtomicType value;
-
-  base::subtle::NoBarrier_Store(&value, kVal1);
-  EXPECT_EQ(kVal1, value);
-  base::subtle::NoBarrier_Store(&value, kVal2);
-  EXPECT_EQ(kVal2, value);
-
-  base::subtle::Acquire_Store(&value, kVal1);
-  EXPECT_EQ(kVal1, value);
-  base::subtle::Acquire_Store(&value, kVal2);
-  EXPECT_EQ(kVal2, value);
-
-  base::subtle::Release_Store(&value, kVal1);
-  EXPECT_EQ(kVal1, value);
-  base::subtle::Release_Store(&value, kVal2);
-  EXPECT_EQ(kVal2, value);
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestLoad() {
-  const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
-  const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
-  AtomicType value;
-
-  value = kVal1;
-  EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
-  value = kVal2;
-  EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
-
-  value = kVal1;
-  EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
-  value = kVal2;
-  EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
-
-  value = kVal1;
-  EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
-  value = kVal2;
-  EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
-}
-
-template <class AtomicType>
-static void TestAtomicOps() {
-  TestCompareAndSwap<AtomicType>();
-  TestAtomicExchange<AtomicType>();
-  TestAtomicIncrementBounds<AtomicType>();
-  TestStore<AtomicType>();
-  TestLoad<AtomicType>();
-}
-
 static void TestCalloc(size_t n, size_t s, bool ok) {
   char* p = reinterpret_cast<char*>(calloc(n, s));
   if (!ok) {
@@ -287,80 +92,10 @@
   }
 }
 
-// MSVC C4530 complains about exception handler usage when exceptions are
-// disabled.  Temporarily disable that warning so we can test that they are, in
-// fact, disabled.
-#if defined(OS_WIN)
-#pragma warning(push)
-#pragma warning(disable: 4530)
-#endif
-
-// A global test counter for number of times the NewHandler is called.
-static int news_handled = 0;
-static void TestNewHandler() {
-  ++news_handled;
-  throw std::bad_alloc();
-}
-
-// Because we compile without exceptions, we expect these will not throw.
-static void TestOneNewWithoutExceptions(void* (*func)(size_t),
-                                        bool should_throw) {
-  // success test
-  try {
-    void* ptr = (*func)(kNotTooBig);
-    EXPECT_NE(reinterpret_cast<void*>(NULL), ptr) <<
-        "allocation should not have failed.";
-  } catch(...) {
-    EXPECT_EQ(0, 1) << "allocation threw unexpected exception.";
-  }
-
-  // failure test
-  try {
-    void* rv = (*func)(kTooBig);
-    EXPECT_EQ(NULL, rv);
-    EXPECT_FALSE(should_throw) << "allocation should have thrown.";
-  } catch(...) {
-    EXPECT_TRUE(should_throw) << "allocation threw unexpected exception.";
-  }
-}
-
-static void TestNothrowNew(void* (*func)(size_t)) {
-  news_handled = 0;
-
-  // test without new_handler:
-  std::new_handler saved_handler = std::set_new_handler(0);
-  TestOneNewWithoutExceptions(func, false);
-
-  // test with new_handler:
-  std::set_new_handler(TestNewHandler);
-  TestOneNewWithoutExceptions(func, true);
-  EXPECT_EQ(news_handled, 1) << "nothrow new_handler was not called.";
-  std::set_new_handler(saved_handler);
-}
-
-#if defined(OS_WIN)
-#pragma warning(pop)
-#endif
-
 }  // namespace
 
 //-----------------------------------------------------------------------------
 
-TEST(Atomics, AtomicIncrementWord) {
-  TestAtomicIncrement<base::subtle::AtomicWord>();
-}
-
-TEST(Atomics, AtomicIncrement32) {
-  TestAtomicIncrement<base::subtle::Atomic32>();
-}
-
-TEST(Atomics, AtomicOpsWord) {
-  TestAtomicIncrement<base::subtle::AtomicWord>();
-}
-
-TEST(Atomics, AtomicOps32) {
-  TestAtomicIncrement<base::subtle::Atomic32>();
-}
 
 TEST(Allocators, Malloc) {
   // Try allocating data with a bunch of alignments and sizes
@@ -394,11 +129,6 @@
   TestCalloc(kMaxSignedSize, kMaxSignedSize, false);
 }
 
-TEST(Allocators, New) {
-  TestNothrowNew(&::operator new);
-  TestNothrowNew(&::operator new[]);
-}
-
 // This makes sure that reallocing a small number of bytes in either
 // direction doesn't cause us to allocate new memory.
 TEST(Allocators, Realloc1) {
@@ -458,23 +188,6 @@
   free(p);
 }
 
-// tcmalloc uses these semantics but system allocators can return NULL for
-// realloc(ptr, 0).
-#if defined(USE_TCMALLOC)
-TEST(Allocators, ReallocZero) {
-  // Test that realloc to zero does not return NULL.
-  for (int size = 0; size >= 0; size = NextSize(size)) {
-    char* ptr = reinterpret_cast<char*>(malloc(size));
-    EXPECT_NE(static_cast<char*>(NULL), ptr);
-    ptr = reinterpret_cast<char*>(realloc(ptr, 0));
-    EXPECT_NE(static_cast<char*>(NULL), ptr);
-    if (ptr)
-      free(ptr);
-  }
-}
-#endif
-
-#ifdef WIN32
 // Test recalloc
 TEST(Allocators, Recalloc) {
   for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
@@ -499,7 +212,7 @@
   // Try allocating data with a bunch of alignments and sizes
   static const int kTestAlignments[] = {8, 16, 256, 4096, 8192, 16384};
   for (int size = 1; size > 0; size = NextSize(size)) {
-    for (int i = 0; i < ARRAYSIZE(kTestAlignments); ++i) {
+    for (int i = 0; i < arraysize(kTestAlignments); ++i) {
       unsigned char* ptr = static_cast<unsigned char*>(
           _aligned_malloc(size, kTestAlignments[i]));
       CheckAlignment(ptr, kTestAlignments[i]);
@@ -526,9 +239,6 @@
   }
 }
 
-#endif
-
-
 int main(int argc, char** argv) {
   testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
diff --git a/android/application_status_listener.cc b/android/application_status_listener.cc
index f487072..02178c4 100644
--- a/android/application_status_listener.cc
+++ b/android/application_status_listener.cc
@@ -60,7 +60,8 @@
 // static
 void ApplicationStatusListener::NotifyApplicationStateChange(
     ApplicationState state) {
-  g_observers.Get().Notify(&ApplicationStatusListener::Notify, state);
+  g_observers.Get().Notify(FROM_HERE, &ApplicationStatusListener::Notify,
+                           state);
 }
 
 static void OnApplicationStateChange(JNIEnv* env,
diff --git a/android/build_info.h b/android/build_info.h
index cef8145..e4e84e8 100644
--- a/android/build_info.h
+++ b/android/build_info.h
@@ -15,6 +15,19 @@
 namespace base {
 namespace android {
 
+// This enumeration maps to the values returned by BuildInfo::sdk_int(),
+// indicating the Android release associated with a given SDK version.
+enum SdkVersion {
+  SDK_VERSION_ICE_CREAM_SANDWICH = 14,
+  SDK_VERSION_ICE_CREAM_SANDWICH_MR1 = 15,
+  SDK_VERSION_JELLY_BEAN = 16,
+  SDK_VERSION_JELLY_BEAN_MR1 = 17,
+  SDK_VERSION_JELLY_BEAN_MR2 = 18,
+  SDK_VERSION_KITKAT = 19,
+  SDK_VERSION_KITKAT_WEAR = 20,
+  SDK_VERSION_LOLLIPOP = 21
+};
+
 // BuildInfo is a singleton class that stores android build and device
 // information. It will be called from Android specific code and gets used
 // primarily in crash reporting.
diff --git a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 2168c21..d68fb4a 100644
--- a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -8,6 +8,7 @@
 import android.os.SystemClock;
 import android.util.Log;
 
+import org.chromium.base.CalledByNative;
 import org.chromium.base.CommandLine;
 import org.chromium.base.JNINamespace;
 import org.chromium.base.TraceEvent;
@@ -40,41 +41,68 @@
     // Guards all access to the libraries
     private static final Object sLock = new Object();
 
+    // The singleton instance of LibraryLoader.
+    private static LibraryLoader sInstance;
+
     // One-way switch becomes true when the libraries are loaded.
-    private static boolean sLoaded = false;
+    private boolean mLoaded;
 
     // One-way switch becomes true when the Java command line is switched to
     // native.
-    private static boolean sCommandLineSwitched = false;
+    private boolean mCommandLineSwitched;
 
     // One-way switch becomes true when the libraries are initialized (
     // by calling nativeLibraryLoaded, which forwards to LibraryLoaded(...) in
     // library_loader_hooks.cc).
-    private static boolean sInitialized = false;
+    private boolean mInitialized;
 
     // One-way switches recording attempts to use Relro sharing in the browser.
     // The flags are used to report UMA stats later.
-    private static boolean sIsUsingBrowserSharedRelros = false;
-    private static boolean sLoadAtFixedAddressFailed = false;
+    private boolean mIsUsingBrowserSharedRelros;
+    private boolean mLoadAtFixedAddressFailed;
 
     // One-way switch becomes true if the device supports memory mapping the
     // APK file with executable permissions.
-    private static boolean sMapApkWithExecPermission = false;
+    private boolean mMapApkWithExecPermission;
 
     // One-way switch to indicate whether we probe for memory mapping the APK
     // file with executable permissions. We suppress the probe under some
     // conditions.
     // For more, see:
     //   https://code.google.com/p/chromium/issues/detail?id=448084
-    private static boolean sProbeMapApkWithExecPermission = true;
+    private boolean mProbeMapApkWithExecPermission = true;
 
     // One-way switch becomes true if the Chromium library was loaded from the
     // APK file directly.
-    private static boolean sLibraryWasLoadedFromApk = false;
+    private boolean mLibraryWasLoadedFromApk;
 
     // One-way switch becomes false if the Chromium library should be loaded
     // directly from the APK file but it was compressed or not aligned.
-    private static boolean sLibraryIsMappableInApk = true;
+    private boolean mLibraryIsMappableInApk = true;
+
+    // The type of process the shared library is loaded in.
+    private int mLibraryProcessType;
+
+    /**
+     * @param libraryProcessType the process the shared library is loaded in. refer to
+     *                           LibraryProcessType for possible values.
+     * @return LibraryLoader if existing, otherwise create a new one.
+     */
+    public static LibraryLoader get(int libraryProcessType) throws ProcessInitException {
+        synchronized (sLock) {
+            if (sInstance != null) {
+                if (sInstance.mLibraryProcessType == libraryProcessType) return sInstance;
+                throw new ProcessInitException(
+                        LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED);
+            }
+            sInstance = new LibraryLoader(libraryProcessType);
+            return sInstance;
+        }
+    }
+
+    private LibraryLoader(int libraryProcessType) {
+        mLibraryProcessType = libraryProcessType;
+    }
 
     /**
      * The same as ensureInitialized(null, false), should only be called
@@ -82,7 +110,7 @@
      *
      * @throws ProcessInitException
      */
-    public static void ensureInitialized() throws ProcessInitException {
+    public void ensureInitialized() throws ProcessInitException {
         ensureInitialized(null, false);
     }
 
@@ -96,11 +124,11 @@
      *  @param shouldDeleteFallbackLibraries The flag tells whether the method
      *    should delete the fallback libraries or not.
      */
-    public static void ensureInitialized(
+    public void ensureInitialized(
             Context context, boolean shouldDeleteFallbackLibraries)
             throws ProcessInitException {
         synchronized (sLock) {
-            if (sInitialized) {
+            if (mInitialized) {
                 // Already initialized, nothing to do.
                 return;
             }
@@ -114,7 +142,7 @@
      */
     public static boolean isInitialized() {
         synchronized (sLock) {
-            return sInitialized;
+            return sInstance != null && sInstance.mInitialized;
         }
     }
 
@@ -124,7 +152,7 @@
      *
      * @throws ProcessInitException
      */
-    public static void loadNow() throws ProcessInitException {
+    public void loadNow() throws ProcessInitException {
         loadNow(null, false);
     }
 
@@ -141,7 +169,7 @@
      *
      * @throws ProcessInitException if the native library failed to load.
      */
-    public static void loadNow(Context context, boolean shouldDeleteFallbackLibraries)
+    public void loadNow(Context context, boolean shouldDeleteFallbackLibraries)
             throws ProcessInitException {
         synchronized (sLock) {
             loadAlreadyLocked(context, shouldDeleteFallbackLibraries);
@@ -153,19 +181,19 @@
      * native will call its "main" thread. The library must have previously been
      * loaded with loadNow.
      */
-    public static void initialize() throws ProcessInitException {
+    public void initialize() throws ProcessInitException {
         synchronized (sLock) {
             initializeAlreadyLocked();
         }
     }
 
     // Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code
-    private static void loadAlreadyLocked(
+    private void loadAlreadyLocked(
             Context context, boolean shouldDeleteFallbackLibraries)
             throws ProcessInitException {
         try {
-            if (!sLoaded) {
-                assert !sInitialized;
+            if (!mLoaded) {
+                assert !mInitialized;
 
                 long startTime = SystemClock.uptimeMillis();
                 boolean useChromiumLinker = Linker.isUsed();
@@ -183,17 +211,17 @@
                     if (manufacturer != null
                             && manufacturer.toLowerCase(Locale.ENGLISH).contains("samsung")) {
                         Log.w(TAG, "Suppressed load from APK support check on this device");
-                        sProbeMapApkWithExecPermission = false;
+                        mProbeMapApkWithExecPermission = false;
                     }
 
                     // Check if the device supports memory mapping the APK file
                     // with executable permissions.
                     if (context != null) {
                         apkFilePath = context.getApplicationInfo().sourceDir;
-                        if (sProbeMapApkWithExecPermission) {
-                            sMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
+                        if (mProbeMapApkWithExecPermission) {
+                            mMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
                         }
-                        if (!sMapApkWithExecPermission && Linker.isInZipFile()) {
+                        if (!mMapApkWithExecPermission && Linker.isInZipFile()) {
                             Log.w(TAG, "the no map executable support fallback will be used because"
                                     + " memory mapping the APK file with executable permissions is"
                                     + " not supported");
@@ -222,9 +250,9 @@
                         if (apkFilePath != null && Linker.isInZipFile()) {
                             // The library is in the APK file.
                             if (!Linker.checkLibraryIsMappableInApk(apkFilePath, libFilePath)) {
-                                sLibraryIsMappableInApk = false;
+                                mLibraryIsMappableInApk = false;
                             }
-                            if (sLibraryIsMappableInApk || useMapExecSupportFallback) {
+                            if (mLibraryIsMappableInApk || useMapExecSupportFallback) {
                                 // Load directly from the APK (or use the no map executable
                                 // support fallback, see crazy_linker_elf_loader.cpp).
                                 zipFilePath = apkFilePath;
@@ -251,7 +279,7 @@
                         // Load the library.
                         boolean isLoaded = false;
                         if (Linker.isUsingBrowserSharedRelros()) {
-                            sIsUsingBrowserSharedRelros = true;
+                            mIsUsingBrowserSharedRelros = true;
                             try {
                                 loadLibrary(zipFilePath, libFilePath);
                                 isLoaded = true;
@@ -259,7 +287,7 @@
                                 Log.w(TAG, "Failed to load native library with shared RELRO, "
                                         + "retrying without");
                                 Linker.disableSharedRelros();
-                                sLoadAtFixedAddressFailed = true;
+                                mLoadAtFixedAddressFailed = true;
                             }
                         }
                         if (!isLoaded) {
@@ -287,7 +315,7 @@
                         startTime % 10000,
                         stopTime % 10000));
 
-                sLoaded = true;
+                mLoaded = true;
             }
         } catch (UnsatisfiedLinkError e) {
             throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED, e);
@@ -305,17 +333,17 @@
 
     // Load a native shared library with the Chromium linker. If the zip file
     // path is not null, the library is loaded directly from the zip file.
-    private static void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
+    private void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
         Linker.loadLibrary(zipFilePath, libFilePath);
         if (zipFilePath != null) {
-            sLibraryWasLoadedFromApk = true;
+            mLibraryWasLoadedFromApk = true;
         }
     }
 
     // The WebView requires the Command Line to be switched over before
     // initialization is done. This is okay in the WebView's case since the
     // JNI is already loaded by this point.
-    public static void switchCommandLineForWebView() {
+    public void switchCommandLineForWebView() {
         synchronized (sLock) {
             ensureCommandLineSwitchedAlreadyLocked();
         }
@@ -324,24 +352,24 @@
     // Switch the CommandLine over from Java to native if it hasn't already been done.
     // This must happen after the code is loaded and after JNI is ready (since after the
     // switch the Java CommandLine will delegate all calls the native CommandLine).
-    private static void ensureCommandLineSwitchedAlreadyLocked() {
-        assert sLoaded;
-        if (sCommandLineSwitched) {
+    private void ensureCommandLineSwitchedAlreadyLocked() {
+        assert mLoaded;
+        if (mCommandLineSwitched) {
             return;
         }
         nativeInitCommandLine(CommandLine.getJavaSwitchesOrNull());
         CommandLine.enableNativeProxy();
-        sCommandLineSwitched = true;
+        mCommandLineSwitched = true;
     }
 
     // Invoke base::android::LibraryLoaded in library_loader_hooks.cc
-    private static void initializeAlreadyLocked() throws ProcessInitException {
-        if (sInitialized) {
+    private void initializeAlreadyLocked() throws ProcessInitException {
+        if (mInitialized) {
             return;
         }
 
         // Setup the native command line if necessary.
-        if (!sCommandLineSwitched) {
+        if (!mCommandLineSwitched) {
             nativeInitCommandLine(CommandLine.getJavaSwitchesOrNull());
         }
 
@@ -352,13 +380,13 @@
         // From this point on, native code is ready to use and checkIsReady()
         // shouldn't complain from now on (and in fact, it's used by the
         // following calls).
-        sInitialized = true;
+        mInitialized = true;
 
         // The Chrome JNI is registered by now so we can switch the Java
         // command line over to delegating to native if it's necessary.
-        if (!sCommandLineSwitched) {
+        if (!mCommandLineSwitched) {
             CommandLine.enableNativeProxy();
-            sCommandLineSwitched = true;
+            mCommandLineSwitched = true;
         }
 
         // From now on, keep tracing in sync with native.
@@ -366,32 +394,32 @@
     }
 
     // Called after all native initializations are complete.
-    public static void onNativeInitializationComplete(Context context) {
+    public void onNativeInitializationComplete(Context context) {
         recordBrowserProcessHistogram(context);
     }
 
     // Record Chromium linker histogram state for the main browser process. Called from
     // onNativeInitializationComplete().
-    private static void recordBrowserProcessHistogram(Context context) {
+    private void recordBrowserProcessHistogram(Context context) {
         if (Linker.isUsed()) {
-            nativeRecordChromiumAndroidLinkerBrowserHistogram(sIsUsingBrowserSharedRelros,
-                                                              sLoadAtFixedAddressFailed,
+            nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSharedRelros,
+                                                              mLoadAtFixedAddressFailed,
                                                               getLibraryLoadFromApkStatus(context));
         }
     }
 
     // Returns the device's status for loading a library directly from the APK file.
     // This method can only be called when the Chromium linker is used.
-    private static int getLibraryLoadFromApkStatus(Context context) {
+    private int getLibraryLoadFromApkStatus(Context context) {
         assert Linker.isUsed();
 
-        if (sLibraryWasLoadedFromApk) {
-            return sMapApkWithExecPermission
+        if (mLibraryWasLoadedFromApk) {
+            return mMapApkWithExecPermission
                     ? LibraryLoadFromApkStatusCodes.SUCCESSFUL
                     : LibraryLoadFromApkStatusCodes.USED_NO_MAP_EXEC_SUPPORT_FALLBACK;
         }
 
-        if (!sLibraryIsMappableInApk) {
+        if (!mLibraryIsMappableInApk) {
             return LibraryLoadFromApkStatusCodes.USED_UNPACK_LIBRARY_FALLBACK;
         }
 
@@ -400,11 +428,11 @@
             return LibraryLoadFromApkStatusCodes.UNKNOWN;
         }
 
-        if (!sProbeMapApkWithExecPermission) {
+        if (!mProbeMapApkWithExecPermission) {
             return LibraryLoadFromApkStatusCodes.UNKNOWN;
         }
 
-        return sMapApkWithExecPermission
+        return mMapApkWithExecPermission
                 ? LibraryLoadFromApkStatusCodes.SUPPORTED
                 : LibraryLoadFromApkStatusCodes.NOT_SUPPORTED;
     }
@@ -413,15 +441,27 @@
     // recorded as a histogram immediately because histograms and IPC are not ready at the
     // time it are captured. This function stores a pending value, so that a later call to
     // RecordChromiumAndroidLinkerRendererHistogram() will record it correctly.
-    public static void registerRendererProcessHistogram(boolean requestedSharedRelro,
-                                                        boolean loadAtFixedAddressFailed) {
+    public void registerRendererProcessHistogram(boolean requestedSharedRelro,
+                                                 boolean loadAtFixedAddressFailed) {
         if (Linker.isUsed()) {
             nativeRegisterChromiumAndroidLinkerRendererHistogram(requestedSharedRelro,
                                                                  loadAtFixedAddressFailed);
         }
     }
 
-    private static native void nativeInitCommandLine(String[] initCommandLine);
+    /**
+     * @return the process the shared library is loaded in, see the LibraryProcessType
+     *         for possible values.
+     */
+    @CalledByNative
+    public static int getLibraryProcessType() {
+        synchronized (sLock) {
+            if (sInstance == null) return LibraryProcessType.PROCESS_UNINITIALIZED;
+            return sInstance.mLibraryProcessType;
+        }
+    }
+
+    private native void nativeInitCommandLine(String[] initCommandLine);
 
     // Only methods needed before or during normal JNI registration are during System.OnLoad.
     // nativeLibraryLoaded is then called to register everything else.  This process is called
@@ -429,13 +469,13 @@
     // definition in base/android/library_loader/library_loader_hooks.cc.
     //
     // Return true on success and false on failure.
-    private static native boolean nativeLibraryLoaded();
+    private native boolean nativeLibraryLoaded();
 
     // Method called to record statistics about the Chromium linker operation for the main
     // browser process. Indicates whether the linker attempted relro sharing for the browser,
     // and if it did, whether the library failed to load at a fixed address. Also records
     // support for loading a library directly from the APK file.
-    private static native void nativeRecordChromiumAndroidLinkerBrowserHistogram(
+    private native void nativeRecordChromiumAndroidLinkerBrowserHistogram(
             boolean isUsingBrowserSharedRelros,
             boolean loadAtFixedAddressFailed,
             int libraryLoadFromApkStatus);
@@ -443,11 +483,11 @@
     // Method called to register (for later recording) statistics about the Chromium linker
     // operation for a renderer process. Indicates whether the linker attempted relro sharing,
     // and if it did, whether the library failed to load at a fixed address.
-    private static native void nativeRegisterChromiumAndroidLinkerRendererHistogram(
+    private native void nativeRegisterChromiumAndroidLinkerRendererHistogram(
             boolean requestedSharedRelro,
             boolean loadAtFixedAddressFailed);
 
     // Get the version of the native library. This is needed so that we can check we
     // have the right version before initializing the (rest of the) JNI.
-    private static native String nativeGetVersionNumber();
+    private native String nativeGetVersionNumber();
 }
diff --git a/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/android/java/src/org/chromium/base/metrics/RecordHistogram.java
index 050708c..08c314f 100644
--- a/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ b/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -7,16 +7,21 @@
 import org.chromium.base.JNINamespace;
 import org.chromium.base.VisibleForTesting;
 
+import java.util.concurrent.TimeUnit;
+
 /**
- * Java API for recording UMA histograms. As opposed to macros used in native code, these calls are
- * not caching the histogram pointer; also, the JNI calls are relatively costly - avoid calling
- * these methods in performance-critical code.
+ * Java API for recording UMA histograms. Internally, the histogram will be cached by
+ * System.identityHashCode(name).
+ *
+ * Note: the JNI calls are relatively costly - avoid calling these methods in performance-critical
+ * code.
  */
 @JNINamespace("base::android")
 public class RecordHistogram {
     /**
      * Records a sample in a boolean UMA histogram of the given name. Boolean histogram has two
-     * buckets, corresponding to success (true) and failure (false).
+     * buckets, corresponding to success (true) and failure (false). This is the Java equivalent of
+     * the UMA_HISTOGRAM_BOOLEAN C++ macro.
      * @param name name of the histogram
      * @param sample sample to be recorded, either true or false
      */
@@ -26,7 +31,8 @@
 
     /**
      * Records a sample in an enumerated histogram of the given name and boundary. Note that
-     * |boundary| identifies the histogram - it should be the same at every invocation.
+     * |boundary| identifies the histogram - it should be the same at every invocation. This is the
+     * Java equivalent of the UMA_HISTOGRAM_ENUMERATION C++ macro.
      * @param name name of the histogram
      * @param sample sample to be recorded, at least 0 and at most |boundary| - 1
      * @param boundary upper bound for legal sample values - all sample values has to be strictly
@@ -37,6 +43,64 @@
     }
 
     /**
+     * Records a sample in a histogram of times. Useful for recording short durations. This is the
+     * Java equivalent of the UMA_HISTOGRAM_TIMES C++ macro.
+     * @param name name of the histogram
+     * @param duration duration to be recorded
+     * @param timeUnit the unit of the duration argument
+     */
+    public static void recordTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+        recordCustomTimesHistogramMilliseconds(
+                name, timeUnit.toMillis(duration), 1, TimeUnit.SECONDS.toMillis(10), 50);
+    }
+
+    /**
+     * Records a sample in a histogram of times. Useful for recording medium durations. This is the
+     * Java equivalent of the UMA_HISTOGRAM_MEDIUM_TIMES C++ macro.
+     * @param name name of the histogram
+     * @param duration duration to be recorded
+     * @param timeUnit the unit of the duration argument
+     */
+    public static void recordMediumTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+        recordCustomTimesHistogramMilliseconds(
+                name, timeUnit.toMillis(duration), 10, TimeUnit.MINUTES.toMillis(3), 50);
+    }
+
+    /**
+     * Records a sample in a histogram of times. Useful for recording long durations. This is the
+     * Java equivalent of the UMA_HISTOGRAM_LONG_TIMES C++ macro.
+     * @param name name of the histogram
+     * @param duration duration to be recorded
+     * @param timeUnit the unit of the duration argument
+     */
+    public static void recordLongTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+        recordCustomTimesHistogramMilliseconds(
+                name, timeUnit.toMillis(duration), 1, TimeUnit.HOURS.toMillis(1), 50);
+    }
+
+    /**
+     * Records a sample in a histogram of times with custom buckets. This is the Java equivalent of
+     * the UMA_HISTOGRAM_CUSTOM_TIMES C++ macro.
+     * @param name name of the histogram
+     * @param duration duration to be recorded
+     * @param min the minimum bucket value
+     * @param max the maximum bucket value
+     * @param timeUnit the unit of the duration, min, and max arguments
+     * @param numBuckets the number of buckets
+     */
+    public static void recordCustomTimesHistogram(
+            String name, long duration, long min, long max, TimeUnit timeUnit, int numBuckets) {
+        recordCustomTimesHistogramMilliseconds(name, timeUnit.toMillis(duration),
+                timeUnit.toMillis(min), timeUnit.toMillis(max), numBuckets);
+    }
+
+    private static void recordCustomTimesHistogramMilliseconds(
+            String name, long duration, long min, long max, int numBuckets) {
+        nativeRecordCustomTimesHistogramMilliseconds(
+                name, System.identityHashCode(name), duration, min, max, numBuckets);
+    }
+
+    /**
      * Returns the number of samples recorded in the given bucket of the given histogram.
      * @param name name of the histogram to look up
      * @param sample the bucket containing this sample value will be looked up
@@ -53,6 +117,9 @@
         nativeInitialize();
     }
 
+    private static native void nativeRecordCustomTimesHistogramMilliseconds(
+            String name, int key, long duration, long min, long max, int numBuckets);
+
     private static native void nativeRecordBooleanHistogram(String name, int key, boolean sample);
     private static native void nativeRecordEnumeratedHistogram(
             String name, int key, int sample, int boundary);
diff --git a/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java b/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
index 82c1ca9..f0489d3 100644
--- a/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
+++ b/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
@@ -8,8 +8,11 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Tests for the Java API for recording UMA histograms.
  */
@@ -17,7 +20,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        LibraryLoader.ensureInitialized();
+        LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
         RecordHistogram.initialize();
     }
 
@@ -75,4 +78,41 @@
         assertEquals(0, oneCount.getDelta());
         assertEquals(1, twoCount.getDelta());
     }
+
+    /**
+     * Tests recording of custom times histograms.
+     */
+    @SmallTest
+    public void testRecordCustomTimesHistogram() {
+        String histogram = "HelloWorld.CustomTimesMetric";
+        HistogramDelta zeroCount = new HistogramDelta(histogram, 0);
+        HistogramDelta oneCount = new HistogramDelta(histogram, 1);
+        HistogramDelta twoCount = new HistogramDelta(histogram, 100);
+
+        assertEquals(0, zeroCount.getDelta());
+        assertEquals(0, oneCount.getDelta());
+        assertEquals(0, twoCount.getDelta());
+
+        TimeUnit milli = TimeUnit.MILLISECONDS;
+
+        RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
+        assertEquals(1, zeroCount.getDelta());
+        assertEquals(0, oneCount.getDelta());
+        assertEquals(0, twoCount.getDelta());
+
+        RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
+        assertEquals(2, zeroCount.getDelta());
+        assertEquals(0, oneCount.getDelta());
+        assertEquals(0, twoCount.getDelta());
+
+        RecordHistogram.recordCustomTimesHistogram(histogram, 95, 1, 100, milli, 3);
+        assertEquals(2, zeroCount.getDelta());
+        assertEquals(1, oneCount.getDelta());
+        assertEquals(0, twoCount.getDelta());
+
+        RecordHistogram.recordCustomTimesHistogram(histogram, 200, 1, 100, milli, 3);
+        assertEquals(2, zeroCount.getDelta());
+        assertEquals(1, oneCount.getDelta());
+        assertEquals(1, twoCount.getDelta());
+    }
 }
diff --git a/android/jni_array.cc b/android/jni_array.cc
index 4bebec7..a157354 100644
--- a/android/jni_array.cc
+++ b/android/jni_array.cc
@@ -7,7 +7,6 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 
 namespace base {
 namespace android {
@@ -54,7 +53,7 @@
 
 ScopedJavaLocalRef<jintArray> ToJavaIntArray(
     JNIEnv* env, const std::vector<int>& ints) {
-  return ToJavaIntArray(env, vector_as_array(&ints), ints.size());
+  return ToJavaIntArray(env, ints.begin(), ints.size());
 }
 
 ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
@@ -73,7 +72,7 @@
 // Returns a new Java long array converted from the given int64 array.
 BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
     JNIEnv* env, const std::vector<int64>& longs) {
-  return ToJavaLongArray(env, vector_as_array(&longs), longs.size());
+  return ToJavaLongArray(env, longs.begin(), longs.size());
 }
 
 ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
diff --git a/android/jni_generator/jni_generator.py b/android/jni_generator/jni_generator.py
index 53de365..6e39c13 100755
--- a/android/jni_generator/jni_generator.py
+++ b/android/jni_generator/jni_generator.py
@@ -209,7 +209,11 @@
   @staticmethod
   def ParseJavaPSignature(signature_line):
     prefix = 'Signature: '
-    return '"%s"' % signature_line[signature_line.index(prefix) + len(prefix):]
+    index = signature_line.find(prefix)
+    if index == -1:
+      prefix = 'descriptor: '
+      index = signature_line.index(prefix)
+    return '"%s"' % signature_line[index + len(prefix):]
 
   @staticmethod
   def JavaToJni(param):
diff --git a/android/jni_generator/jni_generator_tests.py b/android/jni_generator/jni_generator_tests.py
index a7ce537..7e39cda 100755
--- a/android/jni_generator/jni_generator_tests.py
+++ b/android/jni_generator/jni_generator_tests.py
@@ -722,7 +722,7 @@
     self.assertEquals(1, len(jni_from_javap.called_by_natives))
     self.assertGoldenTextEquals(jni_from_javap.GetContent())
 
-  def testSnippnetJavap6_7(self):
+  def testSnippnetJavap6_7_8(self):
     content_javap6 = """
 public class java.util.HashSet {
 public boolean add(java.lang.Object);
@@ -736,16 +736,30 @@
   Signature: (Ljava/lang/Object;)Z
 }
 """
+
+    content_javap8 = """
+public class java.util.HashSet {
+  public boolean add(E);
+    descriptor: (Ljava/lang/Object;)Z
+}
+"""
+
     jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
                                                  TestOptions())
     jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
                                                  TestOptions())
+    jni_from_javap8 = jni_generator.JNIFromJavaP(content_javap8.split('\n'),
+                                                 TestOptions())
     self.assertTrue(jni_from_javap6.GetContent())
     self.assertTrue(jni_from_javap7.GetContent())
+    self.assertTrue(jni_from_javap8.GetContent())
     # Ensure the javap7 is correctly parsed and uses the Signature field rather
     # than the "E" parameter.
     self.assertTextEquals(jni_from_javap6.GetContent(),
                           jni_from_javap7.GetContent())
+    # Ensure the javap8 is correctly parsed and uses the descriptor field.
+    self.assertTextEquals(jni_from_javap7.GetContent(),
+                          jni_from_javap8.GetContent())
 
   def testFromJavaP(self):
     contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]),
diff --git a/android/library_loader/library_loader_hooks.cc b/android/library_loader/library_loader_hooks.cc
index 965d030..97aec8c 100644
--- a/android/library_loader/library_loader_hooks.cc
+++ b/android/library_loader/library_loader_hooks.cc
@@ -51,7 +51,7 @@
 
 static void RegisterChromiumAndroidLinkerRendererHistogram(
     JNIEnv* env,
-    jclass clazz,
+    jobject jcaller,
     jboolean requested_shared_relro,
     jboolean load_at_fixed_address_failed) {
   // Note a pending histogram value for later recording.
@@ -75,7 +75,7 @@
 
 static void RecordChromiumAndroidLinkerBrowserHistogram(
     JNIEnv* env,
-    jclass clazz,
+    jobject jcaller,
     jboolean is_using_browser_shared_relros,
     jboolean load_at_fixed_address_failed,
     jint library_load_from_apk_status) {
@@ -102,16 +102,17 @@
   g_registration_callback = func;
 }
 
-static void InitCommandLine(JNIEnv* env, jclass clazz,
+static void InitCommandLine(JNIEnv* env,
+                            jobject jcaller,
                             jobjectArray init_command_line) {
   InitNativeCommandLineFromJavaArray(env, init_command_line);
 }
 
-static jboolean LibraryLoaded(JNIEnv* env, jclass clazz) {
+static jboolean LibraryLoaded(JNIEnv* env, jobject jcaller) {
   if (g_registration_callback == NULL) {
     return true;
   }
-  return g_registration_callback(env, clazz);
+  return g_registration_callback(env, NULL);
 }
 
 void LibraryLoaderExitHook() {
@@ -132,9 +133,14 @@
   g_library_version_number = strdup(version_number);
 }
 
-jstring GetVersionNumber(JNIEnv* env, jclass clazz) {
+jstring GetVersionNumber(JNIEnv* env, jobject jcaller) {
   return ConvertUTF8ToJavaString(env, g_library_version_number).Release();
 }
 
+LibraryProcessType GetLibraryProcessType(JNIEnv* env) {
+  return static_cast<LibraryProcessType>(
+      Java_LibraryLoader_getLibraryProcessType(env));
+}
+
 }  // namespace android
 }  // namespace base
diff --git a/android/library_loader/library_loader_hooks.h b/android/library_loader/library_loader_hooks.h
index 78dc535..6203eb0 100644
--- a/android/library_loader/library_loader_hooks.h
+++ b/android/library_loader/library_loader_hooks.h
@@ -12,6 +12,19 @@
 namespace base {
 namespace android {
 
+// The process the shared library is loaded in.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.library_loader
+enum LibraryProcessType {
+  // The LibraryLoad has not been initialized.
+  PROCESS_UNINITIALIZED = 0,
+  // Shared library is running in browser process.
+  PROCESS_BROWSER = 1,
+  // Shared library is running in child process.
+  PROCESS_CHILD = 2,
+  // Shared library is running in webview process.
+  PROCESS_WEBVIEW = 3,
+};
+
 // Record any pending renderer histogram value as a histogram.  Pending values
 // are set by RegisterChromiumAndroidLinkerRendererHistogram.
 BASE_EXPORT void RecordChromiumAndroidLinkerRendererHistogram();
@@ -48,6 +61,9 @@
 // created.
 BASE_EXPORT void LibraryLoaderExitHook();
 
+// Return the process type the shared library is loaded in.
+BASE_EXPORT LibraryProcessType GetLibraryProcesssType();
+
 }  // namespace android
 }  // namespace base
 
diff --git a/android/record_histogram.cc b/android/record_histogram.cc
index 9549adc..0df0487 100644
--- a/android/record_histogram.cc
+++ b/android/record_histogram.cc
@@ -12,6 +12,7 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/synchronization/lock.h"
+#include "base/time/time.h"
 #include "jni/RecordHistogram_jni.h"
 
 namespace base {
@@ -46,20 +47,45 @@
     DCHECK(j_histogram_name);
     DCHECK(j_histogram_key);
     HistogramBase* histogram = FindLocked(j_histogram_key);
-    if (histogram)
+    int boundary = static_cast<int>(j_boundary);
+    if (histogram) {
+      DCHECK(histogram->HasConstructionArguments(1, boundary, boundary + 1));
       return histogram;
+    }
 
     std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
-    // Note: This caching bypasses the boundary validation that occurs between
-    // repeated lookups by the same name. It is up to the caller to ensure that
-    // the provided boundary remains consistent.
-    int boundary = static_cast<int>(j_boundary);
     histogram =
         LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1,
                                     HistogramBase::kUmaTargetedHistogramFlag);
     return InsertLocked(j_histogram_key, histogram);
   }
 
+  HistogramBase* CustomTimesHistogram(JNIEnv* env,
+                                      jstring j_histogram_name,
+                                      jint j_histogram_key,
+                                      jlong j_min,
+                                      jlong j_max,
+                                      jint j_bucket_count) {
+    DCHECK(j_histogram_name);
+    DCHECK(j_histogram_key);
+    HistogramBase* histogram = FindLocked(j_histogram_key);
+    int64 min = static_cast<int64>(j_min);
+    int64 max = static_cast<int64>(j_max);
+    int bucket_count = static_cast<int>(j_bucket_count);
+    if (histogram) {
+      DCHECK(histogram->HasConstructionArguments(min, max, bucket_count));
+      return histogram;
+    }
+
+    std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
+    // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet
+    // is just a convenience for constructing the underlying Histogram with
+    // TimeDelta arguments.
+    histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count,
+                                      HistogramBase::kUmaTargetedHistogramFlag);
+    return InsertLocked(j_histogram_key, histogram);
+  }
+
  private:
   HistogramBase* FindLocked(jint j_histogram_key) {
     base::AutoLock locked(lock_);
@@ -107,6 +133,20 @@
       ->Add(sample);
 }
 
+void RecordCustomTimesHistogramMilliseconds(JNIEnv* env,
+                                            jclass clazz,
+                                            jstring j_histogram_name,
+                                            jint j_histogram_key,
+                                            jlong j_duration,
+                                            jlong j_min,
+                                            jlong j_max,
+                                            jint j_num_buckets) {
+  g_histograms.Get()
+      .CustomTimesHistogram(env, j_histogram_name, j_histogram_key, j_min,
+                            j_max, j_num_buckets)
+      ->AddTime(TimeDelta::FromMilliseconds(static_cast<int64>(j_duration)));
+}
+
 void Initialize(JNIEnv* env, jclass) {
   StatisticsRecorder::Initialize();
 }
diff --git a/android/trace_event_binding.cc b/android/trace_event_binding.cc
index b8ce6d9..791b67f 100644
--- a/android/trace_event_binding.cc
+++ b/android/trace_event_binding.cc
@@ -55,7 +55,8 @@
   DISALLOW_COPY_AND_ASSIGN(TraceEventDataConverter);
 };
 
-class TraceEnabledObserver : public debug::TraceLog::EnabledStateObserver {
+class TraceEnabledObserver
+    : public trace_event::TraceLog::EnabledStateObserver {
   public:
    void OnTraceLogEnabled() override {
       JNIEnv* env = base::android::AttachCurrentThread();
@@ -72,18 +73,18 @@
 }  // namespace
 
 static void RegisterEnabledObserver(JNIEnv* env, jclass clazz) {
-  bool enabled = debug::TraceLog::GetInstance()->IsEnabled();
+  bool enabled = trace_event::TraceLog::GetInstance()->IsEnabled();
   base::android::Java_TraceEvent_setEnabled(env, enabled);
-  debug::TraceLog::GetInstance()->AddEnabledStateObserver(
+  trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
       g_trace_enabled_state_observer_.Pointer());
 }
 
 static void StartATrace(JNIEnv* env, jclass clazz) {
-  base::debug::TraceLog::GetInstance()->StartATrace();
+  base::trace_event::TraceLog::GetInstance()->StartATrace();
 }
 
 static void StopATrace(JNIEnv* env, jclass clazz) {
-  base::debug::TraceLog::GetInstance()->StopATrace();
+  base::trace_event::TraceLog::GetInstance()->StopATrace();
 }
 
 static void Instant(JNIEnv* env, jclass clazz,
diff --git a/base.gyp b/base.gyp
index 00244aa..8cd5d6a 100644
--- a/base.gyp
+++ b/base.gyp
@@ -494,10 +494,9 @@
         'gmock_unittest.cc',
         'guid_unittest.cc',
         'hash_unittest.cc',
-        'id_map_unittest.cc',
         'i18n/break_iterator_unittest.cc',
-        'i18n/char_iterator_unittest.cc',
         'i18n/case_conversion_unittest.cc',
+        'i18n/char_iterator_unittest.cc',
         'i18n/file_util_icu_unittest.cc',
         'i18n/icu_string_conversions_unittest.cc',
         'i18n/number_formatting_unittest.cc',
@@ -506,6 +505,8 @@
         'i18n/string_search_unittest.cc',
         'i18n/time_formatting_unittest.cc',
         'i18n/timezone_unittest.cc',
+        'id_map_unittest.cc',
+        'ios/crb_protocol_observers_unittest.mm',
         'ios/device_util_unittest.mm',
         'ios/weak_nsobject_unittest.mm',
         'json/json_parser_unittest.cc',
@@ -545,17 +546,18 @@
         'message_loop/message_pump_glib_unittest.cc',
         'message_loop/message_pump_io_ios_unittest.cc',
         'message_loop/message_pump_libevent_unittest.cc',
-        'metrics/sample_map_unittest.cc',
-        'metrics/sample_vector_unittest.cc',
         'metrics/bucket_ranges_unittest.cc',
         'metrics/field_trial_unittest.cc',
         'metrics/histogram_base_unittest.cc',
         'metrics/histogram_delta_serialization_unittest.cc',
+        'metrics/histogram_macros_unittest.cc',
         'metrics/histogram_snapshot_manager_unittest.cc',
         'metrics/histogram_unittest.cc',
+        'metrics/sample_map_unittest.cc',
+        'metrics/sample_vector_unittest.cc',
         'metrics/sparse_histogram_unittest.cc',
-        'metrics/stats_table_unittest.cc',
         'metrics/statistics_recorder_unittest.cc',
+        'numerics/safe_numerics_unittest.cc',
         'observer_list_unittest.cc',
         'os_compat_android_unittest.cc',
         'path_service_unittest.cc',
@@ -583,7 +585,6 @@
         'process/process_util_unittest.cc',
         'profiler/tracked_time_unittest.cc',
         'rand_util_unittest.cc',
-        'numerics/safe_numerics_unittest.cc',
         'scoped_clear_errno_unittest.cc',
         'scoped_generic_unittest.cc',
         'scoped_native_library_unittest.cc',
@@ -594,13 +595,13 @@
         'strings/nullable_string16_unittest.cc',
         'strings/safe_sprintf_unittest.cc',
         'strings/string16_unittest.cc',
-        'strings/stringprintf_unittest.cc',
         'strings/string_number_conversions_unittest.cc',
         'strings/string_piece_unittest.cc',
         'strings/string_split_unittest.cc',
         'strings/string_tokenizer_unittest.cc',
         'strings/string_util_unittest.cc',
         'strings/stringize_macros_unittest.cc',
+        'strings/stringprintf_unittest.cc',
         'strings/sys_string_conversions_mac_unittest.mm',
         'strings/sys_string_conversions_unittest.cc',
         'strings/utf_offset_string_conversions_unittest.cc',
@@ -643,6 +644,7 @@
         'timer/mock_timer_unittest.cc',
         'timer/timer_unittest.cc',
         'tools_sanity_unittest.cc',
+        'trace_event/memory_dump_manager_unittest.cc',
         'trace_event/trace_event_argument_unittest.cc',
         'trace_event/trace_event_memory_unittest.cc',
         'trace_event/trace_event_synthetic_delay_unittest.cc',
@@ -708,8 +710,6 @@
             ['exclude', '^process/process_unittest\\.cc$'],
             ['exclude', '^process/process_util_unittest\\.cc$'],
             ['include', '^process/process_util_unittest_ios\\.cc$'],
-            # Requires spawning processes.
-            ['exclude', '^metrics/stats_table_unittest\\.cc$'],
             # iOS does not use message_pump_libevent.
             ['exclude', '^message_loop/message_pump_libevent_unittest\\.cc$'],
           ],
@@ -765,8 +765,8 @@
           'sources!': [
             'file_descriptor_shuffle_unittest.cc',
             'files/dir_reader_posix_unittest.cc',
-            'threading/worker_pool_posix_unittest.cc',
             'message_loop/message_pump_libevent_unittest.cc',
+            'threading/worker_pool_posix_unittest.cc',
           ],
           # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
           'msvs_disabled_warnings': [
@@ -838,9 +838,9 @@
         '../testing/gtest.gyp:gtest',
       ],
       'sources': [
-        'threading/thread_perftest.cc',
         'message_loop/message_pump_perftest.cc',
         'test/run_all_unittests.cc',
+        'threading/thread_perftest.cc',
         '../testing/perf/perf_test.cc'
       ],
       'conditions': [
@@ -912,6 +912,8 @@
         'test/gtest_util.h',
         'test/gtest_xml_util.cc',
         'test/gtest_xml_util.h',
+        'test/histogram_tester.cc',
+        'test/histogram_tester.h',
         'test/launcher/test_launcher.cc',
         'test/launcher/test_launcher.h',
         'test/launcher/test_result.cc',
@@ -952,8 +954,6 @@
         'test/simple_test_clock.h',
         'test/simple_test_tick_clock.cc',
         'test/simple_test_tick_clock.h',
-        'test/histogram_tester.cc',
-        'test/histogram_tester.h',
         'test/task_runner_test_template.cc',
         'test/task_runner_test_template.h',
         'test/test_file_util.cc',
@@ -1374,6 +1374,15 @@
           'includes': [ '../build/android/java_cpp_template.gypi' ],
         },
         {
+          # GN: //base:base_android_java_enums_srcjar
+          'target_name': 'base_java_library_process_type',
+          'type': 'none',
+          'variables': {
+            'source_file': 'android/library_loader/library_loader_hooks.h',
+          },
+          'includes': [ '../build/android/java_cpp_enum.gypi' ],
+        },
+        {
           # GN: //base:base_java
           'target_name': 'base_java',
           'type': 'none',
@@ -1384,6 +1393,7 @@
           'dependencies': [
             'base_java_application_state',
             'base_java_library_load_from_apk_status_codes',
+            'base_java_library_process_type',
             'base_java_memory_pressure_level',
             'base_native_libraries_gen',
           ],
diff --git a/base.gypi b/base.gypi
index 6dd6fcf..37a8171 100644
--- a/base.gypi
+++ b/base.gypi
@@ -13,15 +13,6 @@
       ['base_target==1', {
         'sources': [
           '../build/build_config.h',
-          'third_party/dmg_fp/dmg_fp.h',
-          'third_party/dmg_fp/g_fmt.cc',
-          'third_party/dmg_fp/dtoa_wrapper.cc',
-          'third_party/icu/icu_utf.cc',
-          'third_party/icu/icu_utf.h',
-          'third_party/nspr/prtime.cc',
-          'third_party/nspr/prtime.h',
-          'third_party/superfasthash/superfasthash.c',
-          'third_party/xdg_mime/xdgmime.h',
           'allocator/allocator_extension.cc',
           'allocator/allocator_extension.h',
           'allocator/type_profiler_control.cc',
@@ -47,10 +38,8 @@
           'android/fifo_utils.h',
           'android/important_file_writer_android.cc',
           'android/important_file_writer_android.h',
-          'android/locale_utils.h',
-          'android/locale_utils.cc',
-          'android/scoped_java_ref.cc',
-          'android/scoped_java_ref.h',
+          'android/java_handler_thread.cc',
+          'android/java_handler_thread.h',
           'android/jni_android.cc',
           'android/jni_android.h',
           'android/jni_array.cc',
@@ -64,19 +53,21 @@
           'android/jni_utils.h',
           'android/jni_weak_ref.cc',
           'android/jni_weak_ref.h',
+          'android/library_loader/library_load_from_apk_status_codes.h',
           'android/library_loader/library_loader_hooks.cc',
           'android/library_loader/library_loader_hooks.h',
-          'android/library_loader/library_load_from_apk_status_codes.h',
+          'android/locale_utils.cc',
+          'android/locale_utils.h',
           'android/memory_pressure_listener_android.cc',
           'android/memory_pressure_listener_android.h',
-          'android/java_handler_thread.cc',
-          'android/java_handler_thread.h',
           'android/path_service_android.cc',
           'android/path_service_android.h',
           'android/path_utils.cc',
           'android/path_utils.h',
           'android/record_histogram.cc',
           'android/record_histogram.h',
+          'android/scoped_java_ref.cc',
+          'android/scoped_java_ref.h',
           'android/sys_utils.cc',
           'android/sys_utils.h',
           'android/thread_utils.h',
@@ -218,8 +209,8 @@
           'files/file_util_proxy.h',
           'files/file_util_win.cc',
           'files/file_win.cc',
-          'files/important_file_writer.h',
           'files/important_file_writer.cc',
+          'files/important_file_writer.h',
           'files/memory_mapped_file.cc',
           'files/memory_mapped_file.h',
           'files/memory_mapped_file_posix.cc',
@@ -239,6 +230,8 @@
           'hash.h',
           'id_map.h',
           'ios/block_types.h',
+          'ios/crb_protocol_observers.h',
+          'ios/crb_protocol_observers.mm',
           'ios/device_util.h',
           'ios/device_util.mm',
           'ios/ios_util.h',
@@ -284,8 +277,8 @@
           'mac/launchd.h',
           'mac/libdispatch_task_runner.cc',
           'mac/libdispatch_task_runner.h',
-          'mac/mac_logging.h',
           'mac/mac_logging.cc',
+          'mac/mac_logging.h',
           'mac/mac_util.h',
           'mac/mac_util.mm',
           'mac/mach_logging.cc',
@@ -377,10 +370,6 @@
           'message_loop/message_pump_win.cc',
           'message_loop/message_pump_win.h',
           'message_loop/timer_slack.h',
-          'metrics/sample_map.cc',
-          'metrics/sample_map.h',
-          'metrics/sample_vector.cc',
-          'metrics/sample_vector.h',
           'metrics/bucket_ranges.cc',
           'metrics/bucket_ranges.h',
           'metrics/histogram.cc',
@@ -395,14 +384,14 @@
           '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',
           'metrics/statistics_recorder.h',
-          'metrics/stats_counters.cc',
-          'metrics/stats_counters.h',
-          'metrics/stats_table.cc',
-          'metrics/stats_table.h',
           'metrics/user_metrics.cc',
           'metrics/user_metrics.h',
           'metrics/user_metrics_action.h',
@@ -415,6 +404,10 @@
           'nix/mime_util_xdg.h',
           'nix/xdg_util.cc',
           'nix/xdg_util.h',
+          'numerics/safe_conversions.h',
+          'numerics/safe_conversions_impl.h',
+          'numerics/safe_math.h',
+          'numerics/safe_math_impl.h',
           'observer_list.h',
           'observer_list_threadsafe.h',
           'os_compat_android.cc',
@@ -435,11 +428,11 @@
           'posix/unix_domain_socket_linux.h',
           'power_monitor/power_monitor.cc',
           'power_monitor/power_monitor.h',
+          'power_monitor/power_monitor_device_source.cc',
+          'power_monitor/power_monitor_device_source.h',
           'power_monitor/power_monitor_device_source_android.cc',
           'power_monitor/power_monitor_device_source_android.h',
           'power_monitor/power_monitor_device_source_chromeos.cc',
-          'power_monitor/power_monitor_device_source.cc',
-          'power_monitor/power_monitor_device_source.h',
           'power_monitor/power_monitor_device_source_ios.mm',
           'power_monitor/power_monitor_device_source_mac.mm',
           'power_monitor/power_monitor_device_source_posix.cc',
@@ -460,8 +453,8 @@
           'process/launch_mac.cc',
           'process/launch_posix.cc',
           'process/launch_win.cc',
-          'process/memory.h',
           'process/memory.cc',
+          'process/memory.h',
           'process/memory_linux.cc',
           'process/memory_mac.mm',
           'process/memory_win.cc',
@@ -484,8 +477,8 @@
           'process/process_iterator_openbsd.cc',
           'process/process_iterator_win.cc',
           'process/process_linux.cc',
-          'process/process_metrics.h',
           'process/process_metrics.cc',
+          'process/process_metrics.h',
           'process/process_metrics_freebsd.cc',
           'process/process_metrics_ios.cc',
           'process/process_metrics_linux.cc',
@@ -510,10 +503,6 @@
           'rand_util_win.cc',
           'run_loop.cc',
           'run_loop.h',
-          'numerics/safe_conversions.h',
-          'numerics/safe_conversions_impl.h',
-          'numerics/safe_math.h',
-          'numerics/safe_math_impl.h',
           'safe_strerror_posix.cc',
           'safe_strerror_posix.h',
           'scoped_generic.h',
@@ -540,11 +529,11 @@
           'strings/string16.cc',
           'strings/string16.h',
           'strings/string_number_conversions.cc',
-          'strings/string_split.cc',
-          'strings/string_split.h',
           'strings/string_number_conversions.h',
           'strings/string_piece.cc',
           'strings/string_piece.h',
+          'strings/string_split.cc',
+          'strings/string_split.h',
           'strings/string_tokenizer.h',
           'strings/string_util.cc',
           'strings/string_util.h',
@@ -583,8 +572,6 @@
           'synchronization/waitable_event_watcher_posix.cc',
           'synchronization/waitable_event_watcher_win.cc',
           'synchronization/waitable_event_win.cc',
-          'system_monitor/system_monitor.cc',
-          'system_monitor/system_monitor.h',
           'sys_byteorder.h',
           'sys_info.cc',
           'sys_info.h',
@@ -598,12 +585,23 @@
           'sys_info_openbsd.cc',
           'sys_info_posix.cc',
           'sys_info_win.cc',
+          'system_monitor/system_monitor.cc',
+          'system_monitor/system_monitor.h',
           'task/cancelable_task_tracker.cc',
           'task/cancelable_task_tracker.h',
           'task_runner.cc',
           'task_runner.h',
           'task_runner_util.h',
           'template_util.h',
+          'third_party/dmg_fp/dmg_fp.h',
+          'third_party/dmg_fp/dtoa_wrapper.cc',
+          'third_party/dmg_fp/g_fmt.cc',
+          'third_party/icu/icu_utf.cc',
+          'third_party/icu/icu_utf.h',
+          'third_party/nspr/prtime.cc',
+          'third_party/nspr/prtime.h',
+          'third_party/superfasthash/superfasthash.c',
+          'third_party/xdg_mime/xdgmime.h',
           'thread_task_runner_handle.cc',
           'thread_task_runner_handle.h',
           'threading/non_thread_safe.h',
@@ -638,12 +636,12 @@
           'threading/thread_local_storage_posix.cc',
           'threading/thread_local_storage_win.cc',
           'threading/thread_local_win.cc',
-          'threading/thread_restrictions.h',
           'threading/thread_restrictions.cc',
+          'threading/thread_restrictions.h',
           'threading/watchdog.cc',
           'threading/watchdog.h',
-          'threading/worker_pool.h',
           'threading/worker_pool.cc',
+          'threading/worker_pool.h',
           'threading/worker_pool_posix.cc',
           'threading/worker_pool_posix.h',
           'threading/worker_pool_win.cc',
@@ -669,6 +667,11 @@
           'timer/mock_timer.h',
           'timer/timer.cc',
           'timer/timer.h',
+          'trace_event/memory_dump_manager.cc',
+          'trace_event/memory_dump_manager.h',
+          'trace_event/memory_dump_provider.h',
+          'trace_event/process_memory_dump.cc',
+          'trace_event/process_memory_dump.h',
           'trace_event/trace_event.h',
           'trace_event/trace_event_android.cc',
           'trace_event/trace_event_argument.cc',
@@ -689,10 +692,10 @@
           'tracking_info.cc',
           'tracking_info.h',
           'tuple.h',
-          'values.cc',
-          'values.h',
           'value_conversions.cc',
           'value_conversions.h',
+          'values.cc',
+          'values.h',
           'version.cc',
           'version.h',
           'vlog.cc',
@@ -795,6 +798,7 @@
                'files/file_util_posix.cc',
                'files/file_util_proxy.cc',
                'files/important_file_writer.cc',
+               'files/scoped_temp_dir.cc',
                'memory/shared_memory_posix.cc',
                'native_library_posix.cc',
                'path_service.cc',
@@ -808,7 +812,6 @@
                'process/process_posix.cc',
                'rand_util_posix.cc',
                'scoped_native_library.cc',
-               'files/scoped_temp_dir.cc',
                'sys_info.cc',
                'sys_info_posix.cc',
                'third_party/dynamic_annotations/dynamic_annotations.c',
@@ -819,10 +822,10 @@
           }],
           ['OS == "android" and _toolset == "target" and >(nacl_untrusted_build)==0', {
            'sources': [
-             'memory/discardable_memory_ashmem_allocator.cc',
-             'memory/discardable_memory_ashmem_allocator.h',
              'memory/discardable_memory_ashmem.cc',
              'memory/discardable_memory_ashmem.h',
+             'memory/discardable_memory_ashmem_allocator.cc',
+             'memory/discardable_memory_ashmem_allocator.h',
            ],
           }],
           ['OS == "android" and >(nacl_untrusted_build)==0', {
diff --git a/base_unittests.isolate b/base_unittests.isolate
index 0822b24..2e33cc0 100644
--- a/base_unittests.isolate
+++ b/base_unittests.isolate
@@ -58,7 +58,7 @@
         ],
       },
     }],
-    ['OS=="mac" and asan==1', {
+    ['OS=="mac" and asan==1 and fastbuild==0', {
       'variables': {
         'files': [
           '<(PRODUCT_DIR)/base_unittests.dSYM/',
diff --git a/bind_helpers.h b/bind_helpers.h
index f8e89bd..c49b5b8 100644
--- a/bind_helpers.h
+++ b/bind_helpers.h
@@ -535,23 +535,6 @@
 template <typename List1, typename List2>
 using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
 
-template <size_t n, typename List>
-struct NthTypeImpl;
-
-template <size_t n, typename T, typename... Types>
-struct NthTypeImpl<n, TypeList<T, Types...>>
-    : NthTypeImpl<n - 1, TypeList<Types...>> {
-};
-
-template <typename T, typename... Types>
-struct NthTypeImpl<0, TypeList<T, Types...>> {
-  typedef T Type;
-};
-
-// A type-level function that extracts |n|th type from a TypeList.
-template <size_t n, typename List>
-using NthType = typename NthTypeImpl<n, List>::Type;
-
 // Used for MakeFunctionType implementation.
 template <typename R, typename ArgList>
 struct MakeFunctionTypeImpl;
diff --git a/containers/hash_tables.h b/containers/hash_tables.h
index 736e892..6bf029e 100644
--- a/containers/hash_tables.h
+++ b/containers/hash_tables.h
@@ -45,7 +45,7 @@
 #undef __DEPRECATED
 #endif
 
-#if defined(OS_ANDROID) && defined(USE_STLPORT)
+#if defined(OS_ANDROID)
 #include <hash_map>
 #include <hash_set>
 #define BASE_HASH_IMPL_NAMESPACE std
@@ -84,7 +84,7 @@
   }
 };
 
-#if !defined(USE_STLPORT)
+#if !defined(OS_ANDROID)
 // The GNU C++ library provides identity hash functions for many integral types,
 // but not for |long long|.  This hash function will truncate if |size_t| is
 // narrower than |long long|.  This is probably good enough for what we will
@@ -102,7 +102,7 @@
 DEFINE_TRIVIAL_HASH(unsigned long long);
 
 #undef DEFINE_TRIVIAL_HASH
-#endif  // !defined(USE_STLPORT)
+#endif  // !defined(OS_ANDROID)
 
 // Implement string hash functions so that strings of various flavors can
 // be used as keys in STL maps and sets.  The hash algorithm comes from the
diff --git a/files/file_path.h b/files/file_path.h
index 67bbb4b..93f9ec9 100644
--- a/files/file_path.h
+++ b/files/file_path.h
@@ -53,7 +53,7 @@
 // between char[]-based pathnames on POSIX systems and wchar_t[]-based
 // pathnames on Windows.
 //
-// Paths can't contain NULs as a precaution agaist premature truncation.
+// As a precaution against premature truncation, paths can't contain NULs.
 //
 // Because a FilePath object should not be instantiated at the global scope,
 // instead, use a FilePath::CharType[] and initialize it with
@@ -83,9 +83,9 @@
 //    in case it ever comes across such a system.  FilePath needs this support
 //    for Windows UNC paths, anyway.
 //    References:
-//    The Open Group Base Specifications Issue 7, sections 3.266 ("Pathname")
+//    The Open Group Base Specifications Issue 7, sections 3.267 ("Pathname")
 //    and 4.12 ("Pathname Resolution"), available at:
-//    http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_266
+//    http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_267
 //    http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12
 //
 //  - Windows treats c:\\ the same way it treats \\.  This was intended to
diff --git a/files/file_path_watcher_linux.cc b/files/file_path_watcher_linux.cc
index 60267df..06c517a 100644
--- a/files/file_path_watcher_linux.cc
+++ b/files/file_path_watcher_linux.cc
@@ -200,7 +200,7 @@
   CHECK_LE(0, shutdown_fd);
   CHECK_GT(FD_SETSIZE, shutdown_fd);
 
-  debug::TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
+  trace_event::TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
 
   while (true) {
     fd_set rfds;
diff --git a/files/file_util_linux.cc b/files/file_util_linux.cc
index 532962f..b230fd9 100644
--- a/files/file_util_linux.cc
+++ b/files/file_util_linux.cc
@@ -10,21 +10,6 @@
 
 #include "base/files/file_path.h"
 
-// Make sure some of the newer macros from magic.h are defined.
-// TODO(mostynb@opera.com): remove this after 2014.
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-#ifndef HUGETLBFS_MAGIC
-#define HUGETLBFS_MAGIC 0x958458f6
-#endif
-#ifndef RAMFS_MAGIC
-#define RAMFS_MAGIC 0x858458f6
-#endif
-#ifndef TMPFS_MAGIC
-#define TMPFS_MAGIC 0x01021994
-#endif
-
 namespace base {
 
 bool GetFileSystemType(const FilePath& path, FileSystemType* type) {
diff --git a/files/file_util_unittest.cc b/files/file_util_unittest.cc
index 313ed03..af932ce 100644
--- a/files/file_util_unittest.cc
+++ b/files/file_util_unittest.cc
@@ -30,6 +30,7 @@
 #include "base/files/scoped_file.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/path_service.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_file_util.h"
 #include "base/threading/platform_thread.h"
@@ -326,6 +327,13 @@
   //     |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
 
   FilePath base_a = temp_dir_.path().Append(FPL("base_a"));
+#if defined(OS_WIN)
+  // TEMP can have a lower case drive letter.
+  string16 temp_base_a = base_a.value();
+  ASSERT_FALSE(temp_base_a.empty());
+  *temp_base_a.begin() = base::ToUpperASCII(*temp_base_a.begin());
+  base_a = FilePath(temp_base_a);
+#endif
   ASSERT_TRUE(CreateDirectory(base_a));
 
   FilePath sub_a = base_a.Append(FPL("sub_a"));
@@ -428,6 +436,7 @@
 TEST_F(FileUtilTest, DevicePathToDriveLetter) {
   // Get a drive letter.
   std::wstring real_drive_letter = temp_dir_.path().value().substr(0, 2);
+  StringToUpperASCII(&real_drive_letter);
   if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
     LOG(ERROR) << "Can't get a drive letter to test with.";
     return;
@@ -1388,19 +1397,15 @@
       path.value().c_str(),
       read_only ? (attrs | FILE_ATTRIBUTE_READONLY) :
           (attrs & ~FILE_ATTRIBUTE_READONLY)));
-  // Files in the temporary directory should not be indexed ever. If this
-  // assumption change, fix this unit test accordingly.
-  // FILE_ATTRIBUTE_NOT_CONTENT_INDEXED doesn't exist on XP.
+
   DWORD expected = read_only ?
       ((attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY)) |
           FILE_ATTRIBUTE_READONLY) :
       (attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY));
-  // TODO(ripp@yandex-team.ru): this seems out of place here. If we really think
-  // it is important to verify that temp files are not indexed there should be
-  // a dedicated test for that (create a file, inspect the attributes)
-  if (win::GetVersion() >= win::VERSION_VISTA)
-    expected |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
-  attrs = GetFileAttributes(path.value().c_str());
+
+  // Ignore FILE_ATTRIBUTE_NOT_CONTENT_INDEXED if present.
+  attrs = GetFileAttributes(path.value().c_str()) &
+          ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
   ASSERT_EQ(expected, attrs);
 #else
   // On all other platforms, it involves removing/setting the write bit.
diff --git a/i18n/time_formatting.cc b/i18n/time_formatting.cc
index 917ba43..15b34a3 100644
--- a/i18n/time_formatting.cc
+++ b/i18n/time_formatting.cc
@@ -106,6 +106,12 @@
   return TimeFormat(formatter.get(), time);
 }
 
+string16 TimeFormatShortDateAndTimeWithTimeZone(const Time& time) {
+  scoped_ptr<icu::DateFormat> formatter(icu::DateFormat::createDateTimeInstance(
+      icu::DateFormat::kShort, icu::DateFormat::kLong));
+  return TimeFormat(formatter.get(), time);
+}
+
 string16 TimeFormatFriendlyDateAndTime(const Time& time) {
   scoped_ptr<icu::DateFormat> formatter(
       icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull));
diff --git a/i18n/time_formatting.h b/i18n/time_formatting.h
index 226d1a9..2053c0b 100644
--- a/i18n/time_formatting.h
+++ b/i18n/time_formatting.h
@@ -48,6 +48,11 @@
 // Returns a numeric date and time such as "12/13/52 2:44:30 PM".
 BASE_I18N_EXPORT string16 TimeFormatShortDateAndTime(const Time& time);
 
+// Returns a numeric date and time with time zone such as
+// "12/13/52 2:44:30 PM PST".
+BASE_I18N_EXPORT string16
+TimeFormatShortDateAndTimeWithTimeZone(const Time& time);
+
 // Formats a time in a friendly sentence format, e.g.
 // "Monday, March 6, 2008 2:44:30 PM".
 BASE_I18N_EXPORT string16 TimeFormatFriendlyDateAndTime(const Time& time);
diff --git a/i18n/time_formatting_unittest.cc b/i18n/time_formatting_unittest.cc
index 0c2a6e6..4739b62 100644
--- a/i18n/time_formatting_unittest.cc
+++ b/i18n/time_formatting_unittest.cc
@@ -5,10 +5,13 @@
 #include "base/i18n/time_formatting.h"
 
 #include "base/i18n/rtl.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/icu/source/common/unicode/uversion.h"
+#include "third_party/icu/source/i18n/unicode/calendar.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
 
 namespace base {
 namespace {
@@ -18,6 +21,13 @@
   15, 42, 7, 0    // 15:42:07.000
 };
 
+base::string16 GetShortTimeZone() {
+  scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+  icu::UnicodeString name;
+  zone->getDisplayName(true, icu::TimeZone::SHORT, name);
+  return base::string16(name.getBuffer(), name.length());
+}
+
 TEST(TimeFormattingTest, TimeFormatTimeOfDayDefault12h) {
   // Test for a locale defaulted to 12h clock.
   // As an instance, we use third_party/icu/source/data/locales/en.txt.
@@ -129,6 +139,8 @@
 
   EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM"),
             TimeFormatShortDateAndTime(time));
+  EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM ") + GetShortTimeZone(),
+            TimeFormatShortDateAndTimeWithTimeZone(time));
 
   EXPECT_EQ(ASCIIToUTF16("Saturday, April 30, 2011 at 3:42:07 PM"),
             TimeFormatFriendlyDateAndTime(time));
@@ -148,6 +160,8 @@
   EXPECT_EQ(ASCIIToUTF16("30/04/2011"), TimeFormatShortDateNumeric(time));
   EXPECT_EQ(ASCIIToUTF16("30/04/2011 15:42:07"),
             TimeFormatShortDateAndTime(time));
+  EXPECT_EQ(ASCIIToUTF16("30/04/2011 15:42:07 ") + GetShortTimeZone(),
+            TimeFormatShortDateAndTimeWithTimeZone(time));
   EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011 15:42:07"),
             TimeFormatFriendlyDateAndTime(time));
   EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011"),
diff --git a/ios/crb_protocol_observers.h b/ios/crb_protocol_observers.h
new file mode 100644
index 0000000..15d1656
--- /dev/null
+++ b/ios/crb_protocol_observers.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
+#define BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
+
+#import <Foundation/Foundation.h>
+
+typedef void (^ExecutionWithObserverBlock)(id);
+
+// Implements a container for observers that implement a specific Objective-C
+// protocol. The container forwards method invocations to its contained
+// observers, so that sending a message to all the observers is as simple as
+// sending the message to the container.
+@interface CRBProtocolObservers : NSObject
+
+// The Objective-C protocol that the observers in this container conform to.
+@property(nonatomic, readonly) Protocol* protocol;
+
+// Returns a CRBProtocolObservers container for observers that conform to
+// |protocol|.
++ (CRBProtocolObservers*)observersWithProtocol:(Protocol*)protocol;
+
+// Adds |observer| to this container.
+- (void)addObserver:(id)observer;
+
+// Remove |observer| from this container.
+- (void)removeObserver:(id)observer;
+
+// Executes callback on every observer. |callback| cannot be nil.
+- (void)executeOnObservers:(ExecutionWithObserverBlock)callback;
+
+@end
+
+#endif  // BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
diff --git a/ios/crb_protocol_observers.mm b/ios/crb_protocol_observers.mm
new file mode 100644
index 0000000..ee9e23f
--- /dev/null
+++ b/ios/crb_protocol_observers.mm
@@ -0,0 +1,99 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "base/ios/crb_protocol_observers.h"
+
+#include <objc/runtime.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+
+@interface CRBProtocolObservers ()
+
+// Designated initializer.
+- (id)initWithProtocol:(Protocol*)protocol;
+
+@end
+
+@implementation CRBProtocolObservers {
+  base::scoped_nsobject<Protocol> _protocol;
+  base::scoped_nsobject<NSHashTable> _observers;
+}
+
++ (CRBProtocolObservers*)observersWithProtocol:(Protocol*)protocol {
+  return [[[self alloc] initWithProtocol:protocol] autorelease];
+}
+
+- (id)init {
+  NOTREACHED();
+  return nil;
+}
+
+- (id)initWithProtocol:(Protocol*)protocol {
+  self = [super init];
+  if (self) {
+    _protocol.reset([protocol retain]);
+    _observers.reset([[NSHashTable weakObjectsHashTable] retain]);
+  }
+  return self;
+}
+
+- (Protocol*)protocol {
+  return _protocol.get();
+}
+
+- (void)addObserver:(id)observer {
+  DCHECK([observer conformsToProtocol:self.protocol]);
+  [_observers addObject:observer];
+}
+
+- (void)removeObserver:(id)observer {
+  [_observers removeObject:observer];
+}
+
+#pragma mark - NSObject
+
+- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
+  NSMethodSignature* signature = [super methodSignatureForSelector:selector];
+  if (signature)
+    return signature;
+
+  // Look for a required method in the protocol. protocol_getMethodDescription
+  // returns a struct whose fields are null if a method for the selector was
+  // not found.
+  struct objc_method_description description =
+      protocol_getMethodDescription(self.protocol, selector, YES, YES);
+  if (description.types)
+    return [NSMethodSignature signatureWithObjCTypes:description.types];
+
+  // Look for an optional method in the protocol.
+  description = protocol_getMethodDescription(self.protocol, selector, NO, YES);
+  if (description.types)
+    return [NSMethodSignature signatureWithObjCTypes:description.types];
+
+  // There is neither a required nor optional method with this selector in the
+  // protocol, so invoke -[NSObject doesNotRecognizeSelector:] to raise
+  // NSInvalidArgumentException.
+  [self doesNotRecognizeSelector:selector];
+  return nil;
+}
+
+- (void)forwardInvocation:(NSInvocation*)invocation {
+  SEL selector = [invocation selector];
+  base::scoped_nsobject<NSArray> observers([[_observers allObjects] retain]);
+  for (id observer in observers.get()) {
+    if ([observer respondsToSelector:selector])
+      [invocation invokeWithTarget:observer];
+  }
+}
+
+- (void)executeOnObservers:(ExecutionWithObserverBlock)callback {
+  DCHECK(callback);
+  base::scoped_nsobject<NSArray> observers([[_observers allObjects] retain]);
+  for (id observer in observers.get()) {
+    callback(observer);
+  }
+}
+
+@end
diff --git a/ios/crb_protocol_observers_unittest.mm b/ios/crb_protocol_observers_unittest.mm
new file mode 100644
index 0000000..d235c98
--- /dev/null
+++ b/ios/crb_protocol_observers_unittest.mm
@@ -0,0 +1,159 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "base/ios/crb_protocol_observers.h"
+#include "base/ios/weak_nsobject.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/mac/scoped_nsobject.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+@protocol TestObserver
+
+@required
+- (void)requiredMethod;
+- (void)reset;
+
+@optional
+- (void)optionalMethod;
+
+@end
+
+// Implements only the required methods in the TestObserver protocol.
+@interface TestPartialObserver : NSObject<TestObserver>
+@property(nonatomic, readonly) BOOL requiredMethodInvoked;
+@end
+
+// Implements all the methods in the TestObserver protocol.
+@interface TestCompleteObserver : TestPartialObserver<TestObserver>
+@property(nonatomic, readonly) BOOL optionalMethodInvoked;
+@end
+
+namespace {
+
+class CRBProtocolObserversTest : public PlatformTest {
+ public:
+  CRBProtocolObserversTest() {}
+
+ protected:
+  void SetUp() override {
+    PlatformTest::SetUp();
+
+    observers_.reset([[CRBProtocolObservers observersWithProtocol:
+        @protocol(TestObserver)] retain]);
+
+    partial_observer_.reset([[TestPartialObserver alloc] init]);
+    EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+
+    complete_observer_.reset([[TestCompleteObserver alloc] init]);
+    EXPECT_FALSE([complete_observer_ requiredMethodInvoked]);
+    EXPECT_FALSE([complete_observer_ optionalMethodInvoked]);
+  }
+
+  base::scoped_nsobject<id> observers_;
+  base::scoped_nsobject<TestPartialObserver> partial_observer_;
+  base::scoped_nsobject<TestCompleteObserver> complete_observer_;
+};
+
+// Verifies basic functionality of -[CRBProtocolObservers addObserver:] and
+// -[CRBProtocolObservers removeObserver:].
+TEST_F(CRBProtocolObserversTest, AddRemoveObserver) {
+  // Add an observer and verify that the CRBProtocolObservers instance forwards
+  // an invocation to it.
+  [observers_ addObserver:partial_observer_];
+  [observers_ requiredMethod];
+  EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+
+  [partial_observer_ reset];
+  EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+
+  // Remove the observer and verify that the CRBProtocolObservers instance no
+  // longer forwards an invocation to it.
+  [observers_ removeObserver:partial_observer_];
+  [observers_ requiredMethod];
+  EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers correctly forwards the invocation of a
+// required method in the protocol.
+TEST_F(CRBProtocolObserversTest, RequiredMethods) {
+  [observers_ addObserver:partial_observer_];
+  [observers_ addObserver:complete_observer_];
+  [observers_ requiredMethod];
+  EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+  EXPECT_TRUE([complete_observer_ requiredMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers correctly forwards the invocation of an
+// optional method in the protocol.
+TEST_F(CRBProtocolObserversTest, OptionalMethods) {
+  [observers_ addObserver:partial_observer_];
+  [observers_ addObserver:complete_observer_];
+  [observers_ optionalMethod];
+  EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+  EXPECT_FALSE([complete_observer_ requiredMethodInvoked]);
+  EXPECT_TRUE([complete_observer_ optionalMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers only holds a weak reference to an
+// observer.
+TEST_F(CRBProtocolObserversTest, WeakReference) {
+  base::WeakNSObject<TestPartialObserver> weak_observer(
+      partial_observer_);
+  EXPECT_TRUE(weak_observer);
+
+  [observers_ addObserver:partial_observer_];
+
+  {
+    // Need an autorelease pool here, because
+    // -[CRBProtocolObservers forwardInvocation:] creates a temporary
+    // autoreleased array that holds all the observers.
+    base::mac::ScopedNSAutoreleasePool pool;
+    [observers_ requiredMethod];
+    EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+  }
+
+  partial_observer_.reset();
+  EXPECT_FALSE(weak_observer.get());
+}
+
+}  // namespace
+
+@implementation TestPartialObserver {
+  BOOL _requiredMethodInvoked;
+}
+
+- (BOOL)requiredMethodInvoked {
+  return _requiredMethodInvoked;
+}
+
+- (void)requiredMethod {
+  _requiredMethodInvoked = YES;
+}
+
+- (void)reset {
+  _requiredMethodInvoked = NO;
+}
+
+@end
+
+@implementation TestCompleteObserver {
+  BOOL _optionalMethodInvoked;
+}
+
+- (BOOL)optionalMethodInvoked {
+  return _optionalMethodInvoked;
+}
+
+- (void)optionalMethod {
+  _optionalMethodInvoked = YES;
+}
+
+- (void)reset {
+  [super reset];
+  _optionalMethodInvoked = NO;
+}
+
+@end
diff --git a/logging.h b/logging.h
index aa243a9..cc0a5aa 100644
--- a/logging.h
+++ b/logging.h
@@ -350,7 +350,7 @@
   ((verboselevel) <= ::logging::GetVlogLevel(__FILE__))
 
 // Helper macro which avoids evaluating the arguments to a stream if
-// the condition doesn't hold.
+// the condition doesn't hold. Condition is evaluated once and only once.
 #define LAZY_STREAM(stream, condition)                                  \
   !(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream)
 
diff --git a/mac/sdk_forward_declarations.h b/mac/sdk_forward_declarations.h
index faa36ea..2795b19 100644
--- a/mac/sdk_forward_declarations.h
+++ b/mac/sdk_forward_declarations.h
@@ -219,6 +219,55 @@
 - (void)windowDidFailToExitFullScreen:(NSWindow*)window;
 @end
 
+BASE_EXPORT extern "C" NSString* const CBAdvertisementDataServiceDataKey;
+
+enum {
+  CBPeripheralStateDisconnected = 0,
+  CBPeripheralStateConnecting,
+  CBPeripheralStateConnected,
+};
+typedef NSInteger CBPeripheralState;
+
+@interface CBPeripheral : NSObject
+@property(readonly, nonatomic) CFUUIDRef UUID;
+@property(retain, readonly) NSString* name;
+@property(readonly) BOOL isConnected;
+@end
+
+enum {
+  CBCentralManagerStateUnknown = 0,
+  CBCentralManagerStateResetting,
+  CBCentralManagerStateUnsupported,
+  CBCentralManagerStateUnauthorized,
+  CBCentralManagerStatePoweredOff,
+  CBCentralManagerStatePoweredOn,
+};
+typedef NSInteger CBCentralManagerState;
+
+@protocol CBCentralManagerDelegate;
+
+@interface CBCentralManager : NSObject
+@property(readonly) CBCentralManagerState state;
+- (id)initWithDelegate:(id<CBCentralManagerDelegate>)delegate
+                 queue:(dispatch_queue_t)queue;
+- (void)scanForPeripheralsWithServices:(NSArray*)serviceUUIDs
+                               options:(NSDictionary*)options;
+- (void)stopScan;
+@end
+
+@protocol CBCentralManagerDelegate<NSObject>
+- (void)centralManagerDidUpdateState:(CBCentralManager*)central;
+- (void)centralManager:(CBCentralManager*)central
+    didDiscoverPeripheral:(CBPeripheral*)peripheral
+        advertisementData:(NSDictionary*)advertisementData
+                     RSSI:(NSNumber*)RSSI;
+@end
+
+@interface CBUUID : NSObject
+@property(nonatomic, readonly) NSData* data;
++ (CBUUID*)UUIDWithString:(NSString*)theString;
+@end
+
 #endif  // MAC_OS_X_VERSION_10_7
 
 #if !defined(MAC_OS_X_VERSION_10_8) || \
@@ -232,6 +281,10 @@
 - (CGColorRef)CGColor;
 @end
 
+@interface NSUUID : NSObject
+- (NSString*)UUIDString;
+@end
+
 #endif  // MAC_OS_X_VERSION_10_8
 
 
@@ -304,6 +357,12 @@
   NSWorkspaceLaunchWithErrorPresentation = 0x00000040
 };
 
+@interface CBPeripheral (MavericksSDK)
+@property(readonly, nonatomic) NSUUID* identifier;
+@end
+
+BASE_EXPORT extern "C" NSString* const CBAdvertisementDataIsConnectable;
+
 #else  // !MAC_OS_X_VERSION_10_9
 
 typedef enum {
@@ -345,6 +404,10 @@
 
 BASE_EXPORT extern "C" NSString* const NSAppearanceNameVibrantDark;
 
+@interface CBUUID (YosemiteSDK)
+- (NSString*)UUIDString;
+@end
+
 #endif  // MAC_OS_X_VERSION_10_10
 
 #endif  // BASE_MAC_SDK_FORWARD_DECLARATIONS_H_
diff --git a/mac/sdk_forward_declarations.mm b/mac/sdk_forward_declarations.mm
index 7a57032..4edc710 100644
--- a/mac/sdk_forward_declarations.mm
+++ b/mac/sdk_forward_declarations.mm
@@ -23,6 +23,8 @@
 NSString* const NSWindowDidChangeBackingPropertiesNotification =
     @"NSWindowDidChangeBackingPropertiesNotification";
 
+NSString* const CBAdvertisementDataServiceDataKey = @"kCBAdvDataServiceData";
+
 #endif  // MAC_OS_X_VERSION_10_7
 
 // Replicate specific 10.9 SDK declarations for building with prior SDKs.
@@ -32,6 +34,8 @@
 NSString* const NSWindowDidChangeOcclusionStateNotification =
     @"NSWindowDidChangeOcclusionStateNotification";
 
+NSString* const CBAdvertisementDataIsConnectable = @"kCBAdvDataIsConnectable";
+
 #endif  // MAC_OS_X_VERSION_10_9
 
 // Replicate specific 10.10 SDK declarations for building with prior SDKs.
diff --git a/macros.h b/macros.h
index 15408bc..3ea576c 100644
--- a/macros.h
+++ b/macros.h
@@ -63,7 +63,7 @@
 char (&ArraySizeHelper(const T (&array)[N]))[N];
 #endif
 
-#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+#define arraysize(array) (sizeof(::ArraySizeHelper(array)))
 
 
 // Use implicit_cast as a safe version of static_cast or const_cast
diff --git a/memory/discardable_memory.h b/memory/discardable_memory.h
index d8b7a58..c49a99f 100644
--- a/memory/discardable_memory.h
+++ b/memory/discardable_memory.h
@@ -89,10 +89,6 @@
   // Create a DiscardableMemory instance with preferred type and |size|.
   static scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size);
 
-  // Discardable memory implementations might use this to release memory
-  // or resources assigned to instances that have been purged.
-  static void ReleaseFreeMemory();
-
   // Discardable memory implementations might allow an elevated usage level
   // while in frequent use. Call this to have the usage reduced to the base
   // level. Returns true if there's no need to call this again until
@@ -118,12 +114,6 @@
   // Returns the memory address held by this object. The object must be locked
   // before calling this. Otherwise, this will cause a DCHECK error.
   virtual void* Memory() const = 0;
-
-  // Testing utility calls.
-
-  // Purge all discardable memory in the system. This call has global effects
-  // across all running processes, so it should only be used for testing!
-  static void PurgeForTesting();
 };
 
 }  // namespace base
diff --git a/memory/discardable_memory_android.cc b/memory/discardable_memory_android.cc
index de71124..27b390f 100644
--- a/memory/discardable_memory_android.cc
+++ b/memory/discardable_memory_android.cc
@@ -44,11 +44,6 @@
 }  // namespace
 
 // static
-void DiscardableMemory::ReleaseFreeMemory() {
-  internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
 bool DiscardableMemory::ReduceMemoryUsage() {
   return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
 }
@@ -104,11 +99,4 @@
   return nullptr;
 }
 
-// static
-void DiscardableMemory::PurgeForTesting() {
-  g_shared_state.Pointer()->manager.PurgeAll();
-  internal::DiscardableMemoryEmulated::PurgeForTesting();
-  internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
 }  // namespace base
diff --git a/memory/discardable_memory_ashmem.cc b/memory/discardable_memory_ashmem.cc
index df0697c..a590e53 100644
--- a/memory/discardable_memory_ashmem.cc
+++ b/memory/discardable_memory_ashmem.cc
@@ -71,9 +71,5 @@
   ashmem_chunk_.reset();
 }
 
-bool DiscardableMemoryAshmem::IsMemoryResident() const {
-  return true;
-}
-
 }  // namespace internal
 }  // namespace base
diff --git a/memory/discardable_memory_ashmem.h b/memory/discardable_memory_ashmem.h
index 100655b..1269cc2 100644
--- a/memory/discardable_memory_ashmem.h
+++ b/memory/discardable_memory_ashmem.h
@@ -38,7 +38,6 @@
   bool AllocateAndAcquireLock() override;
   void ReleaseLock() override;
   void Purge() override;
-  bool IsMemoryResident() const override;
 
  private:
   const size_t bytes_;
diff --git a/memory/discardable_memory_emulated.cc b/memory/discardable_memory_emulated.cc
index 4303400..b12d7ce 100644
--- a/memory/discardable_memory_emulated.cc
+++ b/memory/discardable_memory_emulated.cc
@@ -68,11 +68,6 @@
   g_manager.Pointer()->ReduceMemoryUsageUntilWithinLimit(bytes);
 }
 
-// static
-void DiscardableMemoryEmulated::PurgeForTesting() {
-  g_manager.Pointer()->PurgeAll();
-}
-
 bool DiscardableMemoryEmulated::Initialize() {
   return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
 }
@@ -113,9 +108,5 @@
   memory_.reset();
 }
 
-bool DiscardableMemoryEmulated::IsMemoryResident() const {
-  return true;
-}
-
 }  // namespace internal
 }  // namespace base
diff --git a/memory/discardable_memory_emulated.h b/memory/discardable_memory_emulated.h
index 150c1ab..aa01a9d 100644
--- a/memory/discardable_memory_emulated.h
+++ b/memory/discardable_memory_emulated.h
@@ -26,8 +26,6 @@
   // unavailable in kernel space. crbug.com/400423
   BASE_EXPORT static void ReduceMemoryUsageUntilWithinLimit(size_t bytes);
 
-  static void PurgeForTesting();
-
   bool Initialize();
 
   // Overridden from DiscardableMemory:
@@ -39,7 +37,6 @@
   bool AllocateAndAcquireLock() override;
   void ReleaseLock() override {}
   void Purge() override;
-  bool IsMemoryResident() const override;
 
  private:
   const size_t bytes_;
diff --git a/memory/discardable_memory_linux.cc b/memory/discardable_memory_linux.cc
index 9b4e940..977b029 100644
--- a/memory/discardable_memory_linux.cc
+++ b/memory/discardable_memory_linux.cc
@@ -11,11 +11,6 @@
 namespace base {
 
 // static
-void DiscardableMemory::ReleaseFreeMemory() {
-  internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
 bool DiscardableMemory::ReduceMemoryUsage() {
   return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
 }
@@ -61,10 +56,4 @@
   return nullptr;
 }
 
-// static
-void DiscardableMemory::PurgeForTesting() {
-  internal::DiscardableMemoryEmulated::PurgeForTesting();
-  internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
 }  // namespace base
diff --git a/memory/discardable_memory_mac.cc b/memory/discardable_memory_mac.cc
index 18cf80a..c8669a6 100644
--- a/memory/discardable_memory_mac.cc
+++ b/memory/discardable_memory_mac.cc
@@ -14,11 +14,6 @@
 namespace base {
 
 // static
-void DiscardableMemory::ReleaseFreeMemory() {
-  internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
 bool DiscardableMemory::ReduceMemoryUsage() {
   return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
 }
@@ -72,11 +67,4 @@
   return nullptr;
 }
 
-// static
-void DiscardableMemory::PurgeForTesting() {
-  internal::DiscardableMemoryMach::PurgeForTesting();
-  internal::DiscardableMemoryEmulated::PurgeForTesting();
-  internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
 }  // namespace base
diff --git a/memory/discardable_memory_mach.cc b/memory/discardable_memory_mach.cc
index 5fc43f2..d96de79 100644
--- a/memory/discardable_memory_mach.cc
+++ b/memory/discardable_memory_mach.cc
@@ -63,12 +63,6 @@
   g_manager.Pointer()->Unregister(this);
 }
 
-// static
-void DiscardableMemoryMach::PurgeForTesting() {
-  int state = 0;
-  vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
-}
-
 bool DiscardableMemoryMach::Initialize() {
   return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
 }
@@ -154,9 +148,5 @@
   memory_.reset();
 }
 
-bool DiscardableMemoryMach::IsMemoryResident() const {
-  return true;
-}
-
 }  // namespace internal
 }  // namespace base
diff --git a/memory/discardable_memory_mach.h b/memory/discardable_memory_mach.h
index af2191f..b3b4b48 100644
--- a/memory/discardable_memory_mach.h
+++ b/memory/discardable_memory_mach.h
@@ -20,8 +20,6 @@
   explicit DiscardableMemoryMach(size_t bytes);
   ~DiscardableMemoryMach() override;
 
-  static void PurgeForTesting();
-
   bool Initialize();
 
   // Overridden from DiscardableMemory:
@@ -33,7 +31,6 @@
   bool AllocateAndAcquireLock() override;
   void ReleaseLock() override;
   void Purge() override;
-  bool IsMemoryResident() const override;
 
  private:
   mac::ScopedMachVM memory_;
diff --git a/memory/discardable_memory_manager.cc b/memory/discardable_memory_manager.cc
index 09e63e3..cbbdb47 100644
--- a/memory/discardable_memory_manager.cc
+++ b/memory/discardable_memory_manager.cc
@@ -51,34 +51,6 @@
   hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time;
 }
 
-void DiscardableMemoryManager::ReleaseFreeMemory() {
-  TRACE_EVENT0("base", "DiscardableMemoryManager::ReleaseFreeMemory");
-
-  AutoLock lock(lock_);
-  size_t bytes_allocated_before_releasing_memory = bytes_allocated_;
-  for (auto& entry : allocations_) {
-    Allocation* allocation = entry.first;
-    AllocationInfo* info = &entry.second;
-
-    if (!info->purgable)
-      continue;
-
-    // Skip if memory is still resident, otherwise purge and adjust
-    // |bytes_allocated_|.
-    if (allocation->IsMemoryResident())
-      continue;
-
-    size_t bytes_purgable = info->bytes;
-    DCHECK_LE(bytes_purgable, bytes_allocated_);
-    bytes_allocated_ -= bytes_purgable;
-    info->purgable = false;
-    allocation->Purge();
-  }
-
-  if (bytes_allocated_ != bytes_allocated_before_releasing_memory)
-    BytesAllocatedChanged(bytes_allocated_);
-}
-
 bool DiscardableMemoryManager::ReduceMemoryUsage() {
   return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit();
 }
diff --git a/memory/discardable_memory_manager.h b/memory/discardable_memory_manager.h
index 8bf9289..43737f8 100644
--- a/memory/discardable_memory_manager.h
+++ b/memory/discardable_memory_manager.h
@@ -31,10 +31,6 @@
   // is acquired on the allocation.
   virtual void Purge() = 0;
 
-  // Check if allocated memory is still resident. It is illegal to call this
-  // while a lock is acquired on the allocation.
-  virtual bool IsMemoryResident() const = 0;
-
  protected:
   virtual ~DiscardableMemoryManagerAllocation() {}
 };
@@ -72,9 +68,6 @@
   void SetHardMemoryLimitExpirationTime(
       TimeDelta hard_memory_limit_expiration_time);
 
-  // This will make sure that all purged memory is released to the OS.
-  void ReleaseFreeMemory();
-
   // This will attempt to reduce memory footprint until within soft memory
   // limit. Returns true if there's no need to call this again until allocations
   // have been used.
diff --git a/memory/discardable_memory_manager_unittest.cc b/memory/discardable_memory_manager_unittest.cc
index 9f06e37..6717f09 100644
--- a/memory/discardable_memory_manager_unittest.cc
+++ b/memory/discardable_memory_manager_unittest.cc
@@ -33,10 +33,6 @@
     DCHECK(is_allocated_);
     is_allocated_ = false;
   }
-  bool IsMemoryResident() const override {
-    DCHECK(is_allocated_);
-    return true;
-  }
 
   bool is_locked() const { return is_locked_; }
 
diff --git a/memory/discardable_memory_shmem.cc b/memory/discardable_memory_shmem.cc
index 416fcf2..9056279 100644
--- a/memory/discardable_memory_shmem.cc
+++ b/memory/discardable_memory_shmem.cc
@@ -6,62 +6,17 @@
 
 #include "base/lazy_instance.h"
 #include "base/memory/discardable_memory_shmem_allocator.h"
-#include "base/memory/discardable_shared_memory.h"
 
 namespace base {
-namespace {
-
-// Have the DiscardableMemoryManager trigger in-process eviction
-// when address space usage gets too high (e.g. 512 MBytes).
-const size_t kMemoryLimit = 512 * 1024 * 1024;
-
-// internal::DiscardableMemoryManager has an explicit constructor that takes
-// a number of memory limit parameters. The LeakyLazyInstanceTraits doesn't
-// handle the case. Thus, we need our own class here.
-struct DiscardableMemoryManagerLazyInstanceTraits {
-  // Leaky as discardable memory clients can use this after the exit handler
-  // has been called.
-  static const bool kRegisterOnExit = false;
-#ifndef NDEBUG
-  static const bool kAllowedToAccessOnNonjoinableThread = true;
-#endif
-
-  static internal::DiscardableMemoryManager* New(void* instance) {
-    return new (instance) internal::DiscardableMemoryManager(
-        kMemoryLimit, kMemoryLimit, TimeDelta::Max());
-  }
-  static void Delete(internal::DiscardableMemoryManager* instance) {
-    instance->~DiscardableMemoryManager();
-  }
-};
-
-LazyInstance<internal::DiscardableMemoryManager,
-             DiscardableMemoryManagerLazyInstanceTraits> g_manager =
-    LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
 namespace internal {
 
 DiscardableMemoryShmem::DiscardableMemoryShmem(size_t bytes)
     : bytes_(bytes), is_locked_(false) {
-  g_manager.Pointer()->Register(this, bytes);
 }
 
 DiscardableMemoryShmem::~DiscardableMemoryShmem() {
   if (is_locked_)
     Unlock();
-  g_manager.Pointer()->Unregister(this);
-}
-
-// static
-void DiscardableMemoryShmem::ReleaseFreeMemory() {
-  g_manager.Pointer()->ReleaseFreeMemory();
-}
-
-// static
-void DiscardableMemoryShmem::PurgeForTesting() {
-  g_manager.Pointer()->PurgeAll();
 }
 
 bool DiscardableMemoryShmem::Initialize() {
@@ -71,18 +26,24 @@
 DiscardableMemoryLockStatus DiscardableMemoryShmem::Lock() {
   DCHECK(!is_locked_);
 
-  bool purged = false;
-  if (!g_manager.Pointer()->AcquireLock(this, &purged))
+  if (chunk_ && chunk_->Lock()) {
+    is_locked_ = true;
+    return DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+  }
+
+  chunk_ = DiscardableMemoryShmemAllocator::GetInstance()
+               ->AllocateLockedDiscardableMemory(bytes_);
+  if (!chunk_)
     return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
 
   is_locked_ = true;
-  return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
-                : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+  return DISCARDABLE_MEMORY_LOCK_STATUS_PURGED;
 }
 
 void DiscardableMemoryShmem::Unlock() {
   DCHECK(is_locked_);
-  g_manager.Pointer()->ReleaseLock(this);
+  DCHECK(chunk_);
+  chunk_->Unlock();
   is_locked_ = false;
 }
 
@@ -92,28 +53,5 @@
   return chunk_->Memory();
 }
 
-bool DiscardableMemoryShmem::AllocateAndAcquireLock() {
-  if (chunk_ && chunk_->Lock())
-    return true;
-
-  chunk_ = DiscardableMemoryShmemAllocator::GetInstance()
-               ->AllocateLockedDiscardableMemory(bytes_);
-  DCHECK(chunk_);
-  return false;
-}
-
-void DiscardableMemoryShmem::ReleaseLock() {
-  chunk_->Unlock();
-}
-
-void DiscardableMemoryShmem::Purge() {
-  DCHECK(!is_locked_);
-  chunk_.reset();
-}
-
-bool DiscardableMemoryShmem::IsMemoryResident() const {
-  return chunk_->IsMemoryResident();
-}
-
 }  // namespace internal
 }  // namespace base
diff --git a/memory/discardable_memory_shmem.h b/memory/discardable_memory_shmem.h
index b04c9b1..98d3b97 100644
--- a/memory/discardable_memory_shmem.h
+++ b/memory/discardable_memory_shmem.h
@@ -7,24 +7,16 @@
 
 #include "base/memory/discardable_memory.h"
 
-#include "base/memory/discardable_memory_manager.h"
-
 namespace base {
 class DiscardableMemoryShmemChunk;
 
 namespace internal {
 
-class DiscardableMemoryShmem
-    : public DiscardableMemory,
-      public internal::DiscardableMemoryManagerAllocation {
+class DiscardableMemoryShmem : public DiscardableMemory {
  public:
   explicit DiscardableMemoryShmem(size_t bytes);
   ~DiscardableMemoryShmem() override;
 
-  static void ReleaseFreeMemory();
-
-  static void PurgeForTesting();
-
   bool Initialize();
 
   // Overridden from DiscardableMemory:
@@ -32,12 +24,6 @@
   void Unlock() override;
   void* Memory() const override;
 
-  // Overridden from internal::DiscardableMemoryManagerAllocation:
-  bool AllocateAndAcquireLock() override;
-  void ReleaseLock() override;
-  void Purge() override;
-  bool IsMemoryResident() const override;
-
  private:
   const size_t bytes_;
   scoped_ptr<DiscardableMemoryShmemChunk> chunk_;
diff --git a/memory/discardable_memory_shmem_allocator.cc b/memory/discardable_memory_shmem_allocator.cc
index 8abe456..761204f 100644
--- a/memory/discardable_memory_shmem_allocator.cc
+++ b/memory/discardable_memory_shmem_allocator.cc
@@ -18,16 +18,12 @@
       : shared_memory_(shared_memory.Pass()) {}
 
   // Overridden from DiscardableMemoryShmemChunk:
-  bool Lock() override {
-    auto result = shared_memory_->Lock(0, 0);
-    DCHECK_NE(result, DiscardableSharedMemory::PURGED);
-    return result == DiscardableSharedMemory::SUCCESS;
+  bool Lock() override { return false; }
+  void Unlock() override {
+    shared_memory_->Unlock(0, 0);
+    shared_memory_.reset();
   }
-  void Unlock() override { shared_memory_->Unlock(0, 0); }
   void* Memory() const override { return shared_memory_->memory(); }
-  bool IsMemoryResident() const override {
-    return shared_memory_->IsMemoryResident();
-  }
 
  private:
   scoped_ptr<DiscardableSharedMemory> shared_memory_;
diff --git a/memory/discardable_memory_shmem_allocator.h b/memory/discardable_memory_shmem_allocator.h
index ed40672..ac4118e 100644
--- a/memory/discardable_memory_shmem_allocator.h
+++ b/memory/discardable_memory_shmem_allocator.h
@@ -19,7 +19,6 @@
   virtual bool Lock() = 0;
   virtual void Unlock() = 0;
   virtual void* Memory() const = 0;
-  virtual bool IsMemoryResident() const = 0;
 };
 
 class BASE_EXPORT DiscardableMemoryShmemAllocator {
diff --git a/memory/discardable_memory_unittest.cc b/memory/discardable_memory_unittest.cc
index 4510413..fb1eba6 100644
--- a/memory/discardable_memory_unittest.cc
+++ b/memory/discardable_memory_unittest.cc
@@ -82,16 +82,6 @@
   ASSERT_TRUE(memory);
 }
 
-// Test forced purging.
-TEST_P(DiscardableMemoryTest, Purge) {
-  const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize));
-  ASSERT_TRUE(memory);
-  memory->Unlock();
-
-  DiscardableMemory::PurgeForTesting();
-  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, memory->Lock());
-}
-
 #if !defined(NDEBUG) && !defined(OS_ANDROID)
 // Death tests are not supported with Android APKs.
 TEST_P(DiscardableMemoryTest, UnlockedMemoryAccessCrashesInDebugMode) {
diff --git a/memory/discardable_memory_win.cc b/memory/discardable_memory_win.cc
index 9b4e940..977b029 100644
--- a/memory/discardable_memory_win.cc
+++ b/memory/discardable_memory_win.cc
@@ -11,11 +11,6 @@
 namespace base {
 
 // static
-void DiscardableMemory::ReleaseFreeMemory() {
-  internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
 bool DiscardableMemory::ReduceMemoryUsage() {
   return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
 }
@@ -61,10 +56,4 @@
   return nullptr;
 }
 
-// static
-void DiscardableMemory::PurgeForTesting() {
-  internal::DiscardableMemoryEmulated::PurgeForTesting();
-  internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
 }  // namespace base
diff --git a/memory/discardable_shared_memory.cc b/memory/discardable_shared_memory.cc
index 3805bed..49e93cd 100644
--- a/memory/discardable_shared_memory.cc
+++ b/memory/discardable_shared_memory.cc
@@ -162,19 +162,19 @@
   DCHECK_EQ(AlignToPageSize(offset), offset);
   DCHECK_EQ(AlignToPageSize(length), length);
 
-  // Calls to this function must synchronized properly.
+  // Calls to this function must be synchronized properly.
   DFAKE_SCOPED_LOCK(thread_collision_warner_);
 
-  // Return false when instance has been purged or not initialized properly by
-  // checking if |last_known_usage_| is NULL.
-  if (last_known_usage_.is_null())
-    return FAILED;
-
   DCHECK(shared_memory_.memory());
 
   // We need to successfully acquire the platform independent lock before
   // individual pages can be locked.
   if (!locked_page_count_) {
+    // Return false when instance has been purged or not initialized properly
+    // by checking if |last_known_usage_| is NULL.
+    if (last_known_usage_.is_null())
+      return FAILED;
+
     SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
     SharedState new_state(SharedState::LOCKED, Time());
     SharedState result(subtle::Acquire_CompareAndSwap(
@@ -226,7 +226,7 @@
   DCHECK_EQ(AlignToPageSize(offset), offset);
   DCHECK_EQ(AlignToPageSize(length), length);
 
-  // Calls to this function must synchronized properly.
+  // Calls to this function must be synchronized properly.
   DFAKE_SCOPED_LOCK(thread_collision_warner_);
 
   // Zero for length means "everything onward".
@@ -294,7 +294,7 @@
 }
 
 bool DiscardableSharedMemory::Purge(Time current_time) {
-  // Calls to this function must synchronized properly.
+  // Calls to this function must be synchronized properly.
   DFAKE_SCOPED_LOCK(thread_collision_warner_);
 
   // Early out if not mapped. This can happen if the segment was previously
diff --git a/memory/discardable_shared_memory_unittest.cc b/memory/discardable_shared_memory_unittest.cc
index 1f08aea..74d19a6 100644
--- a/memory/discardable_shared_memory_unittest.cc
+++ b/memory/discardable_shared_memory_unittest.cc
@@ -234,8 +234,6 @@
   // Lock should fail as memory has been purged.
   auto lock_rv = memory2.Lock(0, 0);
   EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
-  lock_rv = memory1.Lock(0, 0);
-  EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
 }
 
 TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) {
@@ -263,27 +261,39 @@
   rv = memory1.Purge(Time::FromDoubleT(2));
   EXPECT_FALSE(rv);
 
-  // Unlock second page.
+  // Lock first page again.
   memory2.SetNow(Time::FromDoubleT(3));
+  auto lock_rv = memory2.Lock(0, base::GetPageSize());
+  EXPECT_NE(DiscardableSharedMemory::FAILED, lock_rv);
+
+  // Unlock first page.
+  memory2.SetNow(Time::FromDoubleT(4));
+  memory2.Unlock(0, base::GetPageSize());
+
+  rv = memory1.Purge(Time::FromDoubleT(5));
+  EXPECT_FALSE(rv);
+
+  // Unlock second page.
+  memory2.SetNow(Time::FromDoubleT(6));
   memory2.Unlock(base::GetPageSize(), base::GetPageSize());
 
-  rv = memory1.Purge(Time::FromDoubleT(4));
+  rv = memory1.Purge(Time::FromDoubleT(7));
   EXPECT_FALSE(rv);
 
   // Unlock anything onwards.
-  memory2.SetNow(Time::FromDoubleT(5));
+  memory2.SetNow(Time::FromDoubleT(8));
   memory2.Unlock(2 * base::GetPageSize(), 0);
 
   // Memory is unlocked, but our usage timestamp is incorrect.
-  rv = memory1.Purge(Time::FromDoubleT(6));
+  rv = memory1.Purge(Time::FromDoubleT(9));
   EXPECT_FALSE(rv);
 
   // The failed purge attempt should have updated usage time to the correct
   // value.
-  EXPECT_EQ(Time::FromDoubleT(5), memory1.last_known_usage());
+  EXPECT_EQ(Time::FromDoubleT(8), memory1.last_known_usage());
 
   // Purge should now succeed.
-  rv = memory1.Purge(Time::FromDoubleT(7));
+  rv = memory1.Purge(Time::FromDoubleT(10));
   EXPECT_TRUE(rv);
 }
 
diff --git a/memory/memory_pressure_listener.cc b/memory/memory_pressure_listener.cc
index d808502..6a8ed21 100644
--- a/memory/memory_pressure_listener.cc
+++ b/memory/memory_pressure_listener.cc
@@ -54,7 +54,7 @@
   DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE);
   TRACE_EVENT1("memory", "MemoryPressureListener::NotifyMemoryPressure",
       "level", memory_pressure_level);
-  g_observers.Get().Notify(&MemoryPressureListener::Notify,
+  g_observers.Get().Notify(FROM_HERE, &MemoryPressureListener::Notify,
                            memory_pressure_level);
 }
 
diff --git a/memory/scoped_ptr.h b/memory/scoped_ptr.h
index ae9eb0f..987ccfa 100644
--- a/memory/scoped_ptr.h
+++ b/memory/scoped_ptr.h
@@ -85,6 +85,7 @@
 #include <stdlib.h>
 
 #include <algorithm>  // For std::swap().
+#include <iosfwd>
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
@@ -585,4 +586,9 @@
   return scoped_ptr<T>(ptr);
 }
 
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
+  return out << p.get();
+}
+
 #endif  // BASE_MEMORY_SCOPED_PTR_H_
diff --git a/memory/scoped_ptr_unittest.cc b/memory/scoped_ptr_unittest.cc
index ca7cfbf..0887a99 100644
--- a/memory/scoped_ptr_unittest.cc
+++ b/memory/scoped_ptr_unittest.cc
@@ -4,9 +4,12 @@
 
 #include "base/memory/scoped_ptr.h"
 
+#include <sstream>
+
 #include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/strings/stringprintf.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -678,3 +681,13 @@
   scoped_ptr<int, NoOpDeleter> x(owner.get());
   x.reset(x.get());
 }
+
+// Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean
+// value first.
+TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) {
+  scoped_ptr<int> x(new int);
+  std::stringstream s;
+  s << x;
+  std::string expected = base::StringPrintf("%p", x.get());
+  EXPECT_EQ(expected, s.str());
+}
diff --git a/message_loop/message_loop.cc b/message_loop/message_loop.cc
index 86771e4..daa7782 100644
--- a/message_loop/message_loop.cc
+++ b/message_loop/message_loop.cc
@@ -152,7 +152,12 @@
 MessageLoop::~MessageLoop() {
   DCHECK_EQ(this, current());
 
+  // iOS just attaches to the loop, it doesn't Run it.
+  // TODO(stuartmorgan): Consider wiring up a Detach().
+#if !defined(OS_IOS)
   DCHECK(!run_loop_);
+#endif
+
 #if defined(OS_WIN)
   if (in_high_res_mode_)
     Time::ActivateHighResolutionTimer(false);
diff --git a/metrics/field_trial.cc b/metrics/field_trial.cc
index e03c94c..639f6d3 100644
--- a/metrics/field_trial.cc
+++ b/metrics/field_trial.cc
@@ -547,9 +547,8 @@
     return;
 
   global_->observer_list_->Notify(
-      &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
-      field_trial->trial_name(),
-      field_trial->group_name_internal());
+      FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
+      field_trial->trial_name(), field_trial->group_name_internal());
 }
 
 // static
diff --git a/metrics/histogram_macros.h b/metrics/histogram_macros.h
index e9a871c..2aee1a5 100644
--- a/metrics/histogram_macros.h
+++ b/metrics/histogram_macros.h
@@ -229,4 +229,36 @@
         base::CustomHistogram::FactoryGet(name, custom_ranges, \
             base::HistogramBase::kUmaTargetedHistogramFlag))
 
+// Scoped class which logs its time on this earth as a UMA statistic. This is
+// recommended for when you want a histogram which measures the time it takes
+// for a method to execute. This measures up to 10 seconds.
+#define SCOPED_UMA_HISTOGRAM_TIMER(name) \
+  SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, false, __COUNTER__)
+
+// Similar scoped histogram timer, but this uses UMA_HISTOGRAM_LONG_TIMES_100,
+// which measures up to an hour, and uses 100 buckets. This is more expensive
+// to store, so only use if this often takes >10 seconds.
+#define SCOPED_UMA_HISTOGRAM_LONG_TIMER(name) \
+  SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, true, __COUNTER__)
+
+// This nested macro is necessary to expand __COUNTER__ to an actual value.
+#define SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
+  SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
+
+#define SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
+  class ScopedHistogramTimer##key { \
+   public: \
+    ScopedHistogramTimer##key() : constructed_(base::TimeTicks::Now()) {} \
+    ~ScopedHistogramTimer##key() { \
+      base::TimeDelta elapsed = base::TimeTicks::Now() - constructed_; \
+      if (is_long) { \
+        UMA_HISTOGRAM_LONG_TIMES_100(name, elapsed); \
+      } else { \
+        UMA_HISTOGRAM_TIMES(name, elapsed); \
+      } \
+    } \
+   private: \
+    base::TimeTicks constructed_; \
+  } scoped_histogram_timer_##key
+
 #endif  // BASE_METRICS_HISTOGRAM_MACROS_H_
diff --git a/metrics/histogram_macros_unittest.cc b/metrics/histogram_macros_unittest.cc
new file mode 100644
index 0000000..c599161
--- /dev/null
+++ b/metrics/histogram_macros_unittest.cc
@@ -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.
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+TEST(ScopedHistogramTimer, TwoTimersOneScope) {
+  SCOPED_UMA_HISTOGRAM_TIMER("TestTimer0");
+  SCOPED_UMA_HISTOGRAM_TIMER("TestTimer1");
+  SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer0");
+  SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer1");
+}
+
+}  // namespace base
diff --git a/metrics/stats_counters.cc b/metrics/stats_counters.cc
deleted file mode 100644
index 12416d9..0000000
--- a/metrics/stats_counters.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2010 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/metrics/stats_counters.h"
-
-namespace base {
-
-StatsCounter::StatsCounter(const std::string& name)
-    : counter_id_(-1) {
-  // We prepend the name with 'c:' to indicate that it is a counter.
-  if (StatsTable::current()) {
-    // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
-    // static.
-    name_ = "c:";
-    name_.append(name);
-  }
-}
-
-StatsCounter::~StatsCounter() {
-}
-
-void StatsCounter::Set(int value) {
-  int* loc = GetPtr();
-  if (loc)
-    *loc = value;
-}
-
-void StatsCounter::Add(int value) {
-  int* loc = GetPtr();
-  if (loc)
-    (*loc) += value;
-}
-
-StatsCounter::StatsCounter()
-    : counter_id_(-1) {
-}
-
-int* StatsCounter::GetPtr() {
-  StatsTable* table = StatsTable::current();
-  if (!table)
-    return NULL;
-
-  // If counter_id_ is -1, then we haven't looked it up yet.
-  if (counter_id_ == -1) {
-    counter_id_ = table->FindCounter(name_);
-    if (table->GetSlot() == 0) {
-      if (!table->RegisterThread(std::string())) {
-        // There is no room for this thread.  This thread
-        // cannot use counters.
-        counter_id_ = 0;
-        return NULL;
-      }
-    }
-  }
-
-  // If counter_id_ is > 0, then we have a valid counter.
-  if (counter_id_ > 0)
-    return table->GetLocation(counter_id_, table->GetSlot());
-
-  // counter_id_ was zero, which means the table is full.
-  return NULL;
-}
-
-
-StatsCounterTimer::StatsCounterTimer(const std::string& name) {
-  // we prepend the name with 't:' to indicate that it is a timer.
-  if (StatsTable::current()) {
-    // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
-    // static.
-    name_ = "t:";
-    name_.append(name);
-  }
-}
-
-StatsCounterTimer::~StatsCounterTimer() {
-}
-
-void StatsCounterTimer::Start() {
-  if (!Enabled())
-    return;
-  start_time_ = TimeTicks::Now();
-  stop_time_ = TimeTicks();
-}
-
-// Stop the timer and record the results.
-void StatsCounterTimer::Stop() {
-  if (!Enabled() || !Running())
-    return;
-  stop_time_ = TimeTicks::Now();
-  Record();
-}
-
-// Returns true if the timer is running.
-bool StatsCounterTimer::Running() {
-  return Enabled() && !start_time_.is_null() && stop_time_.is_null();
-}
-
-// Accept a TimeDelta to increment.
-void StatsCounterTimer::AddTime(TimeDelta time) {
-  Add(static_cast<int>(time.InMilliseconds()));
-}
-
-void StatsCounterTimer::Record() {
-  AddTime(stop_time_ - start_time_);
-}
-
-
-StatsRate::StatsRate(const std::string& name)
-    : StatsCounterTimer(name),
-      counter_(name),
-      largest_add_(std::string(" ").append(name).append("MAX")) {
-}
-
-StatsRate::~StatsRate() {
-}
-
-void StatsRate::Add(int value) {
-  counter_.Increment();
-  StatsCounterTimer::Add(value);
-  if (value > largest_add_.value())
-    largest_add_.Set(value);
-}
-
-}  // namespace base
diff --git a/metrics/stats_counters.h b/metrics/stats_counters.h
deleted file mode 100644
index 0f8354f..0000000
--- a/metrics/stats_counters.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_METRICS_STATS_COUNTERS_H_
-#define BASE_METRICS_STATS_COUNTERS_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/compiler_specific.h"
-#include "base/metrics/stats_table.h"
-#include "base/time/time.h"
-
-namespace base {
-
-// StatsCounters are dynamically created values which can be tracked in
-// the StatsTable.  They are designed to be lightweight to create and
-// easy to use.
-//
-// Since StatsCounters can be created dynamically by name, there is
-// a hash table lookup to find the counter in the table.  A StatsCounter
-// object can be created once and used across multiple threads safely.
-//
-// Example usage:
-//    {
-//      StatsCounter request_count("RequestCount");
-//      request_count.Increment();
-//    }
-//
-// Note that creating counters on the stack does work, however creating
-// the counter object requires a hash table lookup.  For inner loops, it
-// may be better to create the counter either as a member of another object
-// (or otherwise outside of the loop) for maximum performance.
-//
-// Internally, a counter represents a value in a row of a StatsTable.
-// The row has a 32bit value for each process/thread in the table and also
-// a name (stored in the table metadata).
-//
-// NOTE: In order to make stats_counters usable in lots of different code,
-// avoid any dependencies inside this header file.
-//
-
-//------------------------------------------------------------------------------
-// Define macros for ease of use. They also allow us to change definitions
-// as the implementation varies, or depending on compile options.
-//------------------------------------------------------------------------------
-// First provide generic macros, which exist in production as well as debug.
-#define STATS_COUNTER(name, delta) do { \
-  base::StatsCounter counter(name); \
-  counter.Add(delta); \
-} while (0)
-
-#define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1)
-
-#define RATE_COUNTER(name, duration) do { \
-  base::StatsRate hit_count(name); \
-  hit_count.AddTime(duration); \
-} while (0)
-
-// Define Debug vs non-debug flavors of macros.
-#ifndef NDEBUG
-
-#define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta)
-#define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name)
-#define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration)
-
-#else  // NDEBUG
-
-#define DSTATS_COUNTER(name, delta) do {} while (0)
-#define DSIMPLE_STATS_COUNTER(name) do {} while (0)
-#define DRATE_COUNTER(name, duration) do {} while (0)
-
-#endif  // NDEBUG
-
-//------------------------------------------------------------------------------
-// StatsCounter represents a counter in the StatsTable class.
-class BASE_EXPORT StatsCounter {
- public:
-  // Create a StatsCounter object.
-  explicit StatsCounter(const std::string& name);
-  virtual ~StatsCounter();
-
-  // Sets the counter to a specific value.
-  void Set(int value);
-
-  // Increments the counter.
-  void Increment() {
-    Add(1);
-  }
-
-  virtual void Add(int value);
-
-  // Decrements the counter.
-  void Decrement() {
-    Add(-1);
-  }
-
-  void Subtract(int value) {
-    Add(-value);
-  }
-
-  // Is this counter enabled?
-  // Returns false if table is full.
-  bool Enabled() {
-    return GetPtr() != NULL;
-  }
-
-  int value() {
-    int* loc = GetPtr();
-    if (loc) return *loc;
-    return 0;
-  }
-
- protected:
-  StatsCounter();
-
-  // Returns the cached address of this counter location.
-  int* GetPtr();
-
-  std::string name_;
-  // The counter id in the table.  We initialize to -1 (an invalid value)
-  // and then cache it once it has been looked up.  The counter_id is
-  // valid across all threads and processes.
-  int32 counter_id_;
-};
-
-
-// A StatsCounterTimer is a StatsCounter which keeps a timer during
-// the scope of the StatsCounterTimer.  On destruction, it will record
-// its time measurement.
-class BASE_EXPORT StatsCounterTimer : protected StatsCounter {
- public:
-  // Constructs and starts the timer.
-  explicit StatsCounterTimer(const std::string& name);
-  ~StatsCounterTimer() override;
-
-  // Start the timer.
-  void Start();
-
-  // Stop the timer and record the results.
-  void Stop();
-
-  // Returns true if the timer is running.
-  bool Running();
-
-  // Accept a TimeDelta to increment.
-  virtual void AddTime(TimeDelta time);
-
- protected:
-  // Compute the delta between start and stop, in milliseconds.
-  void Record();
-
-  TimeTicks start_time_;
-  TimeTicks stop_time_;
-};
-
-// A StatsRate is a timer that keeps a count of the number of intervals added so
-// that several statistics can be produced:
-//    min, max, avg, count, total
-class BASE_EXPORT StatsRate : public StatsCounterTimer {
- public:
-  // Constructs and starts the timer.
-  explicit StatsRate(const std::string& name);
-  ~StatsRate() override;
-
-  void Add(int value) override;
-
- private:
-  StatsCounter counter_;
-  StatsCounter largest_add_;
-};
-
-
-// Helper class for scoping a timer or rate.
-template<class T> class StatsScope {
- public:
-  explicit StatsScope<T>(T& timer)
-      : timer_(timer) {
-    timer_.Start();
-  }
-
-  ~StatsScope() {
-    timer_.Stop();
-  }
-
-  void Stop() {
-    timer_.Stop();
-  }
-
- private:
-  T& timer_;
-};
-
-}  // namespace base
-
-#endif  // BASE_METRICS_STATS_COUNTERS_H_
diff --git a/metrics/stats_table.cc b/metrics/stats_table.cc
deleted file mode 100644
index 0986395..0000000
--- a/metrics/stats_table.cc
+++ /dev/null
@@ -1,617 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/metrics/stats_table.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/shared_memory.h"
-#include "base/process/process_handle.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local_storage.h"
-
-namespace base {
-
-// The StatsTable uses a shared memory segment that is laid out as follows
-//
-// +-------------------------------------------+
-// | Version | Size | MaxCounters | MaxThreads |
-// +-------------------------------------------+
-// | Thread names table                        |
-// +-------------------------------------------+
-// | Thread TID table                          |
-// +-------------------------------------------+
-// | Thread PID table                          |
-// +-------------------------------------------+
-// | Counter names table                       |
-// +-------------------------------------------+
-// | Data                                      |
-// +-------------------------------------------+
-//
-// The data layout is a grid, where the columns are the thread_ids and the
-// rows are the counter_ids.
-//
-// If the first character of the thread_name is '\0', then that column is
-// empty.
-// If the first character of the counter_name is '\0', then that row is
-// empty.
-//
-// About Locking:
-// This class is designed to be both multi-thread and multi-process safe.
-// Aside from initialization, this is done by partitioning the data which
-// each thread uses so that no locking is required.  However, to allocate
-// the rows and columns of the table to particular threads, locking is
-// required.
-//
-// At the shared-memory level, we have a lock.  This lock protects the
-// shared-memory table only, and is used when we create new counters (e.g.
-// use rows) or when we register new threads (e.g. use columns).  Reading
-// data from the table does not require any locking at the shared memory
-// level.
-//
-// Each process which accesses the table will create a StatsTable object.
-// The StatsTable maintains a hash table of the existing counters in the
-// table for faster lookup.  Since the hash table is process specific,
-// each process maintains its own cache.  We avoid complexity here by never
-// de-allocating from the hash table.  (Counters are dynamically added,
-// but not dynamically removed).
-
-// In order for external viewers to be able to read our shared memory,
-// we all need to use the same size ints.
-COMPILE_ASSERT(sizeof(int)==4, expect_4_byte_ints);
-
-namespace {
-
-// An internal version in case we ever change the format of this
-// file, and so that we can identify our table.
-const int kTableVersion = 0x13131313;
-
-// The name for un-named counters and threads in the table.
-const char kUnknownName[] = "<unknown>";
-
-// Calculates delta to align an offset to the size of an int
-inline int AlignOffset(int offset) {
-  return (sizeof(int) - (offset % sizeof(int))) % sizeof(int);
-}
-
-inline int AlignedSize(int size) {
-  return size + AlignOffset(size);
-}
-
-}  // namespace
-
-// The StatsTable::Internal maintains convenience pointers into the
-// shared memory segment.  Use this class to keep the data structure
-// clean and accessible.
-class StatsTable::Internal {
- public:
-  // Various header information contained in the memory mapped segment.
-  struct TableHeader {
-    int version;
-    int size;
-    int max_counters;
-    int max_threads;
-  };
-
-  // Construct a new Internal based on expected size parameters, or
-  // return NULL on failure.
-  static Internal* New(const StatsTable::TableIdentifier& table,
-                       int size,
-                       int max_threads,
-                       int max_counters);
-
-  SharedMemory* shared_memory() { return shared_memory_.get(); }
-
-  // Accessors for our header pointers
-  TableHeader* table_header() const { return table_header_; }
-  int version() const { return table_header_->version; }
-  int size() const { return table_header_->size; }
-  int max_counters() const { return table_header_->max_counters; }
-  int max_threads() const { return table_header_->max_threads; }
-
-  // Accessors for our tables
-  char* thread_name(int slot_id) const {
-    return &thread_names_table_[
-      (slot_id-1) * (StatsTable::kMaxThreadNameLength)];
-  }
-  PlatformThreadId* thread_tid(int slot_id) const {
-    return &(thread_tid_table_[slot_id-1]);
-  }
-  int* thread_pid(int slot_id) const {
-    return &(thread_pid_table_[slot_id-1]);
-  }
-  char* counter_name(int counter_id) const {
-    return &counter_names_table_[
-      (counter_id-1) * (StatsTable::kMaxCounterNameLength)];
-  }
-  int* row(int counter_id) const {
-    return &data_table_[(counter_id-1) * max_threads()];
-  }
-
- private:
-  // Constructor is private because you should use New() instead.
-  explicit Internal(SharedMemory* shared_memory)
-      : shared_memory_(shared_memory),
-        table_header_(NULL),
-        thread_names_table_(NULL),
-        thread_tid_table_(NULL),
-        thread_pid_table_(NULL),
-        counter_names_table_(NULL),
-        data_table_(NULL) {
-  }
-
-  // Create or open the SharedMemory used by the stats table.
-  static SharedMemory* CreateSharedMemory(
-      const StatsTable::TableIdentifier& table,
-      int size);
-
-  // Initializes the table on first access.  Sets header values
-  // appropriately and zeroes all counters.
-  void InitializeTable(void* memory, int size, int max_counters,
-                       int max_threads);
-
-  // Initializes our in-memory pointers into a pre-created StatsTable.
-  void ComputeMappedPointers(void* memory);
-
-  scoped_ptr<SharedMemory> shared_memory_;
-  TableHeader* table_header_;
-  char* thread_names_table_;
-  PlatformThreadId* thread_tid_table_;
-  int* thread_pid_table_;
-  char* counter_names_table_;
-  int* data_table_;
-
-  DISALLOW_COPY_AND_ASSIGN(Internal);
-};
-
-// static
-StatsTable::Internal* StatsTable::Internal::New(
-    const StatsTable::TableIdentifier& table,
-    int size,
-    int max_threads,
-    int max_counters) {
-  scoped_ptr<SharedMemory> shared_memory(CreateSharedMemory(table, size));
-  if (!shared_memory.get())
-    return NULL;
-  if (!shared_memory->Map(size))
-    return NULL;
-  void* memory = shared_memory->memory();
-
-  scoped_ptr<Internal> internal(new Internal(shared_memory.release()));
-  TableHeader* header = static_cast<TableHeader*>(memory);
-
-  // If the version does not match, then assume the table needs
-  // to be initialized.
-  if (header->version != kTableVersion)
-    internal->InitializeTable(memory, size, max_counters, max_threads);
-
-  // We have a valid table, so compute our pointers.
-  internal->ComputeMappedPointers(memory);
-
-  return internal.release();
-}
-
-// static
-SharedMemory* StatsTable::Internal::CreateSharedMemory(
-    const StatsTable::TableIdentifier& table,
-    int size) {
-#if defined(OS_POSIX)
-  // Check for existing table.
-  if (table.fd != -1)
-    return new SharedMemory(table, false);
-
-  // Otherwise we need to create it.
-  scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
-  if (!shared_memory->CreateAnonymous(size))
-    return NULL;
-  return shared_memory.release();
-#elif defined(OS_WIN)
-  scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
-  if (table.empty()) {
-    // Create an anonymous table.
-    if (!shared_memory->CreateAnonymous(size))
-      return NULL;
-  } else {
-    // Create a named table for sharing between processes.
-    if (!shared_memory->CreateNamedDeprecated(table, true, size))
-      return NULL;
-  }
-  return shared_memory.release();
-#endif
-}
-
-void StatsTable::Internal::InitializeTable(void* memory, int size,
-                                           int max_counters,
-                                           int max_threads) {
-  // Zero everything.
-  memset(memory, 0, size);
-
-  // Initialize the header.
-  TableHeader* header = static_cast<TableHeader*>(memory);
-  header->version = kTableVersion;
-  header->size = size;
-  header->max_counters = max_counters;
-  header->max_threads = max_threads;
-}
-
-void StatsTable::Internal::ComputeMappedPointers(void* memory) {
-  char* data = static_cast<char*>(memory);
-  int offset = 0;
-
-  table_header_ = reinterpret_cast<TableHeader*>(data);
-  offset += sizeof(*table_header_);
-  offset += AlignOffset(offset);
-
-  // Verify we're looking at a valid StatsTable.
-  DCHECK_EQ(table_header_->version, kTableVersion);
-
-  thread_names_table_ = reinterpret_cast<char*>(data + offset);
-  offset += sizeof(char) *
-            max_threads() * StatsTable::kMaxThreadNameLength;
-  offset += AlignOffset(offset);
-
-  thread_tid_table_ = reinterpret_cast<PlatformThreadId*>(data + offset);
-  offset += sizeof(int) * max_threads();
-  offset += AlignOffset(offset);
-
-  thread_pid_table_ = reinterpret_cast<int*>(data + offset);
-  offset += sizeof(int) * max_threads();
-  offset += AlignOffset(offset);
-
-  counter_names_table_ = reinterpret_cast<char*>(data + offset);
-  offset += sizeof(char) *
-            max_counters() * StatsTable::kMaxCounterNameLength;
-  offset += AlignOffset(offset);
-
-  data_table_ = reinterpret_cast<int*>(data + offset);
-  offset += sizeof(int) * max_threads() * max_counters();
-
-  DCHECK_EQ(offset, size());
-}
-
-// TLSData carries the data stored in the TLS slots for the
-// StatsTable.  This is used so that we can properly cleanup when the
-// thread exits and return the table slot.
-//
-// Each thread that calls RegisterThread in the StatsTable will have
-// a TLSData stored in its TLS.
-struct StatsTable::TLSData {
-  StatsTable* table;
-  int slot;
-};
-
-// We keep a singleton table which can be easily accessed.
-StatsTable* global_table = NULL;
-
-StatsTable::StatsTable(const TableIdentifier& table,
-                       int max_threads,
-                       int max_counters)
-    : internal_(NULL),
-      tls_index_(SlotReturnFunction) {
-  int table_size =
-    AlignedSize(sizeof(Internal::TableHeader)) +
-    AlignedSize((max_counters * sizeof(char) * kMaxCounterNameLength)) +
-    AlignedSize((max_threads * sizeof(char) * kMaxThreadNameLength)) +
-    AlignedSize(max_threads * sizeof(int)) +
-    AlignedSize(max_threads * sizeof(int)) +
-    AlignedSize((sizeof(int) * (max_counters * max_threads)));
-
-  internal_ = Internal::New(table, table_size, max_threads, max_counters);
-
-  if (!internal_)
-    DPLOG(ERROR) << "StatsTable did not initialize";
-}
-
-StatsTable::~StatsTable() {
-  // Before we tear down our copy of the table, be sure to
-  // unregister our thread.
-  UnregisterThread();
-
-  // Return ThreadLocalStorage.  At this point, if any registered threads
-  // still exist, they cannot Unregister.
-  tls_index_.Free();
-
-  // Cleanup our shared memory.
-  delete internal_;
-
-  // If we are the global table, unregister ourselves.
-  if (global_table == this)
-    global_table = NULL;
-}
-
-StatsTable* StatsTable::current() {
-  return global_table;
-}
-
-void StatsTable::set_current(StatsTable* value) {
-  global_table = value;
-}
-
-int StatsTable::GetSlot() const {
-  TLSData* data = GetTLSData();
-  if (!data)
-    return 0;
-  return data->slot;
-}
-
-int StatsTable::RegisterThread(const std::string& name) {
-  int slot = 0;
-  if (!internal_)
-    return 0;
-
-  // Registering a thread requires that we lock the shared memory
-  // so that two threads don't grab the same slot.  Fortunately,
-  // thread creation shouldn't happen in inner loops.
-  // TODO(viettrungluu): crbug.com/345734: Use a different locking mechanism.
-  {
-    SharedMemoryAutoLockDeprecated lock(internal_->shared_memory());
-    slot = FindEmptyThread();
-    if (!slot) {
-      return 0;
-    }
-
-    // We have space, so consume a column in the table.
-    std::string thread_name = name;
-    if (name.empty())
-      thread_name = kUnknownName;
-    strlcpy(internal_->thread_name(slot), thread_name.c_str(),
-            kMaxThreadNameLength);
-    *(internal_->thread_tid(slot)) = PlatformThread::CurrentId();
-    *(internal_->thread_pid(slot)) = GetCurrentProcId();
-  }
-
-  // Set our thread local storage.
-  TLSData* data = new TLSData;
-  data->table = this;
-  data->slot = slot;
-  tls_index_.Set(data);
-  return slot;
-}
-
-int StatsTable::CountThreadsRegistered() const {
-  if (!internal_)
-    return 0;
-
-  // Loop through the shared memory and count the threads that are active.
-  // We intentionally do not lock the table during the operation.
-  int count = 0;
-  for (int index = 1; index <= internal_->max_threads(); index++) {
-    char* name = internal_->thread_name(index);
-    if (*name != '\0')
-      count++;
-  }
-  return count;
-}
-
-int StatsTable::FindCounter(const std::string& name) {
-  // Note: the API returns counters numbered from 1..N, although
-  // internally, the array is 0..N-1.  This is so that we can return
-  // zero as "not found".
-  if (!internal_)
-    return 0;
-
-  // Create a scope for our auto-lock.
-  {
-    AutoLock scoped_lock(counters_lock_);
-
-    // Attempt to find the counter.
-    CountersMap::const_iterator iter;
-    iter = counters_.find(name);
-    if (iter != counters_.end())
-      return iter->second;
-  }
-
-  // Counter does not exist, so add it.
-  return AddCounter(name);
-}
-
-int* StatsTable::GetLocation(int counter_id, int slot_id) const {
-  if (!internal_)
-    return NULL;
-  if (slot_id > internal_->max_threads())
-    return NULL;
-
-  int* row = internal_->row(counter_id);
-  return &(row[slot_id-1]);
-}
-
-const char* StatsTable::GetRowName(int index) const {
-  if (!internal_)
-    return NULL;
-
-  return internal_->counter_name(index);
-}
-
-int StatsTable::GetRowValue(int index) const {
-  return GetRowValue(index, 0);
-}
-
-int StatsTable::GetRowValue(int index, int pid) const {
-  if (!internal_)
-    return 0;
-
-  int rv = 0;
-  int* row = internal_->row(index);
-  for (int slot_id = 1; slot_id <= internal_->max_threads(); slot_id++) {
-    if (pid == 0 || *internal_->thread_pid(slot_id) == pid)
-      rv += row[slot_id-1];
-  }
-  return rv;
-}
-
-int StatsTable::GetCounterValue(const std::string& name) {
-  return GetCounterValue(name, 0);
-}
-
-int StatsTable::GetCounterValue(const std::string& name, int pid) {
-  if (!internal_)
-    return 0;
-
-  int row = FindCounter(name);
-  if (!row)
-    return 0;
-  return GetRowValue(row, pid);
-}
-
-int StatsTable::GetMaxCounters() const {
-  if (!internal_)
-    return 0;
-  return internal_->max_counters();
-}
-
-int StatsTable::GetMaxThreads() const {
-  if (!internal_)
-    return 0;
-  return internal_->max_threads();
-}
-
-int* StatsTable::FindLocation(const char* name) {
-  // Get the static StatsTable
-  StatsTable *table = StatsTable::current();
-  if (!table)
-    return NULL;
-
-  // Get the slot for this thread.  Try to register
-  // it if none exists.
-  int slot = table->GetSlot();
-  if (!slot)
-    slot = table->RegisterThread(std::string());
-  if (!slot)
-    return NULL;
-
-  // Find the counter id for the counter.
-  std::string str_name(name);
-  int counter = table->FindCounter(str_name);
-
-  // Now we can find the location in the table.
-  return table->GetLocation(counter, slot);
-}
-
-void StatsTable::UnregisterThread() {
-  UnregisterThread(GetTLSData());
-}
-
-void StatsTable::UnregisterThread(TLSData* data) {
-  if (!data)
-    return;
-  DCHECK(internal_);
-
-  // Mark the slot free by zeroing out the thread name.
-  char* name = internal_->thread_name(data->slot);
-  *name = '\0';
-
-  // Remove the calling thread's TLS so that it cannot use the slot.
-  tls_index_.Set(NULL);
-  delete data;
-}
-
-void StatsTable::SlotReturnFunction(void* data) {
-  // This is called by the TLS destructor, which on some platforms has
-  // already cleared the TLS info, so use the tls_data argument
-  // rather than trying to fetch it ourselves.
-  TLSData* tls_data = static_cast<TLSData*>(data);
-  if (tls_data) {
-    DCHECK(tls_data->table);
-    tls_data->table->UnregisterThread(tls_data);
-  }
-}
-
-int StatsTable::FindEmptyThread() const {
-  // Note: the API returns slots numbered from 1..N, although
-  // internally, the array is 0..N-1.  This is so that we can return
-  // zero as "not found".
-  //
-  // The reason for doing this is because the thread 'slot' is stored
-  // in TLS, which is always initialized to zero, not -1.  If 0 were
-  // returned as a valid slot number, it would be confused with the
-  // uninitialized state.
-  if (!internal_)
-    return 0;
-
-  int index = 1;
-  for (; index <= internal_->max_threads(); index++) {
-    char* name = internal_->thread_name(index);
-    if (!*name)
-      break;
-  }
-  if (index > internal_->max_threads())
-    return 0;  // The table is full.
-  return index;
-}
-
-int StatsTable::FindCounterOrEmptyRow(const std::string& name) const {
-  // Note: the API returns slots numbered from 1..N, although
-  // internally, the array is 0..N-1.  This is so that we can return
-  // zero as "not found".
-  //
-  // There isn't much reason for this other than to be consistent
-  // with the way we track columns for thread slots.  (See comments
-  // in FindEmptyThread for why it is done this way).
-  if (!internal_)
-    return 0;
-
-  int free_slot = 0;
-  for (int index = 1; index <= internal_->max_counters(); index++) {
-    char* row_name = internal_->counter_name(index);
-    if (!*row_name && !free_slot)
-      free_slot = index;  // save that we found a free slot
-    else if (!strncmp(row_name, name.c_str(), kMaxCounterNameLength))
-      return index;
-  }
-  return free_slot;
-}
-
-int StatsTable::AddCounter(const std::string& name) {
-  if (!internal_)
-    return 0;
-
-  int counter_id = 0;
-  {
-    // To add a counter to the shared memory, we need the
-    // shared memory lock.
-    SharedMemoryAutoLockDeprecated lock(internal_->shared_memory());
-
-    // We have space, so create a new counter.
-    counter_id = FindCounterOrEmptyRow(name);
-    if (!counter_id)
-      return 0;
-
-    std::string counter_name = name;
-    if (name.empty())
-      counter_name = kUnknownName;
-    strlcpy(internal_->counter_name(counter_id), counter_name.c_str(),
-            kMaxCounterNameLength);
-  }
-
-  // now add to our in-memory cache
-  {
-    AutoLock lock(counters_lock_);
-    counters_[name] = counter_id;
-  }
-  return counter_id;
-}
-
-StatsTable::TLSData* StatsTable::GetTLSData() const {
-  TLSData* data =
-    static_cast<TLSData*>(tls_index_.Get());
-  if (!data)
-    return NULL;
-
-  DCHECK(data->slot);
-  DCHECK_EQ(data->table, this);
-  return data;
-}
-
-#if defined(OS_POSIX)
-SharedMemoryHandle StatsTable::GetSharedMemoryHandle() const {
-  if (!internal_)
-    return SharedMemory::NULLHandle();
-  return internal_->shared_memory()->handle();
-}
-#endif
-
-}  // namespace base
diff --git a/metrics/stats_table.h b/metrics/stats_table.h
deleted file mode 100644
index 719e630..0000000
--- a/metrics/stats_table.h
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// A StatsTable is a table of statistics.  It can be used across multiple
-// processes and threads, maintaining cheap statistics counters without
-// locking.
-//
-// The goal is to make it very cheap and easy for developers to add
-// counters to code, without having to build one-off utilities or mechanisms
-// to track the counters, and also to allow a single "view" to display
-// the contents of all counters.
-//
-// To achieve this, StatsTable creates a shared memory segment to store
-// the data for the counters.  Upon creation, it has a specific size
-// which governs the maximum number of counters and concurrent
-// threads/processes which can use it.
-//
-
-#ifndef BASE_METRICS_STATS_TABLE_H_
-#define BASE_METRICS_STATS_TABLE_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#include "base/memory/shared_memory.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_local_storage.h"
-#include "build/build_config.h"
-
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#endif
-
-namespace base {
-
-class BASE_EXPORT StatsTable {
- public:
-  // Identifies a StatsTable. We often want to share these between processes.
-  //
-  // On Windows, we use a named shared memory segment so the table identifier
-  // should be a relatively unique string identifying the table to use. An
-  // empty string can be used to use an anonymous shared memory segment for
-  // cases where the table does not need to be shared between processes.
-  //
-  // Posix does not support named memory so we explicitly share file
-  // descriptors. On Posix, pass a default-constructed file descriptor if a
-  // handle doesn't already exist, and a new one will be created.
-  //
-  // If a table doesn't already exist with the given identifier, a new one will
-  // be created with zeroed counters.
-#if defined(OS_POSIX)
-  typedef FileDescriptor TableIdentifier;
-#elif defined(OS_WIN)
-  typedef std::string TableIdentifier;
-#endif
-
-  // Create a new StatsTable.
-  //
-  // max_threads is the maximum number of threads the table will support.
-  // If the StatsTable already exists, this number is ignored.
-  //
-  // max_counters is the maximum number of counters the table will support.
-  // If the StatsTable already exists, this number is ignored.
-  StatsTable(const TableIdentifier& table,
-             int max_threads,
-             int max_counters);
-
-  // Destroys the StatsTable.  When the last StatsTable is destroyed
-  // (across all processes), the StatsTable is removed from disk.
-  ~StatsTable();
-
-  // For convenience, we create a static table.  This is generally
-  // used automatically by the counters.
-  static StatsTable* current();
-
-  // Set the global table for use in this process.
-  static void set_current(StatsTable* value);
-
-  // Get the slot id for the calling thread. Returns 0 if no
-  // slot is assigned.
-  int GetSlot() const;
-
-  // All threads that contribute data to the table must register with the
-  // table first.  This function will set thread local storage for the
-  // thread containing the location in the table where this thread will
-  // write its counter data.
-  //
-  // name is just a debugging tag to label the thread, and it does not
-  // need to be unique.  It will be truncated to kMaxThreadNameLength-1
-  // characters.
-  //
-  // On success, returns the slot id for this thread.  On failure,
-  // returns 0.
-  int RegisterThread(const std::string& name);
-
-  // Returns the number of threads currently registered.  This is really not
-  // useful except for diagnostics and debugging.
-  int CountThreadsRegistered() const;
-
-  // Find a counter in the StatsTable.
-  //
-  // Returns an id for the counter which can be used to call GetLocation().
-  // If the counter does not exist, attempts to create a row for the new
-  // counter.  If there is no space in the table for the new counter,
-  // returns 0.
-  int FindCounter(const std::string& name);
-
-  // TODO(mbelshe): implement RemoveCounter.
-
-  // Gets the location of a particular value in the table based on
-  // the counter id and slot id.
-  int* GetLocation(int counter_id, int slot_id) const;
-
-  // Gets the counter name at a particular row.  If the row is empty,
-  // returns NULL.
-  const char* GetRowName(int index) const;
-
-  // Gets the sum of the values for a particular row.
-  int GetRowValue(int index) const;
-
-  // Gets the sum of the values for a particular row for a given pid.
-  int GetRowValue(int index, int pid) const;
-
-  // Gets the sum of the values for a particular counter.  If the counter
-  // does not exist, creates the counter.
-  int GetCounterValue(const std::string& name);
-
-  // Gets the sum of the values for a particular counter for a given pid.
-  // If the counter does not exist, creates the counter.
-  int GetCounterValue(const std::string& name, int pid);
-
-  // The maxinum number of counters/rows in the table.
-  int GetMaxCounters() const;
-
-  // The maxinum number of threads/columns in the table.
-  int GetMaxThreads() const;
-
-#if defined(OS_POSIX)
-  // Get the underlying shared memory handle for the table.
-  base::SharedMemoryHandle GetSharedMemoryHandle() const;
-#endif
-
-  // The maximum length (in characters) of a Thread's name including
-  // null terminator, as stored in the shared memory.
-  static const int kMaxThreadNameLength = 32;
-
-  // The maximum length (in characters) of a Counter's name including
-  // null terminator, as stored in the shared memory.
-  static const int kMaxCounterNameLength = 64;
-
-  // Convenience function to lookup a counter location for a
-  // counter by name for the calling thread.  Will register
-  // the thread if it is not already registered.
-  static int* FindLocation(const char *name);
-
- private:
-  class Internal;
-  struct TLSData;
-  typedef hash_map<std::string, int> CountersMap;
-
-  // Returns the space occupied by a thread in the table.  Generally used
-  // if a thread terminates but the process continues.  This function
-  // does not zero out the thread's counters.
-  // Cannot be used inside a posix tls destructor.
-  void UnregisterThread();
-
-  // This variant expects the tls data to be passed in, so it is safe to
-  // call from inside a posix tls destructor (see doc for pthread_key_create).
-  void UnregisterThread(TLSData* tls_data);
-
-  // The SlotReturnFunction is called at thread exit for each thread
-  // which used the StatsTable.
-  static void SlotReturnFunction(void* data);
-
-  // Locates a free slot in the table.  Returns a number > 0 on success,
-  // or 0 on failure.  The caller must hold the shared_memory lock when
-  // calling this function.
-  int FindEmptyThread() const;
-
-  // Locates a counter in the table or finds an empty row.  Returns a
-  // number > 0 on success, or 0 on failure.  The caller must hold the
-  // shared_memory_lock when calling this function.
-  int FindCounterOrEmptyRow(const std::string& name) const;
-
-  // Internal function to add a counter to the StatsTable.  Assumes that
-  // the counter does not already exist in the table.
-  //
-  // name is a unique identifier for this counter, and will be truncated
-  // to kMaxCounterNameLength-1 characters.
-  //
-  // On success, returns the counter_id for the newly added counter.
-  // On failure, returns 0.
-  int AddCounter(const std::string& name);
-
-  // Get the TLS data for the calling thread.  Returns NULL if none is
-  // initialized.
-  TLSData* GetTLSData() const;
-
-  Internal* internal_;
-
-  // The counters_lock_ protects the counters_ hash table.
-  base::Lock counters_lock_;
-
-  // The counters_ hash map is an in-memory hash of the counters.
-  // It is used for quick lookup of counters, but is cannot be used
-  // as a substitute for what is in the shared memory.  Even though
-  // we don't have a counter in our hash table, another process may
-  // have created it.
-  CountersMap counters_;
-  ThreadLocalStorage::Slot tls_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(StatsTable);
-};
-
-}  // namespace base
-
-#endif  // BASE_METRICS_STATS_TABLE_H_
diff --git a/metrics/stats_table_unittest.cc b/metrics/stats_table_unittest.cc
deleted file mode 100644
index 38a21cc..0000000
--- a/metrics/stats_table_unittest.cc
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/shared_memory.h"
-#include "base/metrics/stats_counters.h"
-#include "base/metrics/stats_table.h"
-#include "base/process/kill.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/multiprocess_test.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-
-class StatsTableTest : public MultiProcessTest {
-};
-
-// Open a StatsTable and verify that we can write to each of the
-// locations in the table.
-TEST_F(StatsTableTest, VerifySlots) {
-  const int kMaxThreads = 1;
-  const int kMaxCounter = 5;
-  StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-
-  // Register a single thread.
-  std::string thread_name = "mainThread";
-  int slot_id = table.RegisterThread(thread_name);
-  EXPECT_NE(slot_id, 0);
-
-  // Fill up the table with counters.
-  std::string counter_base_name = "counter";
-  for (int index = 0; index < kMaxCounter; index++) {
-    std::string counter_name = counter_base_name;
-    base::StringAppendF(&counter_name, "counter.ctr%d", index);
-    int counter_id = table.FindCounter(counter_name);
-    EXPECT_GT(counter_id, 0);
-  }
-
-  // Try to allocate an additional thread.  Verify it fails.
-  slot_id = table.RegisterThread("too many threads");
-  EXPECT_EQ(slot_id, 0);
-
-  // Try to allocate an additional counter.  Verify it fails.
-  int counter_id = table.FindCounter(counter_base_name);
-  EXPECT_EQ(counter_id, 0);
-}
-
-// CounterZero will continually be set to 0.
-const std::string kCounterZero = "CounterZero";
-// Counter1313 will continually be set to 1313.
-const std::string kCounter1313 = "Counter1313";
-// CounterIncrement will be incremented each time.
-const std::string kCounterIncrement = "CounterIncrement";
-// CounterDecrement will be decremented each time.
-const std::string kCounterDecrement = "CounterDecrement";
-// CounterMixed will be incremented by odd numbered threads and
-// decremented by even threads.
-const std::string kCounterMixed = "CounterMixed";
-// The number of thread loops that we will do.
-const int kThreadLoops = 100;
-
-class StatsTableThread : public SimpleThread {
- public:
-  StatsTableThread(std::string name, int id)
-      : SimpleThread(name),
-        id_(id) {}
-
-  void Run() override;
-
- private:
-  int id_;
-};
-
-void StatsTableThread::Run() {
-  // Each thread will open the shared memory and set counters
-  // concurrently in a loop.  We'll use some pauses to
-  // mixup the thread scheduling.
-
-  StatsCounter zero_counter(kCounterZero);
-  StatsCounter lucky13_counter(kCounter1313);
-  StatsCounter increment_counter(kCounterIncrement);
-  StatsCounter decrement_counter(kCounterDecrement);
-  for (int index = 0; index < kThreadLoops; index++) {
-    StatsCounter mixed_counter(kCounterMixed);  // create this one in the loop
-    zero_counter.Set(0);
-    lucky13_counter.Set(1313);
-    increment_counter.Increment();
-    decrement_counter.Decrement();
-    if (id_ % 2)
-      mixed_counter.Decrement();
-    else
-      mixed_counter.Increment();
-    PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
-  }
-}
-
-// Create a few threads and have them poke on their counters.
-// See http://crbug.com/10611 for more information.
-// It is disabled on Win x64 incremental linking pending resolution of
-// http://crbug.com/251251.
-#if defined(OS_MACOSX) || defined(THREAD_SANITIZER) || \
-    (defined(OS_WIN) && defined(ARCH_CPU_X86_64) &&    \
-     defined(INCREMENTAL_LINKING))
-#define MAYBE_MultipleThreads DISABLED_MultipleThreads
-#else
-#define MAYBE_MultipleThreads MultipleThreads
-#endif
-TEST_F(StatsTableTest, MAYBE_MultipleThreads) {
-  // Create a stats table.
-  const int kMaxThreads = 20;
-  const int kMaxCounter = 5;
-  StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-  StatsTable::set_current(&table);
-
-  EXPECT_EQ(0, table.CountThreadsRegistered());
-
-  // Spin up a set of threads to go bang on the various counters.
-  // After we join the threads, we'll make sure the counters
-  // contain the values we expected.
-  StatsTableThread* threads[kMaxThreads];
-
-  // Spawn the threads.
-  for (int index = 0; index < kMaxThreads; index++) {
-    threads[index] = new StatsTableThread("MultipleThreadsTest", index);
-    threads[index]->Start();
-  }
-
-  // Wait for the threads to finish.
-  for (int index = 0; index < kMaxThreads; index++) {
-    threads[index]->Join();
-    delete threads[index];
-  }
-
-  StatsCounter zero_counter(kCounterZero);
-  StatsCounter lucky13_counter(kCounter1313);
-  StatsCounter increment_counter(kCounterIncrement);
-  StatsCounter decrement_counter(kCounterDecrement);
-  StatsCounter mixed_counter(kCounterMixed);
-
-  // Verify the various counters are correct.
-  std::string name;
-  name = "c:" + kCounterZero;
-  EXPECT_EQ(0, table.GetCounterValue(name));
-  name = "c:" + kCounter1313;
-  EXPECT_EQ(1313 * kMaxThreads,
-      table.GetCounterValue(name));
-  name = "c:" + kCounterIncrement;
-  EXPECT_EQ(kMaxThreads * kThreadLoops,
-      table.GetCounterValue(name));
-  name = "c:" + kCounterDecrement;
-  EXPECT_EQ(-kMaxThreads * kThreadLoops,
-      table.GetCounterValue(name));
-  name = "c:" + kCounterMixed;
-  EXPECT_EQ((kMaxThreads % 2) * kThreadLoops,
-      table.GetCounterValue(name));
-  EXPECT_EQ(0, table.CountThreadsRegistered());
-}
-
-// This multiprocess test only runs on Windows. On Posix, the shared memory
-// handle is not sent between the processes properly.
-#if defined(OS_WIN)
-const std::string kMPTableName = "MultipleProcessStatTable";
-
-MULTIPROCESS_TEST_MAIN(StatsTableMultipleProcessMain) {
-  // Each process will open the shared memory and set counters
-  // concurrently in a loop.  We'll use some pauses to
-  // mixup the scheduling.
-
-  StatsTable table(kMPTableName, 0, 0);
-  StatsTable::set_current(&table);
-  StatsCounter zero_counter(kCounterZero);
-  StatsCounter lucky13_counter(kCounter1313);
-  StatsCounter increment_counter(kCounterIncrement);
-  StatsCounter decrement_counter(kCounterDecrement);
-  for (int index = 0; index < kThreadLoops; index++) {
-    zero_counter.Set(0);
-    lucky13_counter.Set(1313);
-    increment_counter.Increment();
-    decrement_counter.Decrement();
-    PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
-  }
-  return 0;
-}
-
-// Create a few processes and have them poke on their counters.
-// This test is slow and flaky http://crbug.com/10611
-TEST_F(StatsTableTest, DISABLED_MultipleProcesses) {
-  // Create a stats table.
-  const int kMaxProcs = 20;
-  const int kMaxCounter = 5;
-  StatsTable table(kMPTableName, kMaxProcs, kMaxCounter);
-  StatsTable::set_current(&table);
-  EXPECT_EQ(0, table.CountThreadsRegistered());
-
-  // Spin up a set of processes to go bang on the various counters.
-  // After we join the processes, we'll make sure the counters
-  // contain the values we expected.
-  Process procs[kMaxProcs];
-
-  // Spawn the processes.
-  for (int16 index = 0; index < kMaxProcs; index++) {
-    procs[index] = SpawnChild("StatsTableMultipleProcessMain");
-    EXPECT_TRUE(procs[index].IsValid());
-  }
-
-  // Wait for the processes to finish.
-  for (int index = 0; index < kMaxProcs; index++) {
-    EXPECT_TRUE(WaitForSingleProcess(procs[index].Handle(),
-                                     base::TimeDelta::FromMinutes(1)));
-    procs[index].Close();
-  }
-
-  StatsCounter zero_counter(kCounterZero);
-  StatsCounter lucky13_counter(kCounter1313);
-  StatsCounter increment_counter(kCounterIncrement);
-  StatsCounter decrement_counter(kCounterDecrement);
-
-  // Verify the various counters are correct.
-  std::string name;
-  name = "c:" + kCounterZero;
-  EXPECT_EQ(0, table.GetCounterValue(name));
-  name = "c:" + kCounter1313;
-  EXPECT_EQ(1313 * kMaxProcs,
-      table.GetCounterValue(name));
-  name = "c:" + kCounterIncrement;
-  EXPECT_EQ(kMaxProcs * kThreadLoops,
-      table.GetCounterValue(name));
-  name = "c:" + kCounterDecrement;
-  EXPECT_EQ(-kMaxProcs * kThreadLoops,
-      table.GetCounterValue(name));
-  EXPECT_EQ(0, table.CountThreadsRegistered());
-}
-#endif
-
-class MockStatsCounter : public StatsCounter {
- public:
-  explicit MockStatsCounter(const std::string& name)
-      : StatsCounter(name) {}
-  int* Pointer() { return GetPtr(); }
-};
-
-// Test some basic StatsCounter operations
-TEST_F(StatsTableTest, StatsCounter) {
-  // Create a stats table.
-  const int kMaxThreads = 20;
-  const int kMaxCounter = 5;
-  StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-  StatsTable::set_current(&table);
-
-  MockStatsCounter foo("foo");
-
-  // Test initial state.
-  EXPECT_TRUE(foo.Enabled());
-  ASSERT_NE(foo.Pointer(), static_cast<int*>(0));
-  EXPECT_EQ(0, *(foo.Pointer()));
-  EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-
-  // Test Increment.
-  while (*(foo.Pointer()) < 123) foo.Increment();
-  EXPECT_EQ(123, table.GetCounterValue("c:foo"));
-  foo.Add(0);
-  EXPECT_EQ(123, table.GetCounterValue("c:foo"));
-  foo.Add(-1);
-  EXPECT_EQ(122, table.GetCounterValue("c:foo"));
-
-  // Test Set.
-  foo.Set(0);
-  EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-  foo.Set(100);
-  EXPECT_EQ(100, table.GetCounterValue("c:foo"));
-  foo.Set(-1);
-  EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
-  foo.Set(0);
-  EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-
-  // Test Decrement.
-  foo.Subtract(1);
-  EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
-  foo.Subtract(0);
-  EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
-  foo.Subtract(-1);
-  EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-}
-
-class MockStatsCounterTimer : public StatsCounterTimer {
- public:
-  explicit MockStatsCounterTimer(const std::string& name)
-      : StatsCounterTimer(name) {}
-
-  TimeTicks start_time() { return start_time_; }
-  TimeTicks stop_time() { return stop_time_; }
-};
-
-// Test some basic StatsCounterTimer operations
-TEST_F(StatsTableTest, StatsCounterTimer) {
-  // Create a stats table.
-  const int kMaxThreads = 20;
-  const int kMaxCounter = 5;
-  StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-  StatsTable::set_current(&table);
-
-  MockStatsCounterTimer bar("bar");
-
-  // Test initial state.
-  EXPECT_FALSE(bar.Running());
-  EXPECT_TRUE(bar.start_time().is_null());
-  EXPECT_TRUE(bar.stop_time().is_null());
-
-  const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
-  // Do some timing.
-  bar.Start();
-  PlatformThread::Sleep(kDuration);
-  bar.Stop();
-  EXPECT_GT(table.GetCounterValue("t:bar"), 0);
-  EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
-
-  // Verify that timing again is additive.
-  bar.Start();
-  PlatformThread::Sleep(kDuration);
-  bar.Stop();
-  EXPECT_GT(table.GetCounterValue("t:bar"), 0);
-  EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
-}
-
-// Test some basic StatsRate operations
-TEST_F(StatsTableTest, StatsRate) {
-  // Create a stats table.
-  const int kMaxThreads = 20;
-  const int kMaxCounter = 5;
-  StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-  StatsTable::set_current(&table);
-
-  StatsRate baz("baz");
-
-  // Test initial state.
-  EXPECT_FALSE(baz.Running());
-  EXPECT_EQ(0, table.GetCounterValue("c:baz"));
-  EXPECT_EQ(0, table.GetCounterValue("t:baz"));
-
-  const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
-  // Do some timing.
-  baz.Start();
-  PlatformThread::Sleep(kDuration);
-  baz.Stop();
-  EXPECT_EQ(1, table.GetCounterValue("c:baz"));
-  EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:baz"));
-
-  // Verify that timing again is additive.
-  baz.Start();
-  PlatformThread::Sleep(kDuration);
-  baz.Stop();
-  EXPECT_EQ(2, table.GetCounterValue("c:baz"));
-  EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:baz"));
-}
-
-// Test some basic StatsScope operations
-TEST_F(StatsTableTest, StatsScope) {
-  // Create a stats table.
-  const int kMaxThreads = 20;
-  const int kMaxCounter = 5;
-  StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-  StatsTable::set_current(&table);
-
-  StatsCounterTimer foo("foo");
-  StatsRate bar("bar");
-
-  // Test initial state.
-  EXPECT_EQ(0, table.GetCounterValue("t:foo"));
-  EXPECT_EQ(0, table.GetCounterValue("t:bar"));
-  EXPECT_EQ(0, table.GetCounterValue("c:bar"));
-
-  const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
-  // Try a scope.
-  {
-    StatsScope<StatsCounterTimer> timer(foo);
-    StatsScope<StatsRate> timer2(bar);
-    PlatformThread::Sleep(kDuration);
-  }
-  EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:foo"));
-  EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
-  EXPECT_EQ(1, table.GetCounterValue("c:bar"));
-
-  // Try a second scope.
-  {
-    StatsScope<StatsCounterTimer> timer(foo);
-    StatsScope<StatsRate> timer2(bar);
-    PlatformThread::Sleep(kDuration);
-  }
-  EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:foo"));
-  EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
-  EXPECT_EQ(2, table.GetCounterValue("c:bar"));
-}
-
-}  // namespace base
diff --git a/observer_list_threadsafe.h b/observer_list_threadsafe.h
index b951a71..1a66333 100644
--- a/observer_list_threadsafe.h
+++ b/observer_list_threadsafe.h
@@ -168,7 +168,9 @@
   // that at the completion of the Notify call that all Observers have
   // been Notified.  The notification may still be pending delivery.
   template <class Method, class... Params>
-  void Notify(Method m, const Params&... params) {
+  void Notify(const tracked_objects::Location& from_here,
+              Method m,
+              const Params&... params) {
     UnboundMethod<ObserverType, Method, Tuple<Params...>> method(
         m, MakeTuple(params...));
 
@@ -176,7 +178,7 @@
     for (const auto& entry : observer_lists_) {
       ObserverListContext* context = entry.second;
       context->loop->PostTask(
-          FROM_HERE,
+          from_here,
           base::Bind(
               &ObserverListThreadSafe<ObserverType>::template NotifyWrapper<
                   Method, Tuple<Params...>>,
diff --git a/observer_list_unittest.cc b/observer_list_unittest.cc
index 65ef934..636aa83 100644
--- a/observer_list_unittest.cc
+++ b/observer_list_unittest.cc
@@ -134,7 +134,7 @@
     }
 
     if (do_notifies_) {
-      list_->Notify(&Foo::Observe, 10);
+      list_->Notify(FROM_HERE, &Foo::Observe, 10);
     }
 
     loop_->PostTask(
@@ -217,14 +217,14 @@
   observer_list->AddObserver(&a);
   observer_list->AddObserver(&b);
 
-  observer_list->Notify(&Foo::Observe, 10);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
   RunLoop().RunUntilIdle();
 
   observer_list->AddObserver(&evil);
   observer_list->AddObserver(&c);
   observer_list->AddObserver(&d);
 
-  observer_list->Notify(&Foo::Observe, 10);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
   RunLoop().RunUntilIdle();
 
   EXPECT_EQ(20, a.total);
@@ -247,7 +247,7 @@
   observer_list->RemoveObserver(&a);
   observer_list->RemoveObserver(&b);
 
-  observer_list->Notify(&Foo::Observe, 10);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
   RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0, a.total);
@@ -258,7 +258,7 @@
   // Should also do nothing.
   observer_list->RemoveObserver(&b);
 
-  observer_list->Notify(&Foo::Observe, 10);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
   RunLoop().RunUntilIdle();
 
   EXPECT_EQ(10, a.total);
@@ -280,7 +280,7 @@
     MessageLoop loop;
     observer_list->AddObserver(&c);
 
-    observer_list->Notify(&Foo::Observe, 10);
+    observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
     RunLoop().RunUntilIdle();
 
     EXPECT_EQ(0, a.total);
@@ -294,7 +294,7 @@
     observer_list->RemoveObserver(&c);
 
     // Notify again.
-    observer_list->Notify(&Foo::Observe, 20);
+    observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
     RunLoop().RunUntilIdle();
 
     EXPECT_EQ(20, a.total);
@@ -308,7 +308,7 @@
   // Notifying should not fail but should also be a no-op.
   MessageLoop loop;
   observer_list->AddObserver(&b);
-  observer_list->Notify(&Foo::Observe, 30);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
   RunLoop().RunUntilIdle();
 
   EXPECT_EQ(20, a.total);
@@ -353,7 +353,7 @@
   a.AddFooToRemove(&a);
   a.AddFooToRemove(&b);
 
-  observer_list->Notify(&Foo::Observe, 1);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
   RunLoop().RunUntilIdle();
 }
 
@@ -392,7 +392,7 @@
     if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
       break;
 
-    observer_list->Notify(&Foo::Observe, 10);
+    observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
 
     RunLoop().RunUntilIdle();
   }
@@ -424,7 +424,7 @@
   observer_list->AddObserver(&a);
   delete loop;
   // Test passes if we don't crash here.
-  observer_list->Notify(&Foo::Observe, 1);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
 }
 
 TEST(ObserverListTest, Existing) {
@@ -458,7 +458,7 @@
   observer_list->AddObserver(&a);
   observer_list->AddObserver(&b);
 
-  observer_list->Notify(&Foo::Observe, 1);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
   RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(b.added);
@@ -467,7 +467,7 @@
   EXPECT_EQ(0, b.adder.total);
 
   // Notify again to make sure b's adder is notified.
-  observer_list->Notify(&Foo::Observe, 1);
+  observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
   RunLoop().RunUntilIdle();
   EXPECT_EQ(1, b.adder.total);
 }
diff --git a/power_monitor/power_monitor.cc b/power_monitor/power_monitor.cc
index 14dc4b5..98c9c68 100644
--- a/power_monitor/power_monitor.cc
+++ b/power_monitor/power_monitor.cc
@@ -45,17 +45,18 @@
 void PowerMonitor::NotifyPowerStateChange(bool battery_in_use) {
   DVLOG(1) << "PowerStateChange: " << (battery_in_use ? "On" : "Off")
            << " battery";
-  observers_->Notify(&PowerObserver::OnPowerStateChange, battery_in_use);
+  observers_->Notify(FROM_HERE, &PowerObserver::OnPowerStateChange,
+                     battery_in_use);
 }
 
 void PowerMonitor::NotifySuspend() {
   DVLOG(1) << "Power Suspending";
-  observers_->Notify(&PowerObserver::OnSuspend);
+  observers_->Notify(FROM_HERE, &PowerObserver::OnSuspend);
 }
 
 void PowerMonitor::NotifyResume() {
   DVLOG(1) << "Power Resuming";
-  observers_->Notify(&PowerObserver::OnResume);
+  observers_->Notify(FROM_HERE, &PowerObserver::OnResume);
 }
 
 }  // namespace base
diff --git a/process/kill_win.cc b/process/kill_win.cc
index 4d7225f..f280c6f 100644
--- a/process/kill_win.cc
+++ b/process/kill_win.cc
@@ -182,10 +182,9 @@
 }
 
 bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
-  bool success = WaitForExitCodeWithTimeout(
-      handle, exit_code, base::TimeDelta::FromMilliseconds(INFINITE));
-  CloseProcessHandle(handle);
-  return success;
+  // TODO(rvargas) crbug.com/417532: Remove this function.
+  Process process(handle);
+  return process.WaitForExit(exit_code);
 }
 
 bool WaitForExitCodeWithTimeout(ProcessHandle handle,
diff --git a/process/process_handle.h b/process/process_handle.h
index c99ea15..77f2c58 100644
--- a/process/process_handle.h
+++ b/process/process_handle.h
@@ -40,30 +40,12 @@
 // Returns the ProcessHandle of the current process.
 BASE_EXPORT ProcessHandle GetCurrentProcessHandle();
 
-
-
-// Closes the process handle opened by OpenProcessHandle.
-BASE_EXPORT void CloseProcessHandle(ProcessHandle process);
-
 // Returns the unique ID for the specified process. This is functionally the
 // same as Windows' GetProcessId(), but works on versions of Windows before
 // Win XP SP1 as well.
+// DEPRECATED. New code should be using Process::Pid() instead.
 BASE_EXPORT ProcessId GetProcId(ProcessHandle process);
 
-#if defined(OS_WIN)
-enum IntegrityLevel {
-  INTEGRITY_UNKNOWN,
-  LOW_INTEGRITY,
-  MEDIUM_INTEGRITY,
-  HIGH_INTEGRITY,
-};
-// Determine the integrity level of the specified process. Returns false
-// if the system does not support integrity levels (pre-Vista) or in the case
-// of an underlying system failure.
-BASE_EXPORT bool GetProcessIntegrityLevel(ProcessHandle process,
-                                          IntegrityLevel* level);
-#endif
-
 #if defined(OS_POSIX)
 // Returns the path to the executable of the given process.
 BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process);
diff --git a/process/process_handle_posix.cc b/process/process_handle_posix.cc
index a661ecd..4e332df 100644
--- a/process/process_handle_posix.cc
+++ b/process/process_handle_posix.cc
@@ -16,11 +16,6 @@
   return GetCurrentProcId();
 }
 
-void CloseProcessHandle(ProcessHandle process) {
-  // See OpenProcessHandle, nothing to do.
-  return;
-}
-
 ProcessId GetProcId(ProcessHandle process) {
   return process;
 }
diff --git a/process/process_handle_win.cc b/process/process_handle_win.cc
index 30b2066..f2ffff8 100644
--- a/process/process_handle_win.cc
+++ b/process/process_handle_win.cc
@@ -20,64 +20,9 @@
   return ::GetCurrentProcess();
 }
 
-void CloseProcessHandle(ProcessHandle process) {
-  CloseHandle(process);
-}
-
 ProcessId GetProcId(ProcessHandle process) {
   // This returns 0 if we have insufficient rights to query the process handle.
   return GetProcessId(process);
 }
 
-bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel *level) {
-  if (!level)
-    return false;
-
-  if (win::GetVersion() < base::win::VERSION_VISTA)
-    return false;
-
-  HANDLE process_token;
-  if (!OpenProcessToken(process, TOKEN_QUERY | TOKEN_QUERY_SOURCE,
-      &process_token))
-    return false;
-
-  win::ScopedHandle scoped_process_token(process_token);
-
-  DWORD token_info_length = 0;
-  if (GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0,
-                          &token_info_length) ||
-      GetLastError() != ERROR_INSUFFICIENT_BUFFER)
-    return false;
-
-  scoped_ptr<char[]> token_label_bytes(new char[token_info_length]);
-  if (!token_label_bytes.get())
-    return false;
-
-  TOKEN_MANDATORY_LABEL* token_label =
-      reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
-  if (!token_label)
-    return false;
-
-  if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
-                           token_info_length, &token_info_length))
-    return false;
-
-  DWORD integrity_level = *GetSidSubAuthority(token_label->Label.Sid,
-      (DWORD)(UCHAR)(*GetSidSubAuthorityCount(token_label->Label.Sid)-1));
-
-  if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID) {
-    *level = LOW_INTEGRITY;
-  } else if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
-      integrity_level < SECURITY_MANDATORY_HIGH_RID) {
-    *level = MEDIUM_INTEGRITY;
-  } else if (integrity_level >= SECURITY_MANDATORY_HIGH_RID) {
-    *level = HIGH_INTEGRITY;
-  } else {
-    NOTREACHED();
-    return false;
-  }
-
-  return true;
-}
-
 }  // namespace base
diff --git a/process/process_info.h b/process/process_info.h
index e9e7b4e..85f204d 100644
--- a/process/process_info.h
+++ b/process/process_info.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_PROCESS_PROCESS_PROCESS_INFO_H_
-#define BASE_PROCESS_PROCESS_PROCESS_INFO_H_
+#ifndef BASE_PROCESS_PROCESS_INFO_H_
+#define BASE_PROCESS_PROCESS_INFO_H_
 
 #include "base/base_export.h"
 #include "base/basictypes.h"
+#include "build/build_config.h"
 
 namespace base {
 
@@ -20,6 +21,24 @@
   static const Time CreationTime();
 };
 
+#if defined(OS_WIN)
+
+enum IntegrityLevel {
+  INTEGRITY_UNKNOWN,
+  LOW_INTEGRITY,
+  MEDIUM_INTEGRITY,
+  HIGH_INTEGRITY,
+};
+
+// Returns the integrity level of the process. Returns INTEGRITY_UNKNOWN if the
+// system does not support integrity levels (pre-Vista) or in the case of an
+// underlying system failure.
+BASE_EXPORT IntegrityLevel GetCurrentProcessIntegrityLevel();
+
+#endif  // defined(OS_WIN)
+
+
+
 }  // namespace base
 
-#endif  // BASE_PROCESS_PROCESS_PROCESS_INFO_H_
+#endif  // BASE_PROCESS_PROCESS_INFO_H_
diff --git a/process/process_info_win.cc b/process/process_info_win.cc
index b930ae6..2b9c406 100644
--- a/process/process_info_win.cc
+++ b/process/process_info_win.cc
@@ -7,11 +7,14 @@
 #include <windows.h>
 
 #include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
 
 namespace base {
 
-//static
+// static
 const Time CurrentProcessInfo::CreationTime() {
   FILETIME creation_time = {};
   FILETIME ignore = {};
@@ -22,4 +25,55 @@
   return Time::FromFileTime(creation_time);
 }
 
+IntegrityLevel GetCurrentProcessIntegrityLevel() {
+  if (win::GetVersion() < base::win::VERSION_VISTA)
+    return INTEGRITY_UNKNOWN;
+
+  HANDLE process_token;
+  if (!::OpenProcessToken(::GetCurrentProcess(),
+                          TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
+    return INTEGRITY_UNKNOWN;
+  }
+  win::ScopedHandle scoped_process_token(process_token);
+
+  DWORD token_info_length = 0;
+  if (::GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0,
+                            &token_info_length) ||
+      ::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+    return INTEGRITY_UNKNOWN;
+  }
+
+  scoped_ptr<char[]> token_label_bytes(new char[token_info_length]);
+  if (!token_label_bytes.get())
+    return INTEGRITY_UNKNOWN;
+
+  TOKEN_MANDATORY_LABEL* token_label =
+      reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
+  if (!token_label)
+    return INTEGRITY_UNKNOWN;
+
+  if (!::GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
+                             token_info_length, &token_info_length)) {
+    return INTEGRITY_UNKNOWN;
+  }
+
+  DWORD integrity_level = *::GetSidSubAuthority(
+      token_label->Label.Sid,
+      static_cast<DWORD>(*::GetSidSubAuthorityCount(token_label->Label.Sid)-1));
+
+  if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID)
+    return LOW_INTEGRITY;
+
+  if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
+      integrity_level < SECURITY_MANDATORY_HIGH_RID) {
+    return MEDIUM_INTEGRITY;
+  }
+
+  if (integrity_level >= SECURITY_MANDATORY_HIGH_RID)
+    return HIGH_INTEGRITY;
+
+  NOTREACHED();
+  return INTEGRITY_UNKNOWN;
+}
+
 }  // namespace base
diff --git a/strings/string_util.cc b/strings/string_util.cc
index 8f334da..e084cb5 100644
--- a/strings/string_util.cc
+++ b/strings/string_util.cc
@@ -454,8 +454,8 @@
   return DoLowerCaseEqualsASCII(a_begin, a_end, b);
 }
 
-// TODO(jdduke): Remove guards after complete adoption of libc++ on Android.
-#if !defined(OS_ANDROID) || !defined(USE_STLPORT)
+// TODO(port): Resolve wchar_t/iterator issues that require OS_ANDROID here.
+#if !defined(OS_ANDROID)
 bool LowerCaseEqualsASCII(const char* a_begin,
                           const char* a_end,
                           const char* b) {
@@ -467,7 +467,8 @@
                           const char* b) {
   return DoLowerCaseEqualsASCII(a_begin, a_end, b);
 }
-#endif  // !defined(OS_ANDROID) || !defined(USE_STLPORT)
+
+#endif  // !defined(OS_ANDROID)
 
 bool EqualsASCII(const string16& a, const base::StringPiece& b) {
   if (a.length() != b.length())
@@ -555,23 +556,103 @@
   return base::ASCIIToUTF16(buf);
 }
 
+// Runs in O(n) time in the length of |str|.
 template<class StringType>
 void DoReplaceSubstringsAfterOffset(StringType* str,
-                                    size_t start_offset,
+                                    size_t offset,
                                     const StringType& find_this,
                                     const StringType& replace_with,
                                     bool replace_all) {
-  if ((start_offset == StringType::npos) || (start_offset >= str->length()))
+  DCHECK(!find_this.empty());
+
+  // If the find string doesn't appear, there's nothing to do.
+  offset = str->find(find_this, offset);
+  if (offset == StringType::npos)
     return;
 
-  DCHECK(!find_this.empty());
-  for (size_t offs(str->find(find_this, start_offset));
-      offs != StringType::npos; offs = str->find(find_this, offs)) {
-    str->replace(offs, find_this.length(), replace_with);
-    offs += replace_with.length();
+  // If we're only replacing one instance, there's no need to do anything
+  // complicated.
+  size_t find_length = find_this.length();
+  if (!replace_all) {
+    str->replace(offset, find_length, replace_with);
+    return;
+  }
 
-    if (!replace_all)
-      break;
+  // If the find and replace strings are the same length, we can simply use
+  // replace() on each instance, and finish the entire operation in O(n) time.
+  size_t replace_length = replace_with.length();
+  if (find_length == replace_length) {
+    do {
+      str->replace(offset, find_length, replace_with);
+      offset = str->find(find_this, offset + replace_length);
+    } while (offset != StringType::npos);
+    return;
+  }
+
+  // Since the find and replace strings aren't the same length, a loop like the
+  // one above would be O(n^2) in the worst case, as replace() will shift the
+  // entire remaining string each time.  We need to be more clever to keep
+  // things O(n).
+  //
+  // If we're shortening the string, we can alternate replacements with shifting
+  // forward the intervening characters using memmove().
+  size_t str_length = str->length();
+  if (find_length > replace_length) {
+    size_t write_offset = offset;
+    do {
+      if (replace_length) {
+        str->replace(write_offset, replace_length, replace_with);
+        write_offset += replace_length;
+      }
+      size_t read_offset = offset + find_length;
+      offset = std::min(str->find(find_this, read_offset), str_length);
+      size_t length = offset - read_offset;
+      if (length) {
+        memmove(&(*str)[write_offset], &(*str)[read_offset],
+                length * sizeof(typename StringType::value_type));
+        write_offset += length;
+      }
+    } while (offset < str_length);
+    str->resize(write_offset);
+    return;
+  }
+
+  // We're lengthening the string.  We can use alternating replacements and
+  // memmove() calls like above, but we need to precalculate the final string
+  // length and then expand from back-to-front to avoid overwriting the string
+  // as we're reading it, needing to shift, or having to copy to a second string
+  // temporarily.
+  size_t first_match = offset;
+
+  // First, calculate the final length and resize the string.
+  size_t final_length = str_length;
+  size_t expansion = replace_length - find_length;
+  size_t current_match;
+  do {
+    final_length += expansion;
+    // Minor optimization: save this offset into |current_match|, so that on
+    // exit from the loop, |current_match| will point at the last instance of
+    // the find string, and we won't need to find() it again immediately.
+    current_match = offset;
+    offset = str->find(find_this, offset + find_length);
+  } while (offset != StringType::npos);
+  str->resize(final_length);
+
+  // Now do the replacement loop, working backwards through the string.
+  for (size_t prev_match = str_length, write_offset = final_length; ;
+       current_match = str->rfind(find_this, current_match - 1)) {
+    size_t read_offset = current_match + find_length;
+    size_t length = prev_match - read_offset;
+    if (length) {
+      write_offset -= length;
+      memmove(&(*str)[write_offset], &(*str)[read_offset],
+              length * sizeof(typename StringType::value_type));
+    }
+    write_offset -= replace_length;
+    str->replace(write_offset, replace_length, replace_with);
+    if (current_match == first_match)
+      return;
+    prev_match = current_match;
   }
 }
 
diff --git a/system_monitor/system_monitor.cc b/system_monitor/system_monitor.cc
index 11dd000..99152ab 100644
--- a/system_monitor/system_monitor.cc
+++ b/system_monitor/system_monitor.cc
@@ -46,7 +46,7 @@
 void SystemMonitor::NotifyDevicesChanged(DeviceType device_type) {
   DVLOG(1) << "DevicesChanged with device type " << device_type;
   devices_changed_observer_list_->Notify(
-      &DevicesChangedObserver::OnDevicesChanged, device_type);
+      FROM_HERE, &DevicesChangedObserver::OnDevicesChanged, device_type);
 }
 
 }  // namespace base
diff --git a/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java b/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
index 09e1fd6..797585f 100644
--- a/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
+++ b/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
@@ -16,20 +16,41 @@
 
     /**
      * Construct the full path of a test data file.
-     * @param path Pathname relative to external/chrome/testing/data
+     * @param path Pathname relative to external/chrome/test/data
      */
     public static String getTestFilePath(String path) {
+        // TODO(jbudorick): Remove DATA_DIR once everything has been isolated. crbug/400499
         return PathUtils.getExternalStorageDirectory() + DATA_DIR + path;
     }
 
+    // TODO(jbudorick): Remove this function once everything has been isolated and switched back
+    // to getTestFilePath. crbug/400499
+    /**
+     * Construct the full path of a test data file.
+     * @param path Pathname relative to external/
+     */
+    public static String getIsolatedTestFilePath(String path) {
+        return PathUtils.getExternalStorageDirectory() + "/" + path;
+    }
+
     /**
      * Construct a suitable URL for loading a test data file.
-     * @param path Pathname relative to external/chrome/testing/data
+     * @param path Pathname relative to external/chrome/test/data
      */
     public static String getTestFileUrl(String path) {
         return "file://" + getTestFilePath(path);
     }
 
+    // TODO(jbudorick): Remove this function once everything has been isolated and switched back
+    // to getTestFileUrl. crbug/400499
+    /**
+     * Construct a suitable URL for loading a test data file.
+     * @param path Pathname relative to external/
+     */
+    public static String getIsolatedTestFileUrl(String path) {
+        return "file://" + getIsolatedTestFilePath(path);
+    }
+
     /**
      * Construct a data:text/html URI for loading from an inline HTML.
      * @param html An unencoded HTML
@@ -41,8 +62,7 @@
             // ' '->'+' needs to be undone and replaced with ' '->'%20'
             // to match the Data URI requirements.
             String encoded =
-                    "data:text/html;utf-8," +
-                    java.net.URLEncoder.encode(html, "UTF-8");
+                    "data:text/html;utf-8," + java.net.URLEncoder.encode(html, "UTF-8");
             encoded = encoded.replace("+", "%20");
             return encoded;
         } catch (java.io.UnsupportedEncodingException e) {
diff --git a/test/multiprocess_test.h b/test/multiprocess_test.h
index e419503..b1c73df 100644
--- a/test/multiprocess_test.h
+++ b/test/multiprocess_test.h
@@ -33,16 +33,15 @@
 //     // Maybe set some options (e.g., |start_hidden| on Windows)....
 //
 //     // Start a child process and run |a_test_func|.
-//     base::ProcessHandle test_child_handle =
+//     base::Process test_child_process =
 //         base::SpawnMultiProcessTestChild("a_test_func", command_line,
 //                                          options);
 //
-//     // Do stuff involving |test_child_handle| and the child process....
+//     // Do stuff involving |test_child_process| and the child process....
 //
 //     int rv = -1;
-//     ASSERT_TRUE(base::WaitForExitCodeWithTimeout(
-//         test_child_handle, &rv, TestTimeouts::action_timeout()));
-//     base::CloseProcessHandle(test_child_handle);
+//     ASSERT_TRUE(test_child_process.WaitForExitWithTimeout(
+//         TestTimeouts::action_timeout(), &rv));
 //     EXPECT_EQ(0, rv);
 //   }
 //
diff --git a/test/test_mock_time_task_runner.cc b/test/test_mock_time_task_runner.cc
index 442d991..a878280 100644
--- a/test/test_mock_time_task_runner.cc
+++ b/test/test_mock_time_task_runner.cc
@@ -6,18 +6,21 @@
 
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/time/clock.h"
+#include "base/time/tick_clock.h"
 
 namespace base {
 
 namespace {
 
-// TickClock that always returns the then-current mock time of |task_runner| as
-// the current time.
+// MockTickClock --------------------------------------------------------------
+
+// TickClock that always returns the then-current mock time ticks of
+// |task_runner| as the current time ticks.
 class MockTickClock : public TickClock {
  public:
   explicit MockTickClock(
       scoped_refptr<const TestMockTimeTaskRunner> task_runner);
-  ~MockTickClock() override;
 
   // TickClock:
   TimeTicks NowTicks() override;
@@ -33,22 +36,46 @@
     : task_runner_(task_runner) {
 }
 
-MockTickClock::~MockTickClock() {
+TimeTicks MockTickClock::NowTicks() {
+  return task_runner_->NowTicks();
 }
 
-TimeTicks MockTickClock::NowTicks() {
-  return task_runner_->GetCurrentMockTime();
+// MockClock ------------------------------------------------------------------
+
+// Clock that always returns the then-current mock time of |task_runner| as the
+// current time.
+class MockClock : public Clock {
+ public:
+  explicit MockClock(scoped_refptr<const TestMockTimeTaskRunner> task_runner);
+
+  // Clock:
+  Time Now() override;
+
+ private:
+  scoped_refptr<const TestMockTimeTaskRunner> task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockClock);
+};
+
+MockClock::MockClock(scoped_refptr<const TestMockTimeTaskRunner> task_runner)
+    : task_runner_(task_runner) {
+}
+
+Time MockClock::Now() {
+  return task_runner_->Now();
 }
 
 }  // namespace
 
+// TestMockTimeTaskRunner -----------------------------------------------------
+
 bool TestMockTimeTaskRunner::TemporalOrder::operator()(
     const TestPendingTask& first_task,
     const TestPendingTask& second_task) const {
   return first_task.GetTimeToRun() > second_task.GetTimeToRun();
 }
 
-TestMockTimeTaskRunner::TestMockTimeTaskRunner() {
+TestMockTimeTaskRunner::TestMockTimeTaskRunner() : now_(Time::UnixEpoch()) {
 }
 
 TestMockTimeTaskRunner::~TestMockTimeTaskRunner() {
@@ -56,42 +83,38 @@
 
 void TestMockTimeTaskRunner::FastForwardBy(TimeDelta delta) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_GE(delta, TimeDelta());
 
-  OnBeforeSelectingTask();
-
-  const base::TimeTicks original_now = now_;
-  TestPendingTask task_info;
-  while (DequeueNextTask(original_now, delta, &task_info)) {
-    if (task_info.GetTimeToRun() - now_ > base::TimeDelta()) {
-      now_ = task_info.GetTimeToRun();
-      OnAfterTimePassed();
-    }
-
-    task_info.task.Run();
-
-    OnAfterTaskRun();
-    OnBeforeSelectingTask();
-  }
-
-  if (!delta.is_max() && now_ - original_now < delta) {
-    now_ = original_now + delta;
-    OnAfterTimePassed();
-  }
+  const TimeTicks original_now_ticks = now_ticks_;
+  ProcessAllTasksNoLaterThan(delta);
+  ForwardClocksUntilTickTime(original_now_ticks + delta);
 }
 
 void TestMockTimeTaskRunner::RunUntilIdle() {
-  FastForwardBy(TimeDelta());
+  DCHECK(thread_checker_.CalledOnValidThread());
+  ProcessAllTasksNoLaterThan(TimeDelta());
 }
 
 void TestMockTimeTaskRunner::FastForwardUntilNoTasksRemain() {
-  FastForwardBy(TimeDelta::Max());
+  DCHECK(thread_checker_.CalledOnValidThread());
+  ProcessAllTasksNoLaterThan(TimeDelta::Max());
 }
 
-TimeTicks TestMockTimeTaskRunner::GetCurrentMockTime() const {
+Time TestMockTimeTaskRunner::Now() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   return now_;
 }
 
+TimeTicks TestMockTimeTaskRunner::NowTicks() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return now_ticks_;
+}
+
+scoped_ptr<Clock> TestMockTimeTaskRunner::GetMockClock() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return make_scoped_ptr(new MockClock(this));
+}
+
 scoped_ptr<TickClock> TestMockTimeTaskRunner::GetMockTickClock() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   return make_scoped_ptr(new MockTickClock(this));
@@ -109,7 +132,8 @@
 
 TimeDelta TestMockTimeTaskRunner::NextPendingTaskDelay() const {
   DCHECK(thread_checker_.CalledOnValidThread());
-  return tasks_.empty() ? TimeDelta::Max() : tasks_.top().GetTimeToRun() - now_;
+  return tasks_.empty() ? TimeDelta::Max()
+                        : tasks_.top().GetTimeToRun() - now_ticks_;
 }
 
 bool TestMockTimeTaskRunner::RunsTasksOnCurrentThread() const {
@@ -120,9 +144,9 @@
     const tracked_objects::Location& from_here,
     const Closure& task,
     TimeDelta delay) {
-  base::AutoLock scoped_lock(tasks_lock_);
-  tasks_.push(
-      TestPendingTask(from_here, task, now_, delay, TestPendingTask::NESTABLE));
+  AutoLock scoped_lock(tasks_lock_);
+  tasks_.push(TestPendingTask(from_here, task, now_ticks_, delay,
+                              TestPendingTask::NESTABLE));
   return true;
 }
 
@@ -146,10 +170,36 @@
   // Empty default implementation.
 }
 
-bool TestMockTimeTaskRunner::DequeueNextTask(const base::TimeTicks& reference,
-                                             const base::TimeDelta& max_delta,
+void TestMockTimeTaskRunner::ProcessAllTasksNoLaterThan(TimeDelta max_delta) {
+  DCHECK_GE(max_delta, TimeDelta());
+  const TimeTicks original_now_ticks = now_ticks_;
+  while (true) {
+    OnBeforeSelectingTask();
+    TestPendingTask task_info;
+    if (!DequeueNextTask(original_now_ticks, max_delta, &task_info))
+      break;
+    // If tasks were posted with a negative delay, task_info.GetTimeToRun() will
+    // be less than |now_ticks_|. ForwardClocksUntilTickTime() takes care of not
+    // moving the clock backwards in this case.
+    ForwardClocksUntilTickTime(task_info.GetTimeToRun());
+    task_info.task.Run();
+    OnAfterTaskRun();
+  }
+}
+
+void TestMockTimeTaskRunner::ForwardClocksUntilTickTime(TimeTicks later_ticks) {
+  if (later_ticks <= now_ticks_)
+    return;
+
+  now_ += later_ticks - now_ticks_;
+  now_ticks_ = later_ticks;
+  OnAfterTimePassed();
+}
+
+bool TestMockTimeTaskRunner::DequeueNextTask(const TimeTicks& reference,
+                                             const TimeDelta& max_delta,
                                              TestPendingTask* next_task) {
-  base::AutoLock scoped_lock(tasks_lock_);
+  AutoLock scoped_lock(tasks_lock_);
   if (!tasks_.empty() &&
       (tasks_.top().GetTimeToRun() - reference) <= max_delta) {
     *next_task = tasks_.top();
diff --git a/test/test_mock_time_task_runner.h b/test/test_mock_time_task_runner.h
index 2f59892..1a651f6 100644
--- a/test/test_mock_time_task_runner.h
+++ b/test/test_mock_time_task_runner.h
@@ -14,11 +14,13 @@
 #include "base/synchronization/lock.h"
 #include "base/test/test_pending_task.h"
 #include "base/threading/thread_checker.h"
-#include "base/time/tick_clock.h"
 #include "base/time/time.h"
 
 namespace base {
 
+class Clock;
+class TickClock;
+
 // Runs pending tasks in the order of the tasks' post time + delay, and keeps
 // track of a mock (virtual) tick clock time that can be fast-forwarded.
 //
@@ -31,18 +33,26 @@
 //     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.
+//   - 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
 // that it supports running delayed tasks in the correct temporal order.
-class TestMockTimeTaskRunner : public base::SingleThreadTaskRunner {
+class TestMockTimeTaskRunner : public SingleThreadTaskRunner {
  public:
+  // Constructs an instance whose virtual time will start at the Unix epoch, and
+  // whose time ticks will start at zero.
   TestMockTimeTaskRunner();
 
   // Fast-forwards virtual time by |delta|, causing all tasks with a remaining
-  // delay less than or equal to |delta| to be executed.
-  void FastForwardBy(base::TimeDelta delta);
+  // delay less than or equal to |delta| to be executed. |delta| must be
+  // non-negative.
+  void FastForwardBy(TimeDelta delta);
 
   // Fast-forwards virtual time just until all tasks are executed.
   void FastForwardUntilNoTasksRemain();
@@ -52,11 +62,18 @@
   // elapse.
   void RunUntilIdle();
 
-  // Returns the current virtual time.
-  TimeTicks GetCurrentMockTime() const;
+  // Returns the current virtual time (initially starting at the Unix epoch).
+  Time Now() const;
 
-  // Returns a TickClock that uses the mock time of |this| as its time source.
-  // The returned TickClock will hold a reference to |this|.
+  // Returns the current virtual tick time (initially starting at 0).
+  TimeTicks NowTicks() const;
+
+  // Returns a Clock that uses the virtual time of |this| as its time source.
+  // The returned Clock will hold a reference to |this|.
+  scoped_ptr<Clock> GetMockClock() const;
+
+  // Returns a TickClock that uses the virtual time ticks of |this| as its tick
+  // source. The returned TickClock will hold a reference to |this|.
   scoped_ptr<TickClock> GetMockTickClock() const;
 
   bool HasPendingTask() const;
@@ -66,12 +83,11 @@
   // SingleThreadTaskRunner:
   bool RunsTasksOnCurrentThread() const override;
   bool PostDelayedTask(const tracked_objects::Location& from_here,
-                               const base::Closure& task,
-                               TimeDelta delay) override;
-  bool PostNonNestableDelayedTask(
-      const tracked_objects::Location& from_here,
-      const base::Closure& task,
-      TimeDelta delay) override;
+                       const Closure& task,
+                       TimeDelta delay) override;
+  bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+                                  const Closure& task,
+                                  TimeDelta delay) override;
 
  protected:
   ~TestMockTimeTaskRunner() override;
@@ -100,20 +116,32 @@
                               std::vector<TestPendingTask>,
                               TemporalOrder> TaskPriorityQueue;
 
+  // Core of the implementation for all flavors of fast-forward methods. Given a
+  // non-negative |max_delta|, runs all tasks with a remaining delay less than
+  // or equal to |max_delta|, and moves virtual time forward as needed for each
+  // processed task. Pass in TimeDelta::Max() as |max_delta| to run all tasks.
+  void ProcessAllTasksNoLaterThan(TimeDelta max_delta);
+
+  // Forwards |now_ticks_| until it equals |later_ticks|, and forwards |now_| by
+  // the same amount. Calls OnAfterTimePassed() if |later_ticks| > |now_ticks_|.
+  // Does nothing if |later_ticks| <= |now_ticks_|.
+  void ForwardClocksUntilTickTime(TimeTicks later_ticks);
+
   // Returns the |next_task| to run if there is any with a running time that is
   // at most |reference| + |max_delta|. This additional complexity is required
   // so that |max_delta| == TimeDelta::Max() can be supported.
-  bool DequeueNextTask(const base::TimeTicks& reference,
-                       const base::TimeDelta& max_delta,
+  bool DequeueNextTask(const TimeTicks& reference,
+                       const TimeDelta& max_delta,
                        TestPendingTask* next_task);
 
-  base::ThreadChecker thread_checker_;
-  base::TimeTicks now_;
+  ThreadChecker thread_checker_;
+  Time now_;
+  TimeTicks now_ticks_;
 
   // Temporally ordered heap of pending tasks. Must only be accessed while the
   // |tasks_lock_| is held.
   TaskPriorityQueue tasks_;
-  base::Lock tasks_lock_;
+  Lock tasks_lock_;
 
   DISALLOW_COPY_AND_ASSIGN(TestMockTimeTaskRunner);
 };
diff --git a/test/test_pending_task.cc b/test/test_pending_task.cc
index 94989de..3f2c79d 100644
--- a/test/test_pending_task.cc
+++ b/test/test_pending_task.cc
@@ -34,7 +34,7 @@
 
 TestPendingTask::~TestPendingTask() {}
 
-void TestPendingTask::AsValueInto(base::debug::TracedValue* state) const {
+void TestPendingTask::AsValueInto(base::trace_event::TracedValue* state) const {
   state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
   state->SetString("posting_function", location.ToString());
   state->SetInteger("post_time", post_time.ToInternalValue());
@@ -50,10 +50,10 @@
   state->SetInteger("delay", delay.ToInternalValue());
 }
 
-scoped_refptr<base::debug::ConvertableToTraceFormat> TestPendingTask::AsValue()
-    const {
-  scoped_refptr<base::debug::TracedValue> state =
-      new base::debug::TracedValue();
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+TestPendingTask::AsValue() const {
+  scoped_refptr<base::trace_event::TracedValue> state =
+      new base::trace_event::TracedValue();
   AsValueInto(state.get());
   return state;
 }
diff --git a/test/test_pending_task.h b/test/test_pending_task.h
index 4a2b0e7..829baa6 100644
--- a/test/test_pending_task.h
+++ b/test/test_pending_task.h
@@ -57,8 +57,8 @@
 
   // Functions for using test pending task with tracing, useful in unit
   // testing.
-  void AsValueInto(base::debug::TracedValue* state) const;
-  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+  void AsValueInto(base::trace_event::TracedValue* state) const;
+  scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
   std::string ToString() const;
 };
 
diff --git a/test/trace_event_analyzer.h b/test/trace_event_analyzer.h
index a8be893..57ff2b5 100644
--- a/test/trace_event_analyzer.h
+++ b/test/trace_event_analyzer.h
@@ -6,7 +6,7 @@
 // specific trace events that were generated by the trace_event.h API.
 //
 // Basic procedure:
-// - Get trace events JSON string from base::debug::TraceLog.
+// - Get trace events JSON string from base::trace_event::TraceLog.
 // - Create TraceAnalyzer with JSON string.
 // - Call TraceAnalyzer::AssociateBeginEndEvents (optional).
 // - Call TraceAnalyzer::AssociateEvents (zero or more times).
@@ -89,7 +89,8 @@
 class QueryNode;
 
 // trace_analyzer::TraceEvent is a more convenient form of the
-// base::debug::TraceEvent class to make tracing-based tests easier to write.
+// base::trace_event::TraceEvent class to make tracing-based tests easier to
+// write.
 struct TraceEvent {
   // ProcessThreadID contains a Process ID and Thread ID.
   struct ProcessThreadID {
diff --git a/test/trace_event_analyzer_unittest.cc b/test/trace_event_analyzer_unittest.cc
index cc1f8a3..4bdb941 100644
--- a/test/trace_event_analyzer_unittest.cc
+++ b/test/trace_event_analyzer_unittest.cc
@@ -23,12 +23,12 @@
   void BeginTracing();
   void EndTracing();
 
-  base::debug::TraceResultBuffer::SimpleOutput output_;
-  base::debug::TraceResultBuffer buffer_;
+  base::trace_event::TraceResultBuffer::SimpleOutput output_;
+  base::trace_event::TraceResultBuffer buffer_;
 };
 
 void TraceEventAnalyzerTest::ManualSetUp() {
-  ASSERT_TRUE(base::debug::TraceLog::GetInstance());
+  ASSERT_TRUE(base::trace_event::TraceLog::GetInstance());
   buffer_.SetOutputCallback(output_.GetCallback());
   output_.json_output.clear();
 }
@@ -45,16 +45,16 @@
 void TraceEventAnalyzerTest::BeginTracing() {
   output_.json_output.clear();
   buffer_.Start();
-  base::debug::TraceLog::GetInstance()->SetEnabled(
-      base::debug::CategoryFilter("*"),
-      base::debug::TraceLog::RECORDING_MODE,
-      base::debug::TraceOptions());
+  base::trace_event::TraceLog::GetInstance()->SetEnabled(
+      base::trace_event::CategoryFilter("*"),
+      base::trace_event::TraceLog::RECORDING_MODE,
+      base::trace_event::TraceOptions());
 }
 
 void TraceEventAnalyzerTest::EndTracing() {
-  base::debug::TraceLog::GetInstance()->SetDisabled();
+  base::trace_event::TraceLog::GetInstance()->SetDisabled();
   base::WaitableEvent flush_complete_event(false, false);
-  base::debug::TraceLog::GetInstance()->Flush(
+  base::trace_event::TraceLog::GetInstance()->Flush(
       base::Bind(&TraceEventAnalyzerTest::OnTraceDataCollected,
                  base::Unretained(this),
                  base::Unretained(&flush_complete_event)));
diff --git a/test/trace_to_file.cc b/test/trace_to_file.cc
index 948a6a7..4e2a332 100644
--- a/test/trace_to_file.cc
+++ b/test/trace_to_file.cc
@@ -51,10 +51,10 @@
   path_ = path;
   WriteFileHeader();
 
-  debug::TraceLog::GetInstance()->SetEnabled(
-      debug::CategoryFilter(categories),
-      debug::TraceLog::RECORDING_MODE,
-      debug::TraceOptions(debug::RECORD_UNTIL_FULL));
+  trace_event::TraceLog::GetInstance()->SetEnabled(
+      trace_event::CategoryFilter(categories),
+      trace_event::TraceLog::RECORDING_MODE,
+      trace_event::TraceOptions(trace_event::RECORD_UNTIL_FULL));
 }
 
 void TraceToFile::WriteFileHeader() {
@@ -74,7 +74,7 @@
 
 static void OnTraceDataCollected(
     Closure quit_closure,
-    debug::TraceResultBuffer* buffer,
+    trace_event::TraceResultBuffer* buffer,
     const scoped_refptr<RefCountedString>& json_events_str,
     bool has_more_events) {
   buffer->AddFragment(json_events_str->data());
@@ -87,14 +87,14 @@
     return;
   started_ = false;
 
-  debug::TraceLog::GetInstance()->SetDisabled();
+  trace_event::TraceLog::GetInstance()->SetDisabled();
 
-  debug::TraceResultBuffer buffer;
+  trace_event::TraceResultBuffer buffer;
   buffer.SetOutputCallback(
       Bind(&TraceToFile::TraceOutputCallback, Unretained(this)));
 
   RunLoop run_loop;
-  debug::TraceLog::GetInstance()->Flush(
+  trace_event::TraceLog::GetInstance()->Flush(
       Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
   run_loop.Run();
 
diff --git a/third_party/dynamic_annotations/BUILD.gn b/third_party/dynamic_annotations/BUILD.gn
index 9a47867..e52938c 100644
--- a/third_party/dynamic_annotations/BUILD.gn
+++ b/third_party/dynamic_annotations/BUILD.gn
@@ -4,9 +4,9 @@
 
 source_set("dynamic_annotations") {
   sources = [
+    "../valgrind/valgrind.h",
     "dynamic_annotations.c",
     "dynamic_annotations.h",
-    "../valgrind/valgrind.h",
   ]
   if (is_android && !is_debug) {
     configs -= [ "//build/config/compiler:optimize" ]
diff --git a/third_party/dynamic_annotations/dynamic_annotations.gyp b/third_party/dynamic_annotations/dynamic_annotations.gyp
index 12cfb65..8d2e9ec 100644
--- a/third_party/dynamic_annotations/dynamic_annotations.gyp
+++ b/third_party/dynamic_annotations/dynamic_annotations.gyp
@@ -12,9 +12,9 @@
         '../../../',
       ],
       'sources': [
+        '../valgrind/valgrind.h',
         'dynamic_annotations.c',
         'dynamic_annotations.h',
-        '../valgrind/valgrind.h',
       ],
       'includes': [
         '../../../build/android/increase_size_for_speed.gypi',
diff --git a/third_party/nspr/BUILD.gn b/third_party/nspr/BUILD.gn
index 516ca1f..c0b2ec2 100644
--- a/third_party/nspr/BUILD.gn
+++ b/third_party/nspr/BUILD.gn
@@ -3,7 +3,10 @@
 # found in the LICENSE file.
 
 source_set("nspr") {
-  visibility = [ "//base" ]
+  visibility = [
+    "//base/*",
+  ]
+
   sources = [
     "prtime.cc",
     "prtime.h",
diff --git a/time/time.cc b/time/time.cc
index ce9d12c..951f7ba 100644
--- a/time/time.cc
+++ b/time/time.cc
@@ -274,6 +274,22 @@
   return leaky_unix_epoch_singleton_instance.Get().unix_epoch();
 }
 
+TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
+                                       TimeDelta tick_interval) const {
+  // |interval_offset| is the offset from |this| to the next multiple of
+  // |tick_interval| after |tick_phase|, possibly negative if in the past.
+  TimeDelta interval_offset = TimeDelta::FromInternalValue(
+      (tick_phase - *this).ToInternalValue() % tick_interval.ToInternalValue());
+  // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
+  // Otherwise, if |tick_phase| was in the past, adjust forward to the next
+  // tick after |this|.
+  if (interval_offset.ToInternalValue() != 0 && tick_phase < *this) {
+    interval_offset += tick_interval;
+  }
+
+  return *this + interval_offset;
+}
+
 std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
   // This function formats a TimeTicks object as "bogo-microseconds".
   // The origin and granularity of the count are platform-specific, and may very
diff --git a/time/time.h b/time/time.h
index eb86693..18de085 100644
--- a/time/time.h
+++ b/time/time.h
@@ -680,6 +680,12 @@
     return ticks_;
   }
 
+  // Returns |this| snapped to the next tick, given a |tick_phase| and
+  // repeating |tick_interval| in both directions. |this| may be before,
+  // after, or equal to the |tick_phase|.
+  TimeTicks SnappedToNextTick(TimeTicks tick_phase,
+                              TimeDelta tick_interval) const;
+
   TimeTicks& operator=(TimeTicks other) {
     ticks_ = other.ticks_;
     return *this;
diff --git a/time/time_unittest.cc b/time/time_unittest.cc
index 27f71b4..fdac59d 100644
--- a/time/time_unittest.cc
+++ b/time/time_unittest.cc
@@ -715,6 +715,62 @@
   HighResClockTest(&TimeTicks::NowFromSystemTraceTime);
 }
 
+TEST(TimeTicks, SnappedToNextTickBasic) {
+  base::TimeTicks phase = base::TimeTicks::FromInternalValue(4000);
+  base::TimeDelta interval = base::TimeDelta::FromInternalValue(1000);
+  base::TimeTicks timestamp;
+
+  // Timestamp in previous interval.
+  timestamp = base::TimeTicks::FromInternalValue(3500);
+  EXPECT_EQ(4000,
+            timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+  // Timestamp in next interval.
+  timestamp = base::TimeTicks::FromInternalValue(4500);
+  EXPECT_EQ(5000,
+            timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+  // Timestamp multiple intervals before.
+  timestamp = base::TimeTicks::FromInternalValue(2500);
+  EXPECT_EQ(3000,
+            timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+  // Timestamp multiple intervals after.
+  timestamp = base::TimeTicks::FromInternalValue(6500);
+  EXPECT_EQ(7000,
+            timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+  // Timestamp on previous interval.
+  timestamp = base::TimeTicks::FromInternalValue(3000);
+  EXPECT_EQ(3000,
+            timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+  // Timestamp on next interval.
+  timestamp = base::TimeTicks::FromInternalValue(5000);
+  EXPECT_EQ(5000,
+            timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+  // Timestamp equal to phase.
+  timestamp = base::TimeTicks::FromInternalValue(4000);
+  EXPECT_EQ(4000,
+            timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+}
+
+TEST(TimeTicks, SnappedToNextTickOverflow) {
+  // int(big_timestamp / interval) < 0, so this causes a crash if the number of
+  // intervals elapsed is attempted to be stored in an int.
+  base::TimeTicks phase = base::TimeTicks::FromInternalValue(0);
+  base::TimeDelta interval = base::TimeDelta::FromInternalValue(4000);
+  base::TimeTicks big_timestamp =
+      base::TimeTicks::FromInternalValue(8635916564000);
+
+  EXPECT_EQ(8635916564000,
+            big_timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+  EXPECT_EQ(8635916564000,
+            big_timestamp.SnappedToNextTick(big_timestamp, interval)
+                .ToInternalValue());
+}
+
 TEST(TimeDelta, FromAndIn) {
   EXPECT_TRUE(TimeDelta::FromDays(2) == TimeDelta::FromHours(48));
   EXPECT_TRUE(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180));
diff --git a/trace_event/memory_dump_manager.cc b/trace_event/memory_dump_manager.cc
new file mode 100644
index 0000000..bf631b3
--- /dev/null
+++ b/trace_event/memory_dump_manager.cc
@@ -0,0 +1,135 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/memory_dump_manager.h"
+
+#include <algorithm>
+
+#include "base/compiler_specific.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
+
+// TODO(primiano): in a separate CL rename DeleteTraceLogForTesting into
+// something like base::internal::TeardownSingletonForTesting so we don't have
+// to add a new friend to singleton each time.
+class DeleteTraceLogForTesting {
+ public:
+  static void Delete() {
+    Singleton<
+        base::trace_event::MemoryDumpManager,
+        LeakySingletonTraits<base::trace_event::MemoryDumpManager>>::OnExit(0);
+  }
+};
+
+namespace base {
+namespace trace_event {
+
+// TODO(primiano): this should be smarter and should do something similar to
+// trace event synthetic delays.
+const char MemoryDumpManager::kTraceCategory[] =
+    TRACE_DISABLED_BY_DEFAULT("memory-dumps");
+
+// static
+MemoryDumpManager* MemoryDumpManager::GetInstance() {
+  return Singleton<MemoryDumpManager,
+                   LeakySingletonTraits<MemoryDumpManager>>::get();
+}
+
+// static
+void MemoryDumpManager::DeleteForTesting() {
+  DeleteTraceLogForTesting::Delete();
+}
+
+MemoryDumpManager::MemoryDumpManager() : memory_tracing_enabled_(0) {
+}
+
+MemoryDumpManager::~MemoryDumpManager() {
+  base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
+}
+
+void MemoryDumpManager::Initialize() {
+  TRACE_EVENT0(kTraceCategory, "init");  // Add to trace-viewer category list.
+  trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
+}
+
+void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
+  AutoLock lock(lock_);
+  if (std::find(dump_providers_registered_.begin(),
+                dump_providers_registered_.end(),
+                mdp) != dump_providers_registered_.end()) {
+    return;
+  }
+  dump_providers_registered_.push_back(mdp);
+}
+
+void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
+  AutoLock lock(lock_);
+
+  // Remove from the registered providers list.
+  auto it = std::find(dump_providers_registered_.begin(),
+                      dump_providers_registered_.end(), mdp);
+  if (it != dump_providers_registered_.end())
+    dump_providers_registered_.erase(it);
+
+  // Remove from the enabled providers list. This is to deal with the case that
+  // UnregisterDumpProvider is called while the trace is enabled.
+  it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(),
+                 mdp);
+  if (it != dump_providers_enabled_.end())
+    dump_providers_enabled_.erase(it);
+}
+
+void MemoryDumpManager::RequestDumpPoint(DumpPointType type) {
+  // TODO(primiano): this will have more logic, IPC broadcast & co.
+  // Bail out immediately if tracing is not enabled at all.
+  if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
+    return;
+
+  CreateLocalDumpPoint();
+}
+
+void MemoryDumpManager::BroadcastDumpRequest() {
+  NOTREACHED();  // TODO(primiano): implement IPC synchronization.
+}
+
+// Creates a dump point for the current process and appends it to the trace.
+void MemoryDumpManager::CreateLocalDumpPoint() {
+  AutoLock lock(lock_);
+  // TRACE_EVENT_* macros don't induce scoped_refptr type inference, hence we
+  // need the base ConvertableToTraceFormat and the upcast below. The
+  // alternative would be unnecessarily expensive (double Acquire/Release).
+  scoped_refptr<ConvertableToTraceFormat> pmd(new ProcessMemoryDump());
+
+  for (MemoryDumpProvider* dump_provider : dump_providers_enabled_) {
+    dump_provider->DumpInto(static_cast<ProcessMemoryDump*>(pmd.get()));
+  }
+
+  // TODO(primiano): add the dump point to the trace at this point.
+}
+
+void MemoryDumpManager::OnTraceLogEnabled() {
+  // TODO(primiano): at this point we query  TraceLog::GetCurrentCategoryFilter
+  // to figure out (and cache) which dumpers should be enabled or not.
+  // For the moment piggy back everything on the generic "memory" category.
+  bool enabled;
+  TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
+
+  AutoLock lock(lock_);
+  if (enabled) {
+    dump_providers_enabled_.assign(dump_providers_registered_.begin(),
+                                   dump_providers_registered_.end());
+  } else {
+    dump_providers_enabled_.clear();
+  }
+  subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
+}
+
+void MemoryDumpManager::OnTraceLogDisabled() {
+  AutoLock lock(lock_);
+  dump_providers_enabled_.clear();
+  subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/trace_event/memory_dump_manager.h b/trace_event/memory_dump_manager.h
new file mode 100644
index 0000000..fbc71d5
--- /dev/null
+++ b/trace_event/memory_dump_manager.h
@@ -0,0 +1,87 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
+
+#include <vector>
+
+#include "base/atomicops.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+#include "base/trace_event/trace_event.h"
+
+namespace base {
+namespace trace_event {
+
+class MemoryDumpProvider;
+
+// Captures the reason why a dump point is being requested. This is to allow
+// selective enabling of dump points, filtering and post-processing.
+enum class DumpPointType {
+  TASK_BEGIN,         // Dumping memory at the beginning of a message-loop task.
+  TASK_END,           // Dumping memory at the ending of a message-loop task.
+  PERIODIC_INTERVAL,  // Dumping memory at periodic intervals.
+  EXPLICITLY_TRIGGERED,  // Non maskable dump request.
+};
+
+// This is the interface exposed to the rest of the codebase to deal with
+// memory tracing. The main entry point for clients is represented by
+// RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
+class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
+ public:
+  static MemoryDumpManager* GetInstance();
+
+  // Invoked once per process to register the TraceLog observer.
+  void Initialize();
+
+  // MemoryDumpManager does NOT take memory ownership of |mdp|, which is
+  // expected to be a singleton.
+  void RegisterDumpProvider(MemoryDumpProvider* mdp);
+  void UnregisterDumpProvider(MemoryDumpProvider* mdp);
+
+  // Requests a memory dump. The dump might happen or not depending on the
+  // filters and categories specified when enabling tracing.
+  void RequestDumpPoint(DumpPointType type);
+
+  // TraceLog::EnabledStateObserver implementation.
+  void OnTraceLogEnabled() override;
+  void OnTraceLogDisabled() override;
+
+ private:
+  friend struct DefaultSingletonTraits<MemoryDumpManager>;
+  friend class MemoryDumpManagerTest;
+
+  static const char kTraceCategory[];
+
+  MemoryDumpManager();
+  virtual ~MemoryDumpManager();
+
+  // Tears down the singleton instance.
+  static void DeleteForTesting();
+
+  // Broadcasts the dump requests to the other processes.
+  void BroadcastDumpRequest();
+
+  // Creates a dump point for the current process and appends it to the trace.
+  void CreateLocalDumpPoint();
+
+  std::vector<MemoryDumpProvider*> dump_providers_registered_;  // Not owned.
+  std::vector<MemoryDumpProvider*> dump_providers_enabled_;     // Not owned.
+
+  // Protects from concurrent accesses to the |dump_providers_*|, e.g., tearing
+  // down logging while creating a dump point on another thread.
+  Lock lock_;
+
+  // Optimization to avoid attempting any dump point (i.e. to not walk an empty
+  // dump_providers_enabled_ list) when tracing is not enabled.
+  subtle::AtomicWord memory_tracing_enabled_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
diff --git a/trace_event/memory_dump_manager_unittest.cc b/trace_event/memory_dump_manager_unittest.cc
new file mode 100644
index 0000000..b5337e9
--- /dev/null
+++ b/trace_event/memory_dump_manager_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/memory_dump_manager.h"
+
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace base {
+namespace trace_event {
+
+class MemoryDumpManagerTest : public testing::Test {
+ public:
+  void SetUp() override {
+    MemoryDumpManager::GetInstance()->Initialize();
+    mdm_ = MemoryDumpManager::GetInstance();
+  }
+
+  void TearDown() override {
+    MemoryDumpManager::DeleteForTesting();
+    TraceLog::DeleteForTesting();
+    mdm_ = NULL;
+  }
+
+ protected:
+  const char* const kTraceCategory = MemoryDumpManager::kTraceCategory;
+
+  void EnableTracing(const char* category) {
+    TraceLog::GetInstance()->SetEnabled(
+        CategoryFilter(category), TraceLog::RECORDING_MODE, TraceOptions());
+  }
+
+  void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); }
+
+  MemoryDumpManager* mdm_;
+
+ private:
+  // We want our singleton torn down after each test.
+  ShadowingAtExitManager at_exit_manager_;
+};
+
+class MockDumpProvider : public MemoryDumpProvider {
+ public:
+  MOCK_METHOD1(DumpInto, void(ProcessMemoryDump* pmd));
+};
+
+TEST_F(MemoryDumpManagerTest, SingleDumper) {
+  MockDumpProvider mdp;
+  mdm_->RegisterDumpProvider(&mdp);
+
+  // Check that the dumper is not called if the memory category is not enabled.
+  EnableTracing("foo-and-bar-but-not-memory");
+  EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  DisableTracing();
+
+  // Now repeat enabling the memory category and check that the dumper is
+  // invoked this time.
+  EnableTracing(kTraceCategory);
+  EXPECT_CALL(mdp, DumpInto(_)).Times(3);
+  for (int i = 0; i < 3; ++i)
+    mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  DisableTracing();
+
+  mdm_->UnregisterDumpProvider(&mdp);
+
+  // Finally check the unregister logic (no calls to the mdp after unregister).
+  EnableTracing(kTraceCategory);
+  EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  TraceLog::GetInstance()->SetDisabled();
+}
+
+TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileTracing) {
+  MockDumpProvider mdp;
+  mdm_->RegisterDumpProvider(&mdp);
+
+  EnableTracing(kTraceCategory);
+  EXPECT_CALL(mdp, DumpInto(_)).Times(1);
+  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+  mdm_->UnregisterDumpProvider(&mdp);
+  EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+  DisableTracing();
+}
+
+TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
+  MockDumpProvider mdp1;
+  MockDumpProvider mdp2;
+
+  // Enable only mdp1.
+  mdm_->RegisterDumpProvider(&mdp1);
+  EnableTracing(kTraceCategory);
+  EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
+  EXPECT_CALL(mdp2, DumpInto(_)).Times(0);
+  mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+  DisableTracing();
+
+  // Invert: enable mdp1 and disable mdp2.
+  mdm_->UnregisterDumpProvider(&mdp1);
+  mdm_->RegisterDumpProvider(&mdp2);
+  EnableTracing(kTraceCategory);
+  EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
+  EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
+  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);
+  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
new file mode 100644
index 0000000..18363c5
--- /dev/null
+++ b/trace_event/memory_dump_provider.h
@@ -0,0 +1,33 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+namespace base {
+namespace trace_event {
+
+class ProcessMemoryDump;
+
+// The contract interface that memory dump providers must implement.
+class BASE_EXPORT MemoryDumpProvider {
+ public:
+  // Called by the MemoryDumpManager when generating dump points.
+  virtual void DumpInto(ProcessMemoryDump* pmd) = 0;
+
+ protected:
+  MemoryDumpProvider() {}
+  virtual ~MemoryDumpProvider() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
diff --git a/trace_event/process_memory_dump.cc b/trace_event/process_memory_dump.cc
new file mode 100644
index 0000000..0a3e096
--- /dev/null
+++ b/trace_event/process_memory_dump.cc
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/process_memory_dump.h"
+
+#include "base/json/json_writer.h"
+#include "base/values.h"
+
+namespace base {
+namespace trace_event {
+
+ProcessMemoryDump::ProcessMemoryDump() {
+}
+
+ProcessMemoryDump::~ProcessMemoryDump() {
+}
+
+void ProcessMemoryDump::AppendAsTraceFormat(std::string* out) const {
+  // Build up the [dumper name] -> [serialized snapshot] JSON dictionary.
+  DictionaryValue dict;
+  std::string json_dict;
+  // TODO(primiano): this will append here the actual dumps from the dumpers.
+  base::JSONWriter::Write(&dict, &json_dict);
+  *out += json_dict;
+}
+
+}  // namespace trace_event
+}  // namespace base
diff --git a/trace_event/process_memory_dump.h b/trace_event/process_memory_dump.h
new file mode 100644
index 0000000..ae42987
--- /dev/null
+++ b/trace_event/process_memory_dump.h
@@ -0,0 +1,37 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
+#define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/trace_event/trace_event_impl.h"
+
+namespace base {
+namespace trace_event {
+
+// A container which holds the dumps produced by the MemoryDumpProvider(s)
+// for a specific process. ProcessMemoryDump is as a strongly typed container
+// which enforces the data model for each memory dump point.
+// At trace generation time (i.e. when AppendAsTraceFormat is called) the
+// ProcessMemoryDump will compose a key-value dictionary of the various dumps
+// obtained during at trace dump point time.
+class BASE_EXPORT ProcessMemoryDump : public ConvertableToTraceFormat {
+ public:
+  ProcessMemoryDump();
+
+  // ConvertableToTraceFormat implementation.
+  void AppendAsTraceFormat(std::string* out) const override;
+
+ private:
+  ~ProcessMemoryDump() override;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
+};
+
+}  // namespace trace_event
+}  // namespace base
+
+#endif  // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
diff --git a/trace_event/trace_event.h b/trace_event/trace_event.h
index c8583d7..07a2afa 100644
--- a/trace_event/trace_event.h
+++ b/trace_event/trace_event.h
@@ -1603,12 +1603,4 @@
 }  // namespace trace_event
 }  // namespace base
 
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::TraceScopedTrackableObject;
-}  // namespace debug
-}  // namespace base
-
 #endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */
diff --git a/trace_event/trace_event_argument.h b/trace_event/trace_event_argument.h
index 43a0f38..78d37d4 100644
--- a/trace_event/trace_event_argument.h
+++ b/trace_event/trace_event_argument.h
@@ -56,12 +56,4 @@
 }  // namespace trace_event
 }  // namespace base
 
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::TracedValue;
-}  // namespace debug
-}  // namespace base
-
 #endif  // BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
diff --git a/trace_event/trace_event_impl.cc b/trace_event/trace_event_impl.cc
index 95cf06d..9ca0ddc 100644
--- a/trace_event/trace_event_impl.cc
+++ b/trace_event/trace_event_impl.cc
@@ -1908,11 +1908,13 @@
   AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
 
   DCHECK(name);
+  DCHECK(!timestamp.is_null());
 
   if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
     id ^= process_id_hash_;
 
-  TimeTicks now = OffsetTimestamp(timestamp);
+  TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp);
+  TimeTicks now = OffsetNow();
   TimeTicks thread_now = ThreadNow();
 
   ThreadLocalEventBuffer* thread_local_event_buffer = NULL;
@@ -1985,8 +1987,8 @@
     }
 
     if (trace_event) {
-      trace_event->Initialize(thread_id, now, thread_now, phase,
-                              category_group_enabled, name, id,
+      trace_event->Initialize(thread_id, offset_event_timestamp, thread_now,
+                              phase, category_group_enabled, name, id,
                               num_args, arg_names, arg_types, arg_values,
                               convertable_values, flags);
 
@@ -2024,7 +2026,7 @@
     EventCallback event_callback = reinterpret_cast<EventCallback>(
         subtle::NoBarrier_Load(&event_callback_));
     if (event_callback) {
-      event_callback(now,
+      event_callback(offset_event_timestamp,
                      phase == TRACE_EVENT_PHASE_COMPLETE ?
                          TRACE_EVENT_PHASE_BEGIN : phase,
                      category_group_enabled, name, id,
@@ -2033,6 +2035,9 @@
     }
   }
 
+  // Use |now| instead of |offset_event_timestamp| to compute overhead, because
+  // event timestamp may be not the real time that we started to add the event
+  // (e.g. event with zero timestamp or that was generated some time ago).
   if (thread_local_event_buffer)
     thread_local_event_buffer->ReportOverhead(now, thread_now);
 
diff --git a/trace_event/trace_event_impl.h b/trace_event/trace_event_impl.h
index 742f6b6..efa20c4 100644
--- a/trace_event/trace_event_impl.h
+++ b/trace_event/trace_event_impl.h
@@ -810,21 +810,4 @@
 }  // namespace trace_event
 }  // namespace base
 
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::CategoryFilter;
-using base::trace_event::ConvertableToTraceFormat;
-using base::trace_event::RECORD_UNTIL_FULL;
-using base::trace_event::RECORD_CONTINUOUSLY;
-using base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE;
-using base::trace_event::TraceEventHandle;
-using base::trace_event::TraceLog;
-using base::trace_event::TraceLogStatus;
-using base::trace_event::TraceOptions;
-using base::trace_event::TraceResultBuffer;
-}  // namespace debug
-}  // namespace base
-
 #endif  // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
diff --git a/trace_event/trace_event_win.h b/trace_event/trace_event_win.h
index dcb5aac..4161361 100644
--- a/trace_event/trace_event_win.h
+++ b/trace_event/trace_event_win.h
@@ -122,18 +122,4 @@
 }  // namespace trace_event
 }  // namespace base
 
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::kChromeTraceProviderName;
-using base::trace_event::kTraceEventClass32;
-using base::trace_event::kTraceEventClass64;
-using base::trace_event::kTraceEventTypeBegin;
-using base::trace_event::kTraceEventTypeEnd;
-using base::trace_event::kTraceEventTypeInstant;
-using base::trace_event::TraceEventETWProvider;
-}  // namespace debug
-}  // namespace base
-
 #endif  // BASE_TRACE_EVENT_TRACE_EVENT_WIN_H_