Update from https://crrev.com/320343

This required some manual patching to ui/event and ui/gfx.

Sky tests were suppressed.
https://github.com/domokit/mojo/issues/64

BUG=401761
R=jamesr@chromium.org

Review URL: https://codereview.chromium.org/1001833005
diff --git a/DEPS b/DEPS
index bc8e552..0958e5b 100644
--- a/DEPS
+++ b/DEPS
@@ -21,15 +21,15 @@
   'chromium_git': 'https://chromium.googlesource.com',
   'dart_svn': 'https://dart.googlecode.com',
   'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
-  'skia_revision': 'a9baa652bb329b5a286e1638938f63433701efca',
+  'skia_revision': 'd1783aefcc0da86c5ff1d124c54704252d817621',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and V8 without interference from each other.
-  'v8_revision': 'a1d36b4b6b1a3bb35d3bc5b64fbd5de9f55fed26',
+  'v8_revision': '8f7dfb46871191fa9c96f9030d88be6757d46eab',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '019304886ad8b985d67202edec431407bb1b5c53',
+  'angle_revision': '524e3bde19d0df76cc9d1c5926345f5d0ec4d3f8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -45,7 +45,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '09bdb2a2c3d40646ac4b20f5e73421307a80185f',
+  'boringssl_revision': 'bf0df92964565f819881e78ff3bfb5343e95e130',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lss
   # and whatever else without interference from each other.
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 402b19a..69f366e 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -9,6 +9,41 @@
   import("//build/config/android/rules.gni")
 }
 
+source_set("base_paths") {
+  sources = [
+    "base_paths.cc",
+    "base_paths.h",
+    "base_paths_android.cc",
+    "base_paths_android.h",
+    "base_paths_mac.h",
+    "base_paths_mac.mm",
+    "base_paths_posix.cc",
+    "base_paths_posix.h",
+    "base_paths_win.cc",
+    "base_paths_win.h",
+  ]
+
+  if (is_android || is_mac) {
+    sources -= [ "base_paths_posix.cc" ]
+  }
+
+  if (is_nacl) {
+    sources -= [
+      "base_paths.cc",
+      "base_paths_posix.cc",
+    ]
+  }
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  deps = [
+    "//base/memory",
+    "//base/process",
+  ]
+
+  visibility = [ ":base" ]
+}
+
 component("base") {
   sources = [
     "allocator/allocator_extension.cc",
@@ -92,16 +127,6 @@
     "base64.cc",
     "base64.h",
     "base_export.h",
-    "base_paths.cc",
-    "base_paths.h",
-    "base_paths_android.cc",
-    "base_paths_android.h",
-    "base_paths_mac.h",
-    "base_paths_mac.mm",
-    "base_paths_posix.cc",
-    "base_paths_posix.h",
-    "base_paths_win.cc",
-    "base_paths_win.h",
     "base_switches.h",
     "basictypes.h",
     "big_endian.cc",
@@ -135,43 +160,6 @@
     "cpu.h",
     "critical_closure.h",
     "critical_closure_internal_ios.mm",
-    "debug/alias.cc",
-    "debug/alias.h",
-    "debug/asan_invalid_access.cc",
-    "debug/asan_invalid_access.h",
-    "debug/crash_logging.cc",
-    "debug/crash_logging.h",
-    "debug/debugger.cc",
-    "debug/debugger.h",
-    "debug/debugger_posix.cc",
-    "debug/debugger_win.cc",
-    "debug/dump_without_crashing.cc",
-    "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
-    # allocator.gyp for details).
-    "debug/leak_annotations.h",
-    "debug/leak_tracker.h",
-    "debug/proc_maps_linux.cc",
-    "debug/proc_maps_linux.h",
-    "debug/profiler.cc",
-    "debug/profiler.h",
-    "debug/stack_trace.cc",
-    "debug/stack_trace.h",
-    "debug/stack_trace_android.cc",
-    "debug/stack_trace_posix.cc",
-    "debug/stack_trace_win.cc",
-    "debug/task_annotator.cc",
-    "debug/task_annotator.h",
     "deferred_sequenced_task_runner.cc",
     "deferred_sequenced_task_runner.h",
     "environment.cc",
@@ -243,20 +231,6 @@
     "ios/scoped_critical_action.mm",
     "ios/weak_nsobject.h",
     "ios/weak_nsobject.mm",
-    "json/json_file_value_serializer.cc",
-    "json/json_file_value_serializer.h",
-    "json/json_parser.cc",
-    "json/json_parser.h",
-    "json/json_reader.cc",
-    "json/json_reader.h",
-    "json/json_string_value_serializer.cc",
-    "json/json_string_value_serializer.h",
-    "json/json_value_converter.cc",
-    "json/json_value_converter.h",
-    "json/json_writer.cc",
-    "json/json_writer.h",
-    "json/string_escape.cc",
-    "json/string_escape.h",
     "lazy_instance.cc",
     "lazy_instance.h",
     "linux_util.cc",
@@ -316,46 +290,6 @@
     "macros.h",
     "md5.cc",
     "md5.h",
-    "memory/aligned_memory.cc",
-    "memory/aligned_memory.h",
-    "memory/discardable_memory.cc",
-    "memory/discardable_memory.h",
-    "memory/discardable_memory_android.cc",
-    "memory/discardable_memory_emulated.cc",
-    "memory/discardable_memory_emulated.h",
-    "memory/discardable_memory_linux.cc",
-    "memory/discardable_memory_mac.cc",
-    "memory/discardable_memory_manager.cc",
-    "memory/discardable_memory_manager.h",
-    "memory/discardable_memory_shmem.cc",
-    "memory/discardable_memory_shmem.h",
-    "memory/discardable_memory_shmem_allocator.cc",
-    "memory/discardable_memory_shmem_allocator.h",
-    "memory/discardable_memory_win.cc",
-    "memory/discardable_shared_memory.cc",
-    "memory/discardable_shared_memory.h",
-    "memory/linked_ptr.h",
-    "memory/manual_constructor.h",
-    "memory/memory_pressure_listener.cc",
-    "memory/memory_pressure_listener.h",
-    "memory/raw_scoped_refptr_mismatch_checker.h",
-    "memory/ref_counted.cc",
-    "memory/ref_counted.h",
-    "memory/ref_counted_delete_on_message_loop.h",
-    "memory/ref_counted_memory.cc",
-    "memory/ref_counted_memory.h",
-    "memory/scoped_policy.h",
-    "memory/scoped_ptr.h",
-    "memory/scoped_vector.h",
-    "memory/shared_memory.h",
-    "memory/shared_memory_android.cc",
-    "memory/shared_memory_nacl.cc",
-    "memory/shared_memory_posix.cc",
-    "memory/shared_memory_win.cc",
-    "memory/singleton.cc",
-    "memory/singleton.h",
-    "memory/weak_ptr.cc",
-    "memory/weak_ptr.h",
     "message_loop/incoming_task_queue.cc",
     "message_loop/incoming_task_queue.h",
     "message_loop/message_loop.cc",
@@ -380,33 +314,6 @@
     "message_loop/message_pump_mac.mm",
     "message_loop/message_pump_win.cc",
     "message_loop/message_pump_win.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.",
-    "metrics/histogram_delta_serialization.cc",
-    "metrics/histogram_flattener.h",
-    "metrics/histogram_macros.h",
-    "metrics/histogram_samples.cc",
-    "metrics/histogram_samples.h",
-    "metrics/histogram_snapshot_manager.cc",
-    "metrics/histogram_snapshot_manager.h",
-    "metrics/sample_map.cc",
-    "metrics/sample_map.h",
-    "metrics/sample_vector.cc",
-    "metrics/sample_vector.h",
-    "metrics/sparse_histogram.cc",
-    "metrics/sparse_histogram.h",
-    "metrics/statistics_recorder.cc",
-    "metrics/statistics_recorder.h",
-    "metrics/user_metrics.cc",
-    "metrics/user_metrics.h",
-    "metrics/user_metrics_action.h",
     "move.h",
     "native_library.h",
     "native_library_mac.mm",
@@ -453,54 +360,6 @@
     "power_monitor/power_monitor_source.cc",
     "power_monitor/power_monitor_source.h",
     "power_monitor/power_observer.h",
-    "process/internal_linux.cc",
-    "process/internal_linux.h",
-    "process/kill.cc",
-    "process/kill.h",
-    "process/kill_mac.cc",
-    "process/kill_posix.cc",
-    "process/kill_win.cc",
-    "process/launch.cc",
-    "process/launch.h",
-    "process/launch_ios.cc",
-    "process/launch_mac.cc",
-    "process/launch_posix.cc",
-    "process/launch_win.cc",
-    "process/memory.cc",
-    "process/memory.h",
-    "process/memory_linux.cc",
-    "process/memory_mac.mm",
-    "process/memory_win.cc",
-    "process/process.h",
-    "process/process_handle_freebsd.cc",
-    "process/process_handle_linux.cc",
-    "process/process_handle_mac.cc",
-    "process/process_handle_openbsd.cc",
-    "process/process_handle_posix.cc",
-    "process/process_handle_win.cc",
-    "process/process_info.h",
-    "process/process_info_linux.cc",
-    "process/process_info_mac.cc",
-    "process/process_info_win.cc",
-    "process/process_iterator.cc",
-    "process/process_iterator.h",
-    "process/process_iterator_freebsd.cc",
-    "process/process_iterator_linux.cc",
-    "process/process_iterator_mac.cc",
-    "process/process_iterator_openbsd.cc",
-    "process/process_iterator_win.cc",
-    "process/process_linux.cc",
-    "process/process_metrics.cc",
-    "process/process_metrics.h",
-    "process/process_metrics_freebsd.cc",
-    "process/process_metrics_ios.cc",
-    "process/process_metrics_linux.cc",
-    "process/process_metrics_mac.cc",
-    "process/process_metrics_openbsd.cc",
-    "process/process_metrics_posix.cc",
-    "process/process_metrics_win.cc",
-    "process/process_posix.cc",
-    "process/process_win.cc",
     "profiler/alternate_timer.cc",
     "profiler/alternate_timer.h",
     "profiler/scoped_profile.cc",
@@ -608,6 +467,12 @@
     "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/superfasthash/superfasthash.c",
     "thread_task_runner_handle.cc",
     "thread_task_runner_handle.h",
     "threading/non_thread_safe.h",
@@ -673,34 +538,6 @@
     "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/process_memory_maps.cc",
-    "trace_event/process_memory_maps.h",
-    "trace_event/process_memory_maps_dump_provider.cc",
-    "trace_event/process_memory_maps_dump_provider.h",
-    "trace_event/process_memory_totals.cc",
-    "trace_event/process_memory_totals.h",
-    "trace_event/process_memory_totals_dump_provider.cc",
-    "trace_event/process_memory_totals_dump_provider.h",
-    "trace_event/trace_event.h",
-    "trace_event/trace_event_android.cc",
-    "trace_event/trace_event_argument.cc",
-    "trace_event/trace_event_argument.h",
-    "trace_event/trace_event_impl.cc",
-    "trace_event/trace_event_impl.h",
-    "trace_event/trace_event_impl_constants.cc",
-    "trace_event/trace_event_memory.cc",
-    "trace_event/trace_event_memory.h",
-    "trace_event/trace_event_synthetic_delay.cc",
-    "trace_event/trace_event_synthetic_delay.h",
-    "trace_event/trace_event_system_stats_monitor.cc",
-    "trace_event/trace_event_system_stats_monitor.h",
-    "trace_event/trace_event_win.cc",
-    "trace_event/trace_event_win.h",
     "tracked_objects.cc",
     "tracked_objects.h",
     "tracking_info.cc",
@@ -765,6 +602,63 @@
     "win/wrapped_window_proc.h",
   ]
 
+  sources -= [
+    "sys_info_freebsd.cc",
+    "sys_info_openbsd.cc",
+  ]
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  deps = [
+    ":base_static",
+    "//base/allocator:allocator_extension_thunks",
+    "//base/third_party/dynamic_annotations",
+    "//base/third_party/nspr",
+    "//third_party/modp_b64",
+  ]
+
+  public_deps = [
+    ":base_paths",
+    "//base/debug",
+    "//base/json",
+    "//base/memory",
+    "//base/metrics",
+    "//base/process",
+    "//base/trace_event",
+  ]
+
+  # Allow more direct string conversions on platforms with native utf8
+  # strings
+  if (is_mac || is_ios || is_chromeos) {
+    defines += [ "SYSTEM_NATIVE_UTF8" ]
+  }
+
+  if (is_android) {
+    sources -= [ "power_monitor/power_monitor_device_source_posix.cc" ]
+
+    # Android uses some Linux sources, put those back.
+    set_sources_assignment_filter([])
+    sources += [
+      "files/file_path_watcher_linux.cc",
+      "posix/unix_domain_socket_linux.cc",
+      "sys_info_linux.cc",
+    ]
+    set_sources_assignment_filter(sources_assignment_filter)
+
+    deps += [
+      ":base_jni_headers",
+      "//third_party/ashmem",
+      "//third_party/android_tools:cpu_features",
+    ]
+
+    # logging.cc uses the Android logging library.
+    libs = [ "log" ]
+  }
+
+  if (is_chromeos) {
+    sources -= [ "power_monitor/power_monitor_device_source_posix.cc" ]
+  }
+
   if (is_nacl) {
     # We reset sources_assignment_filter in order to explicitly include
     # the linux file (which would otherwise be filtered out).
@@ -780,110 +674,27 @@
       "allocator/type_profiler_control.cc",
       "allocator/type_profiler_control.h",
       "async_socket_io_handler_posix.cc",
-      "base_paths.cc",
       "cpu.cc",
+      "files/file_enumerator_posix.cc",
       "files/file_proxy.cc",
       "files/file_util.cc",
-      "files/file_util_proxy.cc",
-      "files/scoped_temp_dir.cc",
-      "path_service.cc",
-      "scoped_native_library.cc",
-    ]
-  }
-
-  sources -= [
-    "process/process_handle_freebsd.cc",
-    "process/process_handle_openbsd.cc",
-    "process/process_iterator_freebsd.cc",
-    "process/process_iterator_openbsd.cc",
-    "process/process_metrics_freebsd.cc",
-    "process/process_metrics_openbsd.cc",
-    "sys_info_freebsd.cc",
-    "sys_info_openbsd.cc",
-  ]
-
-  defines = [ "BASE_IMPLEMENTATION" ]
-
-  deps = [
-    ":base_static",
-    "//base/allocator:allocator_extension_thunks",
-    "//base/third_party/dynamic_annotations",
-    "//base/third_party/nspr",
-    "//third_party/modp_b64",
-  ]
-
-  # Allow more direct string conversions on platforms with native utf8
-  # strings
-  if (is_mac || is_ios || is_chromeos) {
-    defines += [ "SYSTEM_NATIVE_UTF8" ]
-  }
-
-  if (is_android) {
-    sources += [
-      "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",
-      "power_monitor/power_monitor_device_source_posix.cc",
-    ]
-
-    # Android uses some Linux sources, put those back.
-    set_sources_assignment_filter([])
-    sources += [
-      "debug/proc_maps_linux.cc",
-      "files/file_path_watcher_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",
-      "sys_info_linux.cc",
-    ]
-    set_sources_assignment_filter(sources_assignment_filter)
-
-    deps += [
-      ":base_jni_headers",
-      "//third_party/ashmem",
-      "//third_party/android_tools:cpu_features",
-    ]
-
-    # logging.cc uses the Android logging library.
-    libs = [ "log" ]
-
-    sources -= [ "debug/stack_trace_posix.cc" ]
-  }
-
-  if (is_chromeos) {
-    sources -= [ "power_monitor/power_monitor_device_source_posix.cc" ]
-  }
-
-  if (is_nacl) {
-    # These things would otherwise be built on a Posix build but aren't
-    # supported on NaCl.
-    sources -= [
-      "debug/stack_trace_posix.cc",
-      "files/file_enumerator_posix.cc",
       "files/file_util_posix.cc",
-      "memory/shared_memory_posix.cc",
+      "files/file_util_proxy.cc",
+      "files/important_file_writer.cc",
+      "files/important_file_writer.h",
+      "files/scoped_temp_dir.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",
+      "path_service.cc",
       "rand_util_posix.cc",
+      "scoped_native_library.cc",
       "sync_socket_posix.cc",
+      "sys_info.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",
@@ -922,12 +733,7 @@
 
   # Mac.
   if (is_mac) {
-    sources += [
-      "memory/discardable_memory_mach.cc",
-      "memory/discardable_memory_mach.h",
-    ]
     sources -= [
-      "base_paths_posix.cc",
       "native_library_posix.cc",
       "strings/sys_string_conversions_posix.cc",
     ]
@@ -990,6 +796,8 @@
     configs -= [ "//build/config/compiler:optimize" ]
     configs += [ "//build/config/compiler:optimize_max" ]
   }
+
+  allow_circular_includes_from = public_deps
 }
 
 # This is the subset of files from base that should not be used with a dynamic
@@ -1065,11 +873,66 @@
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 }
 
+if (is_linux && !is_chromeos) {
+  # TODO(GYP): Figure out which of these work and are needed on other platforms.
+  test("base_perftests") {
+    sources = [
+      "message_loop/message_pump_perftest.cc",
+
+      # "test/run_all_unittests.cc",
+      "threading/thread_perftest.cc",
+    ]
+    deps = [
+      ":base",
+      "//base/test:test_support",
+      "//base/test:test_support_perf",
+      "//testing/perf",
+      "//testing/gtest",
+    ]
+
+    if (is_android) {
+      deps += [ "//testing/android:native_test_native_code" ]
+    }
+  }
+
+  test("base_i18n_perftests") {
+    sources = [
+      "i18n/streaming_utf8_validator_perftest.cc",
+    ]
+    deps = [
+      ":base",
+      ":i18n",
+      "//base/test:test_support",
+      "//base/test:test_support_perf",
+      "//testing/gtest",
+    ]
+  }
+
+  if (!is_ios) {
+    executable("build_utf8_validator_tables") {
+      sources = [
+        "i18n/build_utf8_validator_tables.cc",
+      ]
+      deps = [
+        ":base",
+        "//third_party/icu:icuuc",
+      ]
+    }
+
+    executable("check_example") {
+      sources = [
+        "check_example.cc",
+      ]
+      deps = [
+        ":base",
+      ]
+    }
+  }
+}
+
 source_set("prefs") {
   sources = [
     "prefs/base_prefs_export.h",
-    "prefs/base_prefs_switches.cc",
-    "prefs/base_prefs_switches.h",
     "prefs/default_pref_store.cc",
     "prefs/default_pref_store.h",
     "prefs/json_pref_store.cc",
@@ -1272,7 +1135,6 @@
     "mac/scoped_sending_event_unittest.mm",
     "md5_unittest.cc",
     "memory/aligned_memory_unittest.cc",
-    "memory/discardable_memory_manager_unittest.cc",
     "memory/discardable_memory_unittest.cc",
     "memory/discardable_shared_memory_unittest.cc",
     "memory/linked_ptr_unittest.cc",
@@ -1421,6 +1283,8 @@
     "win/wrapped_window_proc_unittest.cc",
   ]
 
+  defines = []
+
   deps = [
     ":base",
     ":i18n",
@@ -1437,6 +1301,12 @@
     "//third_party/icu",
   ]
 
+  # Allow more direct string conversions on platforms with native utf8
+  # strings
+  if (is_mac || is_ios || is_chromeos) {
+    defines += [ "SYSTEM_NATIVE_UTF8" ]
+  }
+
   if (is_android) {
     apk_deps = [
       ":base_java",
@@ -1471,7 +1341,7 @@
   if (is_linux) {
     sources -= [ "file_version_info_unittest.cc" ]
     sources += [ "nix/xdg_util_unittest.cc" ]
-    defines = [ "USE_SYMBOLIZE" ]
+    defines += [ "USE_SYMBOLIZE" ]
     if (use_glib) {
       configs += [ "//build/config/linux:glib" ]
     }
@@ -1501,8 +1371,8 @@
   # GYP: //base.gyp:base_jni_headers
   generate_jni("base_jni_headers") {
     sources = [
-      "android/java/src/org/chromium/base/ApplicationStatus.java",
       "android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java",
+      "android/java/src/org/chromium/base/ApplicationStatus.java",
       "android/java/src/org/chromium/base/BuildInfo.java",
       "android/java/src/org/chromium/base/CommandLine.java",
       "android/java/src/org/chromium/base/ContentUriUtils.java",
diff --git a/base/OWNERS b/base/OWNERS
index 03c20e7..5d3e38b 100644
--- a/base/OWNERS
+++ b/base/OWNERS
@@ -24,26 +24,6 @@
 
 per-file *.isolate=csharp@chromium.org
 per-file *.isolate=maruel@chromium.org
-per-file bind.h=ajwong@chromium.org
-per-file bind_helpers.cc=ajwong@chromium.org
-per-file bind_helpers.h=ajwong@chromium.org
-per-file bind_helpers_unittest.cc=ajwong@chromium.org
-per-file bind.h.pump=ajwong@chromium.org
-per-file bind_internal.h=ajwong@chromium.org
-per-file bind_internal.h.pump=ajwong@chromium.org
-per-file bind_internal_win.h=ajwong@chromium.org
-per-file bind_internal_win.h.pump=ajwong@chromium.org
-per-file bind_unittest.cc=ajwong@chromium.org
-per-file bind_unittest.nc=ajwong@chromium.org
-per-file callback_forward.h=ajwong@chromium.org
-per-file callback.h=ajwong@chromium.org
-per-file callback_helpers.h=ajwong@chromium.org
-per-file callback.h.pump=ajwong@chromium.org
-per-file callback_internal.cc=ajwong@chromium.org
-per-file callback_internal.h=ajwong@chromium.org
-per-file callback_unittest.cc=ajwong@chromium.org
-per-file callback_unittest.h=ajwong@chromium.org
-per-file callback_unittest.nc=ajwong@chromium.org
 per-file security_unittest.cc=jln@chromium.org
 
 # For Android-specific changes:
diff --git a/base/allocator/allocator_extension.h b/base/allocator/allocator_extension.h
index de3119f..e65822b 100644
--- a/base/allocator/allocator_extension.h
+++ b/base/allocator/allocator_extension.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H
-#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H
+#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H_
+#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H_
 
 #include <stddef.h> // for size_t
 
@@ -56,4 +56,4 @@
 }  // namespace allocator
 }  // namespace base
 
-#endif
+#endif  // BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H_
diff --git a/base/allocator/allocator_extension_thunks.h b/base/allocator/allocator_extension_thunks.h
index 1e97a84..4e5027b 100644
--- a/base/allocator/allocator_extension_thunks.h
+++ b/base/allocator/allocator_extension_thunks.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H
-#define BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H
+#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_THUNKS_H_
+#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_THUNKS_H_
 
 #include <stddef.h> // for size_t
 
@@ -33,4 +33,4 @@
 }  // namespace allocator
 }  // namespace base
 
-#endif
+#endif  // BASE_ALLOCATOR_ALLOCATOR_EXTENSION_THUNKS_H_
diff --git a/base/android/base_jni_onload.cc b/base/android/base_jni_onload.cc
index c3a65d4..7ab4982 100644
--- a/base/android/base_jni_onload.cc
+++ b/base/android/base_jni_onload.cc
@@ -19,6 +19,7 @@
 }
 
 bool Init() {
+  InitAtExitManager();
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::InitReplacementClassLoader(env,
                                             base::android::GetClassLoader(env));
diff --git a/base/android/important_file_writer_android.h b/base/android/important_file_writer_android.h
index 20956ba..88e4441 100644
--- a/base/android/important_file_writer_android.h
+++ b/base/android/important_file_writer_android.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NATIVE_FRAMEWORK_CHROME_IMPORTANT_FILE_WRITE_ANDROID_H_
-#define NATIVE_FRAMEWORK_CHROME_IMPORTANT_FILE_WRITE_ANDROID_H_
+#ifndef BASE_ANDROID_IMPORTANT_FILE_WRITER_ANDROID_H_
+#define BASE_ANDROID_IMPORTANT_FILE_WRITER_ANDROID_H_
 
 #include <jni.h>
 
@@ -15,4 +15,4 @@
 }  // namespace android
 }  // namespace base
 
-#endif  // NATIVE_FRAMEWORK_CHROME_IMPORTANT_FILE_WRITE_ANDROID_H_
+#endif  // BASE_ANDROID_IMPORTANT_FILE_WRITER_ANDROID_H_
diff --git a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
index ad5cdd8..d4b0d98 100644
--- a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
+++ b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
@@ -9,6 +9,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeAnimator;
 import android.animation.TimeAnimator.TimeListener;
+import android.annotation.TargetApi;
+import android.os.Build;
 import android.util.Log;
 
 /**
@@ -80,6 +82,9 @@
     /**
      * Record Android animation frame rate and return the result.
      */
+    // Note: TimeAnimator was added to the Android public API in level 16, but has actually been
+    // available since level 14. So, it's safe to use TimeAnimator here, even on ICS.
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private static class Recorder implements TimeListener {
         // TODO(kkimlabs): If we can use in the future, migrate to Choreographer for minimal
         //                 workload.
diff --git a/base/android/java/src/org/chromium/base/JavaHandlerThread.java b/base/android/java/src/org/chromium/base/JavaHandlerThread.java
index 9643a63..3153a9b 100644
--- a/base/android/java/src/org/chromium/base/JavaHandlerThread.java
+++ b/base/android/java/src/org/chromium/base/JavaHandlerThread.java
@@ -4,6 +4,8 @@
 
 package org.chromium.base;
 
+import android.annotation.TargetApi;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 
@@ -35,15 +37,18 @@
         });
     }
 
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
     @CalledByNative
     private void stop(final long nativeThread, final long nativeEvent) {
+        final boolean quitSafely = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
         new Handler(mThread.getLooper()).post(new Runnable() {
             @Override
             public void run() {
                 nativeStopThread(nativeThread, nativeEvent);
+                if (!quitSafely) mThread.quit();
             }
         });
-        mThread.quitSafely();
+        if (quitSafely) mThread.quitSafely();
     }
 
     private native void nativeInitializeThread(long nativeJavaHandlerThread, long nativeEvent);
diff --git a/base/android/java/src/org/chromium/base/SysUtils.java b/base/android/java/src/org/chromium/base/SysUtils.java
index 1455a61..9dad516 100644
--- a/base/android/java/src/org/chromium/base/SysUtils.java
+++ b/base/android/java/src/org/chromium/base/SysUtils.java
@@ -4,6 +4,7 @@
 
 package org.chromium.base;
 
+import android.annotation.TargetApi;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Build;
@@ -19,10 +20,6 @@
  * Exposes system related information about the current device.
  */
 public class SysUtils {
-    // Any device that runs this or an older version of the system cannot be considered 'low-end'
-    private static final int ANDROID_LOW_MEMORY_ANDROID_SDK_THRESHOLD =
-            Build.VERSION_CODES.JELLY_BEAN_MR2;
-
     // A device reporting strictly more total memory in megabytes cannot be considered 'low-end'.
     private static final int ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB = 512;
 
@@ -107,6 +104,7 @@
         return sLowEndDevice.booleanValue();
     }
 
+    @TargetApi(Build.VERSION_CODES.KITKAT)
     private static boolean detectLowEndDevice() {
         assert CommandLine.isInitialized();
         if (CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_LOW_END_DEVICE_MODE)) {
@@ -115,7 +113,8 @@
         if (CommandLine.getInstance().hasSwitch(BaseSwitches.DISABLE_LOW_END_DEVICE_MODE)) {
             return false;
         }
-        if (Build.VERSION.SDK_INT <= ANDROID_LOW_MEMORY_ANDROID_SDK_THRESHOLD) {
+        // Any pre-KitKat device cannot be considered 'low-end'.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
             return false;
         }
 
diff --git a/base/android/java_handler_thread.h b/base/android/java_handler_thread.h
index 7cd274d..c9a2c02 100644
--- a/base/android/java_handler_thread.h
+++ b/base/android/java_handler_thread.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_THREADING_JAVA_THREAD_H_
-#define BASE_THREADING_JAVA_THREAD_H_
+#ifndef BASE_ANDROID_JAVA_HANDLER_THREAD_H_
+#define BASE_ANDROID_JAVA_HANDLER_THREAD_H_
 
 #include <jni.h>
 
@@ -46,4 +46,4 @@
 }  // namespace android
 }  // namespace base
 
-#endif  // BASE_THREADING_JAVA_THREAD_H_
+#endif  // BASE_ANDROID_JAVA_HANDLER_THREAD_H_
diff --git a/base/android/jni_generator/jni_generator.gyp b/base/android/jni_generator/jni_generator.gyp
index 2ea36b0..4a17f3e 100644
--- a/base/android/jni_generator/jni_generator.gyp
+++ b/base/android/jni_generator/jni_generator.gyp
@@ -7,6 +7,9 @@
     {
       'target_name': 'jni_generator_py_tests',
       'type': 'none',
+      'variables': {
+        'stamp': '<(INTERMEDIATE_DIR)/jni_generator_py_tests.stamp',
+      },
       'actions': [
         {
           'action_name': 'run_jni_generator_py_tests',
@@ -17,10 +20,11 @@
             'golden_sample_for_tests_jni.h',
           ],
           'outputs': [
-            '',
+            '<(stamp)',
           ],
           'action': [
             'python', 'jni_generator_tests.py',
+            '--stamp=<(stamp)',
           ],
         },
       ],
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py
index e29bc0c..6014847 100755
--- a/base/android/jni_generator/jni_generator_tests.py
+++ b/base/android/jni_generator/jni_generator_tests.py
@@ -13,6 +13,7 @@
 
 import difflib
 import inspect
+import optparse
 import os
 import sys
 import unittest
@@ -1148,5 +1149,27 @@
     self.assertGoldenTextEquals(jni_from_java.GetContent())
 
 
+def TouchStamp(stamp_path):
+  dir_name = os.path.dirname(stamp_path)
+  if not os.path.isdir(dir_name):
+    os.makedirs()
+
+  with open(stamp_path, 'a'):
+    os.utime(stamp_path, None)
+
+
+def main(argv):
+  parser = optparse.OptionParser()
+  parser.add_option('--stamp', help='Path to touch on success.')
+  options, _ = parser.parse_args(argv[1:])
+
+  test_result = unittest.main(argv=argv[0:1], exit=False)
+
+  if test_result.result.wasSuccessful() and options.stamp:
+    TouchStamp(options.stamp)
+
+  return not test_result.result.wasSuccessful()
+
+
 if __name__ == '__main__':
-  unittest.main()
+  sys.exit(main(sys.argv))
diff --git a/base/android/jni_generator/sample_for_tests.h b/base/android/jni_generator/sample_for_tests.h
index 4d76408..c98cf97 100644
--- a/base/android/jni_generator/sample_for_tests.h
+++ b/base/android/jni_generator/sample_for_tests.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_
+#define BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_
+
 #include <jni.h>
 #include <map>
 #include <string>
@@ -48,3 +51,5 @@
 
 }  // namespace android
 }  // namespace base
+
+#endif  // BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_
diff --git a/base/android/jni_string.cc b/base/android/jni_string.cc
index d25fed8..57c2805 100644
--- a/base/android/jni_string.cc
+++ b/base/android/jni_string.cc
@@ -18,7 +18,7 @@
   return result;
 }
 
-}
+}  // namespace
 
 namespace base {
 namespace android {
diff --git a/base/android/library_loader/library_load_from_apk_status_codes.h b/base/android/library_loader/library_load_from_apk_status_codes.h
index f99eebc..9591d3f 100644
--- a/base/android/library_loader/library_load_from_apk_status_codes.h
+++ b/base/android/library_loader/library_load_from_apk_status_codes.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_ANDROID_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
-#define BASE_ANDROID_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
+#ifndef BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
+#define BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
 
 namespace base {
 namespace android {
@@ -43,4 +43,4 @@
 }  // namespace android
 }  // namespace base
 
-#endif  // BASE_ANDROID_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
+#endif  // BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
diff --git a/base/android/library_loader/library_loader_hooks.cc b/base/android/library_loader/library_loader_hooks.cc
index 97aec8c..555420a 100644
--- a/base/android/library_loader/library_loader_hooks.cc
+++ b/base/android/library_loader/library_loader_hooks.cc
@@ -123,9 +123,6 @@
 }
 
 bool RegisterLibraryLoaderEntryHook(JNIEnv* env) {
-  // We need the AtExitManager to be created at the very beginning.
-  g_at_exit_manager = new base::AtExitManager();
-
   return RegisterNativesImpl(env);
 }
 
@@ -142,5 +139,9 @@
       Java_LibraryLoader_getLibraryProcessType(env));
 }
 
+void InitAtExitManager() {
+  g_at_exit_manager = new base::AtExitManager();
+}
+
 }  // namespace android
 }  // namespace base
diff --git a/base/android/library_loader/library_loader_hooks.h b/base/android/library_loader/library_loader_hooks.h
index 7e8d527..ca3c5a2 100644
--- a/base/android/library_loader/library_loader_hooks.h
+++ b/base/android/library_loader/library_loader_hooks.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_ANDROID_LIBRARY_LOADER_HOOKS_H_
-#define BASE_ANDROID_LIBRARY_LOADER_HOOKS_H_
+#ifndef BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_
+#define BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_
 
 #include <jni.h>
 
@@ -64,7 +64,11 @@
 // Return the process type the shared library is loaded in.
 BASE_EXPORT LibraryProcessType GetLibraryProcessType(JNIEnv* env);
 
+// Initialize AtExitManager, this must be done at the begining of loading
+// shared library.
+void InitAtExitManager();
+
 }  // namespace android
 }  // namespace base
 
-#endif  // BASE_ANDROID_LIBRARY_LOADER_HOOKS_H_
+#endif  // BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_
diff --git a/base/android/trace_event_binding.h b/base/android/trace_event_binding.h
index ed06266..1c1a60b 100644
--- a/base/android/trace_event_binding.h
+++ b/base/android/trace_event_binding.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_ANDROID_TRACE_EVENT_H_
-#define BASE_ANDROID_TRACE_EVENT_H_
+#ifndef BASE_ANDROID_TRACE_EVENT_BINDING_H_
+#define BASE_ANDROID_TRACE_EVENT_BINDING_H_
 
 #include <jni.h>
 
@@ -15,4 +15,4 @@
 }  // namespace android
 }  // namespace base
 
-#endif  // CONTENT_COMMON_ANDROID_TRACE_EVENT_H_
+#endif  // BASE_ANDROID_TRACE_EVENT_BINDING_H_
diff --git a/base/atomicops_internals_arm64_gcc.h b/base/atomicops_internals_arm64_gcc.h
index bb6a346..ddcfec9 100644
--- a/base/atomicops_internals_arm64_gcc.h
+++ b/base/atomicops_internals_arm64_gcc.h
@@ -301,7 +301,7 @@
   return *ptr;
 }
 
-}  // namespace base::subtle
+}  // namespace subtle
 }  // namespace base
 
 #endif  // BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_
diff --git a/base/atomicops_internals_arm_gcc.h b/base/atomicops_internals_arm_gcc.h
index e654afa..44c91c8 100644
--- a/base/atomicops_internals_arm_gcc.h
+++ b/base/atomicops_internals_arm_gcc.h
@@ -288,7 +288,7 @@
   return *ptr;
 }
 
-}  // namespace base::subtle
+}  // namespace subtle
 }  // namespace base
 
 #endif  // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
diff --git a/base/atomicops_internals_atomicword_compat.h b/base/atomicops_internals_atomicword_compat.h
index e02d11d..342a6e4 100644
--- a/base/atomicops_internals_atomicword_compat.h
+++ b/base/atomicops_internals_atomicword_compat.h
@@ -92,8 +92,8 @@
       reinterpret_cast<volatile const Atomic32*>(ptr));
 }
 
-}   // namespace base::subtle
-}   // namespace base
+}  // namespace subtle
+}  // namespace base
 
 #endif  // !defined(ARCH_CPU_64_BITS)
 
diff --git a/base/atomicops_internals_gcc.h b/base/atomicops_internals_gcc.h
index ed1b2d7..35c95fe 100644
--- a/base/atomicops_internals_gcc.h
+++ b/base/atomicops_internals_gcc.h
@@ -99,7 +99,7 @@
   return *ptr;
 }
 
-}  // namespace base::subtle
+}  // namespace subtle
 }  // namespace base
 
 #endif  // BASE_ATOMICOPS_INTERNALS_GCC_H_
diff --git a/base/atomicops_internals_mac.h b/base/atomicops_internals_mac.h
index ccbb896..98864a7 100644
--- a/base/atomicops_internals_mac.h
+++ b/base/atomicops_internals_mac.h
@@ -191,7 +191,7 @@
 
 #endif  // defined(__LP64__)
 
-}   // namespace base::subtle
-}   // namespace base
+}  // namespace subtle
+}  // namespace base
 
 #endif  // BASE_ATOMICOPS_INTERNALS_MAC_H_
diff --git a/base/atomicops_internals_mips_gcc.h b/base/atomicops_internals_mips_gcc.h
index e206e03..b4551b8 100644
--- a/base/atomicops_internals_mips_gcc.h
+++ b/base/atomicops_internals_mips_gcc.h
@@ -274,7 +274,7 @@
 }
 #endif
 
-} // namespace base::subtle
-} // namespace base
+}  // namespace subtle
+}  // namespace base
 
 #endif  // BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
diff --git a/base/atomicops_internals_portable.h b/base/atomicops_internals_portable.h
index b25099f..d285610 100644
--- a/base/atomicops_internals_portable.h
+++ b/base/atomicops_internals_portable.h
@@ -221,7 +221,7 @@
 }
 
 #endif  // defined(ARCH_CPU_64_BITS)
-}
-}  // namespace base::subtle
+}  // namespace subtle
+}  // namespace base
 
 #endif  // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
diff --git a/base/atomicops_internals_x86_gcc.h b/base/atomicops_internals_x86_gcc.h
index 69eacdb..f0d2242 100644
--- a/base/atomicops_internals_x86_gcc.h
+++ b/base/atomicops_internals_x86_gcc.h
@@ -220,8 +220,8 @@
 
 #endif  // defined(__x86_64__)
 
-} // namespace base::subtle
-} // namespace base
+}  // namespace subtle
+}  // namespace base
 
 #undef ATOMICOPS_COMPILER_BARRIER
 
diff --git a/base/atomicops_internals_x86_msvc.h b/base/atomicops_internals_x86_msvc.h
index 26f1813..71ddca2 100644
--- a/base/atomicops_internals_x86_msvc.h
+++ b/base/atomicops_internals_x86_msvc.h
@@ -189,7 +189,7 @@
 
 #endif  // defined(_WIN64)
 
-}  // namespace base::subtle
+}  // namespace subtle
 }  // namespace base
 
 #endif  // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
diff --git a/base/auto_reset.h b/base/auto_reset.h
index 32f138e..a5bcfaa 100644
--- a/base/auto_reset.h
+++ b/base/auto_reset.h
@@ -36,6 +36,6 @@
   DISALLOW_COPY_AND_ASSIGN(AutoReset);
 };
 
-}
+}  // namespace base
 
 #endif  // BASE_AUTO_RESET_H_
diff --git a/base/barrier_closure.cc b/base/barrier_closure.cc
index 5abe2bf..1b77429 100644
--- a/base/barrier_closure.cc
+++ b/base/barrier_closure.cc
@@ -39,7 +39,7 @@
 
 base::Closure BarrierClosure(int num_callbacks_left,
                              const base::Closure& done_closure) {
-  DCHECK(num_callbacks_left >= 0);
+  DCHECK_GE(num_callbacks_left, 0);
 
   if (num_callbacks_left == 0)
     done_closure.Run();
diff --git a/base/base.gyp b/base/base.gyp
index 3888ad9..5f640d8 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -338,8 +338,6 @@
       ],
       'sources': [
         'prefs/base_prefs_export.h',
-        'prefs/base_prefs_switches.cc',
-        'prefs/base_prefs_switches.h',
         'prefs/default_pref_store.cc',
         'prefs/default_pref_store.h',
         'prefs/json_pref_store.cc',
@@ -543,7 +541,6 @@
         'mac/scoped_sending_event_unittest.mm',
         'md5_unittest.cc',
         'memory/aligned_memory_unittest.cc',
-        'memory/discardable_memory_manager_unittest.cc',
         'memory/discardable_memory_unittest.cc',
         'memory/discardable_shared_memory_unittest.cc',
         'memory/linked_ptr_unittest.cc',
@@ -835,19 +832,20 @@
             ['include', '^sys_string_conversions_mac_unittest\\.mm$'],
           ],
         }],
-        ['OS == "android" and _toolset == "target"', {
-          'sources': [
-            'memory/discardable_memory_ashmem_allocator_unittest.cc',
-          ],
-        }],
         ['OS == "android"', {
           'sources/': [
             ['include', '^debug/proc_maps_linux_unittest\\.cc$'],
           ],
         }],
+        # Enable more direct string conversions on platforms with native utf8
+        # strings
+        ['OS=="mac" or OS=="ios" or <(chromeos)==1 or <(chromecast)==1', {
+          'defines': ['SYSTEM_NATIVE_UTF8'],
+        }],
       ],  # target_conditions
     },
     {
+      # GN: //base:base_perftests
       'target_name': 'base_perftests',
       'type': '<(gtest_target_type)',
       'dependencies': [
@@ -870,6 +868,7 @@
       ],
     },
     {
+      # GN: //base:base_i18n_perftests
       'target_name': 'base_i18n_perftests',
       'type': '<(gtest_target_type)',
       'dependencies': [
@@ -1077,6 +1076,7 @@
     ['OS!="ios"', {
       'targets': [
         {
+          # GN: //base:check_example
           'target_name': 'check_example',
           'type': 'executable',
           'sources': [
diff --git a/base/base.gypi b/base/base.gypi
index 0f8fff2..ebc7e3e 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -319,12 +319,8 @@
           'memory/discardable_memory.cc',
           'memory/discardable_memory.h',
           'memory/discardable_memory_android.cc',
-          'memory/discardable_memory_emulated.cc',
-          'memory/discardable_memory_emulated.h',
           'memory/discardable_memory_linux.cc',
           'memory/discardable_memory_mac.cc',
-          'memory/discardable_memory_manager.cc',
-          'memory/discardable_memory_manager.h',
           'memory/discardable_memory_shmem.cc',
           'memory/discardable_memory_shmem.h',
           'memory/discardable_memory_shmem_allocator.cc',
@@ -829,14 +825,6 @@
               ['include', '^threading/platform_thread_linux\\.cc$'],
             ],
           }],
-          ['OS == "android" and _toolset == "target" and >(nacl_untrusted_build)==0', {
-           'sources': [
-             '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', {
             'sources!': [
               'base_paths_posix.cc',
@@ -979,10 +967,6 @@
             ],
           }],
           ['(OS == "mac" or OS == "ios") and >(nacl_untrusted_build)==0', {
-            'sources': [
-              'memory/discardable_memory_mach.cc',
-              'memory/discardable_memory_mach.h',
-            ],
             'sources/': [
               ['exclude', '^files/file_path_watcher_stub\\.cc$'],
               ['exclude', '^base_paths_posix\\.cc$'],
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate
index 5126fb3..e329152 100644
--- a/base/base_unittests.isolate
+++ b/base/base_unittests.isolate
@@ -3,14 +3,20 @@
 # found in the LICENSE file.
 {
   'conditions': [
-    ['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', {
+    ['use_x11==0', {
       'variables': {
-        'files': [
-          'test/data/',
+        'command': [
+          '../testing/test_env.py',
+          '<(PRODUCT_DIR)/base_unittests<(EXECUTABLE_SUFFIX)',
+          '--brave-new-test-launcher',
+          '--test-launcher-bot-mode',
+          '--asan=<(asan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
       },
     }],
-    ['OS=="linux"', {
+    ['use_x11==1', {
       'variables': {
         'command': [
           '../testing/xvfb.py',
@@ -24,13 +30,14 @@
         ],
         'files': [
           '../testing/xvfb.py',
+          '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
         ],
       },
     }],
-    ['OS=="linux" and use_ozone==0', {
+    ['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', {
       'variables': {
         'files': [
-          '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
+          'test/data/',
         ],
       },
     }],
@@ -43,19 +50,6 @@
         'read_only': 1,
       },
     }],
-    ['OS=="mac" or OS=="win"', {
-      'variables': {
-        'command': [
-          '../testing/test_env.py',
-          '<(PRODUCT_DIR)/base_unittests<(EXECUTABLE_SUFFIX)',
-          '--brave-new-test-launcher',
-          '--test-launcher-bot-mode',
-          '--asan=<(asan)',
-          '--msan=<(msan)',
-          '--tsan=<(tsan)',
-        ],
-      },
-    }],
     ['OS=="mac" and asan==1 and fastbuild==0', {
       'variables': {
         'files': [
diff --git a/base/build_time.h b/base/build_time.h
index c7df479..4f0abc3 100644
--- a/base/build_time.h
+++ b/base/build_time.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_BUILD_TIME_
-#define BASE_BUILD_TIME_
+#ifndef BASE_BUILD_TIME_H_
+#define BASE_BUILD_TIME_H_
 
 #include "base/base_export.h"
 #include "base/time/time.h"
@@ -25,4 +25,4 @@
 
 }  // namespace base
 
-#endif  // BASE_BUILD_TIME_
+#endif  // BASE_BUILD_TIME_H_
diff --git a/base/callback_forward.h b/base/callback_forward.h
index 7983248..262c306 100644
--- a/base/callback_forward.h
+++ b/base/callback_forward.h
@@ -14,4 +14,4 @@
 
 }  // namespace base
 
-#endif  // BASE_CALLBACK_FORWARD_H
+#endif  // BASE_CALLBACK_FORWARD_H_
diff --git a/base/command_line.cc b/base/command_line.cc
index 6125667..d28a4b4 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -187,7 +187,7 @@
 // static
 void CommandLine::set_slash_is_not_a_switch() {
   // The last switch prefix should be slash, so adjust the size to skip it.
-  DCHECK(wcscmp(kSwitchPrefixes[arraysize(kSwitchPrefixes) - 1], L"/") == 0);
+  DCHECK_EQ(wcscmp(kSwitchPrefixes[arraysize(kSwitchPrefixes) - 1], L"/"), 0);
   switch_prefix_count = arraysize(kSwitchPrefixes) - 1;
 }
 #endif
diff --git a/base/containers/hash_tables.h b/base/containers/hash_tables.h
index 6bf029e..d13c469 100644
--- a/base/containers/hash_tables.h
+++ b/base/containers/hash_tables.h
@@ -320,7 +320,7 @@
   }
 };
 
-}
+}  // namespace BASE_HASH_NAMESPACE
 
 #undef DEFINE_PAIR_HASH_FUNCTION_START
 #undef DEFINE_PAIR_HASH_FUNCTION_END
diff --git a/base/containers/mru_cache.h b/base/containers/mru_cache.h
index 15ea2fc..ed1ad25 100644
--- a/base/containers/mru_cache.h
+++ b/base/containers/mru_cache.h
@@ -213,8 +213,7 @@
 template<class PayloadType>
 class MRUCacheNullDeletor {
  public:
-  void operator()(PayloadType& payload) {
-  }
+  void operator()(const PayloadType& payload) {}
 };
 
 // A container that does not do anything to free its data. Use this when storing
@@ -244,9 +243,7 @@
 template<class PayloadType>
 class MRUCachePointerDeletor {
  public:
-  void operator()(PayloadType& payload) {
-    delete payload;
-  }
+  void operator()(const PayloadType& payload) { delete payload; }
 };
 
 // A cache that owns the payload type, which must be a non-const pointer type.
diff --git a/base/containers/stack_container.h b/base/containers/stack_container.h
index 87fa036..54090d3 100644
--- a/base/containers/stack_container.h
+++ b/base/containers/stack_container.h
@@ -176,6 +176,7 @@
   Allocator allocator_;
   ContainerType container_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(StackContainer);
 };
 
diff --git a/base/debug/BUILD.gn b/base/debug/BUILD.gn
new file mode 100644
index 0000000..37a0ab2
--- /dev/null
+++ b/base/debug/BUILD.gn
@@ -0,0 +1,75 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("debug") {
+  sources = [
+    "alias.cc",
+    "alias.h",
+    "asan_invalid_access.cc",
+    "asan_invalid_access.h",
+    "crash_logging.cc",
+    "crash_logging.h",
+    "debugger.cc",
+    "debugger.h",
+    "debugger_posix.cc",
+    "debugger_win.cc",
+    "dump_without_crashing.cc",
+    "dump_without_crashing.h",
+    "gdi_debug_util_win.cc",
+    "gdi_debug_util_win.h",
+
+    # This file depends on files from the "allocator" target,
+    # but this target does not depend on "allocator" (see
+    # allocator.gyp for details).
+    "leak_annotations.h",
+    "leak_tracker.h",
+    "proc_maps_linux.cc",
+    "proc_maps_linux.h",
+    "profiler.cc",
+    "profiler.h",
+    "stack_trace.cc",
+    "stack_trace.h",
+    "stack_trace_android.cc",
+    "stack_trace_posix.cc",
+    "stack_trace_win.cc",
+    "task_annotator.cc",
+    "task_annotator.h",
+  ]
+
+  if (is_android) {
+    # Android uses some Linux sources, put those back.
+    set_sources_assignment_filter([])
+    sources += [ "proc_maps_linux.cc" ]
+    set_sources_assignment_filter(sources_assignment_filter)
+
+    sources -= [ "stack_trace_posix.cc" ]
+  }
+
+  if (is_nacl) {
+    sources -= [
+      "crash_logging.cc",
+      "crash_logging.h",
+      "stack_trace.cc",
+      "stack_trace_posix.cc",
+    ]
+  }
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  deps = [
+    "//base/memory",
+    "//base/process",
+  ]
+
+  if (is_linux) {
+    deps += [ "//base/third_party/symbolize" ]
+  }
+
+  allow_circular_includes_from = [
+    "//base/memory",
+    "//base/process",
+  ]
+
+  visibility = [ "//base/*" ]
+}
diff --git a/base/debug/debugger.h b/base/debug/debugger.h
index d62ea3f..8680e28 100644
--- a/base/debug/debugger.h
+++ b/base/debug/debugger.h
@@ -6,8 +6,8 @@
 // debuggers.  You should use this to test if you're running under a debugger,
 // and if you would like to yield (breakpoint) into the debugger.
 
-#ifndef BASE_DEBUG_DEBUGGER_H
-#define BASE_DEBUG_DEBUGGER_H
+#ifndef BASE_DEBUG_DEBUGGER_H_
+#define BASE_DEBUG_DEBUGGER_H_
 
 #include "base/base_export.h"
 
@@ -41,4 +41,4 @@
 }  // namespace debug
 }  // namespace base
 
-#endif  // BASE_DEBUG_DEBUGGER_H
+#endif  // BASE_DEBUG_DEBUGGER_H_
diff --git a/base/debug/leak_annotations.h b/base/debug/leak_annotations.h
index 27fe663..ef37959 100644
--- a/base/debug/leak_annotations.h
+++ b/base/debug/leak_annotations.h
@@ -21,15 +21,7 @@
 
 #if defined(LEAK_SANITIZER) && !defined(OS_NACL)
 
-// Public LSan API from <sanitizer/lsan_interface.h>.
-extern "C" {
-void __lsan_disable();
-void __lsan_enable();
-void __lsan_ignore_object(const void *p);
-
-// Invoke leak detection immediately. If leaks are found, the process will exit.
-void __lsan_do_leak_check();
-}  // extern "C"
+#include <sanitizer/lsan_interface.h>
 
 class ScopedLeakSanitizerDisabler {
  public:
@@ -46,7 +38,6 @@
 
 #else
 
-// If neither HeapChecker nor LSan are used, the annotations should be no-ops.
 #define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0)
 #define ANNOTATE_LEAKING_OBJECT_PTR(X) ((void)0)
 
diff --git a/base/debug/profiler.h b/base/debug/profiler.h
index e1dda89..c50555e 100644
--- a/base/debug/profiler.h
+++ b/base/debug/profiler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_DEBUG_PROFILER_H
-#define BASE_DEBUG_PROFILER_H
+#ifndef BASE_DEBUG_PROFILER_H_
+#define BASE_DEBUG_PROFILER_H_
 
 #include <string>
 
@@ -87,4 +87,4 @@
 }  // namespace debug
 }  // namespace base
 
-#endif  // BASE_DEBUG_DEBUGGER_H
+#endif  // BASE_DEBUG_PROFILER_H__
diff --git a/base/deferred_sequenced_task_runner.h b/base/deferred_sequenced_task_runner.h
index bc8db7a..110d988 100644
--- a/base/deferred_sequenced_task_runner.h
+++ b/base/deferred_sequenced_task_runner.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_
-#define BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_
+#ifndef BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_
+#define BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_
 
 #include <vector>
 
@@ -75,4 +75,4 @@
 
 }  // namespace base
 
-#endif  // BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_
+#endif  // BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_
diff --git a/base/event_types.h b/base/event_types.h
index af586e4..9905800 100644
--- a/base/event_types.h
+++ b/base/event_types.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_EVENT_TYPES_H
-#define BASE_EVENT_TYPES_H
+#ifndef BASE_EVENT_TYPES_H_
+#define BASE_EVENT_TYPES_H_
 
 #include "build/build_config.h"
 
@@ -34,4 +34,4 @@
 
 } // namespace base
 
-#endif  // BASE_EVENT_TYPES_H
+#endif  // BASE_EVENT_TYPES_H_
diff --git a/base/files/file_path_watcher_browsertest.cc b/base/files/file_path_watcher_browsertest.cc
index 9081626..bc7e630 100644
--- a/base/files/file_path_watcher_browsertest.cc
+++ b/base/files/file_path_watcher_browsertest.cc
@@ -192,6 +192,7 @@
   ScopedTempDir temp_dir_;
   scoped_refptr<NotificationCollector> collector_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(FilePathWatcherTest);
 };
 
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
index af932ce..b107b0f 100644
--- a/base/files/file_util_unittest.cc
+++ b/base/files/file_util_unittest.cc
@@ -197,9 +197,9 @@
 // interface to query whether a given file is present.
 class FindResultCollector {
  public:
-  explicit FindResultCollector(FileEnumerator& enumerator) {
+  explicit FindResultCollector(FileEnumerator* enumerator) {
     FilePath cur_file;
-    while (!(cur_file = enumerator.Next()).value().empty()) {
+    while (!(cur_file = enumerator->Next()).value().empty()) {
       FilePath::StringType path = cur_file.value();
       // The file should not be returned twice.
       EXPECT_TRUE(files_.end() == files_.find(path))
@@ -824,7 +824,7 @@
   // Make sure the file in the directory can't be enumerated.
   FileEnumerator f1(subdir_path, true, FileEnumerator::FILES);
   EXPECT_TRUE(PathExists(subdir_path));
-  FindResultCollector c1(f1);
+  FindResultCollector c1(&f1);
   EXPECT_EQ(0, c1.size());
   EXPECT_FALSE(GetPosixFilePermissions(file_name, &mode));
 
@@ -835,7 +835,7 @@
 
   // Make sure the file in the directory can be enumerated.
   FileEnumerator f2(subdir_path, true, FileEnumerator::FILES);
-  FindResultCollector c2(f2);
+  FindResultCollector c2(&f2);
   EXPECT_TRUE(c2.HasFile(file_name));
   EXPECT_EQ(1, c2.size());
 
@@ -1871,7 +1871,7 @@
 
   // Only enumerate files.
   FileEnumerator f1(temp_dir_.path(), true, FileEnumerator::FILES);
-  FindResultCollector c1(f1);
+  FindResultCollector c1(&f1);
   EXPECT_TRUE(c1.HasFile(file1));
   EXPECT_TRUE(c1.HasFile(file2_abs));
   EXPECT_TRUE(c1.HasFile(dir2file));
@@ -1880,7 +1880,7 @@
 
   // Only enumerate directories.
   FileEnumerator f2(temp_dir_.path(), true, FileEnumerator::DIRECTORIES);
-  FindResultCollector c2(f2);
+  FindResultCollector c2(&f2);
   EXPECT_TRUE(c2.HasFile(dir1));
   EXPECT_TRUE(c2.HasFile(dir2));
   EXPECT_TRUE(c2.HasFile(dir2inner));
@@ -1889,7 +1889,7 @@
   // Only enumerate directories non-recursively.
   FileEnumerator f2_non_recursive(
       temp_dir_.path(), false, FileEnumerator::DIRECTORIES);
-  FindResultCollector c2_non_recursive(f2_non_recursive);
+  FindResultCollector c2_non_recursive(&f2_non_recursive);
   EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
   EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
   EXPECT_EQ(2, c2_non_recursive.size());
@@ -1898,7 +1898,7 @@
   FileEnumerator f2_dotdot(temp_dir_.path(), false,
                            FileEnumerator::DIRECTORIES |
                            FileEnumerator::INCLUDE_DOT_DOT);
-  FindResultCollector c2_dotdot(f2_dotdot);
+  FindResultCollector c2_dotdot(&f2_dotdot);
   EXPECT_TRUE(c2_dotdot.HasFile(dir1));
   EXPECT_TRUE(c2_dotdot.HasFile(dir2));
   EXPECT_TRUE(c2_dotdot.HasFile(temp_dir_.path().Append(FPL(".."))));
@@ -1906,7 +1906,7 @@
 
   // Enumerate files and directories.
   FileEnumerator f3(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
-  FindResultCollector c3(f3);
+  FindResultCollector c3(&f3);
   EXPECT_TRUE(c3.HasFile(dir1));
   EXPECT_TRUE(c3.HasFile(dir2));
   EXPECT_TRUE(c3.HasFile(file1));
@@ -1918,7 +1918,7 @@
 
   // Non-recursive operation.
   FileEnumerator f4(temp_dir_.path(), false, FILES_AND_DIRECTORIES);
-  FindResultCollector c4(f4);
+  FindResultCollector c4(&f4);
   EXPECT_TRUE(c4.HasFile(dir2));
   EXPECT_TRUE(c4.HasFile(dir2));
   EXPECT_TRUE(c4.HasFile(file1));
@@ -1927,7 +1927,7 @@
 
   // Enumerate with a pattern.
   FileEnumerator f5(temp_dir_.path(), true, FILES_AND_DIRECTORIES, FPL("dir*"));
-  FindResultCollector c5(f5);
+  FindResultCollector c5(&f5);
   EXPECT_TRUE(c5.HasFile(dir1));
   EXPECT_TRUE(c5.HasFile(dir2));
   EXPECT_TRUE(c5.HasFile(dir2file));
@@ -1946,7 +1946,7 @@
       // the file system so skip this test for XP.
       // Enumerate the reparse point.
       FileEnumerator f6(dir1, true, FILES_AND_DIRECTORIES);
-      FindResultCollector c6(f6);
+      FindResultCollector c6(&f6);
       FilePath inner2 = dir1.Append(FPL("inner"));
       EXPECT_TRUE(c6.HasFile(inner2));
       EXPECT_TRUE(c6.HasFile(inner2.Append(FPL("innerfile.txt"))));
@@ -1956,7 +1956,7 @@
 
     // No changes for non recursive operation.
     FileEnumerator f7(temp_dir_.path(), false, FILES_AND_DIRECTORIES);
-    FindResultCollector c7(f7);
+    FindResultCollector c7(&f7);
     EXPECT_TRUE(c7.HasFile(dir2));
     EXPECT_TRUE(c7.HasFile(dir2));
     EXPECT_TRUE(c7.HasFile(file1));
@@ -1965,7 +1965,7 @@
 
     // Should not enumerate inside dir1 when using recursion.
     FileEnumerator f8(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
-    FindResultCollector c8(f8);
+    FindResultCollector c8(&f8);
     EXPECT_TRUE(c8.HasFile(dir1));
     EXPECT_TRUE(c8.HasFile(dir2));
     EXPECT_TRUE(c8.HasFile(file1));
diff --git a/base/guid_posix.cc b/base/guid_posix.cc
index 9681b08..f0fedc2 100644
--- a/base/guid_posix.cc
+++ b/base/guid_posix.cc
@@ -39,4 +39,4 @@
                       bytes[1] & 0x0000ffffffffffffULL);
 }
 
-}  // namespace guid
+}  // namespace base
diff --git a/base/guid_win.cc b/base/guid_win.cc
index cdb860a..da3453d 100644
--- a/base/guid_win.cc
+++ b/base/guid_win.cc
@@ -35,4 +35,4 @@
   return WideToUTF8(guid_string.substr(1, guid_string.length() - 2));
 }
 
-}  // namespace guid
+}  // namespace base
diff --git a/base/i18n/string_compare.h b/base/i18n/string_compare.h
index f0f3e29..158c93b 100644
--- a/base/i18n/string_compare.h
+++ b/base/i18n/string_compare.h
@@ -25,4 +25,4 @@
 }  // namespace i18n
 }  // namespace base
 
-#endif  // BASE_I18N_STRING_COMPARATOR_H_
+#endif  // BASE_I18N_STRING_COMPARE_H_
diff --git a/base/i18n/timezone.h b/base/i18n/timezone.h
index b7275f7..f7fda94 100644
--- a/base/i18n/timezone.h
+++ b/base/i18n/timezone.h
@@ -18,4 +18,4 @@
 
 }  // namespace base
 
-#endif  // BASE_TIME_TIMEZONE_H_
+#endif  // BASE_I18N_TIMEZONE_H_
diff --git a/base/json/BUILD.gn b/base/json/BUILD.gn
new file mode 100644
index 0000000..0310ea9
--- /dev/null
+++ b/base/json/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("json") {
+  sources = [
+    "json_file_value_serializer.cc",
+    "json_file_value_serializer.h",
+    "json_parser.cc",
+    "json_parser.h",
+    "json_reader.cc",
+    "json_reader.h",
+    "json_string_value_serializer.cc",
+    "json_string_value_serializer.h",
+    "json_value_converter.cc",
+    "json_value_converter.h",
+    "json_writer.cc",
+    "json_writer.h",
+    "string_escape.cc",
+    "string_escape.h",
+  ]
+
+  if (is_nacl) {
+    sources -= [
+      "json_file_value_serializer.cc",
+      "json_file_value_serializer.h",
+    ]
+  }
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  deps = [
+    "//base/memory",
+  ]
+
+  visibility = [ "//base/*" ]
+}
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc
index 225ee67..b8aebe0 100644
--- a/base/json/json_value_serializer_unittest.cc
+++ b/base/json/json_value_serializer_unittest.cc
@@ -61,7 +61,7 @@
 const char kLinuxLineEnds[] = "\n";
 
 // Verifies the generated JSON against the expected output.
-void CheckJSONIsStillTheSame(Value& value) {
+void CheckJSONIsStillTheSame(const Value& value) {
   // Serialize back the output.
   std::string serialized_json;
   JSONStringValueSerializer str_serializer(&serialized_json);
diff --git a/base/mac/authorization_util.mm b/base/mac/authorization_util.mm
index 003c26d..1dfd5a0 100644
--- a/base/mac/authorization_util.mm
+++ b/base/mac/authorization_util.mm
@@ -28,10 +28,9 @@
     AuthorizationFlags extraFlags) {
   // Create an empty AuthorizationRef.
   ScopedAuthorizationRef authorization;
-  OSStatus status = AuthorizationCreate(NULL,
-                                        kAuthorizationEmptyEnvironment,
+  OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
                                         kAuthorizationFlagDefaults,
-                                        &authorization);
+                                        authorization.get_pointer());
   if (status != errAuthorizationSuccess) {
     OSSTATUS_LOG(ERROR, status) << "AuthorizationCreate";
     return NULL;
diff --git a/base/mac/cocoa_protocols.h b/base/mac/cocoa_protocols.h
index ab34a19..a28795c 100644
--- a/base/mac/cocoa_protocols.h
+++ b/base/mac/cocoa_protocols.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_COCOA_PROTOCOLS_MAC_H_
-#define BASE_COCOA_PROTOCOLS_MAC_H_
+#ifndef BASE_MAC_COCOA_PROTOCOLS_H_
+#define BASE_MAC_COCOA_PROTOCOLS_H_
 
 #import <Cocoa/Cocoa.h>
 
@@ -28,4 +28,4 @@
 
 #undef DEFINE_EMPTY_PROTOCOL
 
-#endif  // BASE_COCOA_PROTOCOLS_MAC_H_
+#endif  // BASE_MAC_COCOA_PROTOCOLS_H_
diff --git a/base/mac/libdispatch_task_runner.h b/base/mac/libdispatch_task_runner.h
index f5fd866..b479bc7 100644
--- a/base/mac/libdispatch_task_runner.h
+++ b/base/mac/libdispatch_task_runner.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_MAC_LIBDISPATCH_SEQUENCED_TASK_RUNNER_H_
-#define BASE_MAC_LIBDISPATCH_SEQUENCED_TASK_RUNNER_H_
+#ifndef BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_
+#define BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_
 
 #include <dispatch/dispatch.h>
 
@@ -77,4 +77,4 @@
 }  // namespace mac
 }  // namespace base
 
-#endif  // BASE_MAC_LIBDISPATCH_SEQUENCED_TASK_RUNNER_H_
+#endif  // BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_
diff --git a/base/mac/scoped_authorizationref.h b/base/mac/scoped_authorizationref.h
index 6413f2e..1811488 100644
--- a/base/mac/scoped_authorizationref.h
+++ b/base/mac/scoped_authorizationref.h
@@ -49,9 +49,7 @@
     return authorization_;
   }
 
-  AuthorizationRef* operator&() {
-    return &authorization_;
-  }
+  AuthorizationRef* get_pointer() { return &authorization_; }
 
   AuthorizationRef get() const {
     return authorization_;
diff --git a/base/mac/scoped_mach_vm.cc b/base/mac/scoped_mach_vm.cc
index 1c28d9c..d52c77f 100644
--- a/base/mac/scoped_mach_vm.cc
+++ b/base/mac/scoped_mach_vm.cc
@@ -8,8 +8,8 @@
 namespace mac {
 
 void ScopedMachVM::reset(vm_address_t address, vm_size_t size) {
-  DCHECK(address % PAGE_SIZE == 0);
-  DCHECK(size % PAGE_SIZE == 0);
+  DCHECK_EQ(address % PAGE_SIZE, 0u);
+  DCHECK_EQ(size % PAGE_SIZE, 0u);
 
   if (size_) {
     if (address_ < address) {
diff --git a/base/mac/scoped_mach_vm.h b/base/mac/scoped_mach_vm.h
index b130a79..ffc00d5 100644
--- a/base/mac/scoped_mach_vm.h
+++ b/base/mac/scoped_mach_vm.h
@@ -48,10 +48,9 @@
 class BASE_EXPORT ScopedMachVM {
  public:
   explicit ScopedMachVM(vm_address_t address = 0, vm_size_t size = 0)
-      : address_(address),
-        size_(size) {
-    DCHECK(address % PAGE_SIZE == 0);
-    DCHECK(size % PAGE_SIZE == 0);
+      : address_(address), size_(size) {
+    DCHECK_EQ(address % PAGE_SIZE, 0u);
+    DCHECK_EQ(size % PAGE_SIZE, 0u);
   }
 
   ~ScopedMachVM() {
diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn
new file mode 100644
index 0000000..5d016ff
--- /dev/null
+++ b/base/memory/BUILD.gn
@@ -0,0 +1,64 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("memory") {
+  sources = [
+    "aligned_memory.cc",
+    "aligned_memory.h",
+    "discardable_memory.cc",
+    "discardable_memory.h",
+    "discardable_memory_android.cc",
+    "discardable_memory_linux.cc",
+    "discardable_memory_mac.cc",
+    "discardable_memory_shmem.cc",
+    "discardable_memory_shmem.h",
+    "discardable_memory_shmem_allocator.cc",
+    "discardable_memory_shmem_allocator.h",
+    "discardable_memory_win.cc",
+    "discardable_shared_memory.cc",
+    "discardable_shared_memory.h",
+    "linked_ptr.h",
+    "manual_constructor.h",
+    "memory_pressure_listener.cc",
+    "memory_pressure_listener.h",
+    "raw_scoped_refptr_mismatch_checker.h",
+    "ref_counted.cc",
+    "ref_counted.h",
+    "ref_counted_delete_on_message_loop.h",
+    "ref_counted_memory.cc",
+    "ref_counted_memory.h",
+    "scoped_policy.h",
+    "scoped_ptr.h",
+    "scoped_vector.h",
+    "shared_memory.h",
+    "shared_memory_android.cc",
+    "shared_memory_nacl.cc",
+    "shared_memory_posix.cc",
+    "shared_memory_win.cc",
+    "singleton.cc",
+    "singleton.h",
+    "weak_ptr.cc",
+    "weak_ptr.h",
+  ]
+
+  if (is_nacl) {
+    sources -= [
+      "discardable_memory.cc",
+      "discardable_memory.h",
+      "discardable_memory_shmem.cc",
+      "discardable_memory_shmem.h",
+      "discardable_memory_shmem_allocator.cc",
+      "discardable_memory_shmem_allocator.h",
+      "discardable_shared_memory.cc",
+      "discardable_shared_memory.h",
+      "shared_memory_posix.cc",
+    ]
+  } else {
+    sources -= [ "shared_memory_nacl.cc" ]
+  }
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  visibility = [ "//base/*" ]
+}
diff --git a/base/memory/discardable_memory.cc b/base/memory/discardable_memory.cc
index 3d82f91..7d19f9a 100644
--- a/base/memory/discardable_memory.cc
+++ b/base/memory/discardable_memory.cc
@@ -14,9 +14,6 @@
   DiscardableMemoryType type;
   const char* name;
 } kTypeNamePairs[] = {
-  { DISCARDABLE_MEMORY_TYPE_ASHMEM, "ashmem" },
-  { DISCARDABLE_MEMORY_TYPE_MACH, "mach" },
-  { DISCARDABLE_MEMORY_TYPE_EMULATED, "emulated" },
   { DISCARDABLE_MEMORY_TYPE_SHMEM, "shmem" }
 };
 
diff --git a/base/memory/discardable_memory.h b/base/memory/discardable_memory.h
index c49a99f..4e5a9af 100644
--- a/base/memory/discardable_memory.h
+++ b/base/memory/discardable_memory.h
@@ -17,18 +17,9 @@
 
 enum DiscardableMemoryType {
   DISCARDABLE_MEMORY_TYPE_NONE,
-  DISCARDABLE_MEMORY_TYPE_ASHMEM,
-  DISCARDABLE_MEMORY_TYPE_MACH,
-  DISCARDABLE_MEMORY_TYPE_EMULATED,
   DISCARDABLE_MEMORY_TYPE_SHMEM
 };
 
-enum DiscardableMemoryLockStatus {
-  DISCARDABLE_MEMORY_LOCK_STATUS_FAILED,
-  DISCARDABLE_MEMORY_LOCK_STATUS_PURGED,
-  DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS
-};
-
 // Platform abstraction for discardable memory. DiscardableMemory is used to
 // cache large objects without worrying about blowing out memory, both on mobile
 // devices where there is no swap, and desktop devices where unused free memory
@@ -89,23 +80,10 @@
   // Create a DiscardableMemory instance with preferred type and |size|.
   static scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size);
 
-  // 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
-  // memory instances have been used. This indicates that all discardable
-  // memory implementations have reduced usage to the base level or below.
-  // Note: calling this too often or while discardable memory is in frequent
-  // use can hurt performance, whereas calling it too infrequently can result
-  // in memory bloat.
-  static bool ReduceMemoryUsage();
-
   // Locks the memory so that it will not be purged by the system. Returns
-  // DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS on success. If the return value is
-  // DISCARDABLE_MEMORY_LOCK_STATUS_FAILED then this object should be
-  // discarded and a new one should be created. If the return value is
-  // DISCARDABLE_MEMORY_LOCK_STATUS_PURGED then the memory is present but any
-  // data that was in it is gone.
-  virtual DiscardableMemoryLockStatus Lock() WARN_UNUSED_RESULT = 0;
+  // true on success. If the return value is false then this object should be
+  // discarded and a new one should be created.
+  virtual bool Lock() WARN_UNUSED_RESULT = 0;
 
   // Unlocks the memory so that it can be purged by the system. Must be called
   // after every successful lock call.
diff --git a/base/memory/discardable_memory_android.cc b/base/memory/discardable_memory_android.cc
index 2b35587..a36f54e 100644
--- a/base/memory/discardable_memory_android.cc
+++ b/base/memory/discardable_memory_android.cc
@@ -4,57 +4,16 @@
 
 #include "base/memory/discardable_memory.h"
 
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/memory/discardable_memory_ashmem.h"
-#include "base/memory/discardable_memory_ashmem_allocator.h"
-#include "base/memory/discardable_memory_emulated.h"
 #include "base/memory/discardable_memory_shmem.h"
-#include "base/sys_info.h"
 
 namespace base {
-namespace {
-
-const char kAshmemAllocatorName[] = "DiscardableMemoryAshmemAllocator";
-
-// For Ashmem, have the DiscardableMemoryManager trigger userspace eviction
-// when address space usage gets too high (e.g. 512 MBytes).
-const size_t kAshmemMemoryLimit = 512 * 1024 * 1024;
-
-size_t GetOptimalAshmemRegionSizeForAllocator() {
-  // Note that this may do some I/O (without hitting the disk though) so it
-  // should not be called on the critical path.
-  return base::SysInfo::AmountOfPhysicalMemory() / 8;
-}
-
-// Holds the shared state used for allocations.
-struct SharedState {
-  SharedState()
-      : manager(kAshmemMemoryLimit, kAshmemMemoryLimit, TimeDelta::Max()),
-        allocator(kAshmemAllocatorName,
-                  GetOptimalAshmemRegionSizeForAllocator()) {}
-
-  internal::DiscardableMemoryManager manager;
-  internal::DiscardableMemoryAshmemAllocator allocator;
-};
-LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-// static
-bool DiscardableMemory::ReduceMemoryUsage() {
-  return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
-}
 
 // static
 void DiscardableMemory::GetSupportedTypes(
     std::vector<DiscardableMemoryType>* types) {
   const DiscardableMemoryType supported_types[] = {
-    DISCARDABLE_MEMORY_TYPE_SHMEM,
-    DISCARDABLE_MEMORY_TYPE_ASHMEM,
-    DISCARDABLE_MEMORY_TYPE_EMULATED
+    DISCARDABLE_MEMORY_TYPE_SHMEM
   };
   types->assign(supported_types, supported_types + arraysize(supported_types));
 }
@@ -63,34 +22,9 @@
 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType(
     DiscardableMemoryType type, size_t size) {
   switch (type) {
-    case DISCARDABLE_MEMORY_TYPE_ASHMEM: {
-      SharedState* const shared_state = g_shared_state.Pointer();
-      scoped_ptr<internal::DiscardableMemoryAshmem> memory(
-          new internal::DiscardableMemoryAshmem(
-              size, &shared_state->allocator, &shared_state->manager));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
-    case DISCARDABLE_MEMORY_TYPE_EMULATED: {
-      scoped_ptr<internal::DiscardableMemoryEmulated> memory(
-          new internal::DiscardableMemoryEmulated(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
-    case DISCARDABLE_MEMORY_TYPE_SHMEM: {
-      scoped_ptr<internal::DiscardableMemoryShmem> memory(
-          new internal::DiscardableMemoryShmem(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
+    case DISCARDABLE_MEMORY_TYPE_SHMEM:
+      return make_scoped_ptr(new internal::DiscardableMemoryShmem(size));
     case DISCARDABLE_MEMORY_TYPE_NONE:
-    case DISCARDABLE_MEMORY_TYPE_MACH:
       NOTREACHED();
       return nullptr;
   }
diff --git a/base/memory/discardable_memory_ashmem.cc b/base/memory/discardable_memory_ashmem.cc
deleted file mode 100644
index a590e53..0000000
--- a/base/memory/discardable_memory_ashmem.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_ashmem.h"
-
-#include "base/memory/discardable_memory_ashmem_allocator.h"
-
-namespace base {
-namespace internal {
-
-DiscardableMemoryAshmem::DiscardableMemoryAshmem(
-    size_t bytes,
-    DiscardableMemoryAshmemAllocator* allocator,
-    DiscardableMemoryManager* manager)
-    : bytes_(bytes),
-      allocator_(allocator),
-      manager_(manager),
-      is_locked_(false) {
-  manager_->Register(this, bytes_);
-}
-
-DiscardableMemoryAshmem::~DiscardableMemoryAshmem() {
-  if (is_locked_)
-    Unlock();
-
-  manager_->Unregister(this);
-}
-
-bool DiscardableMemoryAshmem::Initialize() {
-  return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-}
-
-DiscardableMemoryLockStatus DiscardableMemoryAshmem::Lock() {
-  DCHECK(!is_locked_);
-
-  bool purged = false;
-  if (!manager_->AcquireLock(this, &purged))
-    return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-
-  is_locked_ = true;
-  return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
-                : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
-}
-
-void DiscardableMemoryAshmem::Unlock() {
-  DCHECK(is_locked_);
-  manager_->ReleaseLock(this);
-  is_locked_ = false;
-}
-
-void* DiscardableMemoryAshmem::Memory() const {
-  DCHECK(is_locked_);
-  DCHECK(ashmem_chunk_);
-  return ashmem_chunk_->Memory();
-}
-
-bool DiscardableMemoryAshmem::AllocateAndAcquireLock() {
-  if (ashmem_chunk_)
-    return ashmem_chunk_->Lock();
-
-  ashmem_chunk_ = allocator_->Allocate(bytes_);
-  return false;
-}
-
-void DiscardableMemoryAshmem::ReleaseLock() {
-  ashmem_chunk_->Unlock();
-}
-
-void DiscardableMemoryAshmem::Purge() {
-  ashmem_chunk_.reset();
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/memory/discardable_memory_ashmem.h b/base/memory/discardable_memory_ashmem.h
deleted file mode 100644
index 1269cc2..0000000
--- a/base/memory/discardable_memory_ashmem.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_H_
-
-#include "base/memory/discardable_memory.h"
-
-#include "base/macros.h"
-#include "base/memory/discardable_memory_manager.h"
-
-namespace base {
-namespace internal {
-
-class DiscardableAshmemChunk;
-class DiscardableMemoryAshmemAllocator;
-class DiscardableMemoryManager;
-
-class DiscardableMemoryAshmem
-    : public DiscardableMemory,
-      public internal::DiscardableMemoryManagerAllocation {
- public:
-  explicit DiscardableMemoryAshmem(size_t bytes,
-                                   DiscardableMemoryAshmemAllocator* allocator,
-                                   DiscardableMemoryManager* manager);
-
-  ~DiscardableMemoryAshmem() override;
-
-  bool Initialize();
-
-  // Overridden from DiscardableMemory:
-  DiscardableMemoryLockStatus Lock() override;
-  void Unlock() override;
-  void* Memory() const override;
-
-  // Overridden from internal::DiscardableMemoryManagerAllocation:
-  bool AllocateAndAcquireLock() override;
-  void ReleaseLock() override;
-  void Purge() override;
-
- private:
-  const size_t bytes_;
-  DiscardableMemoryAshmemAllocator* const allocator_;
-  DiscardableMemoryManager* const manager_;
-  bool is_locked_;
-  scoped_ptr<DiscardableAshmemChunk> ashmem_chunk_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryAshmem);
-};
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_H_
diff --git a/base/memory/discardable_memory_ashmem_allocator.cc b/base/memory/discardable_memory_ashmem_allocator.cc
deleted file mode 100644
index 3d4af92..0000000
--- a/base/memory/discardable_memory_ashmem_allocator.cc
+++ /dev/null
@@ -1,528 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_ashmem_allocator.h"
-
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <cmath>
-#include <limits>
-#include <set>
-#include <utility>
-
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/memory/scoped_vector.h"
-#include "third_party/ashmem/ashmem.h"
-
-// The allocator consists of three parts (classes):
-// - DiscardableMemoryAshmemAllocator: entry point of all allocations (through
-// its Allocate() method) that are dispatched to the AshmemRegion instances
-// (which it owns).
-// - AshmemRegion: manages allocations and destructions inside a single large
-// (e.g. 32 MBytes) ashmem region.
-// - DiscardableAshmemChunk: class mimicking the DiscardableMemory interface
-// whose instances are returned to the client.
-
-namespace base {
-namespace {
-
-// Only tolerate fragmentation in used chunks *caused by the client* (as opposed
-// to the allocator when a free chunk is reused). The client can cause such
-// fragmentation by e.g. requesting 4097 bytes. This size would be rounded up to
-// 8192 by the allocator which would cause 4095 bytes of fragmentation (which is
-// currently the maximum allowed). If the client requests 4096 bytes and a free
-// chunk of 8192 bytes is available then the free chunk gets splitted into two
-// pieces to minimize fragmentation (since 8192 - 4096 = 4096 which is greater
-// than 4095).
-// TODO(pliard): tune this if splitting chunks too often leads to performance
-// issues.
-const size_t kMaxChunkFragmentationBytes = 4096 - 1;
-
-const size_t kMinAshmemRegionSize = 32 * 1024 * 1024;
-
-// Returns 0 if the provided size is too high to be aligned.
-size_t AlignToNextPage(size_t size) {
-  const size_t kPageSize = 4096;
-  DCHECK_EQ(static_cast<int>(kPageSize), getpagesize());
-  if (size > std::numeric_limits<size_t>::max() - kPageSize + 1)
-    return 0;
-  const size_t mask = ~(kPageSize - 1);
-  return (size + kPageSize - 1) & mask;
-}
-
-bool CreateAshmemRegion(const char* name,
-                        size_t size,
-                        int* out_fd,
-                        uintptr_t* out_address) {
-  base::ScopedFD fd(ashmem_create_region(name, size));
-  if (!fd.is_valid()) {
-    DLOG(ERROR) << "ashmem_create_region() failed";
-    return false;
-  }
-
-  const int err = ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE);
-  if (err < 0) {
-    DLOG(ERROR) << "Error " << err << " when setting protection of ashmem";
-    return false;
-  }
-
-  // There is a problem using MAP_PRIVATE here. As we are constantly calling
-  // Lock() and Unlock(), data could get lost if they are not written to the
-  // underlying file when Unlock() gets called.
-  void* const address = mmap(
-      NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
-  if (address == MAP_FAILED) {
-    DPLOG(ERROR) << "Failed to map memory.";
-    return false;
-  }
-
-  *out_fd = fd.release();
-  *out_address = reinterpret_cast<uintptr_t>(address);
-  return true;
-}
-
-bool CloseAshmemRegion(int fd, size_t size, void* address) {
-  if (munmap(address, size) == -1) {
-    DPLOG(ERROR) << "Failed to unmap memory.";
-    close(fd);
-    return false;
-  }
-  return close(fd) == 0;
-}
-
-bool LockAshmemRegion(int fd, size_t off, size_t size) {
-  return ashmem_pin_region(fd, off, size) != ASHMEM_WAS_PURGED;
-}
-
-bool UnlockAshmemRegion(int fd, size_t off, size_t size) {
-  const int failed = ashmem_unpin_region(fd, off, size);
-  if (failed)
-    DLOG(ERROR) << "Failed to unpin memory.";
-  return !failed;
-}
-
-}  // namespace
-
-namespace internal {
-
-class AshmemRegion {
- public:
-  // Note that |allocator| must outlive |this|.
-  static scoped_ptr<AshmemRegion> Create(
-      size_t size,
-      const std::string& name,
-      DiscardableMemoryAshmemAllocator* allocator) {
-    DCHECK_EQ(size, AlignToNextPage(size));
-    int fd;
-    uintptr_t base;
-    if (!CreateAshmemRegion(name.c_str(), size, &fd, &base))
-      return scoped_ptr<AshmemRegion>();
-    return make_scoped_ptr(new AshmemRegion(fd, size, base, allocator));
-  }
-
-  ~AshmemRegion() {
-    const bool result = CloseAshmemRegion(
-        fd_, size_, reinterpret_cast<void*>(base_));
-    DCHECK(result);
-    DCHECK(!highest_allocated_chunk_);
-  }
-
-  // Returns a new instance of DiscardableAshmemChunk whose size is greater or
-  // equal than |actual_size| (which is expected to be greater or equal than
-  // |client_requested_size|).
-  // Allocation works as follows:
-  // 1) Reuse a previously freed chunk and return it if it succeeded. See
-  // ReuseFreeChunk_Locked() below for more information.
-  // 2) If no free chunk could be reused and the region is not big enough for
-  // the requested size then NULL is returned.
-  // 3) If there is enough room in the ashmem region then a new chunk is
-  // returned. This new chunk starts at |offset_| which is the end of the
-  // previously highest chunk in the region.
-  scoped_ptr<DiscardableAshmemChunk> Allocate_Locked(
-      size_t client_requested_size,
-      size_t actual_size) {
-    DCHECK_LE(client_requested_size, actual_size);
-    allocator_->lock_.AssertAcquired();
-
-    // Check that the |highest_allocated_chunk_| field doesn't contain a stale
-    // pointer. It should point to either a free chunk or a used chunk.
-    DCHECK(!highest_allocated_chunk_ ||
-           address_to_free_chunk_map_.find(highest_allocated_chunk_) !=
-               address_to_free_chunk_map_.end() ||
-           used_to_previous_chunk_map_.find(highest_allocated_chunk_) !=
-               used_to_previous_chunk_map_.end());
-
-    scoped_ptr<DiscardableAshmemChunk> memory = ReuseFreeChunk_Locked(
-        client_requested_size, actual_size);
-    if (memory)
-      return memory.Pass();
-
-    if (size_ - offset_ < actual_size) {
-      // This region does not have enough space left to hold the requested size.
-      return scoped_ptr<DiscardableAshmemChunk>();
-    }
-
-    uintptr_t const address = base_ + offset_;
-    memory.reset(
-        new DiscardableAshmemChunk(this, fd_, reinterpret_cast<void*>(address),
-                                   offset_, actual_size));
-
-    used_to_previous_chunk_map_.insert(
-        std::make_pair(address, highest_allocated_chunk_));
-    highest_allocated_chunk_ = reinterpret_cast<uintptr_t>(address);
-    offset_ += actual_size;
-    DCHECK_LE(offset_, size_);
-    return memory.Pass();
-  }
-
-  void OnChunkDeletion(uintptr_t chunk, size_t size) {
-    AutoLock auto_lock(allocator_->lock_);
-    MergeAndAddFreeChunk_Locked(chunk, size);
-    // Note that |this| might be deleted beyond this point.
-  }
-
- private:
-  struct FreeChunk {
-    FreeChunk() : previous_chunk(0), start(0), size(0) {}
-
-    explicit FreeChunk(size_t size)
-        : previous_chunk(0),
-          start(0),
-          size(size) {
-    }
-
-    FreeChunk(uintptr_t previous_chunk, uintptr_t start, size_t size)
-        : previous_chunk(previous_chunk),
-          start(start),
-          size(size) {
-      DCHECK_LT(previous_chunk, start);
-    }
-
-    uintptr_t const previous_chunk;
-    uintptr_t const start;
-    const size_t size;
-
-    bool is_null() const { return !start; }
-
-    bool operator<(const FreeChunk& other) const {
-      return size < other.size;
-    }
-  };
-
-  // Note that |allocator| must outlive |this|.
-  AshmemRegion(int fd,
-               size_t size,
-               uintptr_t base,
-               DiscardableMemoryAshmemAllocator* allocator)
-      : fd_(fd),
-        size_(size),
-        base_(base),
-        allocator_(allocator),
-        highest_allocated_chunk_(0),
-        offset_(0) {
-    DCHECK_GE(fd_, 0);
-    DCHECK_GE(size, kMinAshmemRegionSize);
-    DCHECK(base);
-    DCHECK(allocator);
-  }
-
-  // Tries to reuse a previously freed chunk by doing a closest size match.
-  scoped_ptr<DiscardableAshmemChunk> ReuseFreeChunk_Locked(
-      size_t client_requested_size,
-      size_t actual_size) {
-    allocator_->lock_.AssertAcquired();
-    const FreeChunk reused_chunk = RemoveFreeChunkFromIterator_Locked(
-        free_chunks_.lower_bound(FreeChunk(actual_size)));
-    if (reused_chunk.is_null())
-      return scoped_ptr<DiscardableAshmemChunk>();
-
-    used_to_previous_chunk_map_.insert(
-        std::make_pair(reused_chunk.start, reused_chunk.previous_chunk));
-    size_t reused_chunk_size = reused_chunk.size;
-    // |client_requested_size| is used below rather than |actual_size| to
-    // reflect the amount of bytes that would not be usable by the client (i.e.
-    // wasted). Using |actual_size| instead would not allow us to detect
-    // fragmentation caused by the client if he did misaligned allocations.
-    DCHECK_GE(reused_chunk.size, client_requested_size);
-    const size_t fragmentation_bytes =
-        reused_chunk.size - client_requested_size;
-
-    if (fragmentation_bytes > kMaxChunkFragmentationBytes) {
-      // Split the free chunk being recycled so that its unused tail doesn't get
-      // reused (i.e. locked) which would prevent it from being evicted under
-      // memory pressure.
-      reused_chunk_size = actual_size;
-      uintptr_t const new_chunk_start = reused_chunk.start + actual_size;
-      if (reused_chunk.start == highest_allocated_chunk_) {
-        // We also need to update the pointer to the highest allocated chunk in
-        // case we are splitting the highest chunk.
-        highest_allocated_chunk_ = new_chunk_start;
-      }
-      DCHECK_GT(reused_chunk.size, actual_size);
-      const size_t new_chunk_size = reused_chunk.size - actual_size;
-      // Note that merging is not needed here since there can't be contiguous
-      // free chunks at this point.
-      AddFreeChunk_Locked(
-          FreeChunk(reused_chunk.start, new_chunk_start, new_chunk_size));
-    }
-
-    const size_t offset = reused_chunk.start - base_;
-    LockAshmemRegion(fd_, offset, reused_chunk_size);
-    scoped_ptr<DiscardableAshmemChunk> memory(
-        new DiscardableAshmemChunk(this, fd_,
-                                   reinterpret_cast<void*>(reused_chunk.start),
-                                   offset, reused_chunk_size));
-    return memory.Pass();
-  }
-
-  // Makes the chunk identified with the provided arguments free and possibly
-  // merges this chunk with the previous and next contiguous ones.
-  // If the provided chunk is the only one used (and going to be freed) in the
-  // region then the internal ashmem region is closed so that the underlying
-  // physical pages are immediately released.
-  // Note that free chunks are unlocked therefore they can be reclaimed by the
-  // kernel if needed (under memory pressure) but they are not immediately
-  // released unfortunately since madvise(MADV_REMOVE) and
-  // fallocate(FALLOC_FL_PUNCH_HOLE) don't seem to work on ashmem. This might
-  // change in versions of kernel >=3.5 though. The fact that free chunks are
-  // not immediately released is the reason why we are trying to minimize
-  // fragmentation in order not to cause "artificial" memory pressure.
-  void MergeAndAddFreeChunk_Locked(uintptr_t chunk, size_t size) {
-    allocator_->lock_.AssertAcquired();
-    size_t new_free_chunk_size = size;
-    // Merge with the previous chunk.
-    uintptr_t first_free_chunk = chunk;
-    DCHECK(!used_to_previous_chunk_map_.empty());
-    const hash_map<uintptr_t, uintptr_t>::iterator previous_chunk_it =
-        used_to_previous_chunk_map_.find(chunk);
-    DCHECK(previous_chunk_it != used_to_previous_chunk_map_.end());
-    uintptr_t previous_chunk = previous_chunk_it->second;
-    used_to_previous_chunk_map_.erase(previous_chunk_it);
-
-    if (previous_chunk) {
-      const FreeChunk free_chunk = RemoveFreeChunk_Locked(previous_chunk);
-      if (!free_chunk.is_null()) {
-        new_free_chunk_size += free_chunk.size;
-        first_free_chunk = previous_chunk;
-        if (chunk == highest_allocated_chunk_)
-          highest_allocated_chunk_ = previous_chunk;
-
-        // There should not be more contiguous previous free chunks.
-        previous_chunk = free_chunk.previous_chunk;
-        DCHECK(!address_to_free_chunk_map_.count(previous_chunk));
-      }
-    }
-
-    // Merge with the next chunk if free and present.
-    uintptr_t next_chunk = chunk + size;
-    const FreeChunk next_free_chunk = RemoveFreeChunk_Locked(next_chunk);
-    if (!next_free_chunk.is_null()) {
-      new_free_chunk_size += next_free_chunk.size;
-      if (next_free_chunk.start == highest_allocated_chunk_)
-        highest_allocated_chunk_ = first_free_chunk;
-
-      // Same as above.
-      DCHECK(
-          !address_to_free_chunk_map_.count(next_chunk + next_free_chunk.size));
-    }
-
-    const bool whole_ashmem_region_is_free =
-        used_to_previous_chunk_map_.empty();
-    if (!whole_ashmem_region_is_free) {
-      AddFreeChunk_Locked(
-          FreeChunk(previous_chunk, first_free_chunk, new_free_chunk_size));
-      return;
-    }
-
-    // The whole ashmem region is free thus it can be deleted.
-    DCHECK_EQ(base_, first_free_chunk);
-    DCHECK_EQ(base_, highest_allocated_chunk_);
-    DCHECK(free_chunks_.empty());
-    DCHECK(address_to_free_chunk_map_.empty());
-    DCHECK(used_to_previous_chunk_map_.empty());
-    highest_allocated_chunk_ = 0;
-    allocator_->DeleteAshmemRegion_Locked(this);  // Deletes |this|.
-  }
-
-  void AddFreeChunk_Locked(const FreeChunk& free_chunk) {
-    allocator_->lock_.AssertAcquired();
-    const std::multiset<FreeChunk>::iterator it = free_chunks_.insert(
-        free_chunk);
-    address_to_free_chunk_map_.insert(std::make_pair(free_chunk.start, it));
-    // Update the next used contiguous chunk, if any, since its previous chunk
-    // may have changed due to free chunks merging/splitting.
-    uintptr_t const next_used_contiguous_chunk =
-        free_chunk.start + free_chunk.size;
-    hash_map<uintptr_t, uintptr_t>::iterator previous_it =
-        used_to_previous_chunk_map_.find(next_used_contiguous_chunk);
-    if (previous_it != used_to_previous_chunk_map_.end())
-      previous_it->second = free_chunk.start;
-  }
-
-  // Finds and removes the free chunk, if any, whose start address is
-  // |chunk_start|. Returns a copy of the unlinked free chunk or a free chunk
-  // whose content is null if it was not found.
-  FreeChunk RemoveFreeChunk_Locked(uintptr_t chunk_start) {
-    allocator_->lock_.AssertAcquired();
-    const hash_map<
-        uintptr_t, std::multiset<FreeChunk>::iterator>::iterator it =
-            address_to_free_chunk_map_.find(chunk_start);
-    if (it == address_to_free_chunk_map_.end())
-      return FreeChunk();
-    return RemoveFreeChunkFromIterator_Locked(it->second);
-  }
-
-  // Same as above but takes an iterator in.
-  FreeChunk RemoveFreeChunkFromIterator_Locked(
-      std::multiset<FreeChunk>::iterator free_chunk_it) {
-    allocator_->lock_.AssertAcquired();
-    if (free_chunk_it == free_chunks_.end())
-      return FreeChunk();
-    DCHECK(free_chunk_it != free_chunks_.end());
-    const FreeChunk free_chunk(*free_chunk_it);
-    address_to_free_chunk_map_.erase(free_chunk_it->start);
-    free_chunks_.erase(free_chunk_it);
-    return free_chunk;
-  }
-
-  const int fd_;
-  const size_t size_;
-  uintptr_t const base_;
-  DiscardableMemoryAshmemAllocator* const allocator_;
-  // Points to the chunk with the highest address in the region. This pointer
-  // needs to be carefully updated when chunks are merged/split.
-  uintptr_t highest_allocated_chunk_;
-  // Points to the end of |highest_allocated_chunk_|.
-  size_t offset_;
-  // Allows free chunks recycling (lookup, insertion and removal) in O(log N).
-  // Note that FreeChunk values are indexed by their size and also note that
-  // multiple free chunks can have the same size (which is why multiset<> is
-  // used instead of e.g. set<>).
-  std::multiset<FreeChunk> free_chunks_;
-  // Used while merging free contiguous chunks to erase free chunks (from their
-  // start address) in constant time. Note that multiset<>::{insert,erase}()
-  // don't invalidate iterators (except the one for the element being removed
-  // obviously).
-  hash_map<
-      uintptr_t, std::multiset<FreeChunk>::iterator> address_to_free_chunk_map_;
-  // Maps the address of *used* chunks to the address of their previous
-  // contiguous chunk.
-  hash_map<uintptr_t, uintptr_t> used_to_previous_chunk_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(AshmemRegion);
-};
-
-DiscardableAshmemChunk::~DiscardableAshmemChunk() {
-  if (locked_)
-    UnlockAshmemRegion(fd_, offset_, size_);
-  ashmem_region_->OnChunkDeletion(reinterpret_cast<uintptr_t>(address_), size_);
-}
-
-bool DiscardableAshmemChunk::Lock() {
-  DCHECK(!locked_);
-  locked_ = true;
-  return LockAshmemRegion(fd_, offset_, size_);
-}
-
-void DiscardableAshmemChunk::Unlock() {
-  DCHECK(locked_);
-  locked_ = false;
-  UnlockAshmemRegion(fd_, offset_, size_);
-}
-
-void* DiscardableAshmemChunk::Memory() const {
-  return address_;
-}
-
-// Note that |ashmem_region| must outlive |this|.
-DiscardableAshmemChunk::DiscardableAshmemChunk(AshmemRegion* ashmem_region,
-                                               int fd,
-                                               void* address,
-                                               size_t offset,
-                                               size_t size)
-    : ashmem_region_(ashmem_region),
-      fd_(fd),
-      address_(address),
-      offset_(offset),
-      size_(size),
-      locked_(true) {
-}
-
-DiscardableMemoryAshmemAllocator::DiscardableMemoryAshmemAllocator(
-    const std::string& name,
-    size_t ashmem_region_size)
-    : name_(name),
-      ashmem_region_size_(
-          std::max(kMinAshmemRegionSize, AlignToNextPage(ashmem_region_size))),
-      last_ashmem_region_size_(0) {
-  DCHECK_GE(ashmem_region_size_, kMinAshmemRegionSize);
-}
-
-DiscardableMemoryAshmemAllocator::~DiscardableMemoryAshmemAllocator() {
-  DCHECK(ashmem_regions_.empty());
-}
-
-scoped_ptr<DiscardableAshmemChunk> DiscardableMemoryAshmemAllocator::Allocate(
-    size_t size) {
-  const size_t aligned_size = AlignToNextPage(size);
-  if (!aligned_size)
-    return scoped_ptr<DiscardableAshmemChunk>();
-  // TODO(pliard): make this function less naive by e.g. moving the free chunks
-  // multiset to the allocator itself in order to decrease even more
-  // fragmentation/speedup allocation. Note that there should not be more than a
-  // couple (=5) of AshmemRegion instances in practice though.
-  AutoLock auto_lock(lock_);
-  DCHECK_LE(ashmem_regions_.size(), 5U);
-  for (ScopedVector<AshmemRegion>::iterator it = ashmem_regions_.begin();
-       it != ashmem_regions_.end(); ++it) {
-    scoped_ptr<DiscardableAshmemChunk> memory(
-        (*it)->Allocate_Locked(size, aligned_size));
-    if (memory)
-      return memory.Pass();
-  }
-  // The creation of the (large) ashmem region might fail if the address space
-  // is too fragmented. In case creation fails the allocator retries by
-  // repetitively dividing the size by 2.
-  const size_t min_region_size = std::max(kMinAshmemRegionSize, aligned_size);
-  for (size_t region_size = std::max(ashmem_region_size_, aligned_size);
-       region_size >= min_region_size;
-       region_size = AlignToNextPage(region_size / 2)) {
-    scoped_ptr<AshmemRegion> new_region(
-        AshmemRegion::Create(region_size, name_.c_str(), this));
-    if (!new_region)
-      continue;
-    last_ashmem_region_size_ = region_size;
-    ashmem_regions_.push_back(new_region.release());
-    return ashmem_regions_.back()->Allocate_Locked(size, aligned_size);
-  }
-  // TODO(pliard): consider adding an histogram to see how often this happens.
-  return scoped_ptr<DiscardableAshmemChunk>();
-}
-
-size_t DiscardableMemoryAshmemAllocator::last_ashmem_region_size() const {
-  AutoLock auto_lock(lock_);
-  return last_ashmem_region_size_;
-}
-
-void DiscardableMemoryAshmemAllocator::DeleteAshmemRegion_Locked(
-    AshmemRegion* region) {
-  lock_.AssertAcquired();
-  // Note that there should not be more than a couple of ashmem region instances
-  // in |ashmem_regions_|.
-  DCHECK_LE(ashmem_regions_.size(), 5U);
-  const ScopedVector<AshmemRegion>::iterator it = std::find(
-      ashmem_regions_.begin(), ashmem_regions_.end(), region);
-  DCHECK(ashmem_regions_.end() != it);
-  std::swap(*it, ashmem_regions_.back());
-  ashmem_regions_.pop_back();
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/memory/discardable_memory_ashmem_allocator.h b/base/memory/discardable_memory_ashmem_allocator.h
deleted file mode 100644
index 996dde9..0000000
--- a/base/memory/discardable_memory_ashmem_allocator.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/synchronization/lock.h"
-
-namespace base {
-namespace internal {
-
-class AshmemRegion;
-
-// Internal class, whose instances are returned to the client of the allocator
-// (e.g. DiscardableMemoryAshmem), that mimicks the DiscardableMemory interface.
-class BASE_EXPORT_PRIVATE DiscardableAshmemChunk {
- public:
-  ~DiscardableAshmemChunk();
-
-  // Returns whether the memory is still resident.
-  bool Lock();
-
-  void Unlock();
-
-  void* Memory() const;
-
- private:
-  friend class AshmemRegion;
-
-  DiscardableAshmemChunk(AshmemRegion* ashmem_region,
-                         int fd,
-                         void* address,
-                         size_t offset,
-                         size_t size);
-
-  AshmemRegion* const ashmem_region_;
-  const int fd_;
-  void* const address_;
-  const size_t offset_;
-  const size_t size_;
-  bool locked_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiscardableAshmemChunk);
-};
-
-// Ashmem regions are backed by a file (descriptor) therefore they are a limited
-// resource. This allocator minimizes the problem by allocating large ashmem
-// regions internally and returning smaller chunks to the client.
-// Allocated chunks are systematically aligned on a page boundary therefore this
-// allocator should not be used for small allocations.
-class BASE_EXPORT_PRIVATE DiscardableMemoryAshmemAllocator {
- public:
-  // Note that |name| is only used for debugging/measurement purposes.
-  // |ashmem_region_size| is the size that will be used to create the underlying
-  // ashmem regions and is expected to be greater or equal than 32 MBytes.
-  DiscardableMemoryAshmemAllocator(const std::string& name,
-                                   size_t ashmem_region_size);
-
-  ~DiscardableMemoryAshmemAllocator();
-
-  // Note that the allocator must outlive the returned DiscardableAshmemChunk
-  // instance.
-  scoped_ptr<DiscardableAshmemChunk> Allocate(size_t size);
-
-  // Returns the size of the last ashmem region which was created. This is used
-  // for testing only.
-  size_t last_ashmem_region_size() const;
-
- private:
-  friend class AshmemRegion;
-
-  void DeleteAshmemRegion_Locked(AshmemRegion* region);
-
-  const std::string name_;
-  const size_t ashmem_region_size_;
-  mutable Lock lock_;
-  size_t last_ashmem_region_size_;
-  ScopedVector<AshmemRegion> ashmem_regions_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryAshmemAllocator);
-};
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_
diff --git a/base/memory/discardable_memory_ashmem_allocator_unittest.cc b/base/memory/discardable_memory_ashmem_allocator_unittest.cc
deleted file mode 100644
index e9f63ba..0000000
--- a/base/memory/discardable_memory_ashmem_allocator_unittest.cc
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_ashmem_allocator.h"
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/memory/discardable_memory.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-const char kAllocatorName[] = "allocator-for-testing";
-
-const size_t kAshmemRegionSizeForTesting = 32 * 1024 * 1024;
-const size_t kPageSize = 4096;
-
-const size_t kMaxAllowedAllocationSize =
-    std::numeric_limits<size_t>::max() - kPageSize + 1;
-
-class DiscardableMemoryAshmemAllocatorTest : public testing::Test {
- protected:
-  DiscardableMemoryAshmemAllocatorTest()
-      : allocator_(kAllocatorName, kAshmemRegionSizeForTesting) {
-  }
-
-  DiscardableMemoryAshmemAllocator allocator_;
-};
-
-void WriteToDiscardableAshmemChunk(DiscardableAshmemChunk* memory,
-                                   size_t size) {
-  // Write to the first and the last pages only to avoid paging in up to 64
-  // MBytes.
-  static_cast<char*>(memory->Memory())[0] = 'a';
-  static_cast<char*>(memory->Memory())[size - 1] = 'a';
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, Basic) {
-  const size_t size = 128;
-  scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(size));
-  ASSERT_TRUE(memory);
-  WriteToDiscardableAshmemChunk(memory.get(), size);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, ZeroAllocationIsNotSupported) {
-  scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(0));
-  ASSERT_FALSE(memory);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, TooLargeAllocationFails) {
-  scoped_ptr<DiscardableAshmemChunk> memory(
-      allocator_.Allocate(kMaxAllowedAllocationSize + 1));
-  // Page-alignment would have caused an overflow resulting in a small
-  // allocation if the input size wasn't checked correctly.
-  ASSERT_FALSE(memory);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest,
-       AshmemRegionsAreNotSmallerThanRequestedSize) {
-  // The creation of the underlying ashmem region is expected to fail since
-  // there should not be enough room in the address space. When ashmem creation
-  // fails, the allocator repetitively retries by dividing the size by 2. This
-  // size should not be smaller than the size the user requested so the
-  // allocation here should just fail (and not succeed with the minimum ashmem
-  // region size).
-  scoped_ptr<DiscardableAshmemChunk> memory(
-      allocator_.Allocate(kMaxAllowedAllocationSize));
-  ASSERT_FALSE(memory);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest,
-       AshmemRegionsAreAlwaysPageAligned) {
-  // Use a separate allocator here so that we can override the ashmem region
-  // size.
-  DiscardableMemoryAshmemAllocator allocator(
-      kAllocatorName, kMaxAllowedAllocationSize);
-  scoped_ptr<DiscardableAshmemChunk> memory(allocator.Allocate(kPageSize));
-  ASSERT_TRUE(memory);
-  EXPECT_GT(kMaxAllowedAllocationSize, allocator.last_ashmem_region_size());
-  ASSERT_TRUE(allocator.last_ashmem_region_size() % kPageSize == 0);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, LargeAllocation) {
-  const size_t size = 64 * 1024 * 1024;
-  scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(size));
-  ASSERT_TRUE(memory);
-  WriteToDiscardableAshmemChunk(memory.get(), size);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, ChunksArePageAligned) {
-  scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory);
-  EXPECT_EQ(0U, reinterpret_cast<uint64_t>(memory->Memory()) % kPageSize);
-  WriteToDiscardableAshmemChunk(memory.get(), kPageSize);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, AllocateFreeAllocate) {
-  scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(kPageSize));
-  // Extra allocation that prevents the region from being deleted when |memory|
-  // gets deleted.
-  scoped_ptr<DiscardableAshmemChunk> memory_lock(
-      allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory);
-  void* const address = memory->Memory();
-  memory->Unlock();  // Tests that the reused chunk is being locked correctly.
-  memory.reset();
-  memory = allocator_.Allocate(kPageSize);
-  ASSERT_TRUE(memory);
-  // The previously freed chunk should be reused.
-  EXPECT_EQ(address, memory->Memory());
-  WriteToDiscardableAshmemChunk(memory.get(), kPageSize);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest,
-       FreeingWholeAshmemRegionClosesAshmem) {
-  scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory);
-  const int kMagic = 0xdeadbeef;
-  *static_cast<int*>(memory->Memory()) = kMagic;
-  memory.reset();
-  // The previous ashmem region should have been closed thus it should not be
-  // reused.
-  memory = allocator_.Allocate(kPageSize);
-  ASSERT_TRUE(memory);
-  EXPECT_NE(kMagic, *static_cast<const int*>(memory->Memory()));
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, AllocateUsesBestFitAlgorithm) {
-  scoped_ptr<DiscardableAshmemChunk> memory1(
-      allocator_.Allocate(3 * kPageSize));
-  ASSERT_TRUE(memory1);
-  scoped_ptr<DiscardableAshmemChunk> memory2(
-      allocator_.Allocate(2 * kPageSize));
-  ASSERT_TRUE(memory2);
-  scoped_ptr<DiscardableAshmemChunk> memory3(
-      allocator_.Allocate(1 * kPageSize));
-  ASSERT_TRUE(memory3);
-  void* const address_3 = memory3->Memory();
-  memory1.reset();
-  // Don't free |memory2| to avoid merging the 3 blocks together.
-  memory3.reset();
-  memory1 = allocator_.Allocate(1 * kPageSize);
-  ASSERT_TRUE(memory1);
-  // The chunk whose size is closest to the requested size should be reused.
-  EXPECT_EQ(address_3, memory1->Memory());
-  WriteToDiscardableAshmemChunk(memory1.get(), kPageSize);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, MergeFreeChunks) {
-  scoped_ptr<DiscardableAshmemChunk> memory1(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory1);
-  scoped_ptr<DiscardableAshmemChunk> memory2(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory2);
-  scoped_ptr<DiscardableAshmemChunk> memory3(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory3);
-  scoped_ptr<DiscardableAshmemChunk> memory4(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory4);
-  void* const memory1_address = memory1->Memory();
-  memory1.reset();
-  memory3.reset();
-  // Freeing |memory2| (located between memory1 and memory3) should merge the
-  // three free blocks together.
-  memory2.reset();
-  memory1 = allocator_.Allocate(3 * kPageSize);
-  EXPECT_EQ(memory1_address, memory1->Memory());
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, MergeFreeChunksAdvanced) {
-  scoped_ptr<DiscardableAshmemChunk> memory1(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory1);
-  scoped_ptr<DiscardableAshmemChunk> memory2(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory2);
-  void* const memory1_address = memory1->Memory();
-  memory1.reset();
-  memory1 = allocator_.Allocate(2 * kPageSize);
-  memory2.reset();
-  // At this point, the region should be in this state:
-  // 8 KBytes (used), 24 KBytes (free).
-  memory2 = allocator_.Allocate(6 * kPageSize);
-  EXPECT_EQ(
-      static_cast<const char*>(memory2->Memory()),
-      static_cast<const char*>(memory1_address) + 2 * kPageSize);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, MergeFreeChunksAdvanced2) {
-  scoped_ptr<DiscardableAshmemChunk> memory1(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory1);
-  scoped_ptr<DiscardableAshmemChunk> memory2(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory2);
-  void* const memory1_address = memory1->Memory();
-  memory1.reset();
-  memory1 = allocator_.Allocate(2 * kPageSize);
-  scoped_ptr<DiscardableAshmemChunk> memory3(
-      allocator_.Allocate(2 * kPageSize));
-  // At this point, the region should be in this state:
-  // 8 KBytes (used), 8 KBytes (used), 16 KBytes (used).
-  memory3.reset();
-  memory2.reset();
-  // At this point, the region should be in this state:
-  // 8 KBytes (used), 24 KBytes (free).
-  memory2 = allocator_.Allocate(6 * kPageSize);
-  EXPECT_EQ(
-      static_cast<const char*>(memory2->Memory()),
-      static_cast<const char*>(memory1_address) + 2 * kPageSize);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest,
-       MergeFreeChunksAndDeleteAshmemRegion) {
-  scoped_ptr<DiscardableAshmemChunk> memory1(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory1);
-  scoped_ptr<DiscardableAshmemChunk> memory2(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory2);
-  memory1.reset();
-  memory1 = allocator_.Allocate(2 * kPageSize);
-  scoped_ptr<DiscardableAshmemChunk> memory3(
-      allocator_.Allocate(2 * kPageSize));
-  // At this point, the region should be in this state:
-  // 8 KBytes (used), 8 KBytes (used), 16 KBytes (used).
-  memory1.reset();
-  memory3.reset();
-  // At this point, the region should be in this state:
-  // 8 KBytes (free), 8 KBytes (used), 8 KBytes (free).
-  const int kMagic = 0xdeadbeef;
-  *static_cast<int*>(memory2->Memory()) = kMagic;
-  memory2.reset();
-  // The whole region should have been deleted.
-  memory2 = allocator_.Allocate(2 * kPageSize);
-  EXPECT_NE(kMagic, *static_cast<int*>(memory2->Memory()));
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest,
-     TooLargeFreeChunksDontCauseTooMuchFragmentationWhenRecycled) {
-  // Keep |memory_1| below allocated so that the ashmem region doesn't get
-  // closed when |memory_2| is deleted.
-  scoped_ptr<DiscardableAshmemChunk> memory_1(allocator_.Allocate(64 * 1024));
-  ASSERT_TRUE(memory_1);
-  scoped_ptr<DiscardableAshmemChunk> memory_2(allocator_.Allocate(32 * 1024));
-  ASSERT_TRUE(memory_2);
-  void* const address = memory_2->Memory();
-  memory_2.reset();
-  const size_t size = 16 * 1024;
-  memory_2 = allocator_.Allocate(size);
-  ASSERT_TRUE(memory_2);
-  EXPECT_EQ(address, memory_2->Memory());
-  WriteToDiscardableAshmemChunk(memory_2.get(), size);
-  scoped_ptr<DiscardableAshmemChunk> memory_3(allocator_.Allocate(size));
-  // The unused tail (16 KBytes large) of the previously freed chunk should be
-  // reused.
-  EXPECT_EQ(static_cast<char*>(address) + size, memory_3->Memory());
-  WriteToDiscardableAshmemChunk(memory_3.get(), size);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest, UseMultipleAshmemRegions) {
-  // Leave one page untouched at the end of the ashmem region.
-  const size_t size = kAshmemRegionSizeForTesting - kPageSize;
-  scoped_ptr<DiscardableAshmemChunk> memory1(allocator_.Allocate(size));
-  ASSERT_TRUE(memory1);
-  WriteToDiscardableAshmemChunk(memory1.get(), size);
-
-  scoped_ptr<DiscardableAshmemChunk> memory2(
-      allocator_.Allocate(kAshmemRegionSizeForTesting));
-  ASSERT_TRUE(memory2);
-  WriteToDiscardableAshmemChunk(memory2.get(), kAshmemRegionSizeForTesting);
-  // The last page of the first ashmem region should be used for this
-  // allocation.
-  scoped_ptr<DiscardableAshmemChunk> memory3(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory3);
-  WriteToDiscardableAshmemChunk(memory3.get(), kPageSize);
-  EXPECT_EQ(memory3->Memory(), static_cast<char*>(memory1->Memory()) + size);
-}
-
-TEST_F(DiscardableMemoryAshmemAllocatorTest,
-       HighestAllocatedChunkPointerIsUpdatedWhenHighestChunkGetsSplit) {
-  // Prevents the ashmem region from getting closed when |memory2| gets freed.
-  scoped_ptr<DiscardableAshmemChunk> memory1(allocator_.Allocate(kPageSize));
-  ASSERT_TRUE(memory1);
-
-  scoped_ptr<DiscardableAshmemChunk> memory2(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory2);
-
-  memory2.reset();
-  memory2 = allocator_.Allocate(kPageSize);
-  // There should now be a free chunk of size 3 * |kPageSize| starting at offset
-  // 2 * |kPageSize| and the pointer to the highest allocated chunk should have
-  // also been updated to |base_| + 2 * |kPageSize|. This pointer is used to
-  // maintain the container mapping a chunk address to its previous chunk and
-  // this map is in turn used while merging previous contiguous chunks.
-
-  // Allocate more than 3 * |kPageSize| so that the free chunk of size 3 *
-  // |kPageSize| is not reused and |highest_allocated_chunk_| gets used instead.
-  scoped_ptr<DiscardableAshmemChunk> memory3(
-      allocator_.Allocate(4 * kPageSize));
-  ASSERT_TRUE(memory3);
-
-  // Deleting |memory3| (whose size is 4 * |kPageSize|) should result in a merge
-  // with its previous chunk which is the free chunk of size |3 * kPageSize|.
-  memory3.reset();
-  memory3 = allocator_.Allocate((3 + 4) * kPageSize);
-  EXPECT_EQ(memory3->Memory(),
-            static_cast<const char*>(memory2->Memory()) + kPageSize);
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/memory/discardable_memory_emulated.cc b/base/memory/discardable_memory_emulated.cc
deleted file mode 100644
index b12d7ce..0000000
--- a/base/memory/discardable_memory_emulated.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_emulated.h"
-
-#include "base/lazy_instance.h"
-#include "base/memory/discardable_memory_manager.h"
-
-namespace base {
-namespace {
-
-// This is admittedly pretty magical.
-const size_t kEmulatedMemoryLimit = 512 * 1024 * 1024;
-const size_t kEmulatedSoftMemoryLimit = 32 * 1024 * 1024;
-const size_t kEmulatedHardMemoryLimitExpirationTimeMs = 1000;
-
-// 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(
-        kEmulatedMemoryLimit,
-        kEmulatedSoftMemoryLimit,
-        TimeDelta::FromMilliseconds(kEmulatedHardMemoryLimitExpirationTimeMs));
-  }
-  static void Delete(internal::DiscardableMemoryManager* instance) {
-    instance->~DiscardableMemoryManager();
-  }
-};
-
-LazyInstance<internal::DiscardableMemoryManager,
-             DiscardableMemoryManagerLazyInstanceTraits>
-    g_manager = LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-namespace internal {
-
-DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t bytes)
-    : bytes_(bytes),
-      is_locked_(false) {
-  g_manager.Pointer()->Register(this, bytes);
-}
-
-DiscardableMemoryEmulated::~DiscardableMemoryEmulated() {
-  if (is_locked_)
-    Unlock();
-  g_manager.Pointer()->Unregister(this);
-}
-
-// static
-bool DiscardableMemoryEmulated::ReduceMemoryUsage() {
-  return g_manager.Pointer()->ReduceMemoryUsage();
-}
-
-// static
-void DiscardableMemoryEmulated::ReduceMemoryUsageUntilWithinLimit(
-    size_t bytes) {
-  g_manager.Pointer()->ReduceMemoryUsageUntilWithinLimit(bytes);
-}
-
-bool DiscardableMemoryEmulated::Initialize() {
-  return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-}
-
-DiscardableMemoryLockStatus DiscardableMemoryEmulated::Lock() {
-  DCHECK(!is_locked_);
-
-  bool purged = false;
-  if (!g_manager.Pointer()->AcquireLock(this, &purged))
-    return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-
-  is_locked_ = true;
-  return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
-                : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
-}
-
-void DiscardableMemoryEmulated::Unlock() {
-  DCHECK(is_locked_);
-  g_manager.Pointer()->ReleaseLock(this);
-  is_locked_ = false;
-}
-
-void* DiscardableMemoryEmulated::Memory() const {
-  DCHECK(is_locked_);
-  DCHECK(memory_);
-  return memory_.get();
-}
-
-bool DiscardableMemoryEmulated::AllocateAndAcquireLock() {
-  if (memory_)
-    return true;
-
-  memory_.reset(new uint8[bytes_]);
-  return false;
-}
-
-void DiscardableMemoryEmulated::Purge() {
-  memory_.reset();
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/memory/discardable_memory_emulated.h b/base/memory/discardable_memory_emulated.h
deleted file mode 100644
index aa01a9d..0000000
--- a/base/memory/discardable_memory_emulated.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_EMULATED_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_EMULATED_H_
-
-#include "base/memory/discardable_memory.h"
-
-#include "base/memory/discardable_memory_manager.h"
-
-namespace base {
-namespace internal {
-
-class DiscardableMemoryEmulated
-    : public DiscardableMemory,
-      public internal::DiscardableMemoryManagerAllocation {
- public:
-  explicit DiscardableMemoryEmulated(size_t bytes);
-  ~DiscardableMemoryEmulated() override;
-
-  static bool ReduceMemoryUsage();
-
-  // TODO(reveman): Remove this as it is breaking the discardable memory design
-  // principle that implementations should not rely on information this is
-  // unavailable in kernel space. crbug.com/400423
-  BASE_EXPORT static void ReduceMemoryUsageUntilWithinLimit(size_t bytes);
-
-  bool Initialize();
-
-  // Overridden from DiscardableMemory:
-  DiscardableMemoryLockStatus Lock() override;
-  void Unlock() override;
-  void* Memory() const override;
-
-  // Overridden from internal::DiscardableMemoryManagerAllocation:
-  bool AllocateAndAcquireLock() override;
-  void ReleaseLock() override {}
-  void Purge() override;
-
- private:
-  const size_t bytes_;
-  scoped_ptr<uint8[]> memory_;
-  bool is_locked_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryEmulated);
-};
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_EMULATED_H_
diff --git a/base/memory/discardable_memory_linux.cc b/base/memory/discardable_memory_linux.cc
index 670ad7e..b394e07 100644
--- a/base/memory/discardable_memory_linux.cc
+++ b/base/memory/discardable_memory_linux.cc
@@ -5,22 +5,15 @@
 #include "base/memory/discardable_memory.h"
 
 #include "base/logging.h"
-#include "base/memory/discardable_memory_emulated.h"
 #include "base/memory/discardable_memory_shmem.h"
 
 namespace base {
 
 // static
-bool DiscardableMemory::ReduceMemoryUsage() {
-  return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
-}
-
-// static
 void DiscardableMemory::GetSupportedTypes(
     std::vector<DiscardableMemoryType>* types) {
   const DiscardableMemoryType supported_types[] = {
-    DISCARDABLE_MEMORY_TYPE_SHMEM,
-    DISCARDABLE_MEMORY_TYPE_EMULATED
+    DISCARDABLE_MEMORY_TYPE_SHMEM
   };
   types->assign(supported_types, supported_types + arraysize(supported_types));
 }
@@ -29,25 +22,9 @@
 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType(
     DiscardableMemoryType type, size_t size) {
   switch (type) {
-    case DISCARDABLE_MEMORY_TYPE_EMULATED: {
-      scoped_ptr<internal::DiscardableMemoryEmulated> memory(
-          new internal::DiscardableMemoryEmulated(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
-    case DISCARDABLE_MEMORY_TYPE_SHMEM: {
-      scoped_ptr<internal::DiscardableMemoryShmem> memory(
-          new internal::DiscardableMemoryShmem(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
+    case DISCARDABLE_MEMORY_TYPE_SHMEM:
+      return make_scoped_ptr(new internal::DiscardableMemoryShmem(size));
     case DISCARDABLE_MEMORY_TYPE_NONE:
-    case DISCARDABLE_MEMORY_TYPE_ASHMEM:
-    case DISCARDABLE_MEMORY_TYPE_MACH:
       NOTREACHED();
       return nullptr;
   }
diff --git a/base/memory/discardable_memory_mac.cc b/base/memory/discardable_memory_mac.cc
index 2881f5e..d7e6345 100644
--- a/base/memory/discardable_memory_mac.cc
+++ b/base/memory/discardable_memory_mac.cc
@@ -5,26 +5,16 @@
 #include "base/memory/discardable_memory.h"
 
 #include "base/logging.h"
-#include "base/memory/discardable_memory_emulated.h"
-#include "base/memory/discardable_memory_mach.h"
-#include "base/memory/discardable_memory_manager.h"
 #include "base/memory/discardable_memory_shmem.h"
 #include "base/memory/scoped_ptr.h"
 
 namespace base {
 
 // static
-bool DiscardableMemory::ReduceMemoryUsage() {
-  return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
-}
-
-// static
 void DiscardableMemory::GetSupportedTypes(
     std::vector<DiscardableMemoryType>* types) {
   const DiscardableMemoryType supported_types[] = {
-    DISCARDABLE_MEMORY_TYPE_SHMEM,
-    DISCARDABLE_MEMORY_TYPE_MACH,
-    DISCARDABLE_MEMORY_TYPE_EMULATED
+    DISCARDABLE_MEMORY_TYPE_SHMEM
   };
   types->assign(supported_types, supported_types + arraysize(supported_types));
 }
@@ -33,32 +23,9 @@
 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType(
     DiscardableMemoryType type, size_t size) {
   switch (type) {
-    case DISCARDABLE_MEMORY_TYPE_MACH: {
-      scoped_ptr<internal::DiscardableMemoryMach> memory(
-          new internal::DiscardableMemoryMach(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
-    case DISCARDABLE_MEMORY_TYPE_EMULATED: {
-      scoped_ptr<internal::DiscardableMemoryEmulated> memory(
-          new internal::DiscardableMemoryEmulated(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
-    case DISCARDABLE_MEMORY_TYPE_SHMEM: {
-      scoped_ptr<internal::DiscardableMemoryShmem> memory(
-          new internal::DiscardableMemoryShmem(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
+    case DISCARDABLE_MEMORY_TYPE_SHMEM:
+      return make_scoped_ptr(new internal::DiscardableMemoryShmem(size));
     case DISCARDABLE_MEMORY_TYPE_NONE:
-    case DISCARDABLE_MEMORY_TYPE_ASHMEM:
       NOTREACHED();
       return nullptr;
   }
diff --git a/base/memory/discardable_memory_mach.cc b/base/memory/discardable_memory_mach.cc
deleted file mode 100644
index d96de79..0000000
--- a/base/memory/discardable_memory_mach.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_mach.h"
-
-#include <mach/mach.h>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/mac/mach_logging.h"
-
-namespace base {
-namespace {
-
-// For Mach, have the DiscardableMemoryManager trigger userspace eviction when
-// address space usage gets too high (e.g. 512 MBytes).
-const size_t kMachMemoryLimit = 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(
-        kMachMemoryLimit, kMachMemoryLimit, TimeDelta::Max());
-  }
-  static void Delete(internal::DiscardableMemoryManager* instance) {
-    instance->~DiscardableMemoryManager();
-  }
-};
-
-LazyInstance<internal::DiscardableMemoryManager,
-             DiscardableMemoryManagerLazyInstanceTraits>
-    g_manager = LAZY_INSTANCE_INITIALIZER;
-
-// The VM subsystem allows tagging of memory and 240-255 is reserved for
-// application use (see mach/vm_statistics.h). Pick 252 (after chromium's atomic
-// weight of ~52).
-const int kDiscardableMemoryTag = VM_MAKE_TAG(252);
-
-}  // namespace
-
-namespace internal {
-
-DiscardableMemoryMach::DiscardableMemoryMach(size_t bytes)
-    : memory_(0, 0), bytes_(mach_vm_round_page(bytes)), is_locked_(false) {
-  g_manager.Pointer()->Register(this, bytes);
-}
-
-DiscardableMemoryMach::~DiscardableMemoryMach() {
-  if (is_locked_)
-    Unlock();
-  g_manager.Pointer()->Unregister(this);
-}
-
-bool DiscardableMemoryMach::Initialize() {
-  return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-}
-
-DiscardableMemoryLockStatus DiscardableMemoryMach::Lock() {
-  DCHECK(!is_locked_);
-
-  bool purged = false;
-  if (!g_manager.Pointer()->AcquireLock(this, &purged))
-    return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-
-  is_locked_ = true;
-  return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
-                : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
-}
-
-void DiscardableMemoryMach::Unlock() {
-  DCHECK(is_locked_);
-  g_manager.Pointer()->ReleaseLock(this);
-  is_locked_ = false;
-}
-
-void* DiscardableMemoryMach::Memory() const {
-  DCHECK(is_locked_);
-  return reinterpret_cast<void*>(memory_.address());
-}
-
-bool DiscardableMemoryMach::AllocateAndAcquireLock() {
-  kern_return_t ret;
-  bool persistent;
-  if (!memory_.size()) {
-    vm_address_t address = 0;
-    ret = vm_allocate(
-        mach_task_self(),
-        &address,
-        bytes_,
-        VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE | kDiscardableMemoryTag);
-    MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_allocate";
-    memory_.reset(address, bytes_);
-
-    // When making a fresh allocation, it's impossible for |persistent| to
-    // be true.
-    persistent = false;
-  } else {
-    // |persistent| will be reset to false below if appropriate, but when
-    // reusing an existing allocation, it's possible for it to be true.
-    persistent = true;
-
-#if !defined(NDEBUG)
-    ret = vm_protect(mach_task_self(),
-                     memory_.address(),
-                     memory_.size(),
-                     FALSE,
-                     VM_PROT_DEFAULT);
-    MACH_DCHECK(ret == KERN_SUCCESS, ret) << "vm_protect";
-#endif
-  }
-
-  int state = VM_PURGABLE_NONVOLATILE;
-  ret = vm_purgable_control(
-      mach_task_self(), memory_.address(), VM_PURGABLE_SET_STATE, &state);
-  MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_purgable_control";
-  if (state & VM_PURGABLE_EMPTY)
-    persistent = false;
-
-  return persistent;
-}
-
-void DiscardableMemoryMach::ReleaseLock() {
-  int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
-  kern_return_t ret = vm_purgable_control(
-      mach_task_self(), memory_.address(), VM_PURGABLE_SET_STATE, &state);
-  MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_purgable_control";
-
-#if !defined(NDEBUG)
-  ret = vm_protect(
-      mach_task_self(), memory_.address(), memory_.size(), FALSE, VM_PROT_NONE);
-  MACH_DCHECK(ret == KERN_SUCCESS, ret) << "vm_protect";
-#endif
-}
-
-void DiscardableMemoryMach::Purge() {
-  memory_.reset();
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/memory/discardable_memory_mach.h b/base/memory/discardable_memory_mach.h
deleted file mode 100644
index b3b4b48..0000000
--- a/base/memory/discardable_memory_mach.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_MACH_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_MACH_H_
-
-#include "base/memory/discardable_memory.h"
-
-#include "base/mac/scoped_mach_vm.h"
-#include "base/memory/discardable_memory_manager.h"
-
-namespace base {
-namespace internal {
-
-class DiscardableMemoryMach
-    : public DiscardableMemory,
-      public internal::DiscardableMemoryManagerAllocation {
- public:
-  explicit DiscardableMemoryMach(size_t bytes);
-  ~DiscardableMemoryMach() override;
-
-  bool Initialize();
-
-  // Overridden from DiscardableMemory:
-  DiscardableMemoryLockStatus Lock() override;
-  void Unlock() override;
-  void* Memory() const override;
-
-  // Overridden from internal::DiscardableMemoryManagerAllocation:
-  bool AllocateAndAcquireLock() override;
-  void ReleaseLock() override;
-  void Purge() override;
-
- private:
-  mac::ScopedMachVM memory_;
-  const size_t bytes_;
-  bool is_locked_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMach);
-};
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_MACH_H_
diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc
deleted file mode 100644
index cbbdb47..0000000
--- a/base/memory/discardable_memory_manager.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_manager.h"
-
-#include "base/bind.h"
-#include "base/containers/adapters.h"
-#include "base/containers/hash_tables.h"
-#include "base/containers/mru_cache.h"
-#include "base/debug/crash_logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace internal {
-
-DiscardableMemoryManager::DiscardableMemoryManager(
-    size_t memory_limit,
-    size_t soft_memory_limit,
-    TimeDelta hard_memory_limit_expiration_time)
-    : allocations_(AllocationMap::NO_AUTO_EVICT),
-      bytes_allocated_(0u),
-      memory_limit_(memory_limit),
-      soft_memory_limit_(soft_memory_limit),
-      hard_memory_limit_expiration_time_(hard_memory_limit_expiration_time) {
-  BytesAllocatedChanged(bytes_allocated_);
-}
-
-DiscardableMemoryManager::~DiscardableMemoryManager() {
-  DCHECK(allocations_.empty());
-  DCHECK_EQ(0u, bytes_allocated_);
-}
-
-void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) {
-  AutoLock lock(lock_);
-  memory_limit_ = bytes;
-  PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(
-      Now(), memory_limit_);
-}
-
-void DiscardableMemoryManager::SetSoftMemoryLimit(size_t bytes) {
-  AutoLock lock(lock_);
-  soft_memory_limit_ = bytes;
-}
-
-void DiscardableMemoryManager::SetHardMemoryLimitExpirationTime(
-    TimeDelta hard_memory_limit_expiration_time) {
-  AutoLock lock(lock_);
-  hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time;
-}
-
-bool DiscardableMemoryManager::ReduceMemoryUsage() {
-  return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit();
-}
-
-void DiscardableMemoryManager::ReduceMemoryUsageUntilWithinLimit(size_t bytes) {
-  AutoLock lock(lock_);
-  PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(),
-                                                                      bytes);
-}
-
-void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) {
-  AutoLock lock(lock_);
-  DCHECK(allocations_.Peek(allocation) == allocations_.end());
-  allocations_.Put(allocation, AllocationInfo(bytes));
-}
-
-void DiscardableMemoryManager::Unregister(Allocation* allocation) {
-  AutoLock lock(lock_);
-  AllocationMap::iterator it = allocations_.Peek(allocation);
-  DCHECK(it != allocations_.end());
-  const AllocationInfo& info = it->second;
-
-  if (info.purgable) {
-    size_t bytes_purgable = info.bytes;
-    DCHECK_LE(bytes_purgable, bytes_allocated_);
-    bytes_allocated_ -= bytes_purgable;
-    BytesAllocatedChanged(bytes_allocated_);
-  }
-  allocations_.Erase(it);
-}
-
-bool DiscardableMemoryManager::AcquireLock(Allocation* allocation,
-                                           bool* purged) {
-  AutoLock lock(lock_);
-  // Note: |allocations_| is an MRU cache, and use of |Get| here updates that
-  // cache.
-  AllocationMap::iterator it = allocations_.Get(allocation);
-  DCHECK(it != allocations_.end());
-  AllocationInfo* info = &it->second;
-
-  if (!info->bytes)
-    return false;
-
-  TimeTicks now = Now();
-  size_t bytes_required = info->purgable ? 0u : info->bytes;
-
-  if (memory_limit_) {
-    size_t limit = 0;
-    if (bytes_required < memory_limit_)
-      limit = memory_limit_ - bytes_required;
-
-    PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(now,
-                                                                        limit);
-  }
-
-  // Check for overflow.
-  if (std::numeric_limits<size_t>::max() - bytes_required < bytes_allocated_)
-    return false;
-
-  *purged = !allocation->AllocateAndAcquireLock();
-  info->purgable = false;
-  info->last_usage = now;
-  if (bytes_required) {
-    bytes_allocated_ += bytes_required;
-    BytesAllocatedChanged(bytes_allocated_);
-  }
-  return true;
-}
-
-void DiscardableMemoryManager::ReleaseLock(Allocation* allocation) {
-  AutoLock lock(lock_);
-  // Note: |allocations_| is an MRU cache, and use of |Get| here updates that
-  // cache.
-  AllocationMap::iterator it = allocations_.Get(allocation);
-  DCHECK(it != allocations_.end());
-  AllocationInfo* info = &it->second;
-
-  TimeTicks now = Now();
-  allocation->ReleaseLock();
-  info->purgable = true;
-  info->last_usage = now;
-
-  PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(
-      now, memory_limit_);
-}
-
-void DiscardableMemoryManager::PurgeAll() {
-  AutoLock lock(lock_);
-  PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(), 0);
-}
-
-bool DiscardableMemoryManager::IsRegisteredForTest(
-    Allocation* allocation) const {
-  AutoLock lock(lock_);
-  AllocationMap::const_iterator it = allocations_.Peek(allocation);
-  return it != allocations_.end();
-}
-
-bool DiscardableMemoryManager::CanBePurgedForTest(
-    Allocation* allocation) const {
-  AutoLock lock(lock_);
-  AllocationMap::const_iterator it = allocations_.Peek(allocation);
-  return it != allocations_.end() && it->second.purgable;
-}
-
-size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const {
-  AutoLock lock(lock_);
-  return bytes_allocated_;
-}
-
-bool DiscardableMemoryManager::
-    PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit() {
-  AutoLock lock(lock_);
-
-  PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(
-      Now() - hard_memory_limit_expiration_time_, soft_memory_limit_);
-
-  return bytes_allocated_ <= soft_memory_limit_;
-}
-
-void DiscardableMemoryManager::
-    PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(
-        TimeTicks timestamp,
-        size_t limit) {
-  lock_.AssertAcquired();
-
-  size_t bytes_allocated_before_purging = bytes_allocated_;
-  for (auto& entry : base::Reversed(allocations_)) {
-    Allocation* allocation = entry.first;
-    AllocationInfo* info = &entry.second;
-
-    if (bytes_allocated_ <= limit)
-      break;
-
-    bool purgable = info->purgable && info->last_usage <= timestamp;
-    if (!purgable)
-      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_purging)
-    BytesAllocatedChanged(bytes_allocated_);
-}
-
-void DiscardableMemoryManager::BytesAllocatedChanged(
-    size_t new_bytes_allocated) const {
-  TRACE_COUNTER_ID1(
-      "base", "DiscardableMemoryUsage", this, new_bytes_allocated);
-
-  static const char kDiscardableMemoryUsageKey[] = "dm-usage";
-  base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey,
-                                Uint64ToString(new_bytes_allocated));
-}
-
-TimeTicks DiscardableMemoryManager::Now() const {
-  return TimeTicks::Now();
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/memory/discardable_memory_manager.h b/base/memory/discardable_memory_manager.h
deleted file mode 100644
index 43737f8..0000000
--- a/base/memory/discardable_memory_manager.h
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_
-
-#include "base/base_export.h"
-#include "base/containers/hash_tables.h"
-#include "base/containers/mru_cache.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-
-namespace base {
-namespace internal {
-
-// This interface is used by the DiscardableMemoryManager class to provide some
-// level of userspace control over discardable memory allocations.
-class DiscardableMemoryManagerAllocation {
- public:
-  // Allocate and acquire a lock that prevents the allocation from being purged
-  // by the system. Returns true if memory was previously allocated and is still
-  // resident.
-  virtual bool AllocateAndAcquireLock() = 0;
-
-  // Release a previously acquired lock on the allocation so that it can be
-  // purged by the system.
-  virtual void ReleaseLock() = 0;
-
-  // Explicitly purge this allocation. It is illegal to call this while a lock
-  // is acquired on the allocation.
-  virtual void Purge() = 0;
-
- protected:
-  virtual ~DiscardableMemoryManagerAllocation() {}
-};
-
-}  // namespace internal
-}  // namespace base
-
-namespace base {
-namespace internal {
-
-// The DiscardableMemoryManager manages a collection of
-// DiscardableMemoryManagerAllocation instances. It is used on platforms that
-// need some level of userspace control over discardable memory. It keeps track
-// of all allocation instances (in case they need to be purged), and the total
-// amount of allocated memory (in case this forces a purge). When memory usage
-// reaches the limit, the manager purges the LRU memory.
-class BASE_EXPORT_PRIVATE DiscardableMemoryManager {
- public:
-  typedef DiscardableMemoryManagerAllocation Allocation;
-
-  DiscardableMemoryManager(size_t memory_limit,
-                           size_t soft_memory_limit,
-                           TimeDelta hard_memory_limit_expiration_time);
-  virtual ~DiscardableMemoryManager();
-
-  // The maximum number of bytes of memory that may be allocated before we force
-  // a purge.
-  void SetMemoryLimit(size_t bytes);
-
-  // The number of bytes of memory that may be allocated but unused for the hard
-  // limit expiration time without getting purged.
-  void SetSoftMemoryLimit(size_t bytes);
-
-  // Sets the memory usage cutoff time for hard memory limit.
-  void SetHardMemoryLimitExpirationTime(
-      TimeDelta hard_memory_limit_expiration_time);
-
-  // 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.
-  bool ReduceMemoryUsage();
-
-  // This can be called to attempt to reduce memory footprint until within
-  // limit for bytes to keep under moderate pressure.
-  void ReduceMemoryUsageUntilWithinLimit(size_t bytes);
-
-  // Adds the given allocation to the manager's collection.
-  void Register(Allocation* allocation, size_t bytes);
-
-  // Removes the given allocation from the manager's collection.
-  void Unregister(Allocation* allocation);
-
-  // Returns false if an error occurred. Otherwise, returns true and sets
-  // |purged| to indicate whether or not allocation has been purged since last
-  // use.
-  bool AcquireLock(Allocation* allocation, bool* purged);
-
-  // Release a previously acquired lock on allocation. This allows the manager
-  // to purge it if necessary.
-  void ReleaseLock(Allocation* allocation);
-
-  // Purges all discardable memory.
-  void PurgeAll();
-
-  // Returns true if allocation has been added to the manager's collection. This
-  // should only be used by tests.
-  bool IsRegisteredForTest(Allocation* allocation) const;
-
-  // Returns true if allocation can be purged. This should only be used by
-  // tests.
-  bool CanBePurgedForTest(Allocation* allocation) const;
-
-  // Returns total amount of allocated discardable memory. This should only be
-  // used by tests.
-  size_t GetBytesAllocatedForTest() const;
-
- private:
-  struct AllocationInfo {
-    explicit AllocationInfo(size_t bytes) : bytes(bytes), purgable(false) {}
-
-    const size_t bytes;
-    bool purgable;
-    TimeTicks last_usage;
-  };
-  typedef HashingMRUCache<Allocation*, AllocationInfo> AllocationMap;
-
-  // Purges memory not used since |hard_memory_limit_expiration_time_| before
-  // "right now" until usage is less or equal to |soft_memory_limit_|.
-  // Returns true if total amount of memory is less or equal to soft memory
-  // limit.
-  bool PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit();
-
-  // Purges memory that has not been used since |timestamp| until usage is less
-  // or equal to |limit|.
-  // Caller must acquire |lock_| prior to calling this function.
-  void PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(
-      TimeTicks timestamp,
-      size_t limit);
-
-  // Called when a change to |bytes_allocated_| has been made.
-  void BytesAllocatedChanged(size_t new_bytes_allocated) const;
-
-  // Virtual for tests.
-  virtual TimeTicks Now() const;
-
-  // Needs to be held when accessing members.
-  mutable Lock lock_;
-
-  // A MRU cache of all allocated bits of memory. Used for purging.
-  AllocationMap allocations_;
-
-  // The total amount of allocated memory.
-  size_t bytes_allocated_;
-
-  // The maximum number of bytes of memory that may be allocated.
-  size_t memory_limit_;
-
-  // The number of bytes of memory that may be allocated but not used for
-  // |hard_memory_limit_expiration_time_| amount of time when receiving an idle
-  // notification.
-  size_t soft_memory_limit_;
-
-  // Amount of time it takes for an allocation to become affected by
-  // |soft_memory_limit_|.
-  TimeDelta hard_memory_limit_expiration_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryManager);
-};
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_
diff --git a/base/memory/discardable_memory_manager_unittest.cc b/base/memory/discardable_memory_manager_unittest.cc
deleted file mode 100644
index 6717f09..0000000
--- a/base/memory/discardable_memory_manager_unittest.cc
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_manager.h"
-
-#include "base/bind.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation {
- public:
-  TestAllocationImpl() : is_allocated_(false), is_locked_(false) {}
-  ~TestAllocationImpl() override { DCHECK(!is_locked_); }
-
-  // Overridden from internal::DiscardableMemoryManagerAllocation:
-  bool AllocateAndAcquireLock() override {
-    bool was_allocated = is_allocated_;
-    is_allocated_ = true;
-    DCHECK(!is_locked_);
-    is_locked_ = true;
-    return was_allocated;
-  }
-  void ReleaseLock() override {
-    DCHECK(is_locked_);
-    is_locked_ = false;
-  }
-  void Purge() override {
-    DCHECK(is_allocated_);
-    is_allocated_ = false;
-  }
-
-  bool is_locked() const { return is_locked_; }
-
- private:
-  bool is_allocated_;
-  bool is_locked_;
-};
-
-// Tests can assume that the default limit is at least 1024. Tests that rely on
-// something else needs to explicit set the limit.
-const size_t kDefaultMemoryLimit = 1024;
-const size_t kDefaultSoftMemoryLimit = kDefaultMemoryLimit;
-
-class TestDiscardableMemoryManagerImpl
-    : public internal::DiscardableMemoryManager {
- public:
-  TestDiscardableMemoryManagerImpl()
-      : DiscardableMemoryManager(kDefaultMemoryLimit,
-                                 kDefaultSoftMemoryLimit,
-                                 TimeDelta::Max()) {}
-
-  void SetNow(TimeTicks now) { now_ = now; }
-
- private:
-  // Overriden from internal::DiscardableMemoryManager:
-  TimeTicks Now() const override { return now_; }
-
-  TimeTicks now_;
-};
-
-class DiscardableMemoryManagerTestBase {
- public:
-  DiscardableMemoryManagerTestBase() {}
-
- protected:
-  enum LockStatus {
-    LOCK_STATUS_FAILED,
-    LOCK_STATUS_PURGED,
-    LOCK_STATUS_SUCCESS
-  };
-
-  size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); }
-
-  void SetMemoryLimit(size_t bytes) { manager_.SetMemoryLimit(bytes); }
-
-  void SetSoftMemoryLimit(size_t bytes) { manager_.SetSoftMemoryLimit(bytes); }
-
-  void SetHardMemoryLimitExpirationTime(TimeDelta time) {
-    manager_.SetHardMemoryLimitExpirationTime(time);
-  }
-
-  void Register(TestAllocationImpl* allocation, size_t bytes) {
-    manager_.Register(allocation, bytes);
-  }
-
-  void Unregister(TestAllocationImpl* allocation) {
-    manager_.Unregister(allocation);
-  }
-
-  bool IsRegistered(TestAllocationImpl* allocation) const {
-    return manager_.IsRegisteredForTest(allocation);
-  }
-
-  LockStatus Lock(TestAllocationImpl* allocation) {
-    bool purged;
-    if (!manager_.AcquireLock(allocation, &purged))
-      return LOCK_STATUS_FAILED;
-    return purged ? LOCK_STATUS_PURGED : LOCK_STATUS_SUCCESS;
-  }
-
-  void Unlock(TestAllocationImpl* allocation) {
-    manager_.ReleaseLock(allocation);
-  }
-
-  LockStatus RegisterAndLock(TestAllocationImpl* allocation, size_t bytes) {
-    manager_.Register(allocation, bytes);
-    return Lock(allocation);
-  }
-
-  bool CanBePurged(TestAllocationImpl* allocation) const {
-    return manager_.CanBePurgedForTest(allocation);
-  }
-
-  void SetNow(TimeTicks now) { manager_.SetNow(now); }
-
-  void PurgeAll() { return manager_.PurgeAll(); }
-
-  bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); }
-
-  void ReduceMemoryUsageUntilWithinLimit(size_t bytes) {
-    manager_.ReduceMemoryUsageUntilWithinLimit(bytes);
-  }
-
- private:
-  TestDiscardableMemoryManagerImpl manager_;
-};
-
-class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase,
-                                     public testing::Test {
- public:
-  DiscardableMemoryManagerTest() {}
-};
-
-TEST_F(DiscardableMemoryManagerTest, CreateAndLock) {
-  size_t size = 1024;
-  TestAllocationImpl allocation;
-  Register(&allocation, size);
-  EXPECT_TRUE(IsRegistered(&allocation));
-  EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation));
-  EXPECT_TRUE(allocation.is_locked());
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(&allocation));
-  Unlock(&allocation);
-  Unregister(&allocation);
-}
-
-TEST_F(DiscardableMemoryManagerTest, CreateZeroSize) {
-  size_t size = 0;
-  TestAllocationImpl allocation;
-  Register(&allocation, size);
-  EXPECT_TRUE(IsRegistered(&allocation));
-  EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&allocation));
-  EXPECT_EQ(0u, BytesAllocated());
-  Unregister(&allocation);
-}
-
-TEST_F(DiscardableMemoryManagerTest, LockAfterUnlock) {
-  size_t size = 1024;
-  TestAllocationImpl allocation;
-  RegisterAndLock(&allocation, size);
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(&allocation));
-
-  // Now unlock so we can lock later.
-  Unlock(&allocation);
-  EXPECT_TRUE(CanBePurged(&allocation));
-
-  EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(&allocation));
-  EXPECT_FALSE(CanBePurged(&allocation));
-  Unlock(&allocation);
-  Unregister(&allocation);
-}
-
-TEST_F(DiscardableMemoryManagerTest, LockAfterPurge) {
-  size_t size = 1024;
-  TestAllocationImpl allocation;
-  RegisterAndLock(&allocation, size);
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(&allocation));
-
-  // Now unlock so we can lock later.
-  Unlock(&allocation);
-  EXPECT_TRUE(CanBePurged(&allocation));
-
-  // Force the system to purge.
-  PurgeAll();
-
-  EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation));
-  EXPECT_FALSE(CanBePurged(&allocation));
-
-  Unlock(&allocation);
-  Unregister(&allocation);
-}
-
-TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) {
-  size_t size = 1024;
-  TestAllocationImpl allocation;
-  RegisterAndLock(&allocation, size);
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(&allocation));
-
-  // Now unlock so we can lock later.
-  Unlock(&allocation);
-  EXPECT_TRUE(CanBePurged(&allocation));
-
-  // Set max allowed allocation to 1 byte. This will cause the memory to be
-  // purged.
-  SetMemoryLimit(1);
-
-  EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation));
-  EXPECT_FALSE(CanBePurged(&allocation));
-
-  Unlock(&allocation);
-  Unregister(&allocation);
-}
-
-TEST_F(DiscardableMemoryManagerTest, Overflow) {
-  size_t size = 1024;
-  {
-    TestAllocationImpl allocation;
-    RegisterAndLock(&allocation, size);
-    EXPECT_EQ(1024u, BytesAllocated());
-
-    size_t massive_size = std::numeric_limits<size_t>::max();
-    TestAllocationImpl massive_allocation;
-    Register(&massive_allocation, massive_size);
-    EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&massive_allocation));
-    EXPECT_EQ(1024u, BytesAllocated());
-
-    Unlock(&allocation);
-    EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&massive_allocation));
-    Unlock(&massive_allocation);
-    Unregister(&massive_allocation);
-    Unregister(&allocation);
-  }
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-class PermutationTestData {
- public:
-  PermutationTestData(unsigned d0, unsigned d1, unsigned d2) {
-    ordering_[0] = d0;
-    ordering_[1] = d1;
-    ordering_[2] = d2;
-  }
-
-  const unsigned* ordering() const { return ordering_; }
-
- private:
-  unsigned ordering_[3];
-};
-
-class DiscardableMemoryManagerPermutationTest
-    : public DiscardableMemoryManagerTestBase,
-      public testing::TestWithParam<PermutationTestData> {
- public:
-  DiscardableMemoryManagerPermutationTest() {}
-
- protected:
-  // Use memory in order specified by ordering parameter.
-  void RegisterAndUseAllocations() {
-    for (int i = 0; i < 3; ++i) {
-      RegisterAndLock(&allocation_[i], 1024);
-      Unlock(&allocation_[i]);
-    }
-    for (int i = 0; i < 3; ++i) {
-      int index = GetParam().ordering()[i];
-      EXPECT_NE(LOCK_STATUS_FAILED, Lock(&allocation_[index]));
-      // Leave i == 0 locked.
-      if (i > 0)
-        Unlock(&allocation_[index]);
-    }
-  }
-
-  TestAllocationImpl* allocation(unsigned position) {
-    return &allocation_[GetParam().ordering()[position]];
-  }
-
-  void UnlockAndUnregisterAllocations() {
-    for (int i = 0; i < 3; ++i) {
-      if (allocation_[i].is_locked())
-        Unlock(&allocation_[i]);
-      Unregister(&allocation_[i]);
-    }
-  }
-
- private:
-  TestAllocationImpl allocation_[3];
-};
-
-// Verify that memory was discarded in the correct order after reducing usage to
-// limit.
-TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscarded) {
-  RegisterAndUseAllocations();
-
-  SetMemoryLimit(2048);
-
-  ReduceMemoryUsageUntilWithinLimit(1024);
-
-  EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2)));
-  EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1)));
-  // 0 should still be locked.
-  EXPECT_TRUE(allocation(0)->is_locked());
-
-  UnlockAndUnregisterAllocations();
-}
-
-// Verify that memory was discarded in the correct order after changing
-// memory limit.
-TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedExceedLimit) {
-  RegisterAndUseAllocations();
-
-  SetMemoryLimit(2048);
-
-  EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2)));
-  EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1)));
-  // 0 should still be locked.
-  EXPECT_TRUE(allocation(0)->is_locked());
-
-  UnlockAndUnregisterAllocations();
-}
-
-// Verify that no more memory than necessary was discarded after changing
-// memory limit.
-TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedAmount) {
-  SetMemoryLimit(4096);
-
-  RegisterAndUseAllocations();
-
-  SetMemoryLimit(2048);
-
-  EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(allocation(2)));
-  EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1)));
-  // 0 should still be locked.
-  EXPECT_TRUE(allocation(0)->is_locked());
-
-  UnlockAndUnregisterAllocations();
-}
-
-TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) {
-  RegisterAndUseAllocations();
-
-  PurgeAll();
-
-  for (int i = 0; i < 3; ++i) {
-    if (i == 0)
-      EXPECT_TRUE(allocation(i)->is_locked());
-    else
-      EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i)));
-  }
-
-  UnlockAndUnregisterAllocations();
-}
-
-INSTANTIATE_TEST_CASE_P(DiscardableMemoryManagerPermutationTests,
-                        DiscardableMemoryManagerPermutationTest,
-                        ::testing::Values(PermutationTestData(0, 1, 2),
-                                          PermutationTestData(0, 2, 1),
-                                          PermutationTestData(1, 0, 2),
-                                          PermutationTestData(1, 2, 0),
-                                          PermutationTestData(2, 0, 1),
-                                          PermutationTestData(2, 1, 0)));
-
-TEST_F(DiscardableMemoryManagerTest, NormalDestruction) {
-  {
-    size_t size = 1024;
-    TestAllocationImpl allocation;
-    Register(&allocation, size);
-    Unregister(&allocation);
-  }
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-TEST_F(DiscardableMemoryManagerTest, DestructionAfterLocked) {
-  {
-    size_t size = 1024;
-    TestAllocationImpl allocation;
-    RegisterAndLock(&allocation, size);
-    EXPECT_EQ(1024u, BytesAllocated());
-    EXPECT_FALSE(CanBePurged(&allocation));
-    Unlock(&allocation);
-    Unregister(&allocation);
-  }
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-TEST_F(DiscardableMemoryManagerTest, DestructionAfterPurged) {
-  {
-    size_t size = 1024;
-    TestAllocationImpl allocation;
-    RegisterAndLock(&allocation, size);
-    EXPECT_EQ(1024u, BytesAllocated());
-    Unlock(&allocation);
-    EXPECT_TRUE(CanBePurged(&allocation));
-    SetMemoryLimit(0);
-    EXPECT_EQ(0u, BytesAllocated());
-    Unregister(&allocation);
-  }
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-TEST_F(DiscardableMemoryManagerTest, ReduceMemoryUsage) {
-  SetMemoryLimit(3072);
-  SetSoftMemoryLimit(1024);
-  SetHardMemoryLimitExpirationTime(TimeDelta::FromInternalValue(1));
-
-  size_t size = 1024;
-  TestAllocationImpl allocation[3];
-  RegisterAndLock(&allocation[0], size);
-  RegisterAndLock(&allocation[1], size);
-  RegisterAndLock(&allocation[2], size);
-  EXPECT_EQ(3072u, BytesAllocated());
-
-  // Above soft limit but nothing that can be purged.
-  EXPECT_FALSE(ReduceMemoryUsage());
-
-  SetNow(TimeTicks::FromInternalValue(0));
-  Unlock(&allocation[0]);
-
-  // Above soft limit but still nothing that can be purged as all unlocked
-  // allocations are within the hard limit cutoff time.
-  EXPECT_FALSE(ReduceMemoryUsage());
-
-  SetNow(TimeTicks::FromInternalValue(1));
-  Unlock(&allocation[1]);
-
-  // One unlocked allocation is no longer within the hard limit cutoff time. It
-  // should be purged and ReduceMemoryUsage() should return false as we're not
-  // yet within the soft memory limit.
-  EXPECT_FALSE(ReduceMemoryUsage());
-  EXPECT_EQ(2048u, BytesAllocated());
-
-  // One more unlocked allocation is no longer within the hard limit cutoff
-  // time. It should be purged and ReduceMemoryUsage() should return true as
-  // we're now within the soft memory limit.
-  SetNow(TimeTicks::FromInternalValue(2));
-  EXPECT_TRUE(ReduceMemoryUsage());
-  EXPECT_EQ(1024u, BytesAllocated());
-
-  Unlock(&allocation[2]);
-
-  Unregister(&allocation[0]);
-  Unregister(&allocation[1]);
-  Unregister(&allocation[2]);
-}
-
-class ThreadedDiscardableMemoryManagerTest
-    : public DiscardableMemoryManagerTest {
- public:
-  ThreadedDiscardableMemoryManagerTest()
-      : memory_usage_thread_("memory_usage_thread"),
-        thread_sync_(true, false) {}
-
-  void SetUp() override { memory_usage_thread_.Start(); }
-
-  void TearDown() override { memory_usage_thread_.Stop(); }
-
-  void UseMemoryHelper() {
-    size_t size = 1024;
-    TestAllocationImpl allocation;
-    RegisterAndLock(&allocation, size);
-    Unlock(&allocation);
-    Unregister(&allocation);
-  }
-
-  void SignalHelper() { thread_sync_.Signal(); }
-
-  Thread memory_usage_thread_;
-  WaitableEvent thread_sync_;
-};
-
-TEST_F(ThreadedDiscardableMemoryManagerTest, UseMemoryOnThread) {
-  memory_usage_thread_.message_loop()->PostTask(
-      FROM_HERE,
-      Bind(&ThreadedDiscardableMemoryManagerTest::UseMemoryHelper,
-           Unretained(this)));
-  memory_usage_thread_.message_loop()->PostTask(
-      FROM_HERE,
-      Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper,
-           Unretained(this)));
-  thread_sync_.Wait();
-}
-
-}  // namespace
-}  // namespace base
diff --git a/base/memory/discardable_memory_shmem.cc b/base/memory/discardable_memory_shmem.cc
index 9056279..059d84c 100644
--- a/base/memory/discardable_memory_shmem.cc
+++ b/base/memory/discardable_memory_shmem.cc
@@ -11,7 +11,10 @@
 namespace internal {
 
 DiscardableMemoryShmem::DiscardableMemoryShmem(size_t bytes)
-    : bytes_(bytes), is_locked_(false) {
+    : chunk_(DiscardableMemoryShmemAllocator::GetInstance()
+                 ->AllocateLockedDiscardableMemory(bytes)),
+      is_locked_(true) {
+  DCHECK(chunk_);
 }
 
 DiscardableMemoryShmem::~DiscardableMemoryShmem() {
@@ -19,37 +22,27 @@
     Unlock();
 }
 
-bool DiscardableMemoryShmem::Initialize() {
-  return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-}
-
-DiscardableMemoryLockStatus DiscardableMemoryShmem::Lock() {
+bool DiscardableMemoryShmem::Lock() {
   DCHECK(!is_locked_);
+  DCHECK(chunk_);
 
-  if (chunk_ && chunk_->Lock()) {
-    is_locked_ = true;
-    return DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+  if (!chunk_->Lock()) {
+    chunk_.reset();
+    return false;
   }
 
-  chunk_ = DiscardableMemoryShmemAllocator::GetInstance()
-               ->AllocateLockedDiscardableMemory(bytes_);
-  if (!chunk_)
-    return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-
   is_locked_ = true;
-  return DISCARDABLE_MEMORY_LOCK_STATUS_PURGED;
+  return true;
 }
 
 void DiscardableMemoryShmem::Unlock() {
   DCHECK(is_locked_);
-  DCHECK(chunk_);
   chunk_->Unlock();
   is_locked_ = false;
 }
 
 void* DiscardableMemoryShmem::Memory() const {
   DCHECK(is_locked_);
-  DCHECK(chunk_);
   return chunk_->Memory();
 }
 
diff --git a/base/memory/discardable_memory_shmem.h b/base/memory/discardable_memory_shmem.h
index 98d3b97..f394562 100644
--- a/base/memory/discardable_memory_shmem.h
+++ b/base/memory/discardable_memory_shmem.h
@@ -20,12 +20,11 @@
   bool Initialize();
 
   // Overridden from DiscardableMemory:
-  DiscardableMemoryLockStatus Lock() override;
+  bool Lock() override;
   void Unlock() override;
   void* Memory() const override;
 
  private:
-  const size_t bytes_;
   scoped_ptr<DiscardableMemoryShmemChunk> chunk_;
   bool is_locked_;
 
diff --git a/base/memory/discardable_memory_unittest.cc b/base/memory/discardable_memory_unittest.cc
index fb1eba6..a769e17 100644
--- a/base/memory/discardable_memory_unittest.cc
+++ b/base/memory/discardable_memory_unittest.cc
@@ -38,8 +38,12 @@
 }
 
 bool IsNativeType(DiscardableMemoryType type) {
-  return type == DISCARDABLE_MEMORY_TYPE_ASHMEM ||
-         type == DISCARDABLE_MEMORY_TYPE_MACH;
+#if defined(OS_ANDROID)
+    // SHMEM is backed by native discardable memory on Android.
+  return type == DISCARDABLE_MEMORY_TYPE_SHMEM;
+#else
+  return false;
+#endif
 }
 
 TEST_P(DiscardableMemoryTest, SupportedNatively) {
@@ -65,14 +69,7 @@
   const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize));
   ASSERT_TRUE(memory);
   void* addr = memory->Memory();
-  ASSERT_NE(nullptr, addr);
-
-  memory->Unlock();
-
-  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, memory->Lock());
-  addr = memory->Memory();
-  ASSERT_NE(nullptr, addr);
-
+  EXPECT_NE(nullptr, addr);
   memory->Unlock();
 }
 
@@ -107,7 +104,7 @@
     memory = CreateLockedMemory(kLargeSize);
     ASSERT_TRUE(memory);
     void* addr = memory->Memory();
-    ASSERT_NE(nullptr, addr);
+    EXPECT_NE(nullptr, addr);
     memory->Unlock();
   }
 }
diff --git a/base/memory/discardable_memory_win.cc b/base/memory/discardable_memory_win.cc
index 670ad7e..b394e07 100644
--- a/base/memory/discardable_memory_win.cc
+++ b/base/memory/discardable_memory_win.cc
@@ -5,22 +5,15 @@
 #include "base/memory/discardable_memory.h"
 
 #include "base/logging.h"
-#include "base/memory/discardable_memory_emulated.h"
 #include "base/memory/discardable_memory_shmem.h"
 
 namespace base {
 
 // static
-bool DiscardableMemory::ReduceMemoryUsage() {
-  return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
-}
-
-// static
 void DiscardableMemory::GetSupportedTypes(
     std::vector<DiscardableMemoryType>* types) {
   const DiscardableMemoryType supported_types[] = {
-    DISCARDABLE_MEMORY_TYPE_SHMEM,
-    DISCARDABLE_MEMORY_TYPE_EMULATED
+    DISCARDABLE_MEMORY_TYPE_SHMEM
   };
   types->assign(supported_types, supported_types + arraysize(supported_types));
 }
@@ -29,25 +22,9 @@
 scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType(
     DiscardableMemoryType type, size_t size) {
   switch (type) {
-    case DISCARDABLE_MEMORY_TYPE_EMULATED: {
-      scoped_ptr<internal::DiscardableMemoryEmulated> memory(
-          new internal::DiscardableMemoryEmulated(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
-    case DISCARDABLE_MEMORY_TYPE_SHMEM: {
-      scoped_ptr<internal::DiscardableMemoryShmem> memory(
-          new internal::DiscardableMemoryShmem(size));
-      if (!memory->Initialize())
-        return nullptr;
-
-      return memory.Pass();
-    }
+    case DISCARDABLE_MEMORY_TYPE_SHMEM:
+      return make_scoped_ptr(new internal::DiscardableMemoryShmem(size));
     case DISCARDABLE_MEMORY_TYPE_NONE:
-    case DISCARDABLE_MEMORY_TYPE_ASHMEM:
-    case DISCARDABLE_MEMORY_TYPE_MACH:
       NOTREACHED();
       return nullptr;
   }
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h
index f159fb0..6adaeee 100644
--- a/base/memory/memory_pressure_listener.h
+++ b/base/memory/memory_pressure_listener.h
@@ -7,8 +7,8 @@
 // The app will try to discard buffers that aren't deemed essential (individual
 // modules will implement their own policy).
 
-#ifndef BASE_MEMORY_PRESSURE_LISTENER_H_
-#define BASE_MEMORY_PRESSURE_LISTENER_H_
+#ifndef BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
+#define BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
 
 #include "base/base_export.h"
 #include "base/basictypes.h"
@@ -82,4 +82,4 @@
 
 }  // namespace base
 
-#endif  // BASE_MEMORY_PRESSURE_LISTENER_H_
+#endif  // BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc
index fd26ad1..d6c290f 100644
--- a/base/memory/shared_memory_posix.cc
+++ b/base/memory/shared_memory_posix.cc
@@ -16,6 +16,7 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/process/process_metrics.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/safe_strerror_posix.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
@@ -118,6 +119,11 @@
 // In case we want to delete it later, it may be useful to save the value
 // of mem_filename after FilePathForMemoryName().
 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
+  // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437
+  // is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "466437 SharedMemory::Create::Start"));
   DCHECK_EQ(-1, mapped_file_);
   if (options.size == 0) return false;
 
@@ -140,11 +146,22 @@
     // Q: Why not use the shm_open() etc. APIs?
     // A: Because they're limited to 4mb on OS X.  FFFFFFFUUUUUUUUUUU
     FilePath directory;
-    if (GetShmemTempDir(options.executable, &directory))
+    if (GetShmemTempDir(options.executable, &directory)) {
+      // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437
+      // is fixed.
+      tracked_objects::ScopedTracker tracking_profile2(
+          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+              "466437 SharedMemory::Create::OpenTemporaryFile"));
       fp.reset(CreateAndOpenTemporaryFileInDir(directory, &path));
+    }
 
     if (fp) {
       if (options.share_read_only) {
+        // TODO(erikchen): Remove ScopedTracker below once
+        // http://crbug.com/466437 is fixed.
+        tracked_objects::ScopedTracker tracking_profile3(
+            FROM_HERE_WITH_EXPLICIT_FUNCTION(
+                "466437 SharedMemory::Create::OpenReadonly"));
         // Also open as readonly so that we can ShareReadOnlyToProcess.
         readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
         if (!readonly_fd.is_valid()) {
@@ -153,6 +170,12 @@
           return false;
         }
       }
+
+      // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437
+      // is fixed.
+      tracked_objects::ScopedTracker tracking_profile4(
+          FROM_HERE_WITH_EXPLICIT_FUNCTION(
+              "466437 SharedMemory::Create::Unlink"));
       // Deleting the file prevents anyone else from mapping it in (making it
       // private), and prevents the need for cleanup (once the last fd is
       // closed, it is truly freed).
@@ -453,7 +476,7 @@
     case SHARE_READONLY:
       // We could imagine re-opening the file from /dev/fd, but that can't make
       // it readonly on Mac: https://codereview.chromium.org/27265002/#msg10
-      CHECK(readonly_mapped_file_ >= 0);
+      CHECK_GE(readonly_mapped_file_, 0);
       handle_to_dup = readonly_mapped_file_;
       break;
   }
diff --git a/base/message_loop/message_pump_default.h b/base/message_loop/message_pump_default.h
index d63e810..8aeaa62 100644
--- a/base/message_loop/message_pump_default.h
+++ b/base/message_loop/message_pump_default.h
@@ -38,4 +38,4 @@
 
 }  // namespace base
 
-#endif  // BASE__MESSAGE_LOOPMESSAGE_PUMP_DEFAULT_H_
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_DEFAULT_H_
diff --git a/base/message_loop/message_pump_dispatcher.h b/base/message_loop/message_pump_dispatcher.h
index 0dea226..5b1bd55 100644
--- a/base/message_loop/message_pump_dispatcher.h
+++ b/base/message_loop/message_pump_dispatcher.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H
-#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H_
 
 #include <stdint.h>
 
@@ -40,4 +40,4 @@
 
 }  // namespace base
 
-#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H
+#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H_
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc
index 5ef3a50..8226495 100644
--- a/base/message_loop/message_pump_win.cc
+++ b/base/message_loop/message_pump_win.cc
@@ -673,7 +673,7 @@
   // |IOHandler| is at least pointer-size aligned, so the lowest two bits are
   // always cleared. We use the lowest bit to distinguish completion keys with
   // and without the associated |IOContext|.
-  DCHECK((key & 1) == 0);
+  DCHECK_EQ(key & 1, 0u);
 
   // Mark the completion key as context-less.
   if (!has_valid_io_context)
diff --git a/base/metrics/BUILD.gn b/base/metrics/BUILD.gn
new file mode 100644
index 0000000..804e59b
--- /dev/null
+++ b/base/metrics/BUILD.gn
@@ -0,0 +1,49 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("metrics") {
+  sources = [
+    "bucket_ranges.cc",
+    "bucket_ranges.h",
+    "field_trial.cc",
+    "field_trial.h",
+    "histogram.cc",
+    "histogram.h",
+    "histogram_base.cc",
+    "histogram_base.h",
+    "histogram_delta_serialization.",
+    "histogram_delta_serialization.cc",
+    "histogram_flattener.h",
+    "histogram_macros.h",
+    "histogram_samples.cc",
+    "histogram_samples.h",
+    "histogram_snapshot_manager.cc",
+    "histogram_snapshot_manager.h",
+    "sample_map.cc",
+    "sample_map.h",
+    "sample_vector.cc",
+    "sample_vector.h",
+    "sparse_histogram.cc",
+    "sparse_histogram.h",
+    "statistics_recorder.cc",
+    "statistics_recorder.h",
+    "user_metrics.cc",
+    "user_metrics.h",
+    "user_metrics_action.h",
+  ]
+
+  if (is_nacl) {
+    sources -= [ "field_trial.cc" ]
+  }
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  deps = [
+    "//base/debug",
+    "//base/json",
+    "//base/memory",
+  ]
+
+  visibility = [ "//base/*" ]
+}
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index fe85fc6..d9b77f7 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_SAFE_CONVERSIONS_H_
-#define BASE_SAFE_CONVERSIONS_H_
+#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_H_
 
 #include <limits>
 
@@ -60,5 +60,4 @@
 
 }  // namespace base
 
-#endif  // BASE_SAFE_CONVERSIONS_H_
-
+#endif  // BASE_NUMERICS_SAFE_CONVERSIONS_H_
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
index c26757a..504ce7e 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_SAFE_CONVERSIONS_IMPL_H_
-#define BASE_SAFE_CONVERSIONS_IMPL_H_
+#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
 
 #include <limits>
 
@@ -212,5 +212,4 @@
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_SAFE_CONVERSIONS_IMPL_H_
-
+#endif  // BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h
index ccda1c8..1309446 100644
--- a/base/numerics/safe_math.h
+++ b/base/numerics/safe_math.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_SAFE_MATH_H_
-#define BASE_SAFE_MATH_H_
+#ifndef BASE_NUMERICS_SAFE_MATH_H_
+#define BASE_NUMERICS_SAFE_MATH_H_
 
 #include "base/numerics/safe_math_impl.h"
 
@@ -269,4 +269,4 @@
 
 }  // namespace base
 
-#endif  // BASE_SAFE_MATH_H_
+#endif  // BASE_NUMERICS_SAFE_MATH_H_
diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h
index 663f393..c845189 100644
--- a/base/numerics/safe_math_impl.h
+++ b/base/numerics/safe_math_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SAFE_MATH_IMPL_H_
-#define SAFE_MATH_IMPL_H_
+#ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_IMPL_H_
 
 #include <stdint.h>
 
@@ -498,4 +498,4 @@
 }  // namespace internal
 }  // namespace base
 
-#endif  // SAFE_MATH_IMPL_H_
+#endif  // BASE_NUMERICS_SAFE_MATH_IMPL_H_
diff --git a/base/observer_list.h b/base/observer_list.h
index ef45269..f7b9267 100644
--- a/base/observer_list.h
+++ b/base/observer_list.h
@@ -79,7 +79,7 @@
   // also the FOR_EACH_OBSERVER macro defined below.
   class Iterator {
    public:
-    Iterator(ObserverListBase<ObserverType>& list);
+    explicit Iterator(ObserverListBase<ObserverType>* list);
     ~Iterator();
     ObserverType* GetNext();
 
@@ -126,12 +126,11 @@
 
 template <class ObserverType>
 ObserverListBase<ObserverType>::Iterator::Iterator(
-  ObserverListBase<ObserverType>& list)
-    : list_(list.AsWeakPtr()),
+    ObserverListBase<ObserverType>* list)
+    : list_(list->AsWeakPtr()),
       index_(0),
-      max_index_(list.type_ == NOTIFY_ALL ?
-                 std::numeric_limits<size_t>::max() :
-                 list.observers_.size()) {
+      max_index_(list->type_ == NOTIFY_ALL ? std::numeric_limits<size_t>::max()
+                                           : list->observers_.size()) {
   ++list_->notify_depth_;
 }
 
@@ -228,15 +227,15 @@
   }
 };
 
-#define FOR_EACH_OBSERVER(ObserverType, observer_list, func)               \
-  do {                                                                     \
-    if ((observer_list).might_have_observers()) {                          \
-      ObserverListBase<ObserverType>::Iterator                             \
-          it_inside_observer_macro(observer_list);                         \
-      ObserverType* obs;                                                   \
-      while ((obs = it_inside_observer_macro.GetNext()) != NULL)           \
-        obs->func;                                                         \
-    }                                                                      \
+#define FOR_EACH_OBSERVER(ObserverType, observer_list, func)             \
+  do {                                                                   \
+    if ((observer_list).might_have_observers()) {                        \
+      ObserverListBase<ObserverType>::Iterator it_inside_observer_macro( \
+          &observer_list);                                               \
+      ObserverType* obs;                                                 \
+      while ((obs = it_inside_observer_macro.GetNext()) != NULL)         \
+        obs->func;                                                       \
+    }                                                                    \
   } while (0)
 
 #endif  // BASE_OBSERVER_LIST_H__
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h
index 1a663337..46ce880 100644
--- a/base/observer_list_threadsafe.h
+++ b/base/observer_list_threadsafe.h
@@ -199,6 +199,7 @@
     scoped_refptr<base::MessageLoopProxy> loop;
     ObserverList<ObserverType> list;
 
+   private:
     DISALLOW_COPY_AND_ASSIGN(ObserverListContext);
   };
 
@@ -212,7 +213,6 @@
   template <class Method, class Params>
   void NotifyWrapper(ObserverListContext* context,
       const UnboundMethod<ObserverType, Method, Params>& method) {
-
     // Check that this list still needs notifications.
     {
       base::AutoLock lock(list_lock_);
@@ -228,7 +228,7 @@
     }
 
     {
-      typename ObserverList<ObserverType>::Iterator it(context->list);
+      typename ObserverList<ObserverType>::Iterator it(&context->list);
       ObserverType* obs;
       while ((obs = it.GetNext()) != NULL)
         method.Run(obs);
diff --git a/base/path_service.cc b/base/path_service.cc
index ce4966e..3c437ee 100644
--- a/base/path_service.cc
+++ b/base/path_service.cc
@@ -33,7 +33,7 @@
   // Mac and Android.
   bool PathProviderPosix(int key, FilePath* result);
 #endif
-}
+}  // namespace base
 
 namespace {
 
diff --git a/base/path_service.h b/base/path_service.h
index 554eb9e..025550f 100644
--- a/base/path_service.h
+++ b/base/path_service.h
@@ -15,7 +15,7 @@
 namespace base {
 class FilePath;
 class ScopedPathOverride;
-}  // namespace
+}  // namespace base
 
 // The path service is a global table mapping keys to file system paths.  It is
 // OK to use this service from multiple threads.
diff --git a/base/pending_task.h b/base/pending_task.h
index a2edc69..fddfc86 100644
--- a/base/pending_task.h
+++ b/base/pending_task.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef PENDING_TASK_H_
-#define PENDING_TASK_H_
+#ifndef BASE_PENDING_TASK_H_
+#define BASE_PENDING_TASK_H_
 
 #include <queue>
 
@@ -57,4 +57,4 @@
 
 }  // namespace base
 
-#endif  // PENDING_TASK_H_
+#endif  // BASE_PENDING_TASK_H_
diff --git a/base/pickle.cc b/base/pickle.cc
index d461f41..6eb207f 100644
--- a/base/pickle.cc
+++ b/base/pickle.cc
@@ -152,15 +152,15 @@
   return true;
 }
 
-bool PickleIterator::ReadWString(std::wstring* result) {
+bool PickleIterator::ReadStringPiece(base::StringPiece* result) {
   int len;
   if (!ReadInt(&len))
     return false;
-  const char* read_from = GetReadPointerAndAdvance(len, sizeof(wchar_t));
+  const char* read_from = GetReadPointerAndAdvance(len);
   if (!read_from)
     return false;
 
-  result->assign(reinterpret_cast<const wchar_t*>(read_from), len);
+  *result = base::StringPiece(read_from, len);
   return true;
 }
 
@@ -176,6 +176,19 @@
   return true;
 }
 
+bool PickleIterator::ReadStringPiece16(base::StringPiece16* result) {
+  int len;
+  if (!ReadInt(&len))
+    return false;
+  const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16));
+  if (!read_from)
+    return false;
+
+  *result = base::StringPiece16(reinterpret_cast<const char16*>(read_from),
+                                len);
+  return true;
+}
+
 bool PickleIterator::ReadData(const char** data, int* length) {
   *length = 0;
   *data = 0;
@@ -271,22 +284,14 @@
   return *this;
 }
 
-bool Pickle::WriteString(const std::string& value) {
+bool Pickle::WriteString(const base::StringPiece& value) {
   if (!WriteInt(static_cast<int>(value.size())))
     return false;
 
   return WriteBytes(value.data(), static_cast<int>(value.size()));
 }
 
-bool Pickle::WriteWString(const std::wstring& value) {
-  if (!WriteInt(static_cast<int>(value.size())))
-    return false;
-
-  return WriteBytes(value.data(),
-                    static_cast<int>(value.size() * sizeof(wchar_t)));
-}
-
-bool Pickle::WriteString16(const string16& value) {
+bool Pickle::WriteString16(const base::StringPiece16& value) {
   if (!WriteInt(static_cast<int>(value.size())))
     return false;
 
diff --git a/base/pickle.h b/base/pickle.h
index f2a198e..e6b9d81 100644
--- a/base/pickle.h
+++ b/base/pickle.h
@@ -13,6 +13,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/logging.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
 
 class Pickle;
 
@@ -39,8 +40,11 @@
   bool ReadFloat(float* result) WARN_UNUSED_RESULT;
   bool ReadDouble(double* result) WARN_UNUSED_RESULT;
   bool ReadString(std::string* result) WARN_UNUSED_RESULT;
-  bool ReadWString(std::wstring* result) WARN_UNUSED_RESULT;
+  // The StringPiece data will only be valid for the lifetime of the message.
+  bool ReadStringPiece(base::StringPiece* result) WARN_UNUSED_RESULT;
   bool ReadString16(base::string16* result) WARN_UNUSED_RESULT;
+  // The StringPiece16 data will only be valid for the lifetime of the message.
+  bool ReadStringPiece16(base::StringPiece16* result) WARN_UNUSED_RESULT;
 
   // A pointer to the data will be placed in |*data|, and the length will be
   // placed in |*length|. The pointer placed into |*data| points into the
@@ -195,9 +199,8 @@
   bool WriteDouble(double value) {
     return WritePOD(value);
   }
-  bool WriteString(const std::string& value);
-  bool WriteWString(const std::wstring& value);
-  bool WriteString16(const base::string16& value);
+  bool WriteString(const base::StringPiece& value);
+  bool WriteString16(const base::StringPiece16& value);
   // "Data" is a blob with a length. When you read it out you will be given the
   // length. See also WriteBytes.
   bool WriteData(const char* data, int length);
diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc
index 1fa1f32..a2c405c 100644
--- a/base/pickle_unittest.cc
+++ b/base/pickle_unittest.cc
@@ -30,10 +30,13 @@
 const std::string teststring("Hello world");  // note non-aligned string length
 const std::wstring testwstring(L"Hello, world");
 const base::string16 teststring16(base::ASCIIToUTF16("Hello, world"));
+const char testrawstring[] = "Hello new world"; // Test raw string writing
+// Test raw char16 writing, assumes UTF16 encoding is ANSI for alpha chars.
+const base::char16 testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0};
 const char testdata[] = "AAA\0BBB\0";
 const int testdatalen = arraysize(testdata) - 1;
 
-// checks that the result
+// checks that the results can be read correctly from the Pickle
 void VerifyResult(const Pickle& pickle) {
   PickleIterator iter(pickle);
 
@@ -83,14 +86,18 @@
   EXPECT_TRUE(iter.ReadString(&outstring));
   EXPECT_EQ(teststring, outstring);
 
-  std::wstring outwstring;
-  EXPECT_TRUE(iter.ReadWString(&outwstring));
-  EXPECT_EQ(testwstring, outwstring);
-
   base::string16 outstring16;
   EXPECT_TRUE(iter.ReadString16(&outstring16));
   EXPECT_EQ(teststring16, outstring16);
 
+  base::StringPiece outstringpiece;
+  EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
+  EXPECT_EQ(testrawstring, outstringpiece);
+
+  base::StringPiece16 outstringpiece16;
+  EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
+  EXPECT_EQ(testrawstring16, outstringpiece16);
+
   const char* outdata;
   int outdatalen;
   EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
@@ -119,8 +126,9 @@
   EXPECT_TRUE(pickle.WriteFloat(testfloat));
   EXPECT_TRUE(pickle.WriteDouble(testdouble));
   EXPECT_TRUE(pickle.WriteString(teststring));
-  EXPECT_TRUE(pickle.WriteWString(testwstring));
   EXPECT_TRUE(pickle.WriteString16(teststring16));
+  EXPECT_TRUE(pickle.WriteString(testrawstring));
+  EXPECT_TRUE(pickle.WriteString16(testrawstring16));
   EXPECT_TRUE(pickle.WriteData(testdata, testdatalen));
   VerifyResult(pickle);
 
@@ -198,9 +206,9 @@
   EXPECT_EQ("", outstr);
 }
 
-TEST(PickleTest, ZeroLenWStr) {
+TEST(PickleTest, ZeroLenStr16) {
   Pickle pickle;
-  EXPECT_TRUE(pickle.WriteWString(std::wstring()));
+  EXPECT_TRUE(pickle.WriteString16(base::string16()));
 
   PickleIterator iter(pickle);
   std::string outstr;
@@ -217,13 +225,13 @@
   EXPECT_FALSE(iter.ReadString(&outstr));
 }
 
-TEST(PickleTest, BadLenWStr) {
+TEST(PickleTest, BadLenStr16) {
   Pickle pickle;
   EXPECT_TRUE(pickle.WriteInt(-1));
 
   PickleIterator iter(pickle);
-  std::wstring woutstr;
-  EXPECT_FALSE(iter.ReadWString(&woutstr));
+  base::string16 outstr;
+  EXPECT_FALSE(iter.ReadString16(&outstr));
 }
 
 TEST(PickleTest, FindNext) {
@@ -391,13 +399,6 @@
   EXPECT_TRUE(bad_len.WriteInt(1 << 31));
   iter = PickleIterator(bad_len);
   EXPECT_FALSE(iter.ReadString16(&str16));
-
-  // Check we don't fail in a length check with large WStrings.
-  Pickle big_len;
-  EXPECT_TRUE(big_len.WriteInt(1 << 30));
-  iter = PickleIterator(big_len);
-  std::wstring wstr;
-  EXPECT_FALSE(iter.ReadWString(&wstr));
 }
 
 // Check we can write zero bytes of data and 'data' can be NULL.
diff --git a/base/posix/unix_domain_socket_linux.cc b/base/posix/unix_domain_socket_linux.cc
index 203285b..16d8eaa 100644
--- a/base/posix/unix_domain_socket_linux.cc
+++ b/base/posix/unix_domain_socket_linux.cc
@@ -136,8 +136,8 @@
       const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
       if (cmsg->cmsg_level == SOL_SOCKET &&
           cmsg->cmsg_type == SCM_RIGHTS) {
-        DCHECK(payload_len % sizeof(int) == 0);
-        DCHECK(wire_fds == NULL);
+        DCHECK_EQ(payload_len % sizeof(int), 0u);
+        DCHECK_EQ(wire_fds, static_cast<void*>(nullptr));
         wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
         wire_fds_len = payload_len / sizeof(int);
       }
@@ -146,8 +146,8 @@
       // SCM_CREDENTIALS.
       if (cmsg->cmsg_level == SOL_SOCKET &&
           cmsg->cmsg_type == SCM_CREDENTIALS) {
-        DCHECK(payload_len == sizeof(struct ucred));
-        DCHECK(pid == -1);
+        DCHECK_EQ(payload_len, sizeof(struct ucred));
+        DCHECK_EQ(pid, -1);
         pid = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg))->pid;
       }
 #endif
diff --git a/base/prefs/base_prefs_switches.cc b/base/prefs/base_prefs_switches.cc
deleted file mode 100644
index 304248b..0000000
--- a/base/prefs/base_prefs_switches.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/prefs/base_prefs_switches.h"
-
-namespace switches {
-
-// Pretty-prints pref JSON files.
-const char kPrettyPrintPrefs[] = "pretty-print-prefs";
-
-}  // namespace switches
diff --git a/base/prefs/base_prefs_switches.h b/base/prefs/base_prefs_switches.h
deleted file mode 100644
index 7a6b665..0000000
--- a/base/prefs/base_prefs_switches.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_PREFS_BASE_PREFS_SWITCHES_H_
-#define BASE_PREFS_BASE_PREFS_SWITCHES_H_
-
-namespace switches {
-
-extern const char kPrettyPrintPrefs[];
-
-}  // namespace switches
-
-#endif  // BASE_PREFS_BASE_PREFS_SWITCHES_H_
diff --git a/base/prefs/json_pref_store.cc b/base/prefs/json_pref_store.cc
index 2e34b50..47cd424 100644
--- a/base/prefs/json_pref_store.cc
+++ b/base/prefs/json_pref_store.cc
@@ -8,14 +8,12 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram.h"
-#include "base/prefs/base_prefs_switches.h"
 #include "base/prefs/pref_filter.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_util.h"
@@ -400,10 +398,10 @@
     pref_filter_->FilterSerializeData(prefs_.get());
 
   JSONStringValueSerializer serializer(output);
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kPrettyPrintPrefs)) {
-    serializer.set_pretty_print(true);
-  }
+  // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain
+  // readable prefs for debugging purposes, you can dump your prefs into any
+  // command-line or online JSON pretty printing tool.
+  serializer.set_pretty_print(false);
   return serializer.Serialize(*prefs_);
 }
 
diff --git a/base/prefs/pref_member.h b/base/prefs/pref_member.h
index b47cae2..078be95 100644
--- a/base/prefs/pref_member.h
+++ b/base/prefs/pref_member.h
@@ -273,6 +273,7 @@
     // tree.
     mutable ValueType value_;
 
+   private:
     DISALLOW_COPY_AND_ASSIGN(Internal);
   };
 
diff --git a/base/prefs/pref_notifier_impl.cc b/base/prefs/pref_notifier_impl.cc
index 6bf9603..7ae5fe6 100644
--- a/base/prefs/pref_notifier_impl.cc
+++ b/base/prefs/pref_notifier_impl.cc
@@ -22,7 +22,7 @@
   // Verify that there are no pref observers when we shut down.
   for (PrefObserverMap::iterator it = pref_observers_.begin();
        it != pref_observers_.end(); ++it) {
-    PrefObserverList::Iterator obs_iterator(*(it->second));
+    PrefObserverList::Iterator obs_iterator(it->second);
     if (obs_iterator.GetNext()) {
       LOG(WARNING) << "pref observer found at shutdown " << it->first;
     }
diff --git a/base/prefs/pref_notifier_impl_unittest.cc b/base/prefs/pref_notifier_impl_unittest.cc
index 0ecf138..c3cbf4f 100644
--- a/base/prefs/pref_notifier_impl_unittest.cc
+++ b/base/prefs/pref_notifier_impl_unittest.cc
@@ -58,7 +58,7 @@
       return false;
 
     PrefObserverList* observer_list = observer_iterator->second;
-    PrefObserverList::Iterator it(*observer_list);
+    PrefObserverList::Iterator it(observer_list);
     PrefObserver* existing_obs;
     size_t count = 0;
     while ((existing_obs = it.GetNext()) != NULL) {
diff --git a/base/process/BUILD.gn b/base/process/BUILD.gn
new file mode 100644
index 0000000..125b451
--- /dev/null
+++ b/base/process/BUILD.gn
@@ -0,0 +1,107 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("process") {
+  sources = [
+    "internal_linux.cc",
+    "internal_linux.h",
+    "kill.cc",
+    "kill.h",
+    "kill_mac.cc",
+    "kill_posix.cc",
+    "kill_win.cc",
+    "launch.cc",
+    "launch.h",
+    "launch_ios.cc",
+    "launch_mac.cc",
+    "launch_posix.cc",
+    "launch_win.cc",
+    "memory.cc",
+    "memory.h",
+    "memory_linux.cc",
+    "memory_mac.mm",
+    "memory_win.cc",
+    "process.h",
+    "process_handle_freebsd.cc",
+    "process_handle_linux.cc",
+    "process_handle_mac.cc",
+    "process_handle_openbsd.cc",
+    "process_handle_posix.cc",
+    "process_handle_win.cc",
+    "process_info.h",
+    "process_info_linux.cc",
+    "process_info_mac.cc",
+    "process_info_win.cc",
+    "process_iterator.cc",
+    "process_iterator.h",
+    "process_iterator_freebsd.cc",
+    "process_iterator_linux.cc",
+    "process_iterator_mac.cc",
+    "process_iterator_openbsd.cc",
+    "process_iterator_win.cc",
+    "process_linux.cc",
+    "process_metrics.cc",
+    "process_metrics.h",
+    "process_metrics_freebsd.cc",
+    "process_metrics_ios.cc",
+    "process_metrics_linux.cc",
+    "process_metrics_mac.cc",
+    "process_metrics_openbsd.cc",
+    "process_metrics_posix.cc",
+    "process_metrics_win.cc",
+    "process_posix.cc",
+    "process_win.cc",
+  ]
+
+  sources -= [
+    "process_handle_freebsd.cc",
+    "process_handle_openbsd.cc",
+    "process_iterator_freebsd.cc",
+    "process_iterator_openbsd.cc",
+    "process_metrics_freebsd.cc",
+    "process_metrics_openbsd.cc",
+  ]
+
+  if (is_android) {
+    # Android uses some Linux sources, put those back.
+    set_sources_assignment_filter([])
+    sources += [
+      "internal_linux.cc",
+      "memory_linux.cc",
+      "process_handle_linux.cc",
+      "process_iterator_linux.cc",
+      "process_metrics_linux.cc",
+    ]
+    set_sources_assignment_filter(sources_assignment_filter)
+  }
+
+  if (is_nacl) {
+    sources -= [
+      "kill.cc",
+      "kill.h",
+      "kill_posix.cc",
+      "launch.cc",
+      "launch.h",
+      "launch_posix.cc",
+      "memory.cc",
+      "memory.h",
+      "process_iterator.cc",
+      "process_iterator.h",
+      "process_metrics.cc",
+      "process_metrics_posix.cc",
+      "process_posix.cc",
+    ]
+  }
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  deps = [
+    "//base/memory",
+    "//base/third_party/dynamic_annotations",
+  ]
+
+  allow_circular_includes_from = [ "//base/memory" ]
+
+  visibility = [ "//base/*" ]
+}
diff --git a/base/process/internal_linux.h b/base/process/internal_linux.h
index 5fc3356..1837f94 100644
--- a/base/process/internal_linux.h
+++ b/base/process/internal_linux.h
@@ -5,8 +5,8 @@
 // This file contains internal routines that are called by other files in
 // base/process/.
 
-#ifndef BASE_PROCESS_LINUX_INTERNAL_H_
-#define BASE_PROCESS_LINUX_INTERNAL_H_
+#ifndef BASE_PROCESS_INTERNAL_LINUX_H_
+#define BASE_PROCESS_INTERNAL_LINUX_H_
 
 #include <unistd.h>
 
@@ -87,4 +87,4 @@
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_PROCESS_LINUX_INTERNAL_H_
+#endif  // BASE_PROCESS_INTERNAL_LINUX_H_
diff --git a/base/process/kill_mac.cc b/base/process/kill_mac.cc
index 8c42400..a4e0a14 100644
--- a/base/process/kill_mac.cc
+++ b/base/process/kill_mac.cc
@@ -66,8 +66,8 @@
 // work in that case, but waitpid won't, and killing a non-child might not be
 // the best approach.
 void WaitForChildToDie(pid_t child, int timeout) {
-  DCHECK(child > 0);
-  DCHECK(timeout > 0);
+  DCHECK_GT(child, 0);
+  DCHECK_GT(timeout, 0);
 
   // DON'T ADD ANY EARLY RETURNS TO THIS FUNCTION without ensuring that
   // |child| has been reaped. Specifically, even if a kqueue, kevent, or other
diff --git a/base/process/memory.cc b/base/process/memory.cc
index 1dbc363..8542dc5 100644
--- a/base/process/memory.cc
+++ b/base/process/memory.cc
@@ -27,4 +27,4 @@
 
 #endif
 
-}
+}  // namespace base
diff --git a/base/process/process.h b/base/process/process.h
index a834a29..41eef10 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_PROCESS_PROCESS_PROCESS_H_
-#define BASE_PROCESS_PROCESS_PROCESS_H_
+#ifndef BASE_PROCESS_PROCESS_H_
+#define BASE_PROCESS_PROCESS_H_
 
 #include "base/base_export.h"
 #include "base/basictypes.h"
@@ -92,9 +92,11 @@
   void Close();
 
   // Terminates the process with extreme prejudice. The given |result_code| will
-  // be the exit code of the process.
+  // be the exit code of the process. If |wait| is true, this method will wait
+  // for up to one minute for the process to actually terminate.
+  // Returns true if the process terminates within the allowed time.
   // NOTE: On POSIX |result_code| is ignored.
-  void Terminate(int result_code);
+  bool Terminate(int result_code, bool wait) const;
 
   // Waits for the process to exit. Returns true on success.
   // On POSIX, if the process has been signaled then |exit_code| is set to -1.
@@ -130,4 +132,4 @@
 
 }  // namespace base
 
-#endif  // BASE_PROCESS_PROCESS_PROCESS_H_
+#endif  // BASE_PROCESS_PROCESS_H_
diff --git a/base/process/process_linux.cc b/base/process/process_linux.cc
index 59ee288..88a310e 100644
--- a/base/process/process_linux.cc
+++ b/base/process/process_linux.cc
@@ -103,7 +103,7 @@
             &proc)) {
       std::vector<std::string> proc_parts;
       base::SplitString(proc, ':', &proc_parts);
-      DCHECK(proc_parts.size() == 3);
+      DCHECK_EQ(proc_parts.size(), 3u);
       bool ret = proc_parts[2] == std::string(kBackground);
       return ret;
     } else {
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
index dbfaa1a..76767b0 100644
--- a/base/process/process_metrics_unittest.cc
+++ b/base/process/process_metrics_unittest.cc
@@ -143,29 +143,29 @@
     "Hugepagesize:     4096 kB\n";
 
   EXPECT_TRUE(ParseProcMeminfo(valid_input1, &meminfo));
-  EXPECT_TRUE(meminfo.total == 3981504);
-  EXPECT_TRUE(meminfo.free == 140764);
-  EXPECT_TRUE(meminfo.buffers == 116480);
-  EXPECT_TRUE(meminfo.cached == 406160);
-  EXPECT_TRUE(meminfo.active_anon == 2972352);
-  EXPECT_TRUE(meminfo.active_file == 179688);
-  EXPECT_TRUE(meminfo.inactive_anon == 270108);
-  EXPECT_TRUE(meminfo.inactive_file == 202748);
-  EXPECT_TRUE(meminfo.swap_total == 5832280);
-  EXPECT_TRUE(meminfo.swap_free == 3672368);
-  EXPECT_TRUE(meminfo.dirty == 184);
+  EXPECT_EQ(meminfo.total, 3981504);
+  EXPECT_EQ(meminfo.free, 140764);
+  EXPECT_EQ(meminfo.buffers, 116480);
+  EXPECT_EQ(meminfo.cached, 406160);
+  EXPECT_EQ(meminfo.active_anon, 2972352);
+  EXPECT_EQ(meminfo.active_file, 179688);
+  EXPECT_EQ(meminfo.inactive_anon, 270108);
+  EXPECT_EQ(meminfo.inactive_file, 202748);
+  EXPECT_EQ(meminfo.swap_total, 5832280);
+  EXPECT_EQ(meminfo.swap_free, 3672368);
+  EXPECT_EQ(meminfo.dirty, 184);
 #if defined(OS_CHROMEOS)
-  EXPECT_TRUE(meminfo.shmem == 140204);
-  EXPECT_TRUE(meminfo.slab == 54212);
+  EXPECT_EQ(meminfo.shmem, 140204);
+  EXPECT_EQ(meminfo.slab, 54212);
 #endif
   EXPECT_TRUE(ParseProcMeminfo(valid_input2, &meminfo));
-  EXPECT_TRUE(meminfo.total == 255908);
-  EXPECT_TRUE(meminfo.free == 69936);
-  EXPECT_TRUE(meminfo.buffers == 15812);
-  EXPECT_TRUE(meminfo.cached == 115124);
-  EXPECT_TRUE(meminfo.swap_total == 524280);
-  EXPECT_TRUE(meminfo.swap_free == 524200);
-  EXPECT_TRUE(meminfo.dirty == 4);
+  EXPECT_EQ(meminfo.total, 255908);
+  EXPECT_EQ(meminfo.free, 69936);
+  EXPECT_EQ(meminfo.buffers, 15812);
+  EXPECT_EQ(meminfo.cached, 115124);
+  EXPECT_EQ(meminfo.swap_total, 524280);
+  EXPECT_EQ(meminfo.swap_free, 524200);
+  EXPECT_EQ(meminfo.dirty, 4);
 }
 
 TEST_F(SystemMetricsTest, ParseVmstat) {
@@ -260,13 +260,13 @@
     "pgrefill_high 0\n"
     "pgrefill_movable 0\n";
   EXPECT_TRUE(ParseProcVmstat(valid_input1, &meminfo));
-  EXPECT_TRUE(meminfo.pswpin == 179);
-  EXPECT_TRUE(meminfo.pswpout == 406);
-  EXPECT_TRUE(meminfo.pgmajfault == 487192);
+  EXPECT_EQ(meminfo.pswpin, 179);
+  EXPECT_EQ(meminfo.pswpout, 406);
+  EXPECT_EQ(meminfo.pgmajfault, 487192);
   EXPECT_TRUE(ParseProcVmstat(valid_input2, &meminfo));
-  EXPECT_TRUE(meminfo.pswpin == 12);
-  EXPECT_TRUE(meminfo.pswpout == 901);
-  EXPECT_TRUE(meminfo.pgmajfault == 2023);
+  EXPECT_EQ(meminfo.pswpin, 12);
+  EXPECT_EQ(meminfo.pswpout, 901);
+  EXPECT_EQ(meminfo.pgmajfault, 2023);
 }
 #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
 
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index a36bf77..1c4210b 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -287,12 +287,13 @@
   // end up w/ a zombie when it does finally exit.
 }
 
-void Process::Terminate(int result_code) {
+bool Process::Terminate(int result_code, bool wait) const {
   // result_code isn't supportable.
   DCHECK(IsValid());
   // We don't wait here. It's the responsibility of other code to reap the
   // child.
-  KillProcess(process_, result_code, false);
+  // TODO(rvargas) crbug/417532: Move the implementation here.
+  return KillProcess(process_, result_code, wait);
 }
 
 bool Process::WaitForExit(int* exit_code) {
@@ -324,4 +325,4 @@
   return getpriority(PRIO_PROCESS, process_);
 }
 
-}  // namspace base
+}  // namespace base
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc
index 535a36f..ba8e4e6 100644
--- a/base/process/process_unittest.cc
+++ b/base/process/process_unittest.cc
@@ -123,7 +123,7 @@
 
   exit_code = kDummyExitCode;
   int kExpectedExitCode = 250;
-  process.Terminate(kExpectedExitCode);
+  process.Terminate(kExpectedExitCode, false);
   process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
                                  &exit_code);
 
@@ -160,7 +160,7 @@
   EXPECT_FALSE(process.WaitForExitWithTimeout(timeout, &exit_code));
   EXPECT_EQ(kDummyExitCode, exit_code);
 
-  process.Terminate(kDummyExitCode);
+  process.Terminate(kDummyExitCode, false);
 }
 
 // Ensure that the priority of a process is restored correctly after
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index b62fdb4..32da8ab 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -123,17 +123,10 @@
   process_.Close();
 }
 
-void Process::Terminate(int result_code) {
+bool Process::Terminate(int result_code, bool wait) const {
   DCHECK(IsValid());
-
-  // Call NtTerminateProcess directly, without going through the import table,
-  // which might have been hooked with a buggy replacement by third party
-  // software. http://crbug.com/81449.
-  HMODULE module = GetModuleHandle(L"ntdll.dll");
-  typedef UINT (WINAPI *TerminateProcessPtr)(HANDLE handle, UINT code);
-  TerminateProcessPtr terminate_process = reinterpret_cast<TerminateProcessPtr>(
-      GetProcAddress(module, "NtTerminateProcess"));
-  terminate_process(Handle(), result_code);
+  // TODO(rvargas) crbug/417532: Move the implementation here.
+  return KillProcess(Handle(), result_code, wait);
 }
 
 bool Process::WaitForExit(int* exit_code) {
diff --git a/base/scoped_generic.h b/base/scoped_generic.h
index da42609..f6807e2 100644
--- a/base/scoped_generic.h
+++ b/base/scoped_generic.h
@@ -53,7 +53,7 @@
 //   typedef ScopedGeneric<int, FooScopedTraits> ScopedFoo;
 template<typename T, typename Traits>
 class ScopedGeneric {
-  MOVE_ONLY_TYPE_FOR_CPP_03(ScopedGeneric, RValue)
+  MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(ScopedGeneric)
 
  private:
   // This must be first since it's used inline below.
@@ -83,15 +83,21 @@
       : data_(value, traits) {
   }
 
-  // Move constructor for C++03 move emulation.
-  ScopedGeneric(RValue rvalue)
-      : data_(rvalue.object->release(), rvalue.object->get_traits()) {
+  // Move constructor. Allows initialization from a ScopedGeneric rvalue.
+  ScopedGeneric(ScopedGeneric<T, Traits>&& rvalue)
+      : data_(rvalue.release(), rvalue.get_traits()) {
   }
 
   ~ScopedGeneric() {
     FreeIfNecessary();
   }
 
+  // operator=. Allows assignment from a ScopedGeneric rvalue.
+  ScopedGeneric& operator=(ScopedGeneric<T, Traits>&& rvalue) {
+    reset(rvalue.release());
+    return *this;
+  }
+
   // Frees the currently owned object, if any. Then takes ownership of a new
   // object, if given. Self-resets are not allowd as on scoped_ptr. See
   // http://crbug.com/162971
diff --git a/base/scoped_generic_unittest.cc b/base/scoped_generic_unittest.cc
index f0dca22..b28e154 100644
--- a/base/scoped_generic_unittest.cc
+++ b/base/scoped_generic_unittest.cc
@@ -85,7 +85,7 @@
   EXPECT_EQ(kSecond, values_freed[1]);
   values_freed.clear();
 
-  // Pass.
+  // Pass constructor.
   {
     ScopedInt a(kFirst, traits);
     ScopedInt b(a.Pass());
@@ -93,8 +93,25 @@
     ASSERT_EQ(IntTraits::InvalidValue(), a.get());
     ASSERT_EQ(kFirst, b.get());
   }
+
   ASSERT_EQ(1u, values_freed.size());
   ASSERT_EQ(kFirst, values_freed[0]);
+  values_freed.clear();
+
+  // Pass assign.
+  {
+    ScopedInt a(kFirst, traits);
+    ScopedInt b(kSecond, traits);
+    b = a.Pass();
+    ASSERT_EQ(1u, values_freed.size());
+    EXPECT_EQ(kSecond, values_freed[0]);
+    ASSERT_EQ(IntTraits::InvalidValue(), a.get());
+    ASSERT_EQ(kFirst, b.get());
+  }
+
+  ASSERT_EQ(2u, values_freed.size());
+  EXPECT_EQ(kFirst, values_freed[1]);
+  values_freed.clear();
 }
 
 TEST(ScopedGenericTest, Operators) {
diff --git a/base/scoped_native_library.h b/base/scoped_native_library.h
index e9923f4..c0e93f3 100644
--- a/base/scoped_native_library.h
+++ b/base/scoped_native_library.h
@@ -49,4 +49,4 @@
 
 }  // namespace base
 
-#endif  // BASE_MEMORY_NATIVE_LIBRARY_H_
+#endif  // BASE_SCOPED_NATIVE_LIBRARY_H_
diff --git a/base/sequenced_task_runner.h b/base/sequenced_task_runner.h
index 71dcf05..6bb3f2b 100644
--- a/base/sequenced_task_runner.h
+++ b/base/sequenced_task_runner.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_SEQUENCED_TASKRUNNER_H_
-#define BASE_SEQUENCED_TASKRUNNER_H_
+#ifndef BASE_SEQUENCED_TASK_RUNNER_H_
+#define BASE_SEQUENCED_TASK_RUNNER_H_
 
 #include "base/base_export.h"
 #include "base/sequenced_task_runner_helpers.h"
@@ -156,4 +156,4 @@
 
 }  // namespace base
 
-#endif  // BASE_SEQUENCED_TASKRUNNER_H_
+#endif  // BASE_SEQUENCED_TASK_RUNNER_H_
diff --git a/base/stl_util_unittest.cc b/base/stl_util_unittest.cc
index 06ea7cd..42004eb 100644
--- a/base/stl_util_unittest.cc
+++ b/base/stl_util_unittest.cc
@@ -28,7 +28,7 @@
   int value_;
 };
 
-}
+}  // namespace
 
 namespace base {
 namespace {
diff --git a/base/strings/nullable_string16.h b/base/strings/nullable_string16.h
index 5997d17..016c25c 100644
--- a/base/strings/nullable_string16.h
+++ b/base/strings/nullable_string16.h
@@ -41,6 +41,6 @@
 BASE_EXPORT std::ostream& operator<<(std::ostream& out,
                                      const NullableString16& value);
 
-}  // namespace
+}  // namespace base
 
 #endif  // BASE_STRINGS_NULLABLE_STRING16_H_
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc
index 7f50cfb..5336603 100644
--- a/base/strings/string_piece_unittest.cc
+++ b/base/strings/string_piece_unittest.cc
@@ -602,13 +602,13 @@
 
   // check comparison operations on strings longer than 4 bytes.
   ASSERT_TRUE(abc == BasicStringPiece<TypeParam>(alphabet));
-  ASSERT_TRUE(abc.compare(BasicStringPiece<TypeParam>(alphabet)) == 0);
+  ASSERT_EQ(abc.compare(BasicStringPiece<TypeParam>(alphabet)), 0);
 
   ASSERT_TRUE(abc < BasicStringPiece<TypeParam>(alphabet_z));
-  ASSERT_TRUE(abc.compare(BasicStringPiece<TypeParam>(alphabet_z)) < 0);
+  ASSERT_LT(abc.compare(BasicStringPiece<TypeParam>(alphabet_z)), 0);
 
   ASSERT_TRUE(abc > BasicStringPiece<TypeParam>(alphabet_y));
-  ASSERT_TRUE(abc.compare(BasicStringPiece<TypeParam>(alphabet_y)) > 0);
+  ASSERT_GT(abc.compare(BasicStringPiece<TypeParam>(alphabet_y)), 0);
 }
 
 // Test operations only supported by std::string version.
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc
index 7ef4760..692f300 100644
--- a/base/strings/string_split.cc
+++ b/base/strings/string_split.cc
@@ -138,9 +138,9 @@
                  char c,
                  std::vector<std::string>* r) {
 #if CHAR_MIN < 0
-  DCHECK(c >= 0);
+  DCHECK_GE(c, 0);
 #endif
-  DCHECK(c < 0x7F);
+  DCHECK_LT(c, 0x7F);
   SplitStringT(str, c, true, r);
 }
 
@@ -195,9 +195,9 @@
                          std::vector<std::string>* r) {
   DCHECK(IsStringUTF8(str));
 #if CHAR_MIN < 0
-  DCHECK(c >= 0);
+  DCHECK_GE(c, 0);
 #endif
-  DCHECK(c < 0x7F);
+  DCHECK_LT(c, 0x7F);
   SplitStringT(str, c, false, r);
 }
 
diff --git a/base/strings/sys_string_conversions_unittest.cc b/base/strings/sys_string_conversions_unittest.cc
index d2d38e4..0cdd428 100644
--- a/base/strings/sys_string_conversions_unittest.cc
+++ b/base/strings/sys_string_conversions_unittest.cc
@@ -75,7 +75,9 @@
 #if defined(OS_LINUX)  // Tests depend on setting a specific Linux locale.
 
 TEST(SysStrings, SysWideToNativeMB) {
+#if !defined(SYSTEM_NATIVE_UTF8)
   ScopedLocale locale("en_US.utf-8");
+#endif
   EXPECT_EQ("Hello, world", SysWideToNativeMB(L"Hello, world"));
   EXPECT_EQ("\xe4\xbd\xa0\xe5\xa5\xbd", SysWideToNativeMB(L"\x4f60\x597d"));
 
@@ -105,7 +107,9 @@
 
 // We assume the test is running in a UTF8 locale.
 TEST(SysStrings, SysNativeMBToWide) {
+#if !defined(SYSTEM_NATIVE_UTF8)
   ScopedLocale locale("en_US.utf-8");
+#endif
   EXPECT_EQ(L"Hello, world", SysNativeMBToWide("Hello, world"));
   EXPECT_EQ(L"\x4f60\x597d", SysNativeMBToWide("\xe4\xbd\xa0\xe5\xa5\xbd"));
   // >16 bits
@@ -159,7 +163,9 @@
 
 
 TEST(SysStrings, SysNativeMBAndWide) {
+#if !defined(SYSTEM_NATIVE_UTF8)
   ScopedLocale locale("en_US.utf-8");
+#endif
   for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) {
     std::wstring wide = kConvertRoundtripCases[i];
     std::wstring trip = SysNativeMBToWide(SysWideToNativeMB(wide));
diff --git a/base/strings/utf_offset_string_conversions_unittest.cc b/base/strings/utf_offset_string_conversions_unittest.cc
index 529939f..9398a56 100644
--- a/base/strings/utf_offset_string_conversions_unittest.cc
+++ b/base/strings/utf_offset_string_conversions_unittest.cc
@@ -293,4 +293,4 @@
   EXPECT_EQ(2u, adjustments_on_adjusted_string[5].output_length);
 }
 
-}  // namaspace base
+}  // namespace base
diff --git a/base/strings/utf_string_conversions_unittest.cc b/base/strings/utf_string_conversions_unittest.cc
index 009af7c..a7b12ff 100644
--- a/base/strings/utf_string_conversions_unittest.cc
+++ b/base/strings/utf_string_conversions_unittest.cc
@@ -208,4 +208,4 @@
   EXPECT_EQ(expected, converted);
 }
 
-}  // base
+}  // namespace base
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc
index b62aed9..245097f 100644
--- a/base/sys_info_android.cc
+++ b/base/sys_info_android.cc
@@ -60,7 +60,7 @@
 // version to avoid unnecessarily comparison errors with the latest release.
 // This should be manually kept up-to-date on each Android release.
 const int kDefaultAndroidMajorVersion = 5;
-const int kDefaultAndroidMinorVersion = 0;
+const int kDefaultAndroidMinorVersion = 1;
 const int kDefaultAndroidBugfixVersion = 99;
 
 // Parse out the OS version numbers from the system properties.
diff --git a/base/sys_info_linux.cc b/base/sys_info_linux.cc
index 2e679ed..c698f91 100644
--- a/base/sys_info_linux.cc
+++ b/base/sys_info_linux.cc
@@ -43,7 +43,7 @@
   if (limit > std::numeric_limits<size_t>::max()) {
     limit = 0;
   }
-  DCHECK(limit > 0);
+  DCHECK_GT(limit, 0u);
   return static_cast<size_t>(limit);
 }
 
diff --git a/base/system_monitor/system_monitor_unittest.cc b/base/system_monitor/system_monitor_unittest.cc
index d63bc3d..f3db4c7 100644
--- a/base/system_monitor/system_monitor_unittest.cc
+++ b/base/system_monitor/system_monitor_unittest.cc
@@ -23,6 +23,7 @@
   MessageLoop message_loop_;
   scoped_ptr<SystemMonitor> system_monitor_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(SystemMonitorTest);
 };
 
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 120159e..55e710d 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -8,6 +8,20 @@
   import("//build/config/android/rules.gni")
 }
 
+source_set("test_config") {
+  # TODO http://crbug.com/412064 enable this flag all the time.
+  testonly = !is_component_build
+  sources = [
+    "test_switches.cc",
+    "test_switches.h",
+    "test_timeouts.cc",
+    "test_timeouts.h",
+  ]
+  deps = [
+    "//base",
+  ]
+}
+
 # GYP: //base/base.gyp:test_support_base
 source_set("test_support") {
   # TODO http://crbug.com/412064 enable this flag all the time.
@@ -94,10 +108,6 @@
     "test_support_android.h",
     "test_support_ios.h",
     "test_support_ios.mm",
-    "test_switches.cc",
-    "test_switches.h",
-    "test_timeouts.cc",
-    "test_timeouts.h",
     "thread_test_helper.cc",
     "thread_test_helper.h",
     "trace_event_analyzer.cc",
@@ -109,6 +119,7 @@
   ]
 
   public_deps = [
+    ":test_config",
     "//base",
     "//base:i18n",
     "//base:base_static",
diff --git a/base/test/histogram_tester.cc b/base/test/histogram_tester.cc
index 412059a..ea738b0 100644
--- a/base/test/histogram_tester.cc
+++ b/base/test/histogram_tester.cc
@@ -90,7 +90,7 @@
     const std::string& name,
     base::HistogramBase::Sample sample,
     base::HistogramBase::Count expected_count,
-    base::HistogramSamples& samples) const {
+    const base::HistogramSamples& samples) const {
   int actual_count = samples.GetCount(sample);
   std::map<std::string, HistogramSamples*>::const_iterator histogram_data;
   histogram_data = histograms_snapshot_.find(name);
@@ -104,9 +104,10 @@
       << ").";
 }
 
-void HistogramTester::CheckTotalCount(const std::string& name,
-                                      base::HistogramBase::Count expected_count,
-                                      base::HistogramSamples& samples) const {
+void HistogramTester::CheckTotalCount(
+    const std::string& name,
+    base::HistogramBase::Count expected_count,
+    const base::HistogramSamples& samples) const {
   int actual_count = samples.TotalCount();
   std::map<std::string, HistogramSamples*>::const_iterator histogram_data;
   histogram_data = histograms_snapshot_.find(name);
diff --git a/base/test/histogram_tester.h b/base/test/histogram_tester.h
index b672308..96317f9 100644
--- a/base/test/histogram_tester.h
+++ b/base/test/histogram_tester.h
@@ -59,14 +59,14 @@
   void CheckBucketCount(const std::string& name,
                         base::HistogramBase::Sample sample,
                         base::Histogram::Count expected_count,
-                        base::HistogramSamples& samples) const;
+                        const base::HistogramSamples& samples) const;
 
   // Verifies that the total number of values recorded for the histogram |name|
   // is |expected_count|. This is checked against |samples| minus the snapshot
   // that was taken for |name|.
   void CheckTotalCount(const std::string& name,
                        base::Histogram::Count expected_count,
-                       base::HistogramSamples& samples) const;
+                       const base::HistogramSamples& samples) const;
 
   // Used to determine the histogram changes made during this instance's
   // lifecycle. This instance takes ownership of the samples, which are deleted
diff --git a/base/test/mock_devices_changed_observer.h b/base/test/mock_devices_changed_observer.h
index 3ada16b..3255002 100644
--- a/base/test/mock_devices_changed_observer.h
+++ b/base/test/mock_devices_changed_observer.h
@@ -21,6 +21,7 @@
   MOCK_METHOD1(OnDevicesChanged,
                void(base::SystemMonitor::DeviceType device_type));
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(MockDevicesChangedObserver);
 };
 
diff --git a/base/test/null_task_runner.cc b/base/test/null_task_runner.cc
index bf43e6d..ffa6bdf 100644
--- a/base/test/null_task_runner.cc
+++ b/base/test/null_task_runner.cc
@@ -28,4 +28,4 @@
   return true;
 }
 
-}  // namespace
+}  // namespace base
diff --git a/base/test/null_task_runner.h b/base/test/null_task_runner.h
index 2cde880..0f44751 100644
--- a/base/test/null_task_runner.h
+++ b/base/test/null_task_runner.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef BASE_TEST_NULL_TASK_RUNNER_H_
+#define BASE_TEST_NULL_TASK_RUNNER_H_
+
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/single_thread_task_runner.h"
@@ -30,4 +33,6 @@
   DISALLOW_COPY_AND_ASSIGN(NullTaskRunner);
 };
 
-}  // namespace
+}  // namespace base
+
+#endif  // BASE_TEST_NULL_TASK_RUNNER_H_
diff --git a/base/test/sequenced_task_runner_test_template.h b/base/test/sequenced_task_runner_test_template.h
index 48f5354..c208d3c 100644
--- a/base/test/sequenced_task_runner_test_template.h
+++ b/base/test/sequenced_task_runner_test_template.h
@@ -6,8 +6,8 @@
 // pass in order to be conformant. See task_runner_test_template.h for a
 // description of how to use the constructs in this file; these work the same.
 
-#ifndef BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
-#define BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
+#ifndef BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
+#define BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
 
 #include <cstddef>
 #include <iosfwd>
@@ -338,4 +338,4 @@
 
 }  // namespace base
 
-#endif  // BASE_TASK_RUNNER_TEST_TEMPLATE_H_
+#endif  // BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
diff --git a/base/test/sequenced_worker_pool_owner.h b/base/test/sequenced_worker_pool_owner.h
index b52dd67..bf5f2f7 100644
--- a/base/test/sequenced_worker_pool_owner.h
+++ b/base/test/sequenced_worker_pool_owner.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_UNITTEST_H_
-#define BASE_THREADING_SEQUENCED_WORKER_POOL_UNITTEST_H_
+#ifndef BASE_TEST_SEQUENCED_WORKER_POOL_OWNER_H_
+#define BASE_TEST_SEQUENCED_WORKER_POOL_OWNER_H_
 
 #include <cstddef>
 #include <string>
@@ -58,4 +58,4 @@
 
 }  // namespace base
 
-#endif  // BASE_THREADING_SEQUENCED_WORKER_POOL_UNITTEST_H_
+#endif  // BASE_TEST_SEQUENCED_WORKER_POOL_OWNER_H_
diff --git a/base/test/simple_test_clock.h b/base/test/simple_test_clock.h
index e8a79c5..a70f99c 100644
--- a/base/test/simple_test_clock.h
+++ b/base/test/simple_test_clock.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_SIMPLE_TEST_CLOCK_H_
-#define BASE_SIMPLE_TEST_CLOCK_H_
+#ifndef BASE_TEST_SIMPLE_TEST_CLOCK_H_
+#define BASE_TEST_SIMPLE_TEST_CLOCK_H_
 
 #include "base/compiler_specific.h"
 #include "base/synchronization/lock.h"
@@ -38,4 +38,4 @@
 
 }  // namespace base
 
-#endif  // BASE_SIMPLE_TEST_CLOCK_H_
+#endif  // BASE_TEST_SIMPLE_TEST_CLOCK_H_
diff --git a/base/test/simple_test_tick_clock.h b/base/test/simple_test_tick_clock.h
index a637543..aebdebc 100644
--- a/base/test/simple_test_tick_clock.h
+++ b/base/test/simple_test_tick_clock.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_SIMPLE_TEST_TICK_CLOCK_H_
-#define BASE_SIMPLE_TEST_TICK_CLOCK_H_
+#ifndef BASE_TEST_SIMPLE_TEST_TICK_CLOCK_H_
+#define BASE_TEST_SIMPLE_TEST_TICK_CLOCK_H_
 
 #include "base/compiler_specific.h"
 #include "base/synchronization/lock.h"
@@ -35,4 +35,4 @@
 
 }  // namespace base
 
-#endif  // BASE_SIMPLE_TEST_TICK_CLOCK_H_
+#endif  // BASE_TEST_SIMPLE_TEST_TICK_CLOCK_H_
diff --git a/base/test/task_runner_test_template.h b/base/test/task_runner_test_template.h
index 73aa1f4..9bcf70b 100644
--- a/base/test/task_runner_test_template.h
+++ b/base/test/task_runner_test_template.h
@@ -212,4 +212,4 @@
 
 }  // namespace base
 
-#endif  //#define BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
+#endif  // BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
diff --git a/base/test/test_file_util_win.cc b/base/test/test_file_util_win.cc
index af8bd76..5496a55 100644
--- a/base/test/test_file_util_win.cc
+++ b/base/test/test_file_util_win.cc
@@ -175,7 +175,7 @@
     // Move back to the position we just read from.
     // Note that SetFilePointer will also fail if total_bytes isn't sector
     // aligned, but that shouldn't happen here.
-    DCHECK((total_bytes % kOneMB) == 0);
+    DCHECK_EQ(total_bytes % kOneMB, 0);
     SetFilePointer(file_handle.Get(), total_bytes, NULL, FILE_BEGIN);
     if (!::WriteFile(file_handle.Get(), buffer, kOneMB, &bytes_written, NULL) ||
         bytes_written != kOneMB) {
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc
index 8e65ccf..6bcab8b 100644
--- a/base/test/test_mock_time_task_runner.cc
+++ b/base/test/test_mock_time_task_runner.cc
@@ -100,6 +100,13 @@
   ProcessAllTasksNoLaterThan(TimeDelta::Max());
 }
 
+void TestMockTimeTaskRunner::ClearPendingTasks() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  AutoLock scoped_lock(tasks_lock_);
+  while (!tasks_.empty())
+    tasks_.pop();
+}
+
 Time TestMockTimeTaskRunner::Now() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   return now_;
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index 5f06013..c38fd6d 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -61,6 +61,9 @@
   // elapse.
   void RunUntilIdle();
 
+  // Clears the queue of pending tasks without running them.
+  void ClearPendingTasks();
+
   // Returns the current virtual time (initially starting at the Unix epoch).
   Time Now() const;
 
diff --git a/base/test/test_reg_util_win.h b/base/test/test_reg_util_win.h
index db71838..5f23b7f 100644
--- a/base/test/test_reg_util_win.h
+++ b/base/test/test_reg_util_win.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_TEST_TEST_REG_UTIL_H_
-#define BASE_TEST_TEST_REG_UTIL_H_
+#ifndef BASE_TEST_TEST_REG_UTIL_WIN_H_
+#define BASE_TEST_TEST_REG_UTIL_WIN_H_
 
 // Registry utility functions used only by tests.
 
@@ -74,4 +74,4 @@
 
 }  // namespace registry_util
 
-#endif  // BASE_TEST_TEST_REG_UTIL_H_
+#endif  // BASE_TEST_TEST_REG_UTIL_WIN_H_
diff --git a/base/third_party/dynamic_annotations/BUILD.gn b/base/third_party/dynamic_annotations/BUILD.gn
index d6a5123..bc324ae 100644
--- a/base/third_party/dynamic_annotations/BUILD.gn
+++ b/base/third_party/dynamic_annotations/BUILD.gn
@@ -6,7 +6,10 @@
   # Native client doesn't need dynamic annotations, so we provide a
   # dummy target in order for clients to not have to special-case the
   # dependency.
-  group("dynamic_annotations") {
+  source_set("dynamic_annotations") {
+    sources = [
+      "dynamic_annotations.h",
+    ]
   }
 } else {
   source_set("dynamic_annotations") {
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 19b81b7..f20d997 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -1091,7 +1091,7 @@
 void SequencedWorkerPool::Inner::FinishStartingAdditionalThread(
     int thread_number) {
   // Called outside of the lock.
-  DCHECK(thread_number > 0);
+  DCHECK_GT(thread_number, 0);
 
   // The worker is assigned to the list when the thread actually starts, which
   // will manage the memory of the pointer.
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc
index 9d0f607..c132731 100644
--- a/base/threading/sequenced_worker_pool_unittest.cc
+++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -54,7 +54,7 @@
   void Unblock(size_t count) {
     {
       base::AutoLock lock(lock_);
-      DCHECK(unblock_counter_ == 0);
+      DCHECK_EQ(unblock_counter_, 0u);
       unblock_counter_ = count;
     }
     cond_var_.Signal();
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index ad1360b..ea5b174 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -6,11 +6,12 @@
 
 #include "base/bind.h"
 #include "base/lazy_instance.h"
+#include "base/profiler/scoped_tracker.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/thread_id_name_manager.h"
 #include "base/threading/thread_local.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/synchronization/waitable_event.h"
 
 #if defined(OS_WIN)
 #include "base/win/scoped_com_initializer.h"
@@ -94,6 +95,11 @@
 }
 
 bool Thread::StartWithOptions(const Options& options) {
+  // TODO(eroman): Remove once crbug.com/465458 is solved.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+        "465458 base::Thread::StartWithOptions"));
+
   DCHECK(!message_loop_);
 #if defined(OS_WIN)
   DCHECK((com_status_ != STA) ||
@@ -111,6 +117,11 @@
     return false;
   }
 
+  // TODO(eroman): Remove once crbug.com/465458 is solved.
+  tracked_objects::ScopedTracker tracking_profile_wait(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "465458 base::Thread::StartWithOptions (Wait)"));
+
   // Wait for the thread to start and initialize message_loop_
   base::ThreadRestrictions::ScopedAllowWait allow_wait;
   startup_data.event.Wait();
diff --git a/base/threading/thread_collision_warner_unittest.cc b/base/threading/thread_collision_warner_unittest.cc
index 26faff4..d7ce79e 100644
--- a/base/threading/thread_collision_warner_unittest.cc
+++ b/base/threading/thread_collision_warner_unittest.cc
@@ -146,24 +146,23 @@
 
   class QueueUser : public base::DelegateSimpleThread::Delegate {
    public:
-    explicit QueueUser(NonThreadSafeQueue& queue)
-        : queue_(queue) {}
+    explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
 
     void Run() override {
-      queue_.push(0);
-      queue_.pop();
+      queue_->push(0);
+      queue_->pop();
     }
 
    private:
-    NonThreadSafeQueue& queue_;
+    NonThreadSafeQueue* queue_;
   };
 
   AssertReporter* local_reporter = new AssertReporter();
 
   NonThreadSafeQueue queue(local_reporter);
 
-  QueueUser queue_user_a(queue);
-  QueueUser queue_user_b(queue);
+  QueueUser queue_user_a(&queue);
+  QueueUser queue_user_b(&queue);
 
   base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
   base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
@@ -204,24 +203,23 @@
 
   class QueueUser : public base::DelegateSimpleThread::Delegate {
    public:
-    explicit QueueUser(NonThreadSafeQueue& queue)
-        : queue_(queue) {}
+    explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
 
     void Run() override {
-      queue_.push(0);
-      queue_.pop();
+      queue_->push(0);
+      queue_->pop();
     }
 
    private:
-    NonThreadSafeQueue& queue_;
+    NonThreadSafeQueue* queue_;
   };
 
   AssertReporter* local_reporter = new AssertReporter();
 
   NonThreadSafeQueue queue(local_reporter);
 
-  QueueUser queue_user_a(queue);
-  QueueUser queue_user_b(queue);
+  QueueUser queue_user_a(&queue);
+  QueueUser queue_user_b(&queue);
 
   base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
   base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
@@ -264,23 +262,22 @@
   // a lock.
   class QueueUser : public base::DelegateSimpleThread::Delegate {
    public:
-    QueueUser(NonThreadSafeQueue& queue, base::Lock& lock)
-        : queue_(queue),
-          lock_(lock) {}
+    QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
+        : queue_(queue), lock_(lock) {}
 
     void Run() override {
       {
-        base::AutoLock auto_lock(lock_);
-        queue_.push(0);
+        base::AutoLock auto_lock(*lock_);
+        queue_->push(0);
       }
       {
-        base::AutoLock auto_lock(lock_);
-        queue_.pop();
+        base::AutoLock auto_lock(*lock_);
+        queue_->pop();
       }
     }
    private:
-    NonThreadSafeQueue& queue_;
-    base::Lock& lock_;
+    NonThreadSafeQueue* queue_;
+    base::Lock* lock_;
   };
 
   AssertReporter* local_reporter = new AssertReporter();
@@ -289,8 +286,8 @@
 
   base::Lock lock;
 
-  QueueUser queue_user_a(queue, lock);
-  QueueUser queue_user_b(queue, lock);
+  QueueUser queue_user_a(&queue, &lock);
+  QueueUser queue_user_b(&queue, &lock);
 
   base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
   base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
@@ -338,27 +335,26 @@
   // a lock.
   class QueueUser : public base::DelegateSimpleThread::Delegate {
    public:
-    QueueUser(NonThreadSafeQueue& queue, base::Lock& lock)
-        : queue_(queue),
-          lock_(lock) {}
+    QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
+        : queue_(queue), lock_(lock) {}
 
     void Run() override {
       {
-        base::AutoLock auto_lock(lock_);
-        queue_.push(0);
+        base::AutoLock auto_lock(*lock_);
+        queue_->push(0);
       }
       {
-        base::AutoLock auto_lock(lock_);
-        queue_.bar();
+        base::AutoLock auto_lock(*lock_);
+        queue_->bar();
       }
       {
-        base::AutoLock auto_lock(lock_);
-        queue_.pop();
+        base::AutoLock auto_lock(*lock_);
+        queue_->pop();
       }
     }
    private:
-    NonThreadSafeQueue& queue_;
-    base::Lock& lock_;
+    NonThreadSafeQueue* queue_;
+    base::Lock* lock_;
   };
 
   AssertReporter* local_reporter = new AssertReporter();
@@ -367,8 +363,8 @@
 
   base::Lock lock;
 
-  QueueUser queue_user_a(queue, lock);
-  QueueUser queue_user_b(queue, lock);
+  QueueUser queue_user_a(&queue, &lock);
+  QueueUser queue_user_b(&queue, &lock);
 
   base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
   base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
diff --git a/base/threading/thread_local_storage.h b/base/threading/thread_local_storage.h
index 53ebe55..ea41b34 100644
--- a/base/threading/thread_local_storage.h
+++ b/base/threading/thread_local_storage.h
@@ -136,6 +136,7 @@
     DISALLOW_COPY_AND_ASSIGN(Slot);
   };
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorage);
 };
 
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 1e5f510..75d8925 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -43,7 +43,7 @@
 class RenderWidgetResizeHelper;
 class ScopedAllowWaitForAndroidLayoutTests;
 class TextInputClientMac;
-}
+}  // namespace content
 namespace dbus {
 class Bus;
 }
diff --git a/base/threading/worker_pool_posix.cc b/base/threading/worker_pool_posix.cc
index 5aa50ba..32a5e92 100644
--- a/base/threading/worker_pool_posix.cc
+++ b/base/threading/worker_pool_posix.cc
@@ -27,14 +27,6 @@
 
 const int kIdleSecondsBeforeExit = 10 * 60;
 
-#ifdef ADDRESS_SANITIZER
-const int kWorkerThreadStackSize = 256 * 1024;
-#else
-// A stack size of 64 KB is too small for the CERT_PKIXVerifyCert
-// function of NSS because of NSS bug 439169.
-const int kWorkerThreadStackSize = 128 * 1024;
-#endif
-
 class WorkerPoolImpl {
  public:
   WorkerPoolImpl();
@@ -168,7 +160,7 @@
     // which will delete itself on exit.
     WorkerThread* worker =
         new WorkerThread(name_prefix_, this);
-    PlatformThread::CreateNonJoinable(kWorkerThreadStackSize, worker);
+    PlatformThread::CreateNonJoinable(0, worker);
   }
 }
 
diff --git a/base/time/clock.h b/base/time/clock.h
index be389be..507a850 100644
--- a/base/time/clock.h
+++ b/base/time/clock.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_CLOCK_H_
-#define BASE_CLOCK_H_
+#ifndef BASE_TIME_CLOCK_H_
+#define BASE_TIME_CLOCK_H_
 
 #include "base/base_export.h"
 #include "base/time/time.h"
@@ -37,4 +37,4 @@
 
 }  // namespace base
 
-#endif  // BASE_CLOCK_H_
+#endif  // BASE_TIME_CLOCK_H_
diff --git a/base/time/default_clock.h b/base/time/default_clock.h
index 3d2e947..0b8250e 100644
--- a/base/time/default_clock.h
+++ b/base/time/default_clock.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_DEFAULT_CLOCK_H_
-#define BASE_DEFAULT_CLOCK_H_
+#ifndef BASE_TIME_DEFAULT_CLOCK_H_
+#define BASE_TIME_DEFAULT_CLOCK_H_
 
 #include "base/base_export.h"
 #include "base/compiler_specific.h"
@@ -22,4 +22,4 @@
 
 }  // namespace base
 
-#endif  // BASE_DEFAULT_CLOCK_H_
+#endif  // BASE_TIME_DEFAULT_CLOCK_H_
diff --git a/base/time/default_tick_clock.h b/base/time/default_tick_clock.h
index a6d6b15..cb041e6 100644
--- a/base/time/default_tick_clock.h
+++ b/base/time/default_tick_clock.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_DEFAULT_TICK_CLOCK_H_
-#define BASE_DEFAULT_TICK_CLOCK_H_
+#ifndef BASE_TIME_DEFAULT_TICK_CLOCK_H_
+#define BASE_TIME_DEFAULT_TICK_CLOCK_H_
 
 #include "base/base_export.h"
 #include "base/compiler_specific.h"
@@ -22,4 +22,4 @@
 
 }  // namespace base
 
-#endif  // BASE_DEFAULT_CLOCK_H_
+#endif  // BASE_TIME_DEFAULT_TICK_CLOCK_H_
diff --git a/base/time/tick_clock.h b/base/time/tick_clock.h
index 2b8691f..f7aba53 100644
--- a/base/time/tick_clock.h
+++ b/base/time/tick_clock.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_TICK_CLOCK_H_
-#define BASE_TICK_CLOCK_H_
+#ifndef BASE_TIME_TICK_CLOCK_H_
+#define BASE_TIME_TICK_CLOCK_H_
 
 #include "base/base_export.h"
 #include "base/time/time.h"
@@ -37,4 +37,4 @@
 
 }  // namespace base
 
-#endif  // BASE_TICK_CLOCK_H_
+#endif  // BASE_TIME_TICK_CLOCK_H_
diff --git a/base/time/time_win.cc b/base/time/time_win.cc
index 8ae7640..d2403f2 100644
--- a/base/time/time_win.cc
+++ b/base/time/time_win.cc
@@ -203,12 +203,12 @@
   UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs
                                          : kMinTimerIntervalLowResMs;
   if (activating) {
-    DCHECK(g_high_res_timer_count != max);
+    DCHECK_NE(g_high_res_timer_count, max);
     ++g_high_res_timer_count;
     if (g_high_res_timer_count == 1)
       timeBeginPeriod(period);
   } else {
-    DCHECK(g_high_res_timer_count != 0);
+    DCHECK_NE(g_high_res_timer_count, 0u);
     --g_high_res_timer_count;
     if (g_high_res_timer_count == 0)
       timeEndPeriod(period);
diff --git a/base/timer/mock_timer.h b/base/timer/mock_timer.h
index b07c9c0..e18a5c0 100644
--- a/base/timer/mock_timer.h
+++ b/base/timer/mock_timer.h
@@ -38,4 +38,4 @@
 
 }  // namespace base
 
-#endif  // !BASE_TIMER_MOCK_TIMER_H_
+#endif  // BASE_TIMER_MOCK_TIMER_H_
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn
new file mode 100644
index 0000000..eec607b
--- /dev/null
+++ b/base/trace_event/BUILD.gn
@@ -0,0 +1,61 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("trace_event") {
+  sources = [
+    "memory_dump_manager.cc",
+    "memory_dump_manager.h",
+    "memory_dump_provider.h",
+    "process_memory_dump.cc",
+    "process_memory_dump.h",
+    "process_memory_maps.cc",
+    "process_memory_maps.h",
+    "process_memory_maps_dump_provider.cc",
+    "process_memory_maps_dump_provider.h",
+    "process_memory_totals.cc",
+    "process_memory_totals.h",
+    "process_memory_totals_dump_provider.cc",
+    "process_memory_totals_dump_provider.h",
+    "trace_event.h",
+    "trace_event_android.cc",
+    "trace_event_argument.cc",
+    "trace_event_argument.h",
+    "trace_event_impl.cc",
+    "trace_event_impl.h",
+    "trace_event_impl_constants.cc",
+    "trace_event_memory.cc",
+    "trace_event_memory.h",
+    "trace_event_synthetic_delay.cc",
+    "trace_event_synthetic_delay.h",
+    "trace_event_system_stats_monitor.cc",
+    "trace_event_system_stats_monitor.h",
+    "trace_event_win.cc",
+    "trace_event_win.h",
+  ]
+
+  if (is_nacl) {
+    sources -= [
+      "process_memory_totals_dump_provider.cc",
+      "trace_event_system_stats_monitor.cc",
+    ]
+  }
+
+  defines = [ "BASE_IMPLEMENTATION" ]
+
+  deps = [
+    "//base/debug",
+    "//base/json",
+    "//base/memory",
+    "//base/process",
+    "//base/third_party/dynamic_annotations",
+  ]
+
+  allow_circular_includes_from = [
+    "//base/debug",
+    "//base/memory",
+    "//base/process",
+  ]
+
+  visibility = [ "//base/*" ]
+}
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index cbed238..8b2d930 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -37,7 +37,8 @@
   NOTREACHED();
   return "UNKNOWN";
 }
-}
+
+}  // namespace
 
 // TODO(primiano): this should be smarter and should do something similar to
 // trace event synthetic delays.
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 78be377..251a92a 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -148,5 +148,5 @@
   DisableTracing();
 }
 
-}  // namespace trace_Event
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/process_memory_maps_dump_provider.cc b/base/trace_event/process_memory_maps_dump_provider.cc
index 93feded..fbe0eb1 100644
--- a/base/trace_event/process_memory_maps_dump_provider.cc
+++ b/base/trace_event/process_memory_maps_dump_provider.cc
@@ -47,7 +47,7 @@
 
   region->protection_flags = 0;
   *smaps >> protection_flags;
-  CHECK(4UL == protection_flags.size());
+  CHECK_EQ(4UL, protection_flags.size());
   if (protection_flags[0] == 'r') {
     region->protection_flags |=
         ProcessMemoryMaps::VMRegion::kProtectionFlagsRead;
diff --git a/base/trace_event/process_memory_totals_dump_provider_unittest.cc b/base/trace_event/process_memory_totals_dump_provider_unittest.cc
index 4a60036..c37e612 100644
--- a/base/trace_event/process_memory_totals_dump_provider_unittest.cc
+++ b/base/trace_event/process_memory_totals_dump_provider_unittest.cc
@@ -39,5 +39,5 @@
   EXPECT_EQ(rss_after - rss_before, kAllocSize);
 }
 
-}  // namespace trace_Event
+}  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index c30a84a..b90a3ea 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -1607,4 +1607,4 @@
 }  // namespace trace_event
 }  // namespace base
 
-#endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */
+#endif  // BASE_TRACE_EVENT_TRACE_EVENT_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 445cb6d..72b46f9 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -430,25 +430,22 @@
 // and unlocks at the end of scope if locked.
 class TraceLog::OptionalAutoLock {
  public:
-  explicit OptionalAutoLock(Lock& lock)
-      : lock_(lock),
-        locked_(false) {
-  }
+  explicit OptionalAutoLock(Lock* lock) : lock_(lock), locked_(false) {}
 
   ~OptionalAutoLock() {
     if (locked_)
-      lock_.Release();
+      lock_->Release();
   }
 
   void EnsureAcquired() {
     if (!locked_) {
-      lock_.Acquire();
+      lock_->Acquire();
       locked_ = true;
     }
   }
 
  private:
-  Lock& lock_;
+  Lock* lock_;
   bool locked_;
   DISALLOW_COPY_AND_ASSIGN(OptionalAutoLock);
 };
@@ -624,7 +621,7 @@
 
 void TraceEvent::UpdateDuration(const TimeTicks& now,
                                 const TimeTicks& thread_now) {
-  DCHECK(duration_.ToInternalValue() == -1);
+  DCHECK_EQ(duration_.ToInternalValue(), -1);
   duration_ = now - timestamp_;
   thread_duration_ = thread_now - thread_timestamp_;
 }
@@ -1977,7 +1974,7 @@
   std::string console_message;
   if (*category_group_enabled &
       (ENABLED_FOR_RECORDING | ENABLED_FOR_MONITORING)) {
-    OptionalAutoLock lock(lock_);
+    OptionalAutoLock lock(&lock_);
 
     TraceEvent* trace_event = NULL;
     if (thread_local_event_buffer) {
@@ -2130,7 +2127,7 @@
 
   std::string console_message;
   if (*category_group_enabled & ENABLED_FOR_RECORDING) {
-    OptionalAutoLock lock(lock_);
+    OptionalAutoLock lock(&lock_);
 
     TraceEvent* trace_event = GetEventByHandleInternal(handle, &lock);
     if (trace_event) {
@@ -2490,18 +2487,35 @@
   // Do a second pass to check for explicitly disabled categories
   // (those explicitly enabled have priority due to first pass).
   category_group_tokens.Reset();
+  bool category_group_disabled = false;
   while (category_group_tokens.GetNext()) {
     std::string category_group_token = category_group_tokens.token();
     for (StringList::const_iterator ci = excluded_.begin();
          ci != excluded_.end(); ++ci) {
-      if (MatchPattern(category_group_token.c_str(), ci->c_str()))
-        return false;
+      if (MatchPattern(category_group_token.c_str(), ci->c_str())) {
+        // Current token of category_group_name is present in excluded_list.
+        // Flag the exclusion and proceed further to check if any of the
+        // remaining categories of category_group_name is not present in the
+        // excluded_ list.
+        category_group_disabled = true;
+        break;
+      }
+      // One of the category of category_group_name is not present in
+      // excluded_ list. So, it has to be included_ list. Enable the
+      // category_group_name for recording.
+      category_group_disabled = false;
     }
+    // One of the categories present in category_group_name is not present in
+    // excluded_ list. Implies this category_group_name group can be enabled
+    // for recording, since one of its groups is enabled for recording.
+    if (!category_group_disabled)
+      break;
   }
   // If the category group is not excluded, and there are no included patterns
   // we consider this category group enabled, as long as it had categories
   // other than disabled-by-default.
-  return included_.empty() && had_enabled_by_default;
+  return !category_group_disabled &&
+         included_.empty() && had_enabled_by_default;
 }
 
 bool CategoryFilter::IsCategoryEnabled(const char* category_name) const {
@@ -2571,7 +2585,7 @@
 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient(
     const char* category_group, const char* name) {
   // The single atom works because for now the category_group can only be "gpu".
-  DCHECK(strcmp(category_group, "gpu") == 0);
+  DCHECK_EQ(strcmp(category_group, "gpu"), 0);
   static TRACE_EVENT_API_ATOMIC_WORD atomic = 0;
   INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(
       category_group, atomic, category_group_enabled_);
diff --git a/base/trace_event/trace_event_synthetic_delay.h b/base/trace_event/trace_event_synthetic_delay.h
index 14801be..0df794b 100644
--- a/base/trace_event/trace_event_synthetic_delay.h
+++ b/base/trace_event/trace_event_synthetic_delay.h
@@ -163,4 +163,4 @@
 
 }  // namespace trace_event_internal
 
-#endif /* BASE_TRACE_EVENT_TRACE_EVENT_SYNTHETIC_DELAY_H_ */
+#endif  // BASE_TRACE_EVENT_TRACE_EVENT_SYNTHETIC_DELAY_H_
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc
index a6bc0d4..0d3b091 100644
--- a/base/trace_event/trace_event_unittest.cc
+++ b/base/trace_event/trace_event_unittest.cc
@@ -1205,8 +1205,8 @@
   EndTraceAndFlush();
   EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
   EXPECT_FALSE(FindMatchingValue("cat", "inc"));
-  EXPECT_FALSE(FindMatchingValue("cat", "inc2,inc"));
-  EXPECT_FALSE(FindMatchingValue("cat", "inc,inc2"));
+  EXPECT_TRUE(FindMatchingValue("cat", "inc2,inc"));
+  EXPECT_TRUE(FindMatchingValue("cat", "inc,inc2"));
 
   // Exclude existent wildcard -> all categories not matching wildcard
   Clear();
@@ -2624,18 +2624,18 @@
   EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("not-excluded-category"));
   EXPECT_FALSE(
       default_cf.IsCategoryGroupEnabled("disabled-by-default-category"));
-  EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug"));
-  EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1"));
-  EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2"));
+  EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug"));
+  EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1"));
+  EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2"));
 
   // Make sure that upon an empty string, we fall back to the default filter.
   default_cf = CategoryFilter();
   category_filter_str = default_cf.ToString();
   EXPECT_STREQ("-*Debug,-*Test", category_filter_str.c_str());
   EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("not-excluded-category"));
-  EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug"));
-  EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1"));
-  EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2"));
+  EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug"));
+  EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1"));
+  EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2"));
 
   // Using an arbitrary non-empty filter.
   CategoryFilter cf("included,-excluded,inc_pattern*,-exc_pattern*");
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc
index fc29e2e..5359d89 100644
--- a/base/tracked_objects.cc
+++ b/base/tracked_objects.cc
@@ -163,11 +163,6 @@
   return queue_duration_sample_;
 }
 
-void DeathData::ResetMax() {
-  run_duration_max_ = 0;
-  queue_duration_max_ = 0;
-}
-
 void DeathData::Clear() {
   count_ = 0;
   run_duration_sum_ = 0;
@@ -232,10 +227,6 @@
 
 void Births::RecordBirth() { ++birth_count_; }
 
-void Births::ForgetBirth() { --birth_count_; }
-
-void Births::Clear() { birth_count_ = 0; }
-
 //------------------------------------------------------------------------------
 // ThreadData maintains the central data for all births and deaths on a single
 // thread.
@@ -399,12 +390,12 @@
 }
 
 // static
-void ThreadData::Snapshot(bool reset_max, ProcessDataSnapshot* process_data) {
+void ThreadData::Snapshot(ProcessDataSnapshot* process_data) {
   // Add births that have run to completion to |collected_data|.
   // |birth_counts| tracks the total number of births recorded at each location
   // for which we have not seen a death count.
   BirthCountMap birth_counts;
-  ThreadData::SnapshotAllExecutedTasks(reset_max, process_data, &birth_counts);
+  ThreadData::SnapshotAllExecutedTasks(process_data, &birth_counts);
 
   // Add births that are still active -- i.e. objects that have tallied a birth,
   // but have not yet tallied a matching death, and hence must be either
@@ -587,8 +578,7 @@
 }
 
 // static
-void ThreadData::SnapshotAllExecutedTasks(bool reset_max,
-                                          ProcessDataSnapshot* process_data,
+void ThreadData::SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data,
                                           BirthCountMap* birth_counts) {
   if (!kTrackAllTaskObjects)
     return;  // Not compiled in.
@@ -605,19 +595,18 @@
   for (ThreadData* thread_data = my_list;
        thread_data;
        thread_data = thread_data->next()) {
-    thread_data->SnapshotExecutedTasks(reset_max, process_data, birth_counts);
+    thread_data->SnapshotExecutedTasks(process_data, birth_counts);
   }
 }
 
-void ThreadData::SnapshotExecutedTasks(bool reset_max,
-                                       ProcessDataSnapshot* process_data,
+void ThreadData::SnapshotExecutedTasks(ProcessDataSnapshot* process_data,
                                        BirthCountMap* birth_counts) {
   // Get copy of data, so that the data will not change during the iterations
   // and processing.
   ThreadData::BirthMap birth_map;
   ThreadData::DeathMap death_map;
   ThreadData::ParentChildSet parent_child_set;
-  SnapshotMaps(reset_max, &birth_map, &death_map, &parent_child_set);
+  SnapshotMaps(&birth_map, &death_map, &parent_child_set);
 
   for (ThreadData::DeathMap::const_iterator it = death_map.begin();
        it != death_map.end(); ++it) {
@@ -641,8 +630,7 @@
 }
 
 // This may be called from another thread.
-void ThreadData::SnapshotMaps(bool reset_max,
-                              BirthMap* birth_map,
+void ThreadData::SnapshotMaps(BirthMap* birth_map,
                               DeathMap* death_map,
                               ParentChildSet* parent_child_set) {
   base::AutoLock lock(map_lock_);
@@ -652,8 +640,6 @@
   for (DeathMap::iterator it = death_map_.begin();
        it != death_map_.end(); ++it) {
     (*death_map)[it->first] = it->second;
-    if (reset_max)
-      it->second.ResetMax();
   }
 
   if (!kTrackParentChildLinks)
@@ -664,26 +650,6 @@
     parent_child_set->insert(*it);
 }
 
-// static
-void ThreadData::ResetAllThreadData() {
-  ThreadData* my_list = first();
-
-  for (ThreadData* thread_data = my_list;
-       thread_data;
-       thread_data = thread_data->next())
-    thread_data->Reset();
-}
-
-void ThreadData::Reset() {
-  base::AutoLock lock(map_lock_);
-  for (DeathMap::iterator it = death_map_.begin();
-       it != death_map_.end(); ++it)
-    it->second.Clear();
-  for (BirthMap::iterator it = birth_map_.begin();
-       it != birth_map_.end(); ++it)
-    it->second->Clear();
-}
-
 static void OptionallyInitializeAlternateTimer() {
   NowFunction* alternate_time_source = GetAlternateTimeSource();
   if (alternate_time_source)
diff --git a/base/tracked_objects.h b/base/tracked_objects.h
index 5196f19..7840fec 100644
--- a/base/tracked_objects.h
+++ b/base/tracked_objects.h
@@ -240,13 +240,6 @@
   // When we have a birth we update the count for this birthplace.
   void RecordBirth();
 
-  // When a birthplace is changed (updated), we need to decrement the counter
-  // for the old instance.
-  void ForgetBirth();
-
-  // Hack to quickly reset all counts to zero.
-  void Clear();
-
  private:
   // The number of births on this thread for our location_.
   int birth_count_;
@@ -284,9 +277,6 @@
   int32 queue_duration_max() const;
   int32 queue_duration_sample() const;
 
-  // Reset the max values to zero.
-  void ResetMax();
-
   // Reset all tallies to zero. This is used as a hack on realtime data.
   void Clear();
 
@@ -386,9 +376,7 @@
   static ThreadData* Get();
 
   // Fills |process_data| with all the recursive results in our process.
-  // During the scavenging, if |reset_max| is true, then the DeathData instances
-  // max-values are reset to zero during this scan.
-  static void Snapshot(bool reset_max, ProcessDataSnapshot* process_data);
+  static void Snapshot(ProcessDataSnapshot* process_data);
 
   // Finds (or creates) a place to count births from the given location in this
   // thread, and increment that tally.
@@ -427,12 +415,6 @@
 
   const std::string& thread_name() const { return thread_name_; }
 
-  // Hack: asynchronously clear all birth counts and death tallies data values
-  // in all ThreadData instances.  The numerical (zeroing) part is done without
-  // use of a locks or atomics exchanges, and may (for int64 values) produce
-  // bogus counts VERY rarely.
-  static void ResetAllThreadData();
-
   // Initializes all statics if needed (this initialization call should be made
   // while we are single threaded). Returns false if unable to initialize.
   static bool Initialize();
@@ -530,11 +512,8 @@
 
   // Snapshot (under a lock) the profiled data for the tasks in each ThreadData
   // instance.  Also updates the |birth_counts| tally for each task to keep
-  // track of the number of living instances of the task.  If |reset_max| is
-  // true, then the max values in each DeathData instance are reset during the
-  // scan.
-  static void SnapshotAllExecutedTasks(bool reset_max,
-                                       ProcessDataSnapshot* process_data,
+  // track of the number of living instances of the task.
+  static void SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data,
                                        BirthCountMap* birth_counts);
 
   // Snapshots (under a lock) the profiled data for the tasks for this thread
@@ -542,26 +521,17 @@
   // with with entries in the death_map_ -- into |process_data|.  Also updates
   // the |birth_counts| tally for each task to keep track of the number of
   // living instances of the task -- that is, each task maps to the number of
-  // births for the task that have not yet been balanced by a death.  If
-  // |reset_max| is true, then the max values in each DeathData instance are
-  // reset during the scan.
-  void SnapshotExecutedTasks(bool reset_max,
-                             ProcessDataSnapshot* process_data,
+  // births for the task that have not yet been balanced by a death.
+  void SnapshotExecutedTasks(ProcessDataSnapshot* process_data,
                              BirthCountMap* birth_counts);
 
   // Using our lock, make a copy of the specified maps.  This call may be made
   // on  non-local threads, which necessitate the use of the lock to prevent
-  // the map(s) from being reallocated while they are copied. If |reset_max| is
-  // true, then, just after we copy the DeathMap, we will set the max values to
-  // zero in the active DeathMap (not the snapshot).
-  void SnapshotMaps(bool reset_max,
-                    BirthMap* birth_map,
+  // the map(s) from being reallocated while they are copied.
+  void SnapshotMaps(BirthMap* birth_map,
                     DeathMap* death_map,
                     ParentChildSet* parent_child_set);
 
-  // Using our lock to protect the iteration, Clear all birth and death data.
-  void Reset();
-
   // This method is called by the TLS system when a thread terminates.
   // The argument may be NULL if this thread has never tracked a birth or death.
   static void OnThreadTermination(void* thread_data);
diff --git a/base/tracked_objects_unittest.cc b/base/tracked_objects_unittest.cc
index e2ea362..7713091 100644
--- a/base/tracked_objects_unittest.cc
+++ b/base/tracked_objects_unittest.cc
@@ -138,7 +138,7 @@
   ThreadData::BirthMap birth_map;
   ThreadData::DeathMap death_map;
   ThreadData::ParentChildSet parent_child_set;
-  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
+  data->SnapshotMaps(&birth_map, &death_map, &parent_child_set);
   EXPECT_EQ(0u, birth_map.size());
   EXPECT_EQ(0u, death_map.size());
   EXPECT_EQ(0u, parent_child_set.size());
@@ -158,7 +158,7 @@
   birth_map.clear();
   death_map.clear();
   parent_child_set.clear();
-  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
+  data->SnapshotMaps(&birth_map, &death_map, &parent_child_set);
   EXPECT_EQ(0u, birth_map.size());
   EXPECT_EQ(0u, death_map.size());
   EXPECT_EQ(0u, parent_child_set.size());
@@ -182,7 +182,7 @@
   ThreadData::BirthMap birth_map;
   ThreadData::DeathMap death_map;
   ThreadData::ParentChildSet parent_child_set;
-  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
+  data->SnapshotMaps(&birth_map, &death_map, &parent_child_set);
   EXPECT_EQ(1u, birth_map.size());                         // 1 birth location.
   EXPECT_EQ(1, birth_map.begin()->second->birth_count());  // 1 birth.
   EXPECT_EQ(0u, death_map.size());                         // No deaths.
@@ -211,7 +211,7 @@
   birth_map.clear();
   death_map.clear();
   parent_child_set.clear();
-  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
+  data->SnapshotMaps(&birth_map, &death_map, &parent_child_set);
   EXPECT_EQ(1u, birth_map.size());                         // 1 birth location.
   EXPECT_EQ(2, birth_map.begin()->second->birth_count());  // 2 births.
   EXPECT_EQ(1u, death_map.size());                         // 1 location.
@@ -228,7 +228,7 @@
   EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
 
   ASSERT_EQ(1u, process_data.tasks.size());
   EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
@@ -317,7 +317,7 @@
   TallyABirth(location, std::string());
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   EXPECT_EQ(0u, process_data.tasks.size());
   EXPECT_EQ(0u, process_data.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
@@ -334,7 +334,7 @@
   TallyABirth(location, kMainThreadName);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   EXPECT_EQ(0u, process_data.tasks.size());
   EXPECT_EQ(0u, process_data.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
@@ -351,7 +351,7 @@
   TallyABirth(location, std::string());
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName,
                           kStillAlive, 1, 0, 0);
 }
@@ -367,7 +367,7 @@
   TallyABirth(location, kMainThreadName);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kStillAlive,
                           1, 0, 0);
 }
@@ -399,7 +399,7 @@
   ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ExpectSimpleProcessData(process_data, kFunction, kMainThreadName,
                           kMainThreadName, 1, 2, 4);
 }
@@ -439,7 +439,7 @@
   ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ExpectSimpleProcessData(process_data, kFunction, kMainThreadName,
                           kMainThreadName, 1, 2, 4);
 }
@@ -473,76 +473,12 @@
   ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   EXPECT_EQ(0u, process_data.tasks.size());
   EXPECT_EQ(0u, process_data.descendants.size());
   EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id);
 }
 
-TEST_F(TrackedObjectsTest, LifeCycleToSnapshotWorkerThread) {
-  if (!ThreadData::InitializeAndSetTrackingStatus(
-          ThreadData::PROFILING_CHILDREN_ACTIVE)) {
-    return;
-  }
-
-  const char kFunction[] = "LifeCycleToSnapshotWorkerThread";
-  Location location(kFunction, kFile, kLineNumber, NULL);
-  // Do not delete |birth|.  We don't own it.
-  Births* birth = ThreadData::TallyABirthIfActive(location);
-  EXPECT_NE(reinterpret_cast<Births*>(NULL), birth);
-
-  const unsigned int kTimePosted = 1;
-  const unsigned int kStartOfRun = 5;
-  const unsigned int kEndOfRun = 7;
-  SetTestTime(kStartOfRun);
-  TaskStopwatch stopwatch;
-  stopwatch.Start();
-  SetTestTime(kEndOfRun);
-  stopwatch.Stop();
-
-  ThreadData::TallyRunOnWorkerThreadIfTracking(
-  birth, TrackedTime() + Duration::FromMilliseconds(kTimePosted), stopwatch);
-
-  // Call for the ToSnapshot, but tell it to not reset the maxes after scanning.
-  ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
-  ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName,
-                          kWorkerThreadName, 1, 2, 4);
-
-  // Call for the ToSnapshot, but tell it to reset the maxes after scanning.
-  // We'll still get the same values, but the data will be reset (which we'll
-  // see in a moment).
-  ProcessDataSnapshot process_data_pre_reset;
-  ThreadData::Snapshot(true, &process_data_pre_reset);
-  ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName,
-                          kWorkerThreadName, 1, 2, 4);
-
-  // Call for the ToSnapshot, and now we'll see the result of the last
-  // translation, as the max will have been pushed back to zero.
-  ProcessDataSnapshot process_data_post_reset;
-  ThreadData::Snapshot(true, &process_data_post_reset);
-  ASSERT_EQ(1u, process_data_post_reset.tasks.size());
-  EXPECT_EQ(kFile, process_data_post_reset.tasks[0].birth.location.file_name);
-  EXPECT_EQ(kFunction,
-            process_data_post_reset.tasks[0].birth.location.function_name);
-  EXPECT_EQ(kLineNumber,
-            process_data_post_reset.tasks[0].birth.location.line_number);
-  EXPECT_EQ(kWorkerThreadName,
-            process_data_post_reset.tasks[0].birth.thread_name);
-  EXPECT_EQ(1, process_data_post_reset.tasks[0].death_data.count);
-  EXPECT_EQ(2, process_data_post_reset.tasks[0].death_data.run_duration_sum);
-  EXPECT_EQ(0, process_data_post_reset.tasks[0].death_data.run_duration_max);
-  EXPECT_EQ(2, process_data_post_reset.tasks[0].death_data.run_duration_sample);
-  EXPECT_EQ(4, process_data_post_reset.tasks[0].death_data.queue_duration_sum);
-  EXPECT_EQ(0, process_data_post_reset.tasks[0].death_data.queue_duration_max);
-  EXPECT_EQ(4,
-            process_data_post_reset.tasks[0].death_data.queue_duration_sample);
-  EXPECT_EQ(kWorkerThreadName,
-            process_data_post_reset.tasks[0].death_thread_name);
-  EXPECT_EQ(0u, process_data_post_reset.descendants.size());
-  EXPECT_EQ(base::GetCurrentProcId(), process_data_post_reset.process_id);
-}
-
 TEST_F(TrackedObjectsTest, TwoLives) {
   if (!ThreadData::InitializeAndSetTrackingStatus(
           ThreadData::PROFILING_CHILDREN_ACTIVE)) {
@@ -581,7 +517,7 @@
   ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2, stopwatch2);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ExpectSimpleProcessData(process_data, kFunction, kMainThreadName,
                           kMainThreadName, 2, 2, 4);
 }
@@ -621,7 +557,7 @@
   pending_task2.time_posted = kTimePosted;  // Overwrite implied Now().
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ASSERT_EQ(2u, process_data.tasks.size());
 
   EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name);
@@ -685,7 +621,7 @@
   ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ExpectSimpleProcessData(process_data, kFunction, kMainThreadName,
                           kMainThreadName, 1, 6, 4);
 }
@@ -728,7 +664,7 @@
   ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
   ExpectSimpleProcessData(process_data, kFunction, kMainThreadName,
                           kMainThreadName, 1, 13, 4);
 }
@@ -781,7 +717,7 @@
   ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch);
 
   ProcessDataSnapshot process_data;
-  ThreadData::Snapshot(false, &process_data);
+  ThreadData::Snapshot(&process_data);
 
   // The order in which the two task follow is platform-dependent.
   int t0 = (process_data.tasks[0].birth.location.line_number == kLineNumber) ?
diff --git a/base/value_conversions.h b/base/value_conversions.h
index fde9a26..452c587 100644
--- a/base/value_conversions.h
+++ b/base/value_conversions.h
@@ -24,6 +24,6 @@
 BASE_EXPORT StringValue* CreateTimeDeltaValue(const TimeDelta& time);
 BASE_EXPORT bool GetValueAsTimeDelta(const Value& value, TimeDelta* time);
 
-}  // namespace
+}  // namespace base
 
 #endif  // BASE_VALUE_CONVERSIONS_H_
diff --git a/base/version.cc b/base/version.cc
index 933356e..ede8a45 100644
--- a/base/version.cc
+++ b/base/version.cc
@@ -23,7 +23,7 @@
 // is the resulting integer vector. Function returns true if all numbers were
 // parsed successfully, false otherwise.
 bool ParseVersionNumbers(const std::string& version_str,
-                         std::vector<uint16>* parsed) {
+                         std::vector<uint32_t>* parsed) {
   std::vector<std::string> numbers;
   SplitString(version_str, '.', &numbers);
   if (numbers.empty())
@@ -33,22 +33,18 @@
        it != numbers.end(); ++it) {
     if (StartsWithASCII(*it, "+", false))
       return false;
-    int num;
-    if (!StringToInt(*it, &num))
-      return false;
-
-    if (num < 0)
-      return false;
-
-    const uint16 max = 0xFFFF;
-    if (num > max)
+    unsigned int num;
+    if (!StringToUint(*it, &num))
       return false;
 
     // This throws out leading zeros for the first item only.
-    if (it == numbers.begin() && IntToString(num) != *it)
+    if (it == numbers.begin() && UintToString(num) != *it)
       return false;
 
-    parsed->push_back(static_cast<uint16>(num));
+    // StringToUint returns unsigned int but Version fields are uint32_t.
+    static_assert(sizeof (uint32_t) == sizeof (unsigned int),
+        "uint32_t must be same as unsigned int");
+    parsed->push_back(num);
   }
   return true;
 }
@@ -56,8 +52,8 @@
 // Compares version components in |components1| with components in
 // |components2|. Returns -1, 0 or 1 if |components1| is less than, equal to,
 // or greater than |components2|, respectively.
-int CompareVersionComponents(const std::vector<uint16>& components1,
-                             const std::vector<uint16>& components2) {
+int CompareVersionComponents(const std::vector<uint32_t>& components1,
+                             const std::vector<uint32_t>& components2) {
   const size_t count = std::min(components1.size(), components2.size());
   for (size_t i = 0; i < count; ++i) {
     if (components1[i] > components2[i])
@@ -88,7 +84,7 @@
 }
 
 Version::Version(const std::string& version_str) {
-  std::vector<uint16> parsed;
+  std::vector<uint32_t> parsed;
   if (!ParseVersionNumbers(version_str, &parsed))
     return;
 
@@ -127,7 +123,7 @@
     return CompareTo(version);
   }
 
-  std::vector<uint16> parsed;
+  std::vector<uint32_t> parsed;
   const bool success = ParseVersionNumbers(
       wildcard_string.substr(0, wildcard_string.length() - 2), &parsed);
   DCHECK(success);
diff --git a/base/version.h b/base/version.h
index b3012eb..814acaa 100644
--- a/base/version.h
+++ b/base/version.h
@@ -5,6 +5,7 @@
 #ifndef BASE_VERSION_H_
 #define BASE_VERSION_H_
 
+#include <stdint.h>
 #include <string>
 #include <vector>
 
@@ -57,10 +58,10 @@
   // Return the string representation of this version.
   const std::string GetString() const;
 
-  const std::vector<uint16>& components() const { return components_; }
+  const std::vector<uint32_t>& components() const { return components_; }
 
  private:
-  std::vector<uint16> components_;
+  std::vector<uint32_t> components_;
 };
 
 }  // namespace base
diff --git a/base/version_unittest.cc b/base/version_unittest.cc
index 46d8255..f40ed27 100644
--- a/base/version_unittest.cc
+++ b/base/version_unittest.cc
@@ -31,39 +31,44 @@
   static const struct version_string {
     const char* input;
     size_t parts;
+    uint32_t firstpart;
     bool success;
   } cases[] = {
-    {"", 0, false},
-    {" ", 0, false},
-    {"\t", 0, false},
-    {"\n", 0, false},
-    {"  ", 0, false},
-    {".", 0, false},
-    {" . ", 0, false},
-    {"0", 1, true},
-    {"0.", 0, false},
-    {"0.0", 2, true},
-    {"65537.0", 0, false},
-    {"-1.0", 0, false},
-    {"1.-1.0", 0, false},
-    {"1,--1.0", 0, false},
-    {"+1.0", 0, false},
-    {"1.+1.0", 0, false},
-    {"1+1.0", 0, false},
-    {"++1.0", 0, false},
-    {"1.0a", 0, false},
-    {"1.2.3.4.5.6.7.8.9.0", 10, true},
-    {"02.1", 0, false},
-    {"0.01", 2, true},
-    {"f.1", 0, false},
-    {"15.007.20011", 3, true},
+    {"", 0, 0, false},
+    {" ", 0, 0, false},
+    {"\t", 0, 0, false},
+    {"\n", 0, 0, false},
+    {"  ", 0, 0, false},
+    {".", 0, 0, false},
+    {" . ", 0, 0, false},
+    {"0", 1, 0, true},
+    {"0.", 0, 0, false},
+    {"0.0", 2, 0, true},
+    {"4294967295.0", 2, 4294967295, true},
+    {"4294967296.0", 0, 0, false},
+    {"-1.0", 0, 0, false},
+    {"1.-1.0", 0, 0, false},
+    {"1,--1.0", 0, 0, false},
+    {"+1.0", 0, 0, false},
+    {"1.+1.0", 0, 0, false},
+    {"1+1.0", 0, 0, false},
+    {"++1.0", 0, 0, false},
+    {"1.0a", 0, 0, false},
+    {"1.2.3.4.5.6.7.8.9.0", 10, 1, true},
+    {"02.1", 0, 0, false},
+    {"0.01", 2, 0, true},
+    {"f.1", 0, 0, false},
+    {"15.007.20011", 3, 15, true},
+    {"15.5.28.130162", 4, 15, true},
   };
 
   for (size_t i = 0; i < arraysize(cases); ++i) {
     Version version(cases[i].input);
     EXPECT_EQ(cases[i].success, version.IsValid());
-    if (cases[i].success)
+    if (cases[i].success) {
       EXPECT_EQ(cases[i].parts, version.components().size());
+      EXPECT_EQ(cases[i].firstpart, version.components()[0]);
+    }
   }
 }
 
@@ -84,6 +89,7 @@
     {"1.0.0", "1.0", 0},
     {"1.0.3", "1.0.20", -1},
     {"11.0.10", "15.007.20011", -1},
+    {"11.0.10", "15.5.28.130162", -1},
   };
   for (size_t i = 0; i < arraysize(cases); ++i) {
     Version lhs(cases[i].lhs);
diff --git a/base/vlog.cc b/base/vlog.cc
index 434a70e..8612071 100644
--- a/base/vlog.cc
+++ b/base/vlog.cc
@@ -178,4 +178,4 @@
   return false;
 }
 
-}  // namespace
+}  // namespace logging
diff --git a/base/win/metro.cc b/base/win/metro.cc
index 6e443ba..7946698 100644
--- a/base/win/metro.cc
+++ b/base/win/metro.cc
@@ -4,10 +4,7 @@
 
 #include "base/win/metro.h"
 
-#include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
-#include "base/win/scoped_comptr.h"
-#include "base/win/windows_version.h"
 
 namespace base {
 namespace win {
@@ -73,38 +70,6 @@
   return dest;
 }
 
-bool IsParentalControlActivityLoggingOn() {
-  // Query this info on Windows 7 and above.
-  if (base::win::GetVersion() < base::win::VERSION_WIN7)
-    return false;
-
-  static bool parental_control_logging_required = false;
-  static bool parental_control_status_determined = false;
-
-  if (parental_control_status_determined)
-    return parental_control_logging_required;
-
-  parental_control_status_determined = true;
-
-  ScopedComPtr<IWindowsParentalControlsCore> parent_controls;
-  HRESULT hr = parent_controls.CreateInstance(
-      __uuidof(WindowsParentalControls));
-  if (FAILED(hr))
-    return false;
-
-  ScopedComPtr<IWPCSettings> settings;
-  hr = parent_controls->GetUserSettings(NULL, settings.Receive());
-  if (FAILED(hr))
-    return false;
-
-  unsigned long restrictions = 0;
-  settings->GetRestrictions(&restrictions);
-
-  parental_control_logging_required =
-      (restrictions & WPCFLAG_LOGGING_REQUIRED) == WPCFLAG_LOGGING_REQUIRED;
-  return parental_control_logging_required;
-}
-
 // Metro driver exports for getting the launch type, initial url, initial
 // search term, etc.
 extern "C" {
diff --git a/base/win/metro.h b/base/win/metro.h
index 5894ef0..0696006 100644
--- a/base/win/metro.h
+++ b/base/win/metro.h
@@ -6,7 +6,6 @@
 #define BASE_WIN_METRO_H_
 
 #include <windows.h>
-#include <wpcapi.h>
 
 #include "base/base_export.h"
 #include "base/callback.h"
@@ -80,11 +79,6 @@
 // copying the src to it.
 BASE_EXPORT wchar_t* LocalAllocAndCopyString(const string16& src);
 
-// Returns true if Windows Parental control activity logging is enabled. This
-// feature is available on Windows Vista and beyond.
-// This function should ideally be called on the UI thread.
-BASE_EXPORT bool IsParentalControlActivityLoggingOn();
-
 // Returns the type of launch and the activation params. For example if the
 // the launch is for METRO_PROTOCOL then the params is a url.
 BASE_EXPORT MetroLaunchType GetMetroLaunchParams(string16* params);
diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h
index ecd0415..0ae2532 100644
--- a/base/win/object_watcher.h
+++ b/base/win/object_watcher.h
@@ -103,4 +103,4 @@
 }  // namespace win
 }  // namespace base
 
-#endif  // BASE_OBJECT_WATCHER_H_
+#endif  // BASE_WIN_OBJECT_WATCHER_H_
diff --git a/base/win/registry.cc b/base/win/registry.cc
index b39b749..d0df48a 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -210,7 +210,7 @@
 }
 
 HKEY RegKey::Take() {
-  DCHECK(wow64access_ == 0);
+  DCHECK_EQ(wow64access_, 0u);
   HKEY key = key_;
   key_ = NULL;
   return key;
diff --git a/base/win/scoped_bstr.h b/base/win/scoped_bstr.h
index d703f62..7c9f5df 100644
--- a/base/win/scoped_bstr.h
+++ b/base/win/scoped_bstr.h
@@ -94,4 +94,4 @@
 }  // namespace win
 }  // namespace base
 
-#endif  // BASE_SCOPED_BSTR_H_
+#endif  // BASE_WIN_SCOPED_BSTR_H_
diff --git a/base/win/scoped_comptr_unittest.cc b/base/win/scoped_comptr_unittest.cc
index 711c52f..d38752d 100644
--- a/base/win/scoped_comptr_unittest.cc
+++ b/base/win/scoped_comptr_unittest.cc
@@ -31,8 +31,8 @@
 }  // namespace
 
 TEST(ScopedComPtrTest, ScopedComPtr) {
-  EXPECT_TRUE(memcmp(&ScopedComPtr<IUnknown>::iid(), &IID_IUnknown,
-                     sizeof(IID)) == 0);
+  EXPECT_EQ(memcmp(&ScopedComPtr<IUnknown>::iid(), &IID_IUnknown, sizeof(IID)),
+            0);
 
   base::win::ScopedCOMInitializer com_initializer;
   EXPECT_TRUE(com_initializer.succeeded());
diff --git a/base/win/scoped_handle.h b/base/win/scoped_handle.h
index db24f4b..97fd7a5 100644
--- a/base/win/scoped_handle.h
+++ b/base/win/scoped_handle.h
@@ -174,4 +174,4 @@
 }  // namespace win
 }  // namespace base
 
-#endif  // BASE_SCOPED_HANDLE_WIN_H_
+#endif  // BASE_WIN_SCOPED_HANDLE_H_
diff --git a/base/win/scoped_propvariant.h b/base/win/scoped_propvariant.h
index 711d51a..62cc6a6 100644
--- a/base/win/scoped_propvariant.h
+++ b/base/win/scoped_propvariant.h
@@ -41,8 +41,7 @@
   }
 
   const PROPVARIANT& get() const { return pv_; }
-
-  const PROPVARIANT* operator&() const { return &pv_; }
+  const PROPVARIANT* ptr() const { return &pv_; }
 
  private:
   PROPVARIANT pv_;
diff --git a/base/win/scoped_variant.h b/base/win/scoped_variant.h
index b6e6579..322fcf7 100644
--- a/base/win/scoped_variant.h
+++ b/base/win/scoped_variant.h
@@ -122,9 +122,7 @@
   // This support is necessary for the V_XYZ (e.g. V_BSTR) set of macros to
   // work properly but still doesn't allow modifications since we want control
   // over that.
-  const VARIANT* operator&() const {
-    return &var_;
-  }
+  const VARIANT* ptr() const { return &var_; }
 
   // Like other scoped classes (e.g scoped_refptr, ScopedComPtr, ScopedBstr)
   // we support the assignment operator for the type we wrap.
@@ -161,6 +159,6 @@
 };
 
 }  // namespace win
-}  // namesoace base
+}  // namespace base
 
 #endif  // BASE_WIN_SCOPED_VARIANT_H_
diff --git a/base/win/scoped_variant_unittest.cc b/base/win/scoped_variant_unittest.cc
index 1f017cf..284a6ef 100644
--- a/base/win/scoped_variant_unittest.cc
+++ b/base/win/scoped_variant_unittest.cc
@@ -72,41 +72,41 @@
 TEST(ScopedVariantTest, ScopedVariant) {
   ScopedVariant var;
   EXPECT_TRUE(var.type() == VT_EMPTY);
-  // V_BSTR(&var) = NULL;  <- NOTE: Assignment like that is not supported
+  // V_BSTR(var.ptr()) = NULL;  <- NOTE: Assignment like that is not supported.
 
   ScopedVariant var_bstr(L"VT_BSTR");
-  EXPECT_EQ(VT_BSTR, V_VT(&var_bstr));
-  EXPECT_TRUE(V_BSTR(&var_bstr) != NULL);  // can't use EXPECT_NE for BSTR
+  EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr()));
+  EXPECT_TRUE(V_BSTR(var_bstr.ptr()) != NULL);  // can't use EXPECT_NE for BSTR
   var_bstr.Reset();
-  EXPECT_NE(VT_BSTR, V_VT(&var_bstr));
+  EXPECT_NE(VT_BSTR, V_VT(var_bstr.ptr()));
   var_bstr.Set(kTestString2);
-  EXPECT_EQ(VT_BSTR, V_VT(&var_bstr));
+  EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr()));
 
   VARIANT tmp = var_bstr.Release();
-  EXPECT_EQ(VT_EMPTY, V_VT(&var_bstr));
+  EXPECT_EQ(VT_EMPTY, V_VT(var_bstr.ptr()));
   EXPECT_EQ(VT_BSTR, V_VT(&tmp));
   EXPECT_EQ(0, lstrcmp(V_BSTR(&tmp), kTestString2));
 
   var.Reset(tmp);
-  EXPECT_EQ(VT_BSTR, V_VT(&var));
-  EXPECT_EQ(0, lstrcmpW(V_BSTR(&var), kTestString2));
+  EXPECT_EQ(VT_BSTR, V_VT(var.ptr()));
+  EXPECT_EQ(0, lstrcmpW(V_BSTR(var.ptr()), kTestString2));
 
   var_bstr.Swap(var);
-  EXPECT_EQ(VT_EMPTY, V_VT(&var));
-  EXPECT_EQ(VT_BSTR, V_VT(&var_bstr));
-  EXPECT_EQ(0, lstrcmpW(V_BSTR(&var_bstr), kTestString2));
+  EXPECT_EQ(VT_EMPTY, V_VT(var.ptr()));
+  EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr()));
+  EXPECT_EQ(0, lstrcmpW(V_BSTR(var_bstr.ptr()), kTestString2));
   var_bstr.Reset();
 
   // Test the Compare and Copy routines.
   GiveMeAVariant(var_bstr.Receive());
-  ScopedVariant var_bstr2(V_BSTR(&var_bstr));
+  ScopedVariant var_bstr2(V_BSTR(var_bstr.ptr()));
   EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
   var_bstr2.Reset();
   EXPECT_NE(0, var_bstr.Compare(var_bstr2));
   var_bstr2.Reset(var_bstr.Copy());
   EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
   var_bstr2.Reset();
-  var_bstr2.Set(V_BSTR(&var_bstr));
+  var_bstr2.Set(V_BSTR(var_bstr.ptr()));
   EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
   var_bstr2.Reset();
   var_bstr.Reset();
@@ -119,7 +119,7 @@
   var.Reset();
   var.SetDate(date);
   EXPECT_EQ(VT_DATE, var.type());
-  EXPECT_EQ(date, V_DATE(&var));
+  EXPECT_EQ(date, V_DATE(var.ptr()));
 
   // Simple setter tests.  These do not require resetting the variant
   // after each test since the variant type is not "leakable" (i.e. doesn't
@@ -128,75 +128,75 @@
   // We need static cast here since char defaults to int (!?).
   var.Set(static_cast<int8>('v'));
   EXPECT_EQ(VT_I1, var.type());
-  EXPECT_EQ('v', V_I1(&var));
+  EXPECT_EQ('v', V_I1(var.ptr()));
 
   var.Set(static_cast<short>(123));
   EXPECT_EQ(VT_I2, var.type());
-  EXPECT_EQ(123, V_I2(&var));
+  EXPECT_EQ(123, V_I2(var.ptr()));
 
   var.Set(static_cast<int32>(123));
   EXPECT_EQ(VT_I4, var.type());
-  EXPECT_EQ(123, V_I4(&var));
+  EXPECT_EQ(123, V_I4(var.ptr()));
 
   var.Set(static_cast<int64>(123));
   EXPECT_EQ(VT_I8, var.type());
-  EXPECT_EQ(123, V_I8(&var));
+  EXPECT_EQ(123, V_I8(var.ptr()));
 
   var.Set(static_cast<uint8>(123));
   EXPECT_EQ(VT_UI1, var.type());
-  EXPECT_EQ(123, V_UI1(&var));
+  EXPECT_EQ(123, V_UI1(var.ptr()));
 
   var.Set(static_cast<unsigned short>(123));
   EXPECT_EQ(VT_UI2, var.type());
-  EXPECT_EQ(123, V_UI2(&var));
+  EXPECT_EQ(123, V_UI2(var.ptr()));
 
   var.Set(static_cast<uint32>(123));
   EXPECT_EQ(VT_UI4, var.type());
-  EXPECT_EQ(123, V_UI4(&var));
+  EXPECT_EQ(123, V_UI4(var.ptr()));
 
   var.Set(static_cast<uint64>(123));
   EXPECT_EQ(VT_UI8, var.type());
-  EXPECT_EQ(123, V_UI8(&var));
+  EXPECT_EQ(123, V_UI8(var.ptr()));
 
   var.Set(123.123f);
   EXPECT_EQ(VT_R4, var.type());
-  EXPECT_EQ(123.123f, V_R4(&var));
+  EXPECT_EQ(123.123f, V_R4(var.ptr()));
 
   var.Set(static_cast<double>(123.123));
   EXPECT_EQ(VT_R8, var.type());
-  EXPECT_EQ(123.123, V_R8(&var));
+  EXPECT_EQ(123.123, V_R8(var.ptr()));
 
   var.Set(true);
   EXPECT_EQ(VT_BOOL, var.type());
-  EXPECT_EQ(VARIANT_TRUE, V_BOOL(&var));
+  EXPECT_EQ(VARIANT_TRUE, V_BOOL(var.ptr()));
   var.Set(false);
   EXPECT_EQ(VT_BOOL, var.type());
-  EXPECT_EQ(VARIANT_FALSE, V_BOOL(&var));
+  EXPECT_EQ(VARIANT_FALSE, V_BOOL(var.ptr()));
 
   // Com interface tests
 
   var.Set(static_cast<IDispatch*>(NULL));
   EXPECT_EQ(VT_DISPATCH, var.type());
-  EXPECT_EQ(NULL, V_DISPATCH(&var));
+  EXPECT_EQ(NULL, V_DISPATCH(var.ptr()));
   var.Reset();
 
   var.Set(static_cast<IUnknown*>(NULL));
   EXPECT_EQ(VT_UNKNOWN, var.type());
-  EXPECT_EQ(NULL, V_UNKNOWN(&var));
+  EXPECT_EQ(NULL, V_UNKNOWN(var.ptr()));
   var.Reset();
 
   FakeComObject faker;
   EXPECT_EQ(0, faker.ref_count());
   var.Set(static_cast<IDispatch*>(&faker));
   EXPECT_EQ(VT_DISPATCH, var.type());
-  EXPECT_EQ(&faker, V_DISPATCH(&var));
+  EXPECT_EQ(&faker, V_DISPATCH(var.ptr()));
   EXPECT_EQ(1, faker.ref_count());
   var.Reset();
   EXPECT_EQ(0, faker.ref_count());
 
   var.Set(static_cast<IUnknown*>(&faker));
   EXPECT_EQ(VT_UNKNOWN, var.type());
-  EXPECT_EQ(&faker, V_UNKNOWN(&var));
+  EXPECT_EQ(&faker, V_UNKNOWN(var.ptr()));
   EXPECT_EQ(1, faker.ref_count());
   var.Reset();
   EXPECT_EQ(0, faker.ref_count());
@@ -204,7 +204,7 @@
   {
     ScopedVariant disp_var(&faker);
     EXPECT_EQ(VT_DISPATCH, disp_var.type());
-    EXPECT_EQ(&faker, V_DISPATCH(&disp_var));
+    EXPECT_EQ(&faker, V_DISPATCH(disp_var.ptr()));
     EXPECT_EQ(1, faker.ref_count());
   }
   EXPECT_EQ(0, faker.ref_count());
@@ -223,7 +223,7 @@
   {
     ScopedVariant unk_var(static_cast<IUnknown*>(&faker));
     EXPECT_EQ(VT_UNKNOWN, unk_var.type());
-    EXPECT_EQ(&faker, V_UNKNOWN(&unk_var));
+    EXPECT_EQ(&faker, V_UNKNOWN(unk_var.ptr()));
     EXPECT_EQ(1, faker.ref_count());
   }
   EXPECT_EQ(0, faker.ref_count());
@@ -240,7 +240,7 @@
   {
     ScopedVariant number(123);
     EXPECT_EQ(VT_I4, number.type());
-    EXPECT_EQ(123, V_I4(&number));
+    EXPECT_EQ(123, V_I4(number.ptr()));
   }
 
   // SAFEARRAY tests
@@ -253,7 +253,7 @@
   var.Set(sa);
   EXPECT_TRUE(ScopedVariant::IsLeakableVarType(var.type()));
   EXPECT_EQ(VT_ARRAY | VT_UI1, var.type());
-  EXPECT_EQ(sa, V_ARRAY(&var));
+  EXPECT_EQ(sa, V_ARRAY(var.ptr()));
   // The array is destroyed in the destructor of var.
 }
 
diff --git a/base/win/startup_information.h b/base/win/startup_information.h
index 7cef81f..e7e21cb 100644
--- a/base/win/startup_information.h
+++ b/base/win/startup_information.h
@@ -45,5 +45,4 @@
 }  // namespace win
 }  // namespace base
 
-#endif  // BASE_WIN_SCOPED_STARTUP_INFO_EX_H_
-
+#endif  // BASE_WIN_STARTUP_INFORMATION_H__
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index 957f937..59ae375 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -70,6 +70,53 @@
     return true;
   }
 
+  // If the device is docked, the user is treating the device as a PC.
+  if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0)
+    return true;
+
+  // To determine whether a keyboard is present on the device, we do the
+  // following:-
+  // 1. Check whether the device supports auto rotation. If it does then
+  //    it possibly supports flipping from laptop to slate mode. If it
+  //    does not support auto rotation, then we assume it is a desktop
+  //    or a normal laptop and assume that there is a keyboard.
+
+  // 2. If the device supports auto rotation, then we get its platform role
+  //    and check the system metric SM_CONVERTIBLESLATEMODE to see if it is
+  //    being used in slate mode. If yes then we return false here to ensure
+  //    that the OSK is displayed.
+
+  // 3. If step 1 and 2 fail then we check attached keyboards and return true
+  //    if we find ACPI\* or HID\VID* keyboards.
+
+  typedef BOOL (WINAPI* GetAutoRotationState)(PAR_STATE state);
+
+  GetAutoRotationState get_rotation_state =
+      reinterpret_cast<GetAutoRotationState>(::GetProcAddress(
+          GetModuleHandle(L"user32.dll"), "GetAutoRotationState"));
+
+  if (get_rotation_state) {
+    AR_STATE auto_rotation_state = AR_ENABLED;
+    get_rotation_state(&auto_rotation_state);
+    if ((auto_rotation_state & AR_NOSENSOR) ||
+        (auto_rotation_state & AR_NOT_SUPPORTED)) {
+      // If there is no auto rotation sensor or rotation is not supported in
+      // the current configuration, then we can assume that this is a desktop
+      // or a traditional laptop.
+      return true;
+    }
+  }
+
+  // Check if the device is being used as a laptop or a tablet. This can be
+  // checked by first checking the role of the device and then the
+  // corresponding system metric (SM_CONVERTIBLESLATEMODE). If it is being used
+  // as a tablet then we want the OSK to show up.
+  POWER_PLATFORM_ROLE role = PowerDeterminePlatformRole();
+
+  if (((role == PlatformRoleMobile) || (role == PlatformRoleSlate)) &&
+       (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0))
+    return false;
+
   const GUID KEYBOARD_CLASS_GUID =
       { 0x4D36E96B, 0xE325,  0x11CE,
           { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } };
@@ -97,10 +144,9 @@
                                         MAX_DEVICE_ID_LEN,
                                         0);
     if (status == CR_SUCCESS) {
-      // To reduce the scope of the hack we only look for PNP, MSF and HID
-      // keyboards.
-      if (StartsWith(device_id, L"ACPI\\PNP", false) ||
-          StartsWith(device_id, L"ACPI\\MSF", false) ||
+      // To reduce the scope of the hack we only look for ACPI and HID\\VID
+      // prefixes in the keyboard device ids.
+      if (StartsWith(device_id, L"ACPI", false) ||
           StartsWith(device_id, L"HID\\VID", false)) {
         keyboard_count++;
       }
diff --git a/base/win/win_util_unittest.cc b/base/win/win_util_unittest.cc
index 8300c16..24141cd 100644
--- a/base/win/win_util_unittest.cc
+++ b/base/win/win_util_unittest.cc
@@ -49,9 +49,9 @@
 TEST(BaseWinUtilTest, TestGetNonClientMetrics) {
   NONCLIENTMETRICS_XP metrics = {0};
   GetNonClientMetrics(&metrics);
-  EXPECT_TRUE(metrics.cbSize > 0);
-  EXPECT_TRUE(metrics.iScrollWidth > 0);
-  EXPECT_TRUE(metrics.iScrollHeight > 0);
+  EXPECT_GT(metrics.cbSize, 0u);
+  EXPECT_GT(metrics.iScrollWidth, 0);
+  EXPECT_GT(metrics.iScrollHeight, 0);
 }
 
 }  // namespace win
diff --git a/build/OWNERS b/build/OWNERS
index da383a1..17d067c 100644
--- a/build/OWNERS
+++ b/build/OWNERS
@@ -1,4 +1,5 @@
 cjhopman@chromium.org
+dpranke@chromium.org
 jochen@chromium.org
 scottmg@chromium.org
 thakis@chromium.org
diff --git a/build/all.gyp b/build/all.gyp
index 499fc57..4108962 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -66,7 +66,6 @@
             '../third_party/mojo/mojo_public.gyp:mojo_public_test_utils',
             '../third_party/mojo/mojo_public.gyp:mojo_system',
             '../ui/base/ui_base_tests.gyp:ui_base_unittests',
-            '../ui/ios/ui_ios_tests.gyp:ui_ios_unittests',
             '../ui/gfx/gfx_tests.gyp:gfx_unittests',
           ],
         }],
@@ -642,13 +641,6 @@
           ],
         }, # target_name: chromium_gpu_debug_builder
         {
-          'target_name': 'chromium_builder_perf_av',
-          'type': 'none',
-          'dependencies': [
-            'blink_tests', # to run layout tests
-          ],
-        },  # target_name: chromium_builder_perf_av
-        {
           # This target contains everything we need to run tests on the special
           # device-equipped WebRTC bots. We have device-requiring tests in
           # browser_tests and content_browsertests.
@@ -789,6 +781,7 @@
             '../content/content_shell_and_tests.gyp:content_shell_test_apk',
             '../content/content_shell_and_tests.gyp:content_unittests',
             '../gpu/gpu.gyp:gl_tests',
+            '../gpu/gpu.gyp:gpu_perftests_apk',
             '../gpu/gpu.gyp:gpu_unittests',
             '../ipc/ipc.gyp:ipc_tests',
             '../media/media.gyp:media_perftests_apk',
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index c3c344b..c9be13a 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -466,6 +466,8 @@
     provision_cmd.append('--auto-reconnect')
   if options.skip_wipe:
     provision_cmd.append('--skip-wipe')
+  if options.disable_location:
+    provision_cmd.append('--disable-location')
   RunCmd(provision_cmd, halt_on_failure=True)
 
 
@@ -713,6 +715,8 @@
       help='Push script to device which restarts adbd on disconnections.')
   parser.add_option('--skip-wipe', action='store_true',
                     help='Do not wipe devices during provisioning.')
+  parser.add_option('--disable-location', action='store_true',
+                    help='Disable location settings.')
   parser.add_option(
       '--logcat-dump-output',
       help='The logcat dump output will be "tee"-ed into this file')
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml
index fba286d..5060e47 100644
--- a/build/android/findbugs_filter/findbugs_exclude.xml
+++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -18,7 +18,16 @@
     <Class name="~org\.chromium\..*\.Manifest(\$\w+)?" />
   </Match>
   <!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform -->
-
+  <Match>
+    <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
+    <Method name="onCancel" />
+    <Bug code="Dm" />
+  </Match>
+  <Match>
+    <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" />
+    <Method name="onClick" />
+    <Bug code="Dm" />
+  </Match>
   <Bug pattern="DM_DEFAULT_ENCODING" />
   <!-- Ignore bugs that are often false-positives in test code -->
   <Match>
diff --git a/build/android/findbugs_filter/findbugs_known_bugs.txt b/build/android/findbugs_filter/findbugs_known_bugs.txt
deleted file mode 100644
index 01b546a..0000000
--- a/build/android/findbugs_filter/findbugs_known_bugs.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-M M LI: Incorrect lazy initialization of static field org.chromium.chrome.browser.download.DownloadManagerService.sDownloadManagerService in org.chromium.chrome.browser.download.DownloadManagerService.getDownloadManagerService(Context)  At DownloadManagerService.java
-M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.extraHeaders  At DocumentTabModelSelector.java
-M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.postData  At DocumentTabModelSelector.java
-M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.referrer  At DocumentTabModelSelector.java
-M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.webContents  In PendingDocumentData.java
-M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.originalIntent  In PendingDocumentData.java
-M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.url  In PendingDocumentData.java
-M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.requestId  In PendingDocumentData.java
-M D BC: Unchecked/unconfirmed cast from android.view.View to org.chromium.chrome.browser.firstrun.AccountFirstRunView in org.chromium.chrome.browser.firstrun.AccountFirstRunFragment.onViewCreated(View, Bundle)  At AccountFirstRunFragment.java
-M M LI: Incorrect lazy initialization and update of static field org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings.sSettings in org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings.initialize(Context)  At DataReductionProxySettings.java
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py
index 953ea54..9402780 100755
--- a/build/android/gyp/lint.py
+++ b/build/android/gyp/lint.py
@@ -20,7 +20,8 @@
 
 
 def _RunLint(lint_path, config_path, processed_config_path, manifest_path,
-             result_path, product_dir, sources, jar_path, resource_dir=None):
+             result_path, product_dir, sources, jar_path, resource_dir=None,
+             can_fail_build=False):
 
   def _RelativizePath(path):
     """Returns relative path to top-level src dir.
@@ -147,8 +148,7 @@
                                              'lint', 'suppress.py')),
                 _RelativizePath(result_path)))
         print >> sys.stderr, msg
-        # Lint errors do not fail the build.
-        return 0
+        return 1 if can_fail_build else 0
 
   return 0
 
@@ -167,6 +167,9 @@
   parser.add_option('--java-files', help='Paths to java files.')
   parser.add_option('--jar-path', help='Jar file containing class files.')
   parser.add_option('--resource-dir', help='Path to resource dir.')
+  parser.add_option('--can-fail-build', action='store_true',
+                    help='If set, script will exit with nonzero exit status'
+                    ' if lint errors are present')
   parser.add_option('--stamp', help='Path to touch on success.')
   parser.add_option('--enable', action='store_true',
                     help='Run lint instead of just touching stamp.')
@@ -195,7 +198,7 @@
                   options.processed_config_path,
                   options.manifest_path, options.result_path,
                   options.product_dir, sources, options.jar_path,
-                  options.resource_dir)
+                  options.resource_dir, options.can_fail_build)
 
   if options.depfile:
     build_utils.WriteDepfile(
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml
index cfbf858..ba476d5 100644
--- a/build/android/lint/suppressions.xml
+++ b/build/android/lint/suppressions.xml
@@ -95,9 +95,6 @@
     <ignore path="org/chromium/media/VideoCaptureCamera2.class"/>
     <ignore path="org/chromium/media/VideoCaptureCamera2$*.class"/>
     <ignore path="org/chromium/media/WebAudioMediaCodecBridge.class"/>
-    <ignore path="org/chromium/printing/PrintDocumentAdapterWrapper.class"/>
-    <ignore path="org/chromium/printing/PrintManagerDelegateImpl.class"/>
-    <ignore path="org/chromium/printing/PrintingControllerImpl.class"/>
     <ignore path="org/chromium/ui/base/Clipboard.class"/>
     <ignore path="org/chromium/ui/ColorPickerAdvancedComponent.class"/>
     <ignore path="org/chromium/ui/gfx/DeviceDisplayInfo.class"/>
diff --git a/build/android/pylib/gtest/filter/content_browsertests_disabled b/build/android/pylib/gtest/filter/content_browsertests_disabled
index 613c833..3c36264 100644
--- a/build/android/pylib/gtest/filter/content_browsertests_disabled
+++ b/build/android/pylib/gtest/filter/content_browsertests_disabled
@@ -15,10 +15,6 @@
 # Crashes
 RenderFrameHostManagerTest.IgnoreRendererDebugURLsWhenCrashed
 
-# Crashes due to using --disable-gpu.
-# Needs to investigate more in http://crbug.com/461624.
-ScreenOrientationBrowserTest.*
-
 # Plugins are not supported.
 BrowserPluginThreadedCompositorPixelTest.*
 BrowserPluginHostTest.*
@@ -74,7 +70,3 @@
 
 # http://crbug.com/343604
 MSE_ClearKey/EncryptedMediaTest.ConfigChangeVideo/0
-
-# http://crbug.com/463041
-ScreenOrientationBrowserTest.ScreenOrientationChange
-ScreenOrientationBrowserTest.WindowOrientationCange
diff --git a/build/android/pylib/host_driven/test_server.py b/build/android/pylib/host_driven/test_server.py
index 959e7a9..0783500 100644
--- a/build/android/pylib/host_driven/test_server.py
+++ b/build/android/pylib/host_driven/test_server.py
@@ -106,7 +106,8 @@
     cmd = ['python', os.path.join(src_dir, test_server_path),
            '--log-to-console',
            ('--host=%s' % self.host),
-           ('--port=%d' % self.port)] + test_server_flags
+           ('--port=%d' % self.port),
+           '--on-remote-server'] + test_server_flags
     self._test_server_process = subprocess.Popen(
           cmd, env={'PYTHONPATH': python_path})
     test_url = 'http://%s:%d/%s' % (self.host, self.port,
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index 3b0c029..8875096 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -286,12 +286,22 @@
       return 0
 
     logging.critical('Available %s Devices:', self._device_type)
-    logging.critical('  %s %s %s', 'OS'.ljust(7),
-                     'Device Name'.ljust(20), '# Available')
+    logging.critical(
+        '  %s %s %s %s %s',
+        'OS'.ljust(10),
+        'Device Name'.ljust(30),
+        'Available'.ljust(10),
+        'Busy'.ljust(10),
+        'All'.ljust(10))
     devices = (d for d in device_list if d['os_name'] == self._device_type)
     for d in sorted(devices, compare_devices):
-      logging.critical('  %s %s %s', d['os_version'].ljust(7),
-                       d['name'].ljust(20), d['available_devices_count'])
+      logging.critical(
+          '  %s %s %s %s %s',
+          d['os_version'].ljust(10),
+          d['name'].ljust(30),
+          str(d['available_devices_count']).ljust(10),
+          str(d['busy_devices_count']).ljust(10),
+          str(d['all_devices_count']).ljust(10))
 
   def _GetDeviceList(self):
     with appurify_sanitized.SanitizeLogging(self._verbose_count,
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py
index 60d326e..fcbe427 100644
--- a/build/android/pylib/utils/isolator.py
+++ b/build/android/pylib/utils/isolator.py
@@ -41,6 +41,7 @@
     'use_instrumented_libraries': '0',
     'use_openssl': '0',
     'use_ozone': '0',
+    'use_x11': '0',
     'v8_use_external_startup_data': '1',
   }
 
diff --git a/build/common.gypi b/build/common.gypi
index d72c76f..043dd92 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -416,6 +416,9 @@
       # See https://code.google.com/p/sawbuck/wiki/SyzyASanHowTo
       'syzyasan%': 0,
 
+      # Enable crash reporting via Kasko.
+      'kasko%': 0,
+
       # Enable building with LSan (Clang's -fsanitize=leak option).
       # -fsanitize=leak only works with clang, but lsan=1 implies clang=1
       # See https://sites.google.com/a/chromium.org/dev/developers/testing/leaksanitizer
@@ -643,6 +646,10 @@
       # Libxkbcommon usage.
       'use_xkbcommon%': 0,
 
+      # Control Flow Integrity for virtual calls.
+      # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
+      'cfi_vptr%': 0,
+
       'conditions': [
         # A flag for POSIX platforms
         ['OS=="win"', {
@@ -771,7 +778,6 @@
         }],
 
         ['OS=="mac" or OS=="ios"', {
-          'native_discardable_memory%': 1,
           'native_memory_pressure_signals%': 1,
         }],
 
@@ -808,7 +814,6 @@
           'enable_supervised_users%': 0,
           'enable_task_manager%': 0,
           'use_system_libcxx%': 1,
-          'support_pre_M6_history_database%': 0,
         }],
 
         # Use GPU accelerated cross process image transport by default
@@ -1063,9 +1068,6 @@
       'google_default_client_secret%': '',
       # Native Client is enabled by default.
       'disable_nacl%': '0',
-
-      # Set to 1 to support old history files
-      'support_pre_M6_history_database%': '1',
     },
 
     # Copy conditionally-set variables out one scope.
@@ -1140,6 +1142,7 @@
     'asan_field_padding%': '<(asan_field_padding)',
     'use_sanitizer_options%': '<(use_sanitizer_options)',
     'syzyasan%': '<(syzyasan)',
+    'kasko%': '<(kasko)',
     'syzygy_optimize%': '<(syzygy_optimize)',
     'lsan%': '<(lsan)',
     'msan%': '<(msan)',
@@ -1214,8 +1217,8 @@
     'use_lto_o2%': '<(use_lto_o2)',
     'gold_icf_level%': '<(gold_icf_level)',
     'video_hole%': '<(video_hole)',
-    'support_pre_M6_history_database%': '<(support_pre_M6_history_database)',
     'v8_use_external_startup_data%': '<(v8_use_external_startup_data)',
+    'cfi_vptr%': '<(cfi_vptr)',
 
     # Use system protobuf instead of bundled one.
     'use_system_protobuf%': 0,
@@ -1951,6 +1954,9 @@
           ['asan==1 or syzyasan==1', {
             'win_use_allocator_shim%': 0,
           }],
+          ['syzyasan==1', {
+            'kasko%': 1,
+          }],
           ['component=="shared_library" and "<(GENERATOR)"=="ninja"', {
             # Only enabled by default for ninja because it's buggy in VS.
             # Not enabled for component=static_library because some targets
@@ -2162,8 +2168,19 @@
         'enable_service_discovery%': 1
       }],
       ['clang_use_chrome_plugins==1 and OS!="win"', {
+        'variables': {
+          'conditions': [
+            ['OS=="mac" or OS=="ios"', {
+              'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib',
+            }, { # OS != "mac" or OS != "ios"
+              'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so',
+            }],
+          ],
+        },
+        # If you change these, also change build/config/clang/BUILD.gn.
         'clang_chrome_plugins_flags%':
-          '<!(python <(DEPTH)/tools/clang/scripts/plugin_flags.py)',
+          '-Xclang -load -Xclang <(clang_lib_path)'
+          ' -Xclang -add-plugin -Xclang find-bad-constructs',
       }],
       ['asan==1 or msan==1 or lsan==1 or tsan==1', {
         'clang%': 1,
@@ -2376,10 +2393,11 @@
       }, {
          'use_seccomp_bpf%': 0,
       }],
-    ],
 
-    # older history files use fts2 instead of fts3
-    'sqlite_enable_fts2%': '<(support_pre_M6_history_database)',
+      ['cfi_vptr==1', {
+        'use_lto%': 1,
+      }],
+    ],
 
     # The path to the ANGLE library.
     'angle_path': '<(DEPTH)/third_party/angle',
@@ -2796,6 +2814,11 @@
             'MEMORY_TOOL_REPLACES_ALLOCATOR',
             'MEMORY_SANITIZER_INITIAL_SIZE',
         ],
+      }],
+      ['kasko==1', {
+        'defines': [
+            'KASKO',
+        ],
         'include_dirs': [
           '<(DEPTH)/third_party/kasko/include',
         ],
@@ -2953,9 +2976,6 @@
       ['disable_ftp_support==1', {
         'defines': ['DISABLE_FTP_SUPPORT=1'],
       }],
-      ['use_icu_alternatives_on_android==1', {
-        'defines': ['USE_ICU_ALTERNATIVES_ON_ANDROID=1'],
-      }],
       ['enable_supervised_users==1', {
         'defines': ['ENABLE_SUPERVISED_USERS=1'],
       }],
@@ -3990,6 +4010,7 @@
                       ['clang==1', {
                         'cflags!': [
                           # Clang does not support the following options.
+                          '-mapcs-frame',
                           '-mthumb-interwork',
                           '-finline-limit=64',
                           '-fno-tree-sra',
@@ -4461,6 +4482,14 @@
                   # '-Wl,--threads',
                   # '-Wl,--thread-count=4',
                 ],
+                'conditions': [
+                  # TODO(thestig): Enable this for disabled cases.
+                  [ 'buildtype!="Official" and chromeos==0 and release_valgrind_build==0 and asan==0 and lsan==0 and tsan==0 and msan==0 and ubsan==0 and ubsan_vptr==0', {
+                    'ldflags': [
+                      '-Wl,--detect-odr-violations',
+                    ],
+                  }],
+                ],
               }],
             ],
             'conditions': [
@@ -5927,6 +5956,20 @@
         ],
       },
     }],
+    ['cfi_vptr==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize=cfi-vptr',
+            ],
+            'ldflags': [
+              '-fsanitize=cfi-vptr',
+            ],
+          }],
+        ],
+      },
+    }],
   ],
   'xcode_settings': {
     # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 49b5cfe..15441a9 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -14,11 +14,16 @@
   # catching bugs but in some cases may cause conflicts or excessive slowness.
   disable_iterator_debugging = false
 
-  # Set to true to not store any build metadata (this isn't working yet but
-  # this flag will help us to get there). See http://crbug.com/314403.
-  # TODO(sebmarchand): Update this comment once this flag guarantee that
-  #     there's no build metadata in the build artifacts.
-  dont_embed_build_metadata = false
+  # Set to true to not store any build metadata, e.g. ifdef out all __DATE__
+  # and __TIME__. Set to 0 to reenable the use of these macros in the code
+  # base. See http://crbug.com/314403.
+  #
+  # Continue to embed build meta data in Official builds, basically the
+  # time it was built.
+  # TODO(maruel): This decision should be revisited because having an
+  # official deterministic build has high value too but MSVC toolset can't
+  # generate anything deterministic with WPO enabled AFAIK.
+  dont_embed_build_metadata = is_official_build
 
   # Set to true to enable dcheck in Release builds.
   dcheck_always_on = false
@@ -214,6 +219,12 @@
   if (v8_use_external_startup_data) {
     defines += [ "V8_USE_EXTERNAL_STARTUP_DATA" ]
   }
+  if (enable_background) {
+    defines += [ "ENABLE_BACKGROUND=1" ]
+  }
+  if (enable_pre_sync_backup) {
+    defines += [ "ENABLE_PRE_SYNC_BACKUP" ]
+  }
 }
 
 # Debug/release ----------------------------------------------------------------
@@ -225,6 +236,10 @@
     "WTF_USE_DYNAMIC_ANNOTATIONS=1",
   ]
 
+  if (is_nacl) {
+    defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ]
+  }
+
   if (is_win) {
     if (disable_iterator_debugging) {
       # Iterator debugging is enabled by the compiler on debug builds, and we
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 4397151..f75ad06 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -78,7 +78,7 @@
 #
 # Base compiler configuration.
 #
-# See also "runtime_library" below for related stuff and a discusison about
+# See also "runtime_library" below for related stuff and a discussion about
 # where stuff should go. Put warning related stuff in the "warnings" config.
 
 config("compiler") {
@@ -100,10 +100,6 @@
       "/GS",  # Enable buffer security checking.
       "/FS",  # Preserve previous PDB behavior.
     ]
-    if (is_component_build) {
-      cflags += [ "/EHsc" ]  # Assume C functions can't throw exceptions and don't catch
-                             # structured exceptions (only C++ ones).
-    }
   } else {
     # Common GCC compiler flags setup.
     # --------------------------------
@@ -161,7 +157,7 @@
     ]
   }
 
-  if (is_clang && !is_win) {
+  if (is_clang && !is_win && !is_nacl) {
     # This is here so that all files get recompiled after a clang roll and
     # when turning clang on or off. (defines are passed via the command line,
     # and build system rebuild things when their commandline changes). Nothing
@@ -403,6 +399,13 @@
       #"-Wl,--threads",
       #"-Wl,--thread-count=4",
     ]
+
+    # TODO(thestig): Make this flag work with GN.
+    #if (!is_official_build && !is_chromeos && !(is_asan || is_lsan || is_tsan || is_msan)) {
+    #  ldflags += [
+    #    "-Wl,--detect-odr-violations",
+    #  ]
+    #}
   }
 
   if (linux_use_bundled_binutils) {
@@ -534,9 +537,6 @@
   } else {
     # Static CRT.
     if (is_win) {
-      # We don't use exceptions, and when we link statically we can just get
-      # rid of them entirely.
-      defines += [ "_HAS_EXCEPTIONS=0" ]
       if (is_debug) {
         cflags += [ "/MTd" ]
       } else {
@@ -548,10 +548,9 @@
   if (is_win) {
     defines += [
       "__STD_C",
-      "__STDC_CONSTANT_MACROS",
-      "__STDC_FORMAT_MACROS",
       "_CRT_RAND_S",
       "_CRT_SECURE_NO_DEPRECATE",
+      "_HAS_EXCEPTIONS=0",
       "_SCL_SECURE_NO_DEPRECATE",
     ]
   }
@@ -727,7 +726,6 @@
   if (is_win) {
     cflags = [
       "/WX",  # Treat warnings as errors.
-
       # Warnings permanently disabled:
 
       # TODO(GYP) The GYP build doesn't have this globally enabled but disabled
@@ -782,7 +780,6 @@
       # have to turn off this warning (and be careful about how object
       # destruction happens in such cases).
       "/wd4611",
-
       # Warnings to evaluate and possibly fix/reenable later:
 
       "/wd4100",  # Unreferenced formal function parameter.
diff --git a/build/config/features.gni b/build/config/features.gni
index 4d01a87..ee61da5 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -178,3 +178,6 @@
 # For official GYP builds, this flag is set, it will likely need to be
 # parameterized in the future for a similar use.
 enable_hangout_services_extension = false
+
+# Whether to back up data before sync.
+enable_pre_sync_backup = is_win || is_mac || (is_linux && !is_chromeos)
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 201d45b..3e98c1a 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -17,6 +17,9 @@
     "PSAPI_VERSION=1",
     "WIN32",
     "_SECURE_ATL",
+
+    # This is required for ATL to use XP-safe versions of its functions.
+    "_USING_V110_SDK71_",
   ]
 }
 
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index 273c38e..92c050f 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -34,60 +34,145 @@
       'target_name': 'gn_all',
       'type': 'none',
       'dependencies': [
+        '../base/base.gyp:base_i18n_perftests',
+        '../base/base.gyp:base_perftests',
         '../base/base.gyp:base_unittests',
+        '../base/base.gyp:build_utf8_validator_tables#host',
+        '../base/base.gyp:check_example',
+        '../base/base.gyp:protect_file_posix',
+        '../breakpad/breakpad.gyp:core-2-minidump',
+        '../breakpad/breakpad.gyp:microdump_stackwalk',
+        '../breakpad/breakpad.gyp:minidump_dump',
+        '../breakpad/breakpad.gyp:minidump_stackwalk',
+        '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
+        '../cc/cc_tests.gyp:cc_perftests',
         '../cc/cc_tests.gyp:cc_unittests',
+        '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
         '../chrome/chrome.gyp:chrome',
         '../chrome/chrome.gyp:browser_tests',
+        '../chrome/chrome.gyp:chrome_app_unittests',
+        '../chrome/chrome.gyp:chromedriver',
+        '../chrome/chrome.gyp:chromedriver_tests',
+        '../chrome/chrome.gyp:chromedriver_unittests',
         '../chrome/chrome.gyp:interactive_ui_tests',
+        '../chrome/chrome.gyp:load_library_perf_tests',
+        '../chrome/chrome.gyp:service_discovery_sniffer',
         '../chrome/chrome.gyp:sync_integration_tests',
+        '../chrome/chrome.gyp:sync_performance_tests',
         '../chrome/chrome.gyp:unit_tests',
+        '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler',
+        '../components/components.gyp:network_hints_browser',
+        '../components/components.gyp:webui_generator',
+        '../components/components_tests.gyp:components_perftests',
         '../components/components_tests.gyp:components_unittests',
-        '../content/content_shell_and_tests.gyp:content_shell',
+        '../components/nacl.gyp:nacl_loader_unittests',
+        '../content/content.gyp:content_app_browser',
+        '../content/content.gyp:content_app_child',
         '../content/content_shell_and_tests.gyp:content_browsertests',
+        '../content/content_shell_and_tests.gyp:content_gl_benchmark',
+        '../content/content_shell_and_tests.gyp:content_gl_tests',
         '../content/content_shell_and_tests.gyp:content_perftests',
+        '../content/content_shell_and_tests.gyp:content_shell',
         '../content/content_shell_and_tests.gyp:content_unittests',
+        '../courgette/courgette.gyp:courgette',
+        '../courgette/courgette.gyp:courgette_fuzz',
+        '../courgette/courgette.gyp:courgette_minimal_tool',
+        '../courgette/courgette.gyp:courgette_unittests',
         '../crypto/crypto.gyp:crypto_unittests',
         '../extensions/extensions_tests.gyp:extensions_browsertests',
         '../extensions/extensions_tests.gyp:extensions_unittests',
+        '../device/device_tests.gyp:device_unittests',
+        '../gin/gin.gyp:gin_v8_snapshot_fingerprint',
+        '../gin/gin.gyp:gin_shell',
+        '../gin/gin.gyp:gin_unittests',
         '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+        '../google_apis/gcm/gcm.gyp:mcs_probe',
+        '../google_apis/google_apis.gyp:google_apis_unittests',
+        '../gpu/gpu.gyp:angle_unittests',
+        '../gpu/gpu.gyp:gl_tests',
+        '../gpu/gpu.gyp:gpu_perftests',
         '../gpu/gpu.gyp:gpu_unittests',
+        '../ipc/ipc.gyp:ipc_perftests',
         '../ipc/ipc.gyp:ipc_tests',
         '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
         '../jingle/jingle.gyp:jingle_unittests',
+        '../media/media.gyp:ffmpeg_regression_tests',  # TODO(GYP) this should be conditional on media_use_ffmpeg
+        '../media/media.gyp:media_perftests',
         '../media/media.gyp:media_unittests',
+        '../media/cast/cast.gyp:cast_benchmarks',
         '../media/cast/cast.gyp:cast_unittests',
+        '../media/cast/cast.gyp:generate_barcode_video',
+        '../media/cast/cast.gyp:generate_timecode_audio',
         '../mojo/mojo.gyp:mojo',
+        '../mojo/mojo_base.gyp:mojo_application_chromium',
         '../mojo/mojo_base.gyp:mojo_common_unittests',
+        '../net/net.gyp:crash_cache',
+        '../net/net.gyp:crl_set_dump',
+        '../net/net.gyp:dns_fuzz_stub',
+        '../net/net.gyp:dump_cache',
+        '../net/net.gyp:gdig',
+        '../net/net.gyp:get_server_time',
         '../net/net.gyp:net_unittests',
+        '../net/net.gyp:net_watcher',  # TODO(GYP): This should be conditional on use_v8_in_net
+        '../net/net.gyp:run_testserver',
+        '../net/net.gyp:stress_cache',
+        '../net/net.gyp:tld_cleanup',
+        '../ppapi/ppapi_internal.gyp:*',  # TODO(GYP) - list all of the examples explicitly.
+        '../ppapi/ppapi_internal.gyp:ppapi_tests',  # TODO(GYP): Split out the examples and tests
+        '../ppapi/ppapi_internal.gyp:ppapi_unittests',
         '../printing/printing.gyp:printing_unittests',
         '../skia/skia_tests.gyp:skia_unittests',
+        '../skia/skia.gyp:filter_fuzz_stub',
+        '../skia/skia.gyp:image_operations_bench',
         '../sql/sql.gyp:sql_unittests',
+        '../sync/sync.gyp:run_sync_testserver',
+        '../sync/sync.gyp:sync_endtoend_tests',
         '../sync/sync.gyp:sync_unit_tests',
-        '../third_party/WebKit/public/all.gyp:all_blink',
+        '../sync/tools/sync_tools.gyp:sync_client',
+        '../sync/tools/sync_tools.gyp:sync_listen_notifications',
+        '../testing/gmock.gyp:gmock_main',
+        '../third_party/WebKit/public/all.gyp:blink_tests',
         '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
         '../third_party/codesighs/codesighs.gyp:codesighs',
+        '../third_party/codesighs/codesighs.gyp:maptsvdifftool',
+        '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+        '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+        '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_system_unittests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests',
+        '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
         '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
         '../third_party/pdfium/samples/samples.gyp:pdfium_test',
         '../third_party/smhasher/smhasher.gyp:pmurhash',
         '../third_party/sqlite/sqlite.gyp:sqlite_shell',
         '../tools/gn/gn.gyp:gn',
+        '../tools/gn/gn.gyp:generate_test_gn_data',
         '../tools/gn/gn.gyp:gn_unittests',
+        '../tools/imagediff/image_diff.gyp:image_diff',
+        '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache',
+        '../tools/telemetry/telemetry.gyp:bitmaptools#host',
         '../ui/accessibility/accessibility.gyp:accessibility_unittests',
         '../ui/app_list/app_list.gyp:app_list_unittests',
         '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+        '../ui/compositor/compositor.gyp:compositor_unittests',
         '../ui/display/display.gyp:display_unittests',
         '../ui/events/events.gyp:events_unittests',
         '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+        '../ui/keyboard/keyboard.gyp:keyboard_unittests',
+        '../ui/message_center/message_center.gyp:message_center_unittests',
+        '../ui/snapshot/snapshot.gyp:snapshot_unittests',
         '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+        '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
         '../url/url.gyp:url_unittests',
+        '../v8/tools/gyp/v8.gyp:v8_snapshot',
+        '../v8/tools/gyp/v8.gyp:postmortem-metadata',
       ],
       'conditions': [
         ['enable_extensions==1 and OS!="mac"', {
           'dependencies': [
+            '../extensions/shell/app_shell.gyp:app_shell',
             '../extensions/shell/app_shell.gyp:app_shell_unittests',
           ],
         }],
@@ -98,16 +183,35 @@
         }],
         ['use_x11==1', {
           'dependencies': [
+            '../media/media.gyp:player_x11',
             '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
           ],
+          'conditions': [
+            ['target_arch!="arm"', {
+              'dependencies': [
+                '../gpu/tools/tools.gyp:compositor_model_bench',
+              ],
+            }],
+          ],
         }],
         ['toolkit_views==1', {
           'dependencies': [
+            '../ui/app_list/app_list.gyp:app_list_demo',
             '../ui/views/views.gyp:views_unittests',
           ],
         }],
+        ['use_ash==1', {
+          'dependencies': [
+            '../ash/ash.gyp:ash_shell',
+            '../ash/ash.gyp:ash_shell_unittests',
+            '../ash/ash.gyp:ash_unittests',
+          ],
+        }],
         ['use_aura==1', {
           'dependencies': [
+            '../ui/aura/aura.gyp:aura_bench',
+            '../ui/aura/aura.gyp:aura_demo',
+            '../ui/aura/aura.gyp:aura_unittests',
             '../ui/wm/wm.gyp:wm_unittests',
           ],
         }],
@@ -124,11 +228,12 @@
         ['OS=="android"', {
           'dependencies': [
             '../base/base.gyp:chromium_android_linker', 
+            '../breakpad/breakpad.gyp:dump_syms',
             '../build/android/rezip.gyp:rezip_apk_jar',
             '../chrome/chrome.gyp:chrome_shell_apk',
             '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
             #"//clank" TODO(GYP) - conditional somehow?
-            '../tools/imagediff/imagediff.gyp:imagediff#host',
+            '../tools/imagediff/image_diff.gyp:image_diff#host',
             '../tools/telemetry/telemetry.gyp:bitmaptools#host',
       
             # TODO(GYP): Remove these when the components_unittests work.
@@ -163,6 +268,8 @@
           'dependencies!': [
             '../breakpad/breakpad.gyp:symupload',
             '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:chromedriver',
+            '../chrome/chrome.gyp:chromedriver_unitests',
             '../chrome/chrome.gyp:interactive_ui_tests',
             '../chrome/chrome.gyp:sync_integration_tests',
             '../chrome/chrome.gyp:unit_tests',
@@ -176,64 +283,87 @@
             '../third_party/pdfium/samples/samples.gyp:pdfium_test',
             '../tools/gn/gn.gyp:gn',
             '../tools/gn/gn.gyp:gn_unittests',
+            '../tools/imagediff/image_diff.gyp:image_diff',
+            '../tools/gn/gn.gyp:gn',
+            '../tools/gn/gn.gyp:gn_unittests',
             '../ui/app_list/app_list.gyp:app_list_unittests',
             '../url/url.gyp:url_unittests',
           ],
         }],
         ['OS=="linux"', {
           'dependencies': [
+            '../breakpad/breakpad.gyp:breakpad_unittests',
+            '../breakpad/breakpad.gyp:dump_syms',
+            '../breakpad/breakpad.gyp:generate_test_dump',
+            '../breakpad/breakpad.gyp:minidump-2-core',
+            '../dbus/dbus.gyp:dbus_test_server',
+            '../dbus/dbus.gyp:dbus_unittests',
+            '../media/cast/cast.gyp:tap_proxy',
+            '../net/net.gyp:disk_cache_memory_test',
+            '../net/net.gyp:flip_in_mem_edsm_server',
+            '../net/net.gyp:flip_in_mem_edsm_server_unittests',
+            '../net/net.gyp:hpack_example_generator',
+            '../net/net.gyp:hpack_fuzz_mutator',
+            '../net/net.gyp:hpack_fuzz_wrapper',
+            '../net/net.gyp:net_perftests',
+            '../net/net.gyp:quic_client',
+            '../net/net.gyp:quic_server',
             '../sandbox/sandbox.gyp:chrome_sandbox',
             '../sandbox/sandbox.gyp:sandbox_linux_unittests',
+            '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
          ],
         }],
         ['OS=="mac"', {
           'dependencies': [
+            '../breakpad/breakpad.gyp:crash_inspector',
+            '../breakpad/breakpad.gyp:dump_syms',
+            '../breakpad/breakpad.gyp:symupload',
             '../third_party/apple_sample_code/apple_sample_code.gyp:apple_sample_code',
             '../third_party/molokocacao/molokocacao.gyp:molokocacao',
 
             # TODO(GYP): remove these when the corresponding root targets work.
-            "//cc/blink",
-            "//components/ui/zoom:ui_zoom",
-            "//content",
-            "//content/test:test_support",
-            "//device/battery",
-            "//device/bluetooth",
-            "//device/nfc",
-            "//device/usb",
-            "//device/vibration",
-            "//media/blink",
-            "//pdf",
-            "//storage/browser",
-            "//third_party/brotli",
-            "//third_party/flac",
-            "//third_party/hunspell",
-            "//third_party/iccjpeg",
-            "//third_party/libphonenumber",
-            "//third_party/ots",
-            "//third_party/qcms",
-            "//third_party/smhasher:murmurhash3",
-            "//third_party/speex",
-            "//third_party/webrtc/system_wrappers",
-            "//ui/native_theme",
-            "//ui/snapshot",
-            "//ui/surface",
+            #"//cc/blink",
+            #"//components/ui/zoom:ui_zoom",
+            #"//content",
+            #"//content/test:test_support",
+            #"//device/battery",
+            #"//device/bluetooth",
+            #"//device/nfc",
+            #"//device/usb",
+            #"//device/vibration",
+            #"//media/blink",
+            #"//pdf",
+            #"//storage/browser",
+            #"//third_party/brotli",
+            #"//third_party/flac",
+            #"//third_party/hunspell",
+            #//third_party/iccjpeg",
+            #"//third_party/libphonenumber",
+            #"//third_party/ots",
+            #"//third_party/qcms",
+            #"//third_party/smhasher:murmurhash3",
+            #"//third_party/speex",
+            #"//third_party/webrtc/system_wrappers",
+            #"//ui/native_theme",
+            #"//ui/snapshot",
+            #"//ui/surface",
           ],
           'dependencies!': [
-            "//chrome",  # TODO(GYP)
-            "//chrome/test:browser_tests",  # TODO(GYP)
-            "//chrome/test:interactive_ui_tests",  # TODO(GYP)
-            "//chrome/test:sync_integration_tests",  # TODO(GYP)
-            "//chrome/test:unit_tests",  # TODO(GYP)
-            "//components:components_unittests",  # TODO(GYP)
-            "//content/test:content_browsertests",  # TODO(GYP)
-            "//content/test:content_perftests",  # TODO(GYP)
-            "//content/test:content_unittests",  # TODO(GYP)
-            "//extensions:extensions_browsertests",  # TODO(GYP)
-            "//extensions:extensions_unittests",  # TODO(GYP)
-            "//net:net_unittests",  # TODO(GYP)
-            "//third_party/usrsctp",  # TODO(GYP)
-            "//ui/app_list:app_list_unittests",  # TODO(GYP)
-            "//ui/gfx:gfx_unittests",  # TODO(GYP)
+            #"//chrome",  # TODO(GYP)
+            #"//chrome/test:browser_tests",  # TODO(GYP)
+            #"//chrome/test:interactive_ui_tests",  # TODO(GYP)
+            #"//chrome/test:sync_integration_tests",  # TODO(GYP)
+            #"//chrome/test:unit_tests",  # TODO(GYP)
+            #"//components:components_unittests",  # TODO(GYP)
+            #"//content/test:content_browsertests",  # TODO(GYP)
+            #"//content/test:content_perftests",  # TODO(GYP)
+            #"//content/test:content_unittests",  # TODO(GYP)
+            #"//extensions:extensions_browsertests",  # TODO(GYP)
+            #"//extensions:extensions_unittests",  # TODO(GYP)
+            #"//net:net_unittests",  # TODO(GYP)
+            #"//third_party/usrsctp",  # TODO(GYP)
+            #"//ui/app_list:app_list_unittests",  # TODO(GYP)
+            #"//ui/gfx:gfx_unittests",  # TODO(GYP)
           ],
         }],
         ['OS=="win"', {
@@ -245,93 +375,11 @@
             "//crypto:crypto_unittests",  # TODO(GYP)
             "//net:net_unittests",  # TODO(GYP)
           ],
-        }],
-      ],
-    },
-    {
-      # This target contains a list of things that actually currently
-      # build in GN, but aren't listed in //:gn_all
-      'target_name': 'add_to_gn_all',
-      'type': 'none',
-      'dependencies': [
-        '../breakpad/breakpad.gyp:microdump_stackwalk',
-        '../breakpad/breakpad.gyp:minidump_dump',
-        '../breakpad/breakpad.gyp:minidump_stackwalk',
-        '../cc/cc_tests.gyp:cc_perftests',
-        '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
-        '../chrome/chrome.gyp:sync_performance_tests',
-        '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler',
-        '../courgette/courgette.gyp:courgette_minimal_tool',
-        '../courgette/courgette.gyp:courgette_unittests',
-        '../extensions/shell/app_shell.gyp:app_shell',
-        '../gin/gin.gyp:gin_unittests',
-        '../google_apis/google_apis.gyp:google_apis_unittests',
-        '../gpu/gpu.gyp:angle_unittests',
-        '../gpu/gpu.gyp:gpu_perftests',
-        '../ipc/ipc.gyp:ipc_perftests',
-        '../media/media.gyp:ffmpeg_regression_tests',  # TODO(GYP) this should be conditional on media_use_ffmpeg
-        '../media/media.gyp:media_perftests',
-        '../net/net.gyp:crash_cache',
-        '../net/net.gyp:crl_set_dump',
-        '../net/net.gyp:dns_fuzz_stub',
-        '../net/net.gyp:dump_cache',
-        '../net/net.gyp:gdig',
-        '../net/net.gyp:get_server_time',
-        '../net/net.gyp:net_watcher',  # TODO(GYP): This should be conditional on use_v8_in_net
-        '../net/net.gyp:run_testserver',
-        '../net/net.gyp:stress_cache',
-        '../net/net.gyp:tld_cleanup',
-        '../ppapi/ppapi_internal.gyp:ppapi_tests', # TODO(GYP): Split out the examples and tests
-        '../third_party/codesighs/codesighs.gyp:maptsvdifftool',
-        '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
-        '../ui/compositor/compositor.gyp:compositor_unittests',
-        '../ui/keyboard/keyboard.gyp:keyboard_unittests',
-        '../ui/snapshot/snapshot.gyp:snapshot_unittests',
-      ],
-      'conditions': [
-        ['use_aura==1', {
-          'dependencies': [
-            '../ui/aura/aura.gyp:aura_bench',
-          ],
-        }],
-        ['use_ash==1', {
-          'dependencies': [
-            '../ash/ash.gyp:ash_shell',
-            '../ash/ash.gyp:ash_shell_unittests',
-            '../ash/ash.gyp:ash_unittests',
-          ],
-        }],
-        ['OS=="android"', {
-          'dependencies': [
-            '../breakpad/breakpad.gyp:dump_syms',
-          ],
-        }],
-        ['OS=="linux"', {
-          'dependencies': [
-            '../breakpad/breakpad.gyp:breakpad_unittests',
-            '../breakpad/breakpad.gyp:dump_syms',
-            '../breakpad/breakpad.gyp:generate_test_dump',
-            '../breakpad/breakpad.gyp:minidump-2-core',
-            '../net/net.gyp:disk_cache_memory_test',
-            '../net/net.gyp:flip_in_mem_edsm_server',
-            '../net/net.gyp:flip_in_mem_edsm_server_unittests',
-            '../net/net.gyp:quic_client',
-            '../net/net.gyp:quic_server',
-            '../dbus/dbus.gyp:dbus_unittests',
-          ],
-        }],
-        ['OS!="win"', {
+        }, {
           'dependencies': [
             '../third_party/codesighs/codesighs.gyp:nm2tsv',
           ],
         }],
-        ['OS=="mac"', {
-          'dependencies': [
-            '../breakpad/breakpad.gyp:crash_inspector',
-            '../breakpad/breakpad.gyp:dump_syms',
-            '../breakpad/breakpad.gyp:symupload',
-          ],
-        }],
         ['OS=="android" or OS=="linux"', {
           'dependencies': [
             '../net/net.gyp:disk_cache_memory_test',
@@ -342,30 +390,12 @@
     {
       'target_name': 'gyp_remaining',
       'type': 'none',
-      'dependencies': [
-        ':add_to_gn_all',
-      ],
       'conditions': [
         ['OS=="linux"', {
           'dependencies': [
-            '../base/base.gyp:base_i18n_perftests',
-            '../base/base.gyp:base_perftests',
-            '../base/base.gyp:build_utf8_validator_tables#host',
-            '../base/base.gyp:check_example',
-            '../base/base.gyp:protect_file_posix',
-            '../breakpad/breakpad.gyp:core-2-minidump',
-            '../build/sanitizers/sanitizers.gyp:llvm-symbolizer',
-            '../chrome/chrome.gyp:chrome_app_unittests',
-            '../chrome/chrome.gyp:chromedriver',
-            '../chrome/chrome.gyp:chromedriver_tests',
-            '../chrome/chrome.gyp:chromedriver_unittests',
-            '../chrome/chrome.gyp:load_library_perf_tests',
             '../chrome/chrome.gyp:performance_browser_tests',
-            '../chrome/chrome.gyp:service_discovery_sniffer',
             '../cloud_print/cloud_print.gyp:cloud_print_unittests',
-            '../components/components.gyp:network_hints_browser',
             '../components/components.gyp:policy_templates',
-            '../components/components.gyp:session_manager_component',
             '../components/components_tests.gyp:components_browsertests',
             '../components/components_tests.gyp:components_perftests',
             '../content/content.gyp:content_app_browser',
@@ -380,7 +410,6 @@
             '../gin/gin.gyp:gin_shell',
             '../google_apis/gcm/gcm.gyp:mcs_probe',
             '../gpu/gpu.gyp:gl_tests',
-            '../gpu/tools/tools.gyp:compositor_model_bench',
             '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
             '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',
             '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',
@@ -388,7 +417,6 @@
             '../media/cast/cast.gyp:generate_barcode_video',
             '../media/cast/cast.gyp:generate_timecode_audio',
             '../media/cast/cast.gyp:tap_proxy',
-            '../media/media.gyp:player_x11',
             '../mojo/mojo_base.gyp:mojo_application_chromium',
             '../net/net.gyp:hpack_example_generator',
             '../net/net.gyp:hpack_fuzz_mutator',
@@ -396,15 +424,6 @@
             '../net/net.gyp:net_perftests',
             '../ppapi/ppapi_internal.gyp:ppapi_unittests',
             '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma',
-            '../remoting/app_remoting_webapp.gyp:ar_sample_app',
-            '../remoting/remoting.gyp:remoting_host',
-            '../remoting/remoting.gyp:remoting_it2me_native_messaging_host',
-            '../remoting/remoting.gyp:remoting_me2me_host',
-            '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
-            '../remoting/remoting.gyp:remoting_native_messaging_manifests',
-            '../remoting/remoting.gyp:remoting_perftests',
-            '../remoting/remoting.gyp:remoting_start_host',
-            '../remoting/remoting.gyp:remoting_unittests',
             '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests',
             '../skia/skia.gyp:filter_fuzz_stub',
             '../skia/skia.gyp:image_operations_bench',
@@ -421,7 +440,6 @@
             '../tools/gn/gn.gyp:generate_test_gn_data',
             '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache',
             #'../tools/telemetry/telemetry.gyp:bitmaptools', TODO(GYP) should this be #host ?
-            '../ui/app_list/app_list.gyp:app_list_demo',
             '../ui/compositor/compositor.gyp:compositor_unittests',
             '../ui/message_center/message_center.gyp:message_center_unittests',
             '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
@@ -435,13 +453,42 @@
             ['disable_nacl==0 and disable_nacl_untrusted==0', {
               'dependencies': [
                 '../components/nacl.gyp:nacl_loader_unittests',
-                '../mojo/mojo_nacl.gyp:monacl_shell',
+                '../mojo/mojo_nacl.gyp:monacl_shell',  # TODO(GYP) This will be deleted; don't port
                 '../remoting/remoting.gyp:remoting_key_tester',
               ]
             }],
+            ['chromeos== 1 or use_ash==1', {
+              'dependencies': [
+                '../components/components.gyp:session_manager_component',
+              ],
+            }],
+            ['use_x11==1', {
+              'dependencies': [
+                '../gpu/tools/tools.gyp:compositor_model_bench',
+                '../media/media.gyp:player_x11',
+              ],
+            }],
+            ['remoting==1', {
+              'dependencies': [
+                '../remoting/app_remoting_webapp.gyp:ar_sample_app',
+                '../remoting/remoting.gyp:remoting_host',
+                '../remoting/remoting.gyp:remoting_it2me_native_messaging_host',
+                '../remoting/remoting.gyp:remoting_key_tester',
+                '../remoting/remoting.gyp:remoting_me2me_host',
+                '../remoting/remoting.gyp:remoting_me2me_native_messaging_host',
+                '../remoting/remoting.gyp:remoting_native_messaging_manifests',
+                '../remoting/remoting.gyp:remoting_perftests',
+                '../remoting/remoting.gyp:remoting_start_host',
+                '../remoting/remoting.gyp:remoting_unittests',
+              ],
+            }],
+            ['toolkit_views==1', {
+              'dependencies': [
+                '../ui/app_list/app_list.gyp:app_list_demo',
+              ],
+            }],
             ['test_isolation_mode!="noop"', {
               'dependencies': [
-                '../ash/ash.gyp:ash_unittests_run',
                 '../base/base.gyp:base_unittests_run',
                 '../cc/cc_tests.gyp:cc_unittests_run',
                 '../chrome/chrome.gyp:browser_tests_run',
@@ -468,15 +515,16 @@
                 '../ui/message_center/message_center.gyp:message_center_unittests_run',
                 '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run',
               ],
+              'conditions': [
+                ['use_ash==1', {
+                  'dependencies': [
+                    '../ash/ash.gyp:ash_unittests_run',
+                  ],
+                }],
+              ],
             }],
           ],
         }],
-        ['use_aura==1', {
-          'dependencies': [
-            '../ui/aura/aura.gyp:aura_demo',
-            '../ui/aura/aura.gyp:aura_unittests',
-          ],
-        }],
       ],
     },
     {
@@ -497,6 +545,6 @@
         'chromium_gpu_debug_builder',
       ],
     },
-      ]
+  ]
 }
 
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 484f806..0d19361 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -46,6 +46,7 @@
 IDR_NET_INTERNALS_INDEX_JS
 IDR_OMAHA_HTML
 IDR_OMAHA_JS
+IDR_OMNIBOX_CALCULATOR
 IDR_OMNIBOX_CLEAR_IOS
 IDR_OMNIBOX_CLEAR_OTR_IOS
 IDR_OMNIBOX_CLEAR_OTR_PRESSED_IOS
@@ -323,10 +324,10 @@
 IDS_EDIT_FIND_MAC
 IDS_EMPTY_KEYWORD_VALUE
 IDS_ERRORPAGES_BUTTON_LESS
-IDS_ERRORPAGES_BUTTON_LOAD_STALE
-IDS_ERRORPAGES_BUTTON_LOAD_STALE_HELP
 IDS_ERRORPAGES_BUTTON_MORE
 IDS_ERRORPAGES_BUTTON_RELOAD
+IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY
+IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY_HELP
 IDS_ERRORPAGES_DETAILS_ADDRESS_UNREACHABLE
 IDS_ERRORPAGES_DETAILS_BAD_GATEWAY
 IDS_ERRORPAGES_DETAILS_BAD_SSL_CLIENT_AUTH_CERT
diff --git a/build/isolate.gypi b/build/isolate.gypi
index fbb6d3c..5fa1e67 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -95,6 +95,7 @@
         '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
         '--config-variable', 'use_openssl=<(use_openssl)',
         '--config-variable', 'use_ozone=<(use_ozone)',
+        '--config-variable', 'use_x11=<(use_x11)',
         '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
       ],
       'conditions': [
diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni
index d42babd..05b673b 100644
--- a/build/module_args/v8.gni
+++ b/build/module_args/v8.gni
@@ -6,6 +6,9 @@
   import("//build/config/android/config.gni")
 }
 
+# TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456.
+enable_correct_v8_arch = false
+
 # Many V8 users in mojo do not support external startup data for V8, so
 # we disable it. If enabled, special care should be taken to ensure the
 # appropriate startup data is correctly bundled for apps.
diff --git a/build/sanitizers/BUILD.gn b/build/sanitizers/BUILD.gn
new file mode 100644
index 0000000..4f81f3e
--- /dev/null
+++ b/build/sanitizers/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_linux && !is_chromeos) {
+  # TODO(GYP): Figure out which of these work and are needed on other platforms.
+  copy("copy_llvm_symbolizer") {
+    if (is_win) {
+      sources = [
+        "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer.exe",
+      ]
+      outputs = [
+        "$root_out_dir/llvm-symbolizer.exe",
+      ]
+    } else {
+      sources = [
+        "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer",
+      ]
+      outputs = [
+        "$root_out_dir/llvm-symbolizer",
+      ]
+    }
+  }
+}
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 4659a3f..43db731 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -137,9 +137,6 @@
 // http://crbug.com/272095
 "race:base::g_top_manager\n"
 
-// http://crbug.com/272987
-"race:webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>::set_enabled\n"
-
 // http://crbug.com/273047
 "race:base::*::g_lazy_tls_ptr\n"
 "race:IPC::SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_\n"
diff --git a/build/secondary/third_party/cacheinvalidation/BUILD.gn b/build/secondary/third_party/cacheinvalidation/BUILD.gn
index 2e02633..17e4d1c 100644
--- a/build/secondary/third_party/cacheinvalidation/BUILD.gn
+++ b/build/secondary/third_party/cacheinvalidation/BUILD.gn
@@ -81,8 +81,11 @@
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
   public_configs = [ ":cacheinvalidation_config" ]
 
-  deps = [
+  public_deps = [
     "src/google/cacheinvalidation:cacheinvalidation_proto_cpp",
+  ]
+
+  deps = [
     "//base",
   ]
 }
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index e217b12..4ee07db 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -246,6 +246,8 @@
     "output/delegating_renderer.h",
     "output/direct_renderer.cc",
     "output/direct_renderer.h",
+    "output/dynamic_geometry_binding.cc",
+    "output/dynamic_geometry_binding.h",
     "output/filter_operation.cc",
     "output/filter_operation.h",
     "output/filter_operations.cc",
@@ -286,6 +288,8 @@
     "output/software_output_device.h",
     "output/software_renderer.cc",
     "output/software_renderer.h",
+    "output/static_geometry_binding.cc",
+    "output/static_geometry_binding.h",
     "output/viewport_selection_bound.cc",
     "output/viewport_selection_bound.h",
     "output/vsync_parameter_observer.h",
@@ -386,6 +390,8 @@
     "resources/picture_pile_impl.h",
     "resources/pixel_buffer_tile_task_worker_pool.cc",
     "resources/pixel_buffer_tile_task_worker_pool.h",
+    "resources/pixel_ref_map.cc",
+    "resources/pixel_ref_map.h",
     "resources/platform_color.h",
     "resources/prioritized_resource.cc",
     "resources/prioritized_resource.h",
@@ -493,8 +499,6 @@
     "trees/damage_tracker.h",
     "trees/draw_property_utils.cc",
     "trees/draw_property_utils.h",
-    "trees/layer_sorter.cc",
-    "trees/layer_sorter.h",
     "trees/layer_tree_host.cc",
     "trees/layer_tree_host.h",
     "trees/layer_tree_host_client.h",
@@ -502,6 +506,7 @@
     "trees/layer_tree_host_common.h",
     "trees/layer_tree_host_impl.cc",
     "trees/layer_tree_host_impl.h",
+    "trees/layer_tree_host_single_thread_client.h",
     "trees/layer_tree_impl.cc",
     "trees/layer_tree_impl.h",
     "trees/layer_tree_settings.cc",
@@ -791,6 +796,7 @@
     "resources/picture_pile_impl_unittest.cc",
     "resources/picture_pile_unittest.cc",
     "resources/picture_unittest.cc",
+    "resources/pixel_ref_map_unittest.cc",
     "resources/platform_color_unittest.cc",
     "resources/prioritized_resource_unittest.cc",
     "resources/resource_provider_unittest.cc",
@@ -812,7 +818,6 @@
     "test/test_web_graphics_context_3d_unittest.cc",
     "trees/blocking_task_runner_unittest.cc",
     "trees/damage_tracker_unittest.cc",
-    "trees/layer_sorter_unittest.cc",
     "trees/layer_tree_host_common_unittest.cc",
     "trees/layer_tree_host_impl_unittest.cc",
     "trees/layer_tree_host_pixeltest_blending.cc",
@@ -906,3 +911,5 @@
     "//ui/gl",
   ]
 }
+# When adding support for isolates, please have a look at run-time dependencies
+# in the cc_unittests_run target in cc_tests.gyp.
diff --git a/cc/animation/animation_registrar.cc b/cc/animation/animation_registrar.cc
index 5327926..3fb8055 100644
--- a/cc/animation/animation_registrar.cc
+++ b/cc/animation/animation_registrar.cc
@@ -4,6 +4,7 @@
 
 #include "cc/animation/animation_registrar.h"
 
+#include "base/trace_event/trace_event_argument.h"
 #include "cc/animation/layer_animation_controller.h"
 
 namespace cc {
@@ -55,4 +56,75 @@
   DidDeactivateAnimationController(controller);
 }
 
+bool AnimationRegistrar::ActivateAnimations() {
+  if (!needs_animate_layers())
+    return false;
+
+  TRACE_EVENT0("cc", "AnimationRegistrar::ActivateAnimations");
+  AnimationControllerMap active_controllers_copy =
+      active_animation_controllers_;
+  for (auto& it : active_controllers_copy)
+    it.second->ActivateAnimations();
+
+  return true;
+}
+
+bool AnimationRegistrar::AnimateLayers(base::TimeTicks monotonic_time) {
+  if (!needs_animate_layers())
+    return false;
+
+  TRACE_EVENT0("cc", "AnimationRegistrar::AnimateLayers");
+  AnimationControllerMap controllers_copy = active_animation_controllers_;
+  for (auto& it : controllers_copy)
+    it.second->Animate(monotonic_time);
+
+  return true;
+}
+
+bool AnimationRegistrar::UpdateAnimationState(bool start_ready_animations,
+                                              AnimationEventsVector* events) {
+  if (!needs_animate_layers())
+    return false;
+
+  TRACE_EVENT0("cc", "AnimationRegistrar::UpdateAnimationState");
+  AnimationControllerMap active_controllers_copy =
+      active_animation_controllers_;
+  for (auto& it : active_controllers_copy)
+    it.second->UpdateState(start_ready_animations, events);
+
+  return true;
+}
+
+void AnimationRegistrar::SetAnimationEvents(
+    scoped_ptr<AnimationEventsVector> events) {
+  for (size_t event_index = 0; event_index < events->size(); ++event_index) {
+    int event_layer_id = (*events)[event_index].layer_id;
+
+    // Use the map of all controllers, not just active ones, since non-active
+    // controllers may still receive events for impl-only animations.
+    const AnimationRegistrar::AnimationControllerMap& animation_controllers =
+        all_animation_controllers_;
+    auto iter = animation_controllers.find(event_layer_id);
+    if (iter != animation_controllers.end()) {
+      switch ((*events)[event_index].type) {
+        case AnimationEvent::STARTED:
+          (*iter).second->NotifyAnimationStarted((*events)[event_index]);
+          break;
+
+        case AnimationEvent::FINISHED:
+          (*iter).second->NotifyAnimationFinished((*events)[event_index]);
+          break;
+
+        case AnimationEvent::ABORTED:
+          (*iter).second->NotifyAnimationAborted((*events)[event_index]);
+          break;
+
+        case AnimationEvent::PROPERTY_UPDATE:
+          (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]);
+          break;
+      }
+    }
+  }
+}
+
 }  // namespace cc
diff --git a/cc/animation/animation_registrar.h b/cc/animation/animation_registrar.h
index 36c45c7..5302390 100644
--- a/cc/animation/animation_registrar.h
+++ b/cc/animation/animation_registrar.h
@@ -8,6 +8,7 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "cc/animation/animation_events.h"
 #include "cc/base/cc_export.h"
 
 namespace cc {
@@ -43,11 +44,12 @@
   // Unregisters the given controller as alive.
   void UnregisterAnimationController(LayerAnimationController* controller);
 
-  const AnimationControllerMap& active_animation_controllers() const {
+  const AnimationControllerMap& active_animation_controllers_for_testing()
+      const {
     return active_animation_controllers_;
   }
 
-  const AnimationControllerMap& all_animation_controllers() const {
+  const AnimationControllerMap& all_animation_controllers_for_testing() const {
     return all_animation_controllers_;
   }
 
@@ -57,6 +59,21 @@
 
   bool supports_scroll_animations() { return supports_scroll_animations_; }
 
+  bool needs_animate_layers() const {
+    return !active_animation_controllers_.empty();
+  }
+
+  bool ActivateAnimations();
+  bool AnimateLayers(base::TimeTicks monotonic_time);
+  bool UpdateAnimationState(bool start_ready_animations,
+                            AnimationEventsVector* events);
+
+  scoped_ptr<AnimationEventsVector> CreateEvents() {
+    return make_scoped_ptr(new AnimationEventsVector());
+  }
+
+  void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events);
+
  private:
   AnimationRegistrar();
 
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
index c253dae..25e38cc 100644
--- a/cc/animation/layer_animation_controller.cc
+++ b/cc/animation/layer_animation_controller.cc
@@ -955,7 +955,7 @@
     bool notify_pending_observers) {
   if (value_observers_.might_have_observers()) {
     ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        value_observers_);
+        &value_observers_);
     LayerAnimationValueObserver* obs;
     while ((obs = it.GetNext()) != nullptr) {
       if ((notify_active_observers && notify_pending_observers) ||
@@ -972,7 +972,7 @@
     bool notify_pending_observers) {
   if (value_observers_.might_have_observers()) {
     ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        value_observers_);
+        &value_observers_);
     LayerAnimationValueObserver* obs;
     while ((obs = it.GetNext()) != nullptr) {
       if ((notify_active_observers && notify_pending_observers) ||
@@ -989,7 +989,7 @@
     bool notify_pending_observers) {
   if (value_observers_.might_have_observers()) {
     ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        value_observers_);
+        &value_observers_);
     LayerAnimationValueObserver* obs;
     while ((obs = it.GetNext()) != nullptr) {
       if ((notify_active_observers && notify_pending_observers) ||
@@ -1006,7 +1006,7 @@
     bool notify_pending_observers) {
   if (value_observers_.might_have_observers()) {
     ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        value_observers_);
+        &value_observers_);
     LayerAnimationValueObserver* obs;
     while ((obs = it.GetNext()) != nullptr) {
       if ((notify_active_observers && notify_pending_observers) ||
@@ -1026,7 +1026,7 @@
 bool LayerAnimationController::HasValueObserver() {
   if (value_observers_.might_have_observers()) {
     ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        value_observers_);
+        &value_observers_);
     return it.GetNext() != nullptr;
   }
   return false;
@@ -1035,7 +1035,7 @@
 bool LayerAnimationController::HasActiveValueObserver() {
   if (value_observers_.might_have_observers()) {
     ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        value_observers_);
+        &value_observers_);
     LayerAnimationValueObserver* obs;
     while ((obs = it.GetNext()) != nullptr)
       if (obs->IsActive())
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc
index d8d0b05..48e9e92 100644
--- a/cc/animation/layer_animation_controller_unittest.cc
+++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -171,40 +171,43 @@
 
   controller->SetAnimationRegistrar(registrar.get());
   controller_impl->SetAnimationRegistrar(registrar_impl.get());
-  EXPECT_EQ(1u, registrar->all_animation_controllers().size());
-  EXPECT_EQ(1u, registrar_impl->all_animation_controllers().size());
+  EXPECT_EQ(1u, registrar->all_animation_controllers_for_testing().size());
+  EXPECT_EQ(1u, registrar_impl->all_animation_controllers_for_testing().size());
 
   // Initially, both controllers should be inactive.
-  EXPECT_EQ(0u, registrar->active_animation_controllers().size());
-  EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
+  EXPECT_EQ(0u, registrar->active_animation_controllers_for_testing().size());
+  EXPECT_EQ(0u,
+            registrar_impl->active_animation_controllers_for_testing().size());
 
   AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
   // The main thread controller should now be active.
-  EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+  EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
   controller_impl->ActivateAnimations();
   // Both controllers should now be active.
-  EXPECT_EQ(1u, registrar->active_animation_controllers().size());
-  EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size());
+  EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size());
+  EXPECT_EQ(1u,
+            registrar_impl->active_animation_controllers_for_testing().size());
 
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_EQ(1u, events->size());
   controller->NotifyAnimationStarted((*events)[0]);
 
-  EXPECT_EQ(1u, registrar->active_animation_controllers().size());
-  EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size());
+  EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size());
+  EXPECT_EQ(1u,
+            registrar_impl->active_animation_controllers_for_testing().size());
 
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller->UpdateState(true, nullptr);
-  EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+  EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size());
 
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, nullptr);
   EXPECT_EQ(Animation::FINISHED,
             controller->GetAnimation(Animation::OPACITY)->run_state());
-  EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+  EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size());
 
   events.reset(new AnimationEventsVector);
   controller_impl->Animate(kInitialTickTime +
@@ -214,7 +217,8 @@
   EXPECT_EQ(Animation::WAITING_FOR_DELETION,
             controller_impl->GetAnimation(Animation::OPACITY)->run_state());
   // The impl thread controller should have de-activated.
-  EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
+  EXPECT_EQ(0u,
+            registrar_impl->active_animation_controllers_for_testing().size());
 
   EXPECT_EQ(1u, events->size());
   controller->NotifyAnimationFinished((*events)[0]);
@@ -224,14 +228,15 @@
   EXPECT_EQ(Animation::WAITING_FOR_DELETION,
             controller->GetAnimation(Animation::OPACITY)->run_state());
   // The main thread controller should have de-activated.
-  EXPECT_EQ(0u, registrar->active_animation_controllers().size());
+  EXPECT_EQ(0u, registrar->active_animation_controllers_for_testing().size());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
   controller_impl->ActivateAnimations();
   EXPECT_FALSE(controller->has_any_animation());
   EXPECT_FALSE(controller_impl->has_any_animation());
-  EXPECT_EQ(0u, registrar->active_animation_controllers().size());
-  EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
+  EXPECT_EQ(0u, registrar->active_animation_controllers_for_testing().size());
+  EXPECT_EQ(0u,
+            registrar_impl->active_animation_controllers_for_testing().size());
 
   controller->SetAnimationRegistrar(nullptr);
   controller_impl->SetAnimationRegistrar(nullptr);
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 0c4ee74..bc83b1f 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -279,6 +279,8 @@
         'output/delegating_renderer.h',
         'output/direct_renderer.cc',
         'output/direct_renderer.h',
+        'output/dynamic_geometry_binding.cc',
+        'output/dynamic_geometry_binding.h',
         'output/filter_operation.cc',
         'output/filter_operation.h',
         'output/filter_operations.cc',
@@ -319,6 +321,8 @@
         'output/software_output_device.h',
         'output/software_renderer.cc',
         'output/software_renderer.h',
+        'output/static_geometry_binding.cc',
+        'output/static_geometry_binding.h',
         'output/viewport_selection_bound.cc',
         'output/viewport_selection_bound.h',
         'output/vsync_parameter_observer.h',
@@ -419,6 +423,8 @@
         'resources/picture_pile_impl.h',
         'resources/pixel_buffer_tile_task_worker_pool.cc',
         'resources/pixel_buffer_tile_task_worker_pool.h',
+        'resources/pixel_ref_map.cc',
+        'resources/pixel_ref_map.h',
         'resources/platform_color.h',
         'resources/prioritized_resource.cc',
         'resources/prioritized_resource.h',
@@ -529,8 +535,6 @@
         'trees/damage_tracker.h',
         'trees/draw_property_utils.cc',
         'trees/draw_property_utils.h',
-        'trees/layer_sorter.cc',
-        'trees/layer_sorter.h',
         'trees/layer_tree_host.cc',
         'trees/layer_tree_host.h',
         'trees/layer_tree_host_client.h',
@@ -538,6 +542,7 @@
         'trees/layer_tree_host_common.h',
         'trees/layer_tree_host_impl.cc',
         'trees/layer_tree_host_impl.h',
+        'trees/layer_tree_host_single_thread_client.h',
         'trees/layer_tree_impl.cc',
         'trees/layer_tree_impl.h',
         'trees/layer_tree_settings.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 4d29a60..bafd747 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -83,6 +83,7 @@
       'resources/picture_pile_impl_unittest.cc',
       'resources/picture_pile_unittest.cc',
       'resources/picture_unittest.cc',
+      'resources/pixel_ref_map_unittest.cc',
       'resources/platform_color_unittest.cc',
       'resources/prioritized_resource_unittest.cc',
       'resources/resource_provider_unittest.cc',
@@ -105,7 +106,6 @@
       'test/test_web_graphics_context_3d_unittest.cc',
       'trees/blocking_task_runner_unittest.cc',
       'trees/damage_tracker_unittest.cc',
-      'trees/layer_sorter_unittest.cc',
       'trees/layer_tree_host_common_unittest.cc',
       'trees/layer_tree_host_impl_unittest.cc',
       'trees/layer_tree_host_pixeltest_blending.cc',
@@ -460,6 +460,17 @@
           'sources': [
             'cc_unittests.isolate',
           ],
+          'conditions': [
+            # crbug.com/464062 xdisplaycheck is used to run cc_unittests_run on
+            # the linux try bots when using X11.
+            ['OS=="linux" and use_ozone==0',
+              {
+                'dependencies': [
+                  '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+                ],
+              }
+            ],
+          ],
         },
       ],
     }],
diff --git a/cc/cc_unittests.isolate b/cc/cc_unittests.isolate
index eab3396..7c359d0 100644
--- a/cc/cc_unittests.isolate
+++ b/cc/cc_unittests.isolate
@@ -3,16 +3,20 @@
 # found in the LICENSE file.
 {
   'conditions': [
-    ['OS=="linux" or OS=="mac" or OS=="win"', {
+    ['use_x11==0', {
       'variables': {
-        'files': [
-          'test/data/',
+        'command': [
           '../testing/test_env.py',
           '<(PRODUCT_DIR)/cc_unittests<(EXECUTABLE_SUFFIX)',
+          '--brave-new-test-launcher',
+          '--test-launcher-bot-mode',
+          '--asan=<(asan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
       },
     }],
-    ['OS=="linux"', {
+    ['use_x11==1', {
       'variables': {
         'command': [
           '../testing/xvfb.py',
@@ -26,29 +30,29 @@
         ],
         'files': [
           '../testing/xvfb.py',
+          '<(PRODUCT_DIR)/xdisplaycheck',
+        ],
+      },
+    }],
+    ['OS=="linux" or OS=="mac" or OS=="win"', {
+      'variables': {
+        'files': [
+          'test/data/',
+          '../testing/test_env.py',
+          '<(PRODUCT_DIR)/cc_unittests<(EXECUTABLE_SUFFIX)',
+        ],
+      },
+    }],
+    ['OS=="linux"', {
+      'variables': {
+        'files': [
           '<(PRODUCT_DIR)/libffmpegsumo.so',
           '<(PRODUCT_DIR)/libosmesa.so',
         ],
       },
     }],
-    ['OS=="linux" and use_ozone==0', {
-      'variables': {
-        'files': [
-          '<(PRODUCT_DIR)/xdisplaycheck',
-        ],
-      },
-    }],
     ['OS=="mac"', {
       'variables': {
-        'command': [
-          '../testing/test_env.py',
-          '<(PRODUCT_DIR)/cc_unittests',
-          '--brave-new-test-launcher',
-          '--test-launcher-bot-mode',
-          '--asan=<(asan)',
-          '--msan=<(msan)',
-          '--tsan=<(tsan)',
-        ],
         'files': [
           '<(PRODUCT_DIR)/ffmpegsumo.so',
           '<(PRODUCT_DIR)/osmesa.so',
@@ -57,15 +61,6 @@
     }],
     ['OS=="win"', {
       'variables': {
-        'command': [
-          '../testing/test_env.py',
-          '<(PRODUCT_DIR)/cc_unittests.exe',
-          '--brave-new-test-launcher',
-          '--test-launcher-bot-mode',
-          '--asan=<(asan)',
-          '--msan=<(msan)',
-          '--tsan=<(tsan)',
-        ],
         'files': [
           '<(PRODUCT_DIR)/ffmpegsumo.dll',
           '<(PRODUCT_DIR)/osmesa.dll',
@@ -89,5 +84,6 @@
   ],
   'includes': [
     '../base/base.isolate',
+    '../third_party/angle/angle.isolate',
   ],
 }
diff --git a/cc/input/top_controls_manager.cc b/cc/input/top_controls_manager.cc
index c8bd534..56c9d8f 100644
--- a/cc/input/top_controls_manager.cc
+++ b/cc/input/top_controls_manager.cc
@@ -107,6 +107,9 @@
   if (pinch_gesture_active_)
     return pending_delta;
 
+  if (!TopControlsHeight())
+    return pending_delta;
+
   if (permitted_state_ == SHOWN && pending_delta.y() > 0)
     return pending_delta;
   else if (permitted_state_ == HIDDEN && pending_delta.y() < 0)
diff --git a/cc/input/top_controls_manager_unittest.cc b/cc/input/top_controls_manager_unittest.cc
index 4befa15..4145cac 100644
--- a/cc/input/top_controls_manager_unittest.cc
+++ b/cc/input/top_controls_manager_unittest.cc
@@ -5,7 +5,9 @@
 #include "cc/input/top_controls_manager.h"
 
 #include <algorithm>
+#include <cmath>
 
+#include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
 #include "cc/input/top_controls_manager_client.h"
@@ -51,6 +53,9 @@
   float TopControlsHeight() const override { return top_controls_height_; }
 
   void SetCurrentTopControlsShownRatio(float ratio) override {
+    ASSERT_FALSE(std::isnan(ratio));
+    ASSERT_FALSE(ratio == std::numeric_limits<float>::infinity());
+    ASSERT_FALSE(ratio == -std::numeric_limits<float>::infinity());
     ratio = std::max(ratio, 0.f);
     ratio = std::min(ratio, 1.f);
     top_controls_shown_ratio_ = ratio;
@@ -446,50 +451,20 @@
   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
 }
 
-TEST(TopControlsManagerTest, ZeroTopControlsHeightScrolling) {
+TEST(TopControlsManagerTest, ScrollByWithZeroHeightControlsIsNoop) {
   MockTopControlsManagerClient client(0.f, 0.5f, 0.5f);
-  client.SetCurrentTopControlsShownRatio(0.f);
   TopControlsManager* manager = client.manager();
   manager->UpdateTopControlsState(BOTH, BOTH, false);
 
   manager->ScrollBegin();
-  EXPECT_FLOAT_EQ(-10.f, manager->ScrollBy(gfx::Vector2dF(0.f, -10.f)).y());
-  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
-
-  client.SetTopControlsHeight(20.f);
-  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
-
-  EXPECT_FLOAT_EQ(0.f, manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)).y());
-  EXPECT_FLOAT_EQ(0.75f, manager->TopControlsShownRatio());
-  client.SetTopControlsHeight(0.f);
+  gfx::Vector2dF pending = manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
+  EXPECT_FLOAT_EQ(20.f, pending.y());
+  EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
+  EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
   manager->ScrollEnd();
-
-  EXPECT_FALSE(manager->animation());
-  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
 }
 
-TEST(TopControlsManagerTest, ZeroTopControlsHeightAnimating) {
-  MockTopControlsManagerClient client(0.f, 0.5f, 0.5f);
-  client.SetCurrentTopControlsShownRatio(0.f);
-  TopControlsManager* manager = client.manager();
-
-  manager->UpdateTopControlsState(BOTH, HIDDEN, false);
-  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
-  manager->UpdateTopControlsState(BOTH, SHOWN, false);
-  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
-
-  manager->UpdateTopControlsState(BOTH, HIDDEN, true);
-  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
-  EXPECT_FALSE(manager->animation());
-  manager->UpdateTopControlsState(BOTH, SHOWN, true);
-  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
-  EXPECT_FALSE(manager->animation());
-
-  client.SetCurrentTopControlsShownRatio(0.3f);
-  manager->MainThreadHasStoppedFlinging();
-  EXPECT_FALSE(manager->animation());
-  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
-}
 
 }  // namespace
 }  // namespace cc
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc
index 04e1b85..87e559a 100644
--- a/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -9,10 +9,10 @@
 #include "cc/quads/render_pass_draw_quad.h"
 #include "cc/quads/solid_color_draw_quad.h"
 #include "cc/test/fake_delegated_renderer_layer_impl.h"
+#include "cc/test/fake_impl_proxy.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
 #include "cc/test/fake_layer_tree_host_impl_client.h"
 #include "cc/test/fake_output_surface.h"
-#include "cc/test/fake_proxy.h"
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/layer_test_common.h"
 #include "cc/test/render_pass_test_common.h"
@@ -44,7 +44,7 @@
   }
 
  protected:
-  FakeProxy proxy_;
+  FakeImplProxy proxy_;
   DebugScopedSetImplThreadAndMainThreadBlocked
       always_impl_thread_and_main_thread_blocked_;
   TestSharedBitmapManager shared_bitmap_manager_;
diff --git a/cc/layers/draw_properties.h b/cc/layers/draw_properties.h
index ff5abd9..930f7bf 100644
--- a/cc/layers/draw_properties.h
+++ b/cc/layers/draw_properties.h
@@ -32,6 +32,7 @@
         num_unclipped_descendants(0),
         layer_or_descendant_has_copy_request(false),
         layer_or_descendant_has_input_handler(false),
+        layer_or_descendant_is_drawn(false),
         has_child_with_a_scroll_parent(false),
         sorted_for_recursion(false),
         visited(false),
@@ -114,6 +115,9 @@
   // If true, the layer or one of its descendants has a wheel or touch handler.
   bool layer_or_descendant_has_input_handler;
 
+  // If true, the layer or one of its descendants is drawn
+  bool layer_or_descendant_is_drawn;
+
   // This is true if the layer has any direct child that has a scroll parent.
   // This layer will not be the scroll parent in this case. This information
   // lets us avoid work in CalculateDrawPropertiesInternal -- if none of our
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index 2ed00a6..e1a9daf 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -20,15 +20,13 @@
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "skia/ext/platform_canvas.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
-#include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/hud_font.h"
 
 namespace cc {
 
@@ -70,12 +68,15 @@
 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
                                                  int id)
     : LayerImpl(tree_impl, id),
-      typeface_(skia::AdoptRef(
-          SkTypeface::CreateFromName("monospace", SkTypeface::kBold))),
+      typeface_(gfx::GetHudTypeface()),
       internal_contents_scale_(1.f),
       fps_graph_(60.0, 80.0),
       paint_time_graph_(16.0, 48.0),
       fade_step_(0) {
+  if (!typeface_) {
+    typeface_ = skia::AdoptRef(
+        SkTypeface::CreateFromName("monospace", SkTypeface::kBold));
+  }
 }
 
 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {}
diff --git a/cc/layers/io_surface_layer_impl.cc b/cc/layers/io_surface_layer_impl.cc
index 6bd03fd..4f52674 100644
--- a/cc/layers/io_surface_layer_impl.cc
+++ b/cc/layers/io_surface_layer_impl.cc
@@ -5,15 +5,10 @@
 #include "cc/layers/io_surface_layer_impl.h"
 
 #include "base/strings/stringprintf.h"
-#include "cc/output/gl_renderer.h"  // For the GLC() macro.
 #include "cc/output/output_surface.h"
 #include "cc/quads/io_surface_draw_quad.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/occlusion.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
 
 namespace cc {
 
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 1cfe1f1..80d36d8 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -79,20 +79,23 @@
 
 void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) {
   Layer::SetLayerTreeHost(host);
-  if (host) {
-    if (!recording_source_) {
-      if (host->settings().use_display_lists) {
-        recording_source_.reset(new DisplayListRecordingSource);
-      } else {
-        recording_source_.reset(
-            new PicturePile(host->settings().minimum_contents_scale,
-                            host->settings().default_tile_grid_size));
-      }
+  if (!host)
+    return;
+
+  if (!recording_source_) {
+    if (host->settings().use_display_lists) {
+      recording_source_.reset(new DisplayListRecordingSource);
+    } else {
+      recording_source_.reset(
+          new PicturePile(host->settings().minimum_contents_scale,
+                          host->settings().default_tile_grid_size));
     }
-    recording_source_->DidMoveToNewCompositor();
-    recording_source_->SetSlowdownRasterScaleFactor(
-        host->debug_state().slow_down_raster_scale_factor);
   }
+  recording_source_->DidMoveToNewCompositor();
+  recording_source_->SetSlowdownRasterScaleFactor(
+      host->debug_state().slow_down_raster_scale_factor);
+
+  DCHECK(host->settings().raster_enabled);
 }
 
 void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
diff --git a/cc/layers/tiled_layer.cc b/cc/layers/tiled_layer.cc
index 2a32741..55143be 100644
--- a/cc/layers/tiled_layer.cc
+++ b/cc/layers/tiled_layer.cc
@@ -18,7 +18,6 @@
 #include "cc/resources/priority_calculator.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/occlusion_tracker.h"
-#include "third_party/khronos/GLES2/gl2.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
 namespace cc {
diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc
index b78a1d8..04aad2d 100644
--- a/cc/layers/tiled_layer_impl.cc
+++ b/cc/layers/tiled_layer_impl.cc
@@ -17,7 +17,6 @@
 #include "cc/quads/tile_draw_quad.h"
 #include "cc/resources/layer_tiling_data.h"
 #include "cc/trees/occlusion.h"
-#include "third_party/khronos/GLES2/gl2.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/quad_f.h"
 
diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc
index 03d9b19..99cc0ca 100644
--- a/cc/layers/tiled_layer_unittest.cc
+++ b/cc/layers/tiled_layer_unittest.cc
@@ -87,6 +87,7 @@
     settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max();
     settings_.layer_transforms_should_scale_layer_contents = true;
     settings_.verify_property_trees = true;
+    settings_.impl_side_painting = false;
   }
 
   void SetUp() override {
diff --git a/cc/output/bsp_tree.cc b/cc/output/bsp_tree.cc
index f2318ce..4eb87cb 100644
--- a/cc/output/bsp_tree.cc
+++ b/cc/output/bsp_tree.cc
@@ -62,10 +62,9 @@
         scoped_ptr<DrawPolygon> polygon;
         scoped_ptr<DrawPolygon> new_front;
         scoped_ptr<DrawPolygon> new_back;
-        bool split_result = false;
         // Time to split this geometry, *it needs to be split by node_data.
         polygon = polygon_list->take_front();
-        split_result =
+        bool split_result =
             polygon->Split(*(node->node_data), &new_front, &new_back);
         DCHECK(split_result);
         if (!split_result) {
diff --git a/cc/output/bsp_walk_action.cc b/cc/output/bsp_walk_action.cc
index da5ada5..9ffc299 100644
--- a/cc/output/bsp_walk_action.cc
+++ b/cc/output/bsp_walk_action.cc
@@ -9,15 +9,37 @@
 #include "base/memory/scoped_ptr.h"
 #include "cc/output/direct_renderer.h"
 #include "cc/quads/draw_polygon.h"
+#include "cc/quads/draw_quad.h"
 
 namespace cc {
 
-void BspWalkActionToVector::operator()(DrawPolygon* item) {
-  list_->push_back(item);
+BspWalkActionDrawPolygon::BspWalkActionDrawPolygon(
+    DirectRenderer* renderer,
+    DirectRenderer::DrawingFrame* frame,
+    const gfx::Rect& render_pass_scissor,
+    bool using_scissor_as_optimization)
+    : renderer_(renderer),
+      frame_(frame),
+      render_pass_scissor_(render_pass_scissor),
+      using_scissor_as_optimization_(using_scissor_as_optimization) {
+}
+
+void BspWalkActionDrawPolygon::operator()(DrawPolygon* item) {
+  gfx::Transform inverse_transform;
+  bool invertible =
+      item->original_ref()->quadTransform().GetInverse(&inverse_transform);
+  DCHECK(invertible);
+  item->TransformToLayerSpace(inverse_transform);
+  renderer_->DoDrawPolygon(*item, frame_, render_pass_scissor_,
+                           using_scissor_as_optimization_);
 }
 
 BspWalkActionToVector::BspWalkActionToVector(std::vector<DrawPolygon*>* in_list)
     : list_(in_list) {
 }
 
+void BspWalkActionToVector::operator()(DrawPolygon* item) {
+  list_->push_back(item);
+}
+
 }  // namespace cc
diff --git a/cc/output/bsp_walk_action.h b/cc/output/bsp_walk_action.h
index ac8fa41..a89d8ea 100644
--- a/cc/output/bsp_walk_action.h
+++ b/cc/output/bsp_walk_action.h
@@ -20,6 +20,22 @@
 
 // The BspTree class takes ownership of all the DrawPolygons returned in list_
 // so the BspTree must be preserved while elements in that vector are in use.
+class CC_EXPORT BspWalkActionDrawPolygon : public BspWalkAction {
+ public:
+  void operator()(DrawPolygon* item) override;
+
+  BspWalkActionDrawPolygon(DirectRenderer* renderer,
+                           DirectRenderer::DrawingFrame* frame,
+                           const gfx::Rect& render_pass_scissor,
+                           bool using_scissor_as_optimization);
+
+ private:
+  DirectRenderer* renderer_;
+  DirectRenderer::DrawingFrame* frame_;
+  const gfx::Rect& render_pass_scissor_;
+  bool using_scissor_as_optimization_;
+};
+
 class CC_EXPORT BspWalkActionToVector : public BspWalkAction {
  public:
   explicit BspWalkActionToVector(std::vector<DrawPolygon*>* in_list);
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 5867fce..0ae4179 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -12,6 +12,8 @@
 #include "base/metrics/histogram.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/math_util.h"
+#include "cc/output/bsp_tree.h"
+#include "cc/output/bsp_walk_action.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/quads/draw_quad.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -299,22 +301,27 @@
   EnsureScissorTestDisabled();
 }
 
+bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad,
+                                    const gfx::Rect& render_pass_scissor) {
+  if (render_pass_scissor.IsEmpty())
+    return true;
+
+  if (quad.isClipped()) {
+    gfx::Rect r = quad.clipRect();
+    r.Intersect(render_pass_scissor);
+    return r.IsEmpty();
+  }
+
+  return false;
+}
+
 void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor(
     const DrawingFrame* frame,
     const DrawQuad& quad,
-    const gfx::Rect& render_pass_scissor,
-    bool* should_skip_quad) {
+    const gfx::Rect& render_pass_scissor) {
   gfx::Rect quad_scissor_rect = render_pass_scissor;
-
   if (quad.isClipped())
     quad_scissor_rect.Intersect(quad.clipRect());
-
-  if (quad_scissor_rect.IsEmpty()) {
-    *should_skip_quad = true;
-    return;
-  }
-
-  *should_skip_quad = false;
   SetScissorTestRectInDrawSpace(frame, quad_scissor_rect);
 }
 
@@ -330,6 +337,46 @@
 
 void DirectRenderer::FinishDrawingQuadList() {}
 
+void DirectRenderer::DoDrawPolygon(const DrawPolygon& poly,
+                                   DrawingFrame* frame,
+                                   const gfx::Rect& render_pass_scissor,
+                                   bool using_scissor_as_optimization) {
+  if (using_scissor_as_optimization) {
+    SetScissorStateForQuadWithRenderPassScissor(frame, *poly.original_ref(),
+                                                render_pass_scissor);
+  } else {
+    SetScissorStateForQuad(frame, *poly.original_ref());
+  }
+
+  // If the poly has not been split, then it is just a normal DrawQuad,
+  // and we should save any extra processing that would have to be done.
+  if (!poly.is_split()) {
+    DoDrawQuad(frame, poly.original_ref(), NULL);
+    return;
+  }
+
+  std::vector<gfx::QuadF> quads;
+  poly.ToQuads2D(&quads);
+  for (size_t i = 0; i < quads.size(); ++i) {
+    DoDrawQuad(frame, poly.original_ref(), &quads[i]);
+  }
+}
+
+void DirectRenderer::FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list,
+                                   DrawingFrame* frame,
+                                   const gfx::Rect& render_pass_scissor,
+                                   bool using_scissor_as_optimization) {
+  if (poly_list->empty()) {
+    return;
+  }
+
+  BspTree bsp_tree(poly_list);
+  BspWalkActionDrawPolygon action_handler(this, frame, render_pass_scissor,
+                                          using_scissor_as_optimization);
+  bsp_tree.TraverseWithActionHandler(&action_handler);
+  DCHECK(poly_list->empty());
+}
+
 void DirectRenderer::DrawRenderPass(DrawingFrame* frame,
                                     const RenderPass* render_pass) {
   TRACE_EVENT0("cc", "DirectRenderer::DrawRenderPass");
@@ -369,21 +416,49 @@
   }
 
   const QuadList& quad_list = render_pass->quad_list;
+  ScopedPtrDeque<DrawPolygon> poly_list;
+
+  int next_polygon_id = 0;
+  int last_sorting_context_id = 0;
   for (auto it = quad_list.BackToFrontBegin(); it != quad_list.BackToFrontEnd();
        ++it) {
     const DrawQuad& quad = **it;
-    bool should_skip_quad = false;
+    gfx::QuadF send_quad(quad.visible_rect);
 
+    if (using_scissor_as_optimization &&
+        ShouldSkipQuad(quad, render_pass_scissor)) {
+      continue;
+    }
+
+    if (last_sorting_context_id != quad.shared_quad_state->sorting_context_id) {
+      last_sorting_context_id = quad.shared_quad_state->sorting_context_id;
+      FlushPolygons(&poly_list, frame, render_pass_scissor,
+                    using_scissor_as_optimization);
+    }
+
+    // This layer is in a 3D sorting context so we add it to the list of
+    // polygons to go into the BSP tree.
+    if (quad.shared_quad_state->sorting_context_id != 0) {
+      scoped_ptr<DrawPolygon> new_polygon(new DrawPolygon(
+          *it, quad.visible_rect, quad.quadTransform(), next_polygon_id++));
+      if (new_polygon->points().size() > 2u) {
+        poly_list.push_back(new_polygon.Pass());
+      }
+      continue;
+    }
+
+    // We are not in a 3d sorting context, so we should draw the quad normally.
     if (using_scissor_as_optimization) {
-      SetScissorStateForQuadWithRenderPassScissor(
-          frame, quad, render_pass_scissor, &should_skip_quad);
+      SetScissorStateForQuadWithRenderPassScissor(frame, quad,
+                                                  render_pass_scissor);
     } else {
       SetScissorStateForQuad(frame, quad);
     }
 
-    if (!should_skip_quad)
-      DoDrawQuad(frame, &quad);
+    DoDrawQuad(frame, &quad, nullptr);
   }
+  FlushPolygons(&poly_list, frame, render_pass_scissor,
+                using_scissor_as_optimization);
   FinishDrawingQuadList();
 }
 
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h
index e07cb93..3399491 100644
--- a/cc/output/direct_renderer.h
+++ b/cc/output/direct_renderer.h
@@ -9,13 +9,17 @@
 #include "base/callback.h"
 #include "base/containers/scoped_ptr_hash_map.h"
 #include "cc/base/cc_export.h"
+#include "cc/base/scoped_ptr_deque.h"
 #include "cc/output/overlay_processor.h"
 #include "cc/output/renderer.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/scoped_resource.h"
+#include "cc/resources/task_graph_runner.h"
+#include "ui/gfx/geometry/quad_f.h"
 
 namespace cc {
 
+class DrawPolygon;
 class ResourceProvider;
 
 // This is the base class for code shared between the GL and software
@@ -56,6 +60,10 @@
   };
 
   void SetEnlargePassTextureAmountForTesting(const gfx::Vector2d& amount);
+  void DoDrawPolygon(const DrawPolygon& poly,
+                     DrawingFrame* frame,
+                     const gfx::Rect& render_pass_scissor,
+                     bool using_scissor_as_optimization);
 
  protected:
   DirectRenderer(RendererClient* client,
@@ -78,16 +86,21 @@
   gfx::Rect DeviceClipRectInWindowSpace(const DrawingFrame* frame) const;
   static gfx::Rect ComputeScissorRectForRenderPass(const DrawingFrame* frame);
   void SetScissorStateForQuad(const DrawingFrame* frame, const DrawQuad& quad);
+  bool ShouldSkipQuad(const DrawQuad& quad,
+                      const gfx::Rect& render_pass_scissor);
   void SetScissorStateForQuadWithRenderPassScissor(
       const DrawingFrame* frame,
       const DrawQuad& quad,
-      const gfx::Rect& render_pass_scissor,
-      bool* should_skip_quad);
+      const gfx::Rect& render_pass_scissor);
   void SetScissorTestRectInDrawSpace(const DrawingFrame* frame,
                                      const gfx::Rect& draw_space_rect);
 
   static gfx::Size RenderPassTextureSize(const RenderPass* render_pass);
 
+  void FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list,
+                     DrawingFrame* frame,
+                     const gfx::Rect& render_pass_scissor,
+                     bool using_scissor_as_optimization);
   void DrawRenderPass(DrawingFrame* frame, const RenderPass* render_pass);
   bool UseRenderPass(DrawingFrame* frame, const RenderPass* render_pass);
 
@@ -101,7 +114,12 @@
                              bool draw_rect_covers_full_surface) = 0;
   virtual void ClearFramebuffer(DrawingFrame* frame,
                                 bool has_external_stencil_test) = 0;
-  virtual void DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) = 0;
+  // clip_region is a (possibly null) pointer to a quad in the same
+  // space as the quad. When non-null only the area of the quad that overlaps
+  // with clip_region will be drawn.
+  virtual void DoDrawQuad(DrawingFrame* frame,
+                          const DrawQuad* quad,
+                          const gfx::QuadF* clip_region) = 0;
   virtual void BeginDrawingFrame(DrawingFrame* frame) = 0;
   virtual void FinishDrawingFrame(DrawingFrame* frame) = 0;
   virtual void FinishDrawingQuadList();
diff --git a/cc/output/dynamic_geometry_binding.cc b/cc/output/dynamic_geometry_binding.cc
new file mode 100644
index 0000000..9e25892
--- /dev/null
+++ b/cc/output/dynamic_geometry_binding.cc
@@ -0,0 +1,67 @@
+// 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 "cc/output/dynamic_geometry_binding.h"
+
+#include "cc/output/gl_renderer.h"  // For the GLC() macro.
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace cc {
+
+DynamicGeometryBinding::DynamicGeometryBinding(gpu::gles2::GLES2Interface* gl)
+    : gl_(gl), quad_vertices_vbo_(0), quad_elements_vbo_(0) {
+  GeometryBindingQuad quads[1];
+  GeometryBindingQuadIndex quad_indices[1];
+
+  static_assert(sizeof(GeometryBindingQuad) == 24 * sizeof(float),
+                "struct Quad should be densely packed");
+  static_assert(sizeof(GeometryBindingQuadIndex) == 6 * sizeof(uint16_t),
+                "struct QuadIndex should be densely packed");
+
+  GLC(gl_, gl_->GenBuffers(1, &quad_vertices_vbo_));
+  GLC(gl_, gl_->GenBuffers(1, &quad_elements_vbo_));
+
+  GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
+  GLC(gl_, gl_->BufferData(GL_ARRAY_BUFFER, sizeof(GeometryBindingQuad) * 1,
+                           quads, GL_DYNAMIC_DRAW));
+
+  GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
+  GLC(gl_, gl_->BufferData(GL_ELEMENT_ARRAY_BUFFER,
+                           sizeof(GeometryBindingQuadIndex) * 1, &quad_indices,
+                           GL_DYNAMIC_DRAW));
+}
+
+void DynamicGeometryBinding::InitializeCustomQuad(const gfx::QuadF& quad) {
+  float uv[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
+  InitializeCustomQuadWithUVs(quad, uv);
+}
+
+void DynamicGeometryBinding::InitializeCustomQuadWithUVs(const gfx::QuadF& quad,
+                                                         const float uv[8]) {
+  GeometryBindingVertex v0 = {
+      {quad.p1().x(), quad.p1().y(), 0.0f}, {uv[0], uv[1]}, 0.0f};
+  GeometryBindingVertex v1 = {
+      {quad.p2().x(), quad.p2().y(), 0.0f}, {uv[2], uv[3]}, 1.0f};
+  GeometryBindingVertex v2 = {
+      {quad.p3().x(), quad.p3().y(), 0.0f}, {uv[4], uv[5]}, 2.0f};
+  GeometryBindingVertex v3 = {
+      {quad.p4().x(), quad.p4().y(), 0.0f}, {uv[6], uv[7]}, 3.0f};
+
+  GeometryBindingQuad local_quad = {v0, v1, v2, v3};
+  GeometryBindingQuadIndex quad_index(
+      static_cast<uint16>(0), static_cast<uint16>(1), static_cast<uint16>(2),
+      static_cast<uint16>(3), static_cast<uint16>(0), static_cast<uint16>(2));
+
+  GLC(gl_, gl_->BufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GeometryBindingQuad),
+                              &local_quad));
+  GLC(gl_, gl_->BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0,
+                              sizeof(GeometryBindingQuadIndex), &quad_index));
+}
+
+void DynamicGeometryBinding::PrepareForDraw() {
+  SetupGLContext(gl_, quad_elements_vbo_, quad_vertices_vbo_);
+}
+
+}  // namespace cc
diff --git a/cc/output/dynamic_geometry_binding.h b/cc/output/dynamic_geometry_binding.h
new file mode 100644
index 0000000..4e4ea3d
--- /dev/null
+++ b/cc/output/dynamic_geometry_binding.h
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_OUTPUT_DYNAMIC_GEOMETRY_BINDING_H_
+#define CC_OUTPUT_DYNAMIC_GEOMETRY_BINDING_H_
+
+#include "cc/output/geometry_binding.h"
+
+namespace cc {
+
+class DynamicGeometryBinding {
+ public:
+  explicit DynamicGeometryBinding(gpu::gles2::GLES2Interface* gl);
+  void PrepareForDraw();
+  void InitializeCustomQuad(const gfx::QuadF& quad);
+  void InitializeCustomQuadWithUVs(const gfx::QuadF& quad, const float uv[8]);
+
+ private:
+  gpu::gles2::GLES2Interface* gl_;
+
+  GLuint quad_vertices_vbo_;
+  GLuint quad_elements_vbo_;
+
+  DISALLOW_COPY_AND_ASSIGN(DynamicGeometryBinding);
+};
+
+}  // namespace cc
+
+#endif  // CC_OUTPUT_DYNAMIC_GEOMETRY_BINDING_H_
diff --git a/cc/output/geometry_binding.cc b/cc/output/geometry_binding.cc
index eda2a5c..88a37de 100644
--- a/cc/output/geometry_binding.cc
+++ b/cc/output/geometry_binding.cc
@@ -10,70 +10,12 @@
 
 namespace cc {
 
-GeometryBinding::GeometryBinding(gpu::gles2::GLES2Interface* gl,
-                                 const gfx::RectF& quad_vertex_rect)
-    : gl_(gl), quad_vertices_vbo_(0), quad_elements_vbo_(0) {
-  struct Vertex {
-    float a_position[3];
-    float a_texCoord[2];
-    // Index of the vertex, divide by 4 to have the matrix for this quad.
-    float a_index;
-  };
-  struct Quad {
-    Vertex v0, v1, v2, v3;
-  };
-  struct QuadIndex {
-    uint16 data[6];
-  };
+void SetupGLContext(gpu::gles2::GLES2Interface* gl,
+                    GLuint quad_elements_vbo,
+                    GLuint quad_vertices_vbo) {
+  GLC(gl, gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo));
 
-  static_assert(sizeof(Quad) == 24 * sizeof(float),
-                "struct Quad should be densely packed");
-  static_assert(sizeof(QuadIndex) == 6 * sizeof(uint16_t),
-                "struct QuadIndex should be densely packed");
-
-  Quad quad_list[8];
-  QuadIndex quad_index_list[8];
-  for (int i = 0; i < 8; i++) {
-    Vertex v0 = {{quad_vertex_rect.x(), quad_vertex_rect.bottom(), 0.0f, },
-                 {0.0f, 1.0f, }, i * 4.0f + 0.0f};
-    Vertex v1 = {{quad_vertex_rect.x(), quad_vertex_rect.y(), 0.0f, },
-                 {0.0f, 0.0f, }, i * 4.0f + 1.0f};
-    Vertex v2 = {{quad_vertex_rect.right(), quad_vertex_rect.y(), 0.0f, },
-                 {1.0f, .0f, }, i * 4.0f + 2.0f};
-    Vertex v3 = {{quad_vertex_rect.right(), quad_vertex_rect.bottom(), 0.0f, },
-                 {1.0f, 1.0f, }, i * 4.0f + 3.0f};
-    Quad x = {v0, v1, v2, v3};
-    quad_list[i] = x;
-    QuadIndex y = {
-        {static_cast<uint16>(0 + 4 * i), static_cast<uint16>(1 + 4 * i),
-         static_cast<uint16>(2 + 4 * i), static_cast<uint16>(3 + 4 * i),
-         static_cast<uint16>(0 + 4 * i), static_cast<uint16>(2 + 4 * i)}};
-    quad_index_list[i] = y;
-  }
-
-  gl_->GenBuffers(1, &quad_vertices_vbo_);
-  gl_->GenBuffers(1, &quad_elements_vbo_);
-  GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
-  GLC(gl_,
-      gl_->BufferData(
-          GL_ARRAY_BUFFER, sizeof(quad_list), quad_list, GL_STATIC_DRAW));
-  GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
-  GLC(gl_,
-      gl_->BufferData(GL_ELEMENT_ARRAY_BUFFER,
-                      sizeof(quad_index_list),
-                      quad_index_list,
-                      GL_STATIC_DRAW));
-}
-
-GeometryBinding::~GeometryBinding() {
-  gl_->DeleteBuffers(1, &quad_vertices_vbo_);
-  gl_->DeleteBuffers(1, &quad_elements_vbo_);
-}
-
-void GeometryBinding::PrepareForDraw() {
-  GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
-
-  GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
+  GLC(gl, gl->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo));
   // OpenGL defines the last parameter to VertexAttribPointer as type
   // "const GLvoid*" even though it is actually an offset into the buffer
   // object's data store and not a pointer to the client's address space.
@@ -83,15 +25,56 @@
       reinterpret_cast<const void*>(5 * sizeof(float)),
   };
 
-  GLC(gl_, gl_->VertexAttribPointer(PositionAttribLocation(), 3, GL_FLOAT,
-                                    false, 6 * sizeof(float), offsets[0]));
-  GLC(gl_, gl_->VertexAttribPointer(TexCoordAttribLocation(), 2, GL_FLOAT,
-                                    false, 6 * sizeof(float), offsets[1]));
-  GLC(gl_, gl_->VertexAttribPointer(TriangleIndexAttribLocation(), 1, GL_FLOAT,
-                                    false, 6 * sizeof(float), offsets[2]));
-  GLC(gl_, gl_->EnableVertexAttribArray(PositionAttribLocation()));
-  GLC(gl_, gl_->EnableVertexAttribArray(TexCoordAttribLocation()));
-  GLC(gl_, gl_->EnableVertexAttribArray(TriangleIndexAttribLocation()));
+  GLC(gl,
+      gl->VertexAttribPointer(GeometryBinding::PositionAttribLocation(), 3,
+                              GL_FLOAT, false, 6 * sizeof(float), offsets[0]));
+  GLC(gl,
+      gl->VertexAttribPointer(GeometryBinding::TexCoordAttribLocation(), 2,
+                              GL_FLOAT, false, 6 * sizeof(float), offsets[1]));
+  GLC(gl,
+      gl->VertexAttribPointer(GeometryBinding::TriangleIndexAttribLocation(), 1,
+                              GL_FLOAT, false, 6 * sizeof(float), offsets[2]));
+  GLC(gl,
+      gl->EnableVertexAttribArray(GeometryBinding::PositionAttribLocation()));
+  GLC(gl,
+      gl->EnableVertexAttribArray(GeometryBinding::TexCoordAttribLocation()));
+  GLC(gl, gl->EnableVertexAttribArray(
+              GeometryBinding::TriangleIndexAttribLocation()));
+}
+
+GeometryBindingQuad::GeometryBindingQuad() {
+  v0 = {{0, 0, 0}, {0, 0}, 0};
+  v1 = {{0, 0, 0}, {0, 0}, 0};
+  v2 = {{0, 0, 0}, {0, 0}, 0};
+  v3 = {{0, 0, 0}, {0, 0}, 0};
+}
+
+GeometryBindingQuad::GeometryBindingQuad(const GeometryBindingVertex& vert0,
+                                         const GeometryBindingVertex& vert1,
+                                         const GeometryBindingVertex& vert2,
+                                         const GeometryBindingVertex& vert3) {
+  v0 = vert0;
+  v1 = vert1;
+  v2 = vert2;
+  v3 = vert3;
+}
+
+GeometryBindingQuadIndex::GeometryBindingQuadIndex() {
+  memset(data, 0x0, sizeof(data));
+}
+
+GeometryBindingQuadIndex::GeometryBindingQuadIndex(uint16 index0,
+                                                   uint16 index1,
+                                                   uint16 index2,
+                                                   uint16 index3,
+                                                   uint16 index4,
+                                                   uint16 index5) {
+  data[0] = index0;
+  data[1] = index1;
+  data[2] = index2;
+  data[3] = index3;
+  data[4] = index4;
+  data[5] = index5;
 }
 
 }  // namespace cc
diff --git a/cc/output/geometry_binding.h b/cc/output/geometry_binding.h
index cfa21ef..ae68687 100644
--- a/cc/output/geometry_binding.h
+++ b/cc/output/geometry_binding.h
@@ -6,43 +6,65 @@
 #define CC_OUTPUT_GEOMETRY_BINDING_H_
 
 #include "base/basictypes.h"
+#include "cc/output/gl_renderer.h"  // For the GLC() macro.
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "ui/gfx/geometry/rect_f.h"
 
 namespace gfx {
-class RectF;
-}
-namespace gpu {
-namespace gles2 {
-class GLES2Interface;
-}
+class QuadF;
+class Quad;
+class QuadIndex;
+class PointF;
 }
 
 namespace cc {
 
-class GeometryBinding {
- public:
-  GeometryBinding(gpu::gles2::GLES2Interface* gl,
-                  const gfx::RectF& quad_vertex_rect);
-  ~GeometryBinding();
+struct GeometryBindingVertex {
+  float a_position[3];
+  float a_texCoord[2];
+  // Index of the vertex, divide by 4 to have the matrix for this quad.
+  float a_index;
+};
 
-  void PrepareForDraw();
+struct GeometryBindingQuad {
+  GeometryBindingQuad();
+  GeometryBindingQuad(const GeometryBindingVertex& vert0,
+                      const GeometryBindingVertex& vert1,
+                      const GeometryBindingVertex& vert2,
+                      const GeometryBindingVertex& vert3);
+  GeometryBindingVertex v0, v1, v2, v3;
+};
 
+struct GeometryBindingQuadIndex {
+  GeometryBindingQuadIndex();
+  GeometryBindingQuadIndex(uint16 index0,
+                           uint16 index1,
+                           uint16 index2,
+                           uint16 index3,
+                           uint16 index4,
+                           uint16 index5);
+
+  uint16 data[6];
+};
+
+class DrawQuad;
+class DrawPolygon;
+
+struct GeometryBinding {
   // All layer shaders share the same attribute locations for the vertex
   // positions and texture coordinates. This allows switching shaders without
   // rebinding attribute arrays.
   static int PositionAttribLocation() { return 0; }
   static int TexCoordAttribLocation() { return 1; }
   static int TriangleIndexAttribLocation() { return 2; }
-
- private:
-  gpu::gles2::GLES2Interface* gl_;
-
-  GLuint quad_vertices_vbo_;
-  GLuint quad_elements_vbo_;
-
-  DISALLOW_COPY_AND_ASSIGN(GeometryBinding);
 };
 
+void SetupGLContext(gpu::gles2::GLES2Interface* gl,
+                    GLuint quad_elements_vbo,
+                    GLuint quad_vertices_vbo);
+
 }  // namespace cc
 
 #endif  // CC_OUTPUT_GEOMETRY_BINDING_H_
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 578faa9..3813e1d 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -11,16 +11,23 @@
 #include <vector>
 
 #include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/math_util.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_metadata.h"
 #include "cc/output/context_provider.h"
 #include "cc/output/copy_output_request.h"
-#include "cc/output/geometry_binding.h"
+#include "cc/output/dynamic_geometry_binding.h"
 #include "cc/output/gl_frame_data.h"
 #include "cc/output/output_surface.h"
 #include "cc/output/render_surface_filters.h"
+#include "cc/output/static_geometry_binding.h"
+#include "cc/quads/draw_polygon.h"
 #include "cc/quads/picture_draw_quad.h"
 #include "cc/quads/render_pass.h"
 #include "cc/quads/stream_video_draw_quad.h"
@@ -323,7 +330,8 @@
       highp_threshold_min_(highp_threshold_min),
       highp_threshold_cache_(0),
       use_sync_query_(false),
-      on_demand_tile_raster_resource_id_(0) {
+      on_demand_tile_raster_resource_id_(0),
+      bound_geometry_(NO_BINDING) {
   DCHECK(gl_);
   DCHECK(context_support_);
 
@@ -493,10 +501,12 @@
   GLC(gl_, gl_->Flush());
 }
 
-void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) {
+void GLRenderer::DoDrawQuad(DrawingFrame* frame,
+                            const DrawQuad* quad,
+                            const gfx::QuadF* clip_region) {
   DCHECK(quad->rect.Contains(quad->visible_rect));
   if (quad->material != DrawQuad::TEXTURE_CONTENT) {
-    FlushTextureQuadCache();
+    FlushTextureQuadCache(SHARED_BINDING);
   }
 
   switch (quad->material) {
@@ -504,26 +514,31 @@
       NOTREACHED();
       break;
     case DrawQuad::CHECKERBOARD:
-      DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad));
+      DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad),
+                           clip_region);
       break;
     case DrawQuad::DEBUG_BORDER:
       DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad));
       break;
     case DrawQuad::IO_SURFACE_CONTENT:
-      DrawIOSurfaceQuad(frame, IOSurfaceDrawQuad::MaterialCast(quad));
+      DrawIOSurfaceQuad(frame, IOSurfaceDrawQuad::MaterialCast(quad),
+                        clip_region);
       break;
     case DrawQuad::PICTURE_CONTENT:
       // PictureDrawQuad should only be used for resourceless software draws.
       NOTREACHED();
       break;
     case DrawQuad::RENDER_PASS:
-      DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad));
+      DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad),
+                         clip_region);
       break;
     case DrawQuad::SOLID_COLOR:
-      DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad));
+      DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad),
+                         clip_region);
       break;
     case DrawQuad::STREAM_VIDEO_CONTENT:
-      DrawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad));
+      DrawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad),
+                          clip_region);
       break;
     case DrawQuad::SURFACE_CONTENT:
       // Surface content should be fully resolved to other quad types before
@@ -531,19 +546,28 @@
       NOTREACHED();
       break;
     case DrawQuad::TEXTURE_CONTENT:
-      EnqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad));
+      EnqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad),
+                         clip_region);
       break;
     case DrawQuad::TILED_CONTENT:
-      DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad));
+      DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad), clip_region);
       break;
     case DrawQuad::YUV_VIDEO_CONTENT:
-      DrawYUVVideoQuad(frame, YUVVideoDrawQuad::MaterialCast(quad));
+      DrawYUVVideoQuad(frame, YUVVideoDrawQuad::MaterialCast(quad),
+                       clip_region);
       break;
   }
 }
 
 void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
-                                      const CheckerboardDrawQuad* quad) {
+                                      const CheckerboardDrawQuad* quad,
+                                      const gfx::QuadF* clip_region) {
+  // TODO(enne) For now since checkerboards shouldn't be part of a 3D
+  // context, clipping regions aren't supported so we skip drawing them
+  // if this becomes the case.
+  if (clip_region) {
+    return;
+  }
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
   const TileCheckerboardProgram* program = GetTileCheckerboardProgram();
@@ -587,6 +611,9 @@
                    program->vertex_shader().matrix_location());
 }
 
+// This function does not handle 3D sorting right now, since the debug border
+// quads are just drawn as their original quads and not in split pieces. This
+// results in some debug border quads drawing over foreground quads.
 void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame,
                                      const DebugBorderDrawQuad* quad) {
   SetBlendEnabled(quad->ShouldDrawWithBlending());
@@ -818,13 +845,56 @@
   return true;
 }
 
+// This takes a gfx::Rect and a clip region quad in the same space,
+// and returns a quad with the same proportions in the space -0.5->0.5.
+bool GetScaledRegion(const gfx::Rect& rect,
+                     const gfx::QuadF* clip,
+                     gfx::QuadF* scaled_region) {
+  if (!clip)
+    return false;
+
+  gfx::PointF p1(((clip->p1().x() - rect.x()) / rect.width()) - 0.5f,
+                 ((clip->p1().y() - rect.y()) / rect.height()) - 0.5f);
+  gfx::PointF p2(((clip->p2().x() - rect.x()) / rect.width()) - 0.5f,
+                 ((clip->p2().y() - rect.y()) / rect.height()) - 0.5f);
+  gfx::PointF p3(((clip->p3().x() - rect.x()) / rect.width()) - 0.5f,
+                 ((clip->p3().y() - rect.y()) / rect.height()) - 0.5f);
+  gfx::PointF p4(((clip->p4().x() - rect.x()) / rect.width()) - 0.5f,
+                 ((clip->p4().y() - rect.y()) / rect.height()) - 0.5f);
+  *scaled_region = gfx::QuadF(p1, p2, p3, p4);
+  return true;
+}
+
+// This takes a gfx::Rect and a clip region quad in the same space,
+// and returns the proportional uv's in the space 0->1.
+bool GetScaledUVs(const gfx::Rect& rect, const gfx::QuadF* clip, float uvs[8]) {
+  if (!clip)
+    return false;
+
+  uvs[0] = ((clip->p1().x() - rect.x()) / rect.width());
+  uvs[1] = ((clip->p1().y() - rect.y()) / rect.height());
+  uvs[2] = ((clip->p2().x() - rect.x()) / rect.width());
+  uvs[3] = ((clip->p2().y() - rect.y()) / rect.height());
+  uvs[4] = ((clip->p3().x() - rect.x()) / rect.width());
+  uvs[5] = ((clip->p3().y() - rect.y()) / rect.height());
+  uvs[6] = ((clip->p4().x() - rect.x()) / rect.width());
+  uvs[7] = ((clip->p4().y() - rect.y()) / rect.height());
+  return true;
+}
+
 gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
     DrawingFrame* frame,
     const RenderPassDrawQuad* quad,
     const gfx::Transform& contents_device_transform,
+    const gfx::QuadF* clip_region,
     bool use_aa) {
+  gfx::QuadF scaled_region;
+  if (!GetScaledRegion(quad->rect, clip_region, &scaled_region)) {
+    scaled_region = SharedGeometryQuad().BoundingBox();
+  }
+
   gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
-      contents_device_transform, SharedGeometryQuad().BoundingBox()));
+      contents_device_transform, scaled_region.BoundingBox()));
 
   if (ShouldApplyBackgroundFilters(frame, quad)) {
     int top, right, bottom, left;
@@ -873,7 +943,8 @@
 }
 
 void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
-                                    const RenderPassDrawQuad* quad) {
+                                    const RenderPassDrawQuad* quad,
+                                    const gfx::QuadF* clip_region) {
   ScopedResource* contents_texture =
       render_pass_textures_.get(quad->render_pass_id);
   if (!contents_texture || !contents_texture->id())
@@ -895,10 +966,8 @@
                 ShouldAntialiasQuad(contents_device_transform, quad,
                                     settings_->force_antialiasing);
 
-  if (use_aa)
-    SetupQuadForAntialiasing(contents_device_transform, quad,
-                             &surface_quad, edge);
-
+  SetupQuadForClippingAndAntialiasing(contents_device_transform, quad, use_aa,
+                                      clip_region, &surface_quad, edge);
   SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode;
   bool use_shaders_for_blending =
       !CanApplyBlendModeUsingBlendFunc(blend_mode) ||
@@ -912,7 +981,7 @@
     // Compute a bounding box around the pixels that will be visible through
     // the quad.
     background_rect = GetBackdropBoundingBoxForRenderPassQuad(
-        frame, quad, contents_device_transform, use_aa);
+        frame, quad, contents_device_transform, clip_region, use_aa);
 
     if (!background_rect.IsEmpty()) {
       // The pixels from the filtered background should completely replace the
@@ -1237,15 +1306,78 @@
   uniforms->color_location = program->fragment_shader().color_location();
 }
 
+namespace {
+// These functions determine if a quad, clipped by a clip_region contains
+// the entire {top|bottom|left|right} edge.
+bool is_top(const gfx::QuadF* clip_region, const DrawQuad* quad) {
+  if (!quad->IsTopEdge())
+    return false;
+  if (!clip_region)
+    return true;
+
+  return std::abs(clip_region->p1().y()) < kAntiAliasingEpsilon &&
+         std::abs(clip_region->p2().y()) < kAntiAliasingEpsilon;
+}
+
+bool is_bottom(const gfx::QuadF* clip_region, const DrawQuad* quad) {
+  if (!quad->IsBottomEdge())
+    return false;
+  if (!clip_region)
+    return true;
+
+  return std::abs(clip_region->p3().y() -
+                  quad->shared_quad_state->content_bounds.height()) <
+             kAntiAliasingEpsilon &&
+         std::abs(clip_region->p4().y() -
+                  quad->shared_quad_state->content_bounds.height()) <
+             kAntiAliasingEpsilon;
+}
+
+bool is_left(const gfx::QuadF* clip_region, const DrawQuad* quad) {
+  if (!quad->IsLeftEdge())
+    return false;
+  if (!clip_region)
+    return true;
+
+  return std::abs(clip_region->p1().x()) < kAntiAliasingEpsilon &&
+         std::abs(clip_region->p4().x()) < kAntiAliasingEpsilon;
+}
+
+bool is_right(const gfx::QuadF* clip_region, const DrawQuad* quad) {
+  if (!quad->IsRightEdge())
+    return false;
+  if (!clip_region)
+    return true;
+
+  return std::abs(clip_region->p2().x() -
+                  quad->shared_quad_state->content_bounds.width()) <
+             kAntiAliasingEpsilon &&
+         std::abs(clip_region->p3().x() -
+                  quad->shared_quad_state->content_bounds.width()) <
+             kAntiAliasingEpsilon;
+}
+}  // anonymous namespace
+
 static gfx::QuadF GetDeviceQuadWithAntialiasingOnExteriorEdges(
     const LayerQuad& device_layer_edges,
     const gfx::Transform& device_transform,
+    const gfx::QuadF* clip_region,
     const DrawQuad* quad) {
-  gfx::Rect tile_rect = quad->visible_rect;
-  gfx::PointF bottom_right = tile_rect.bottom_right();
-  gfx::PointF bottom_left = tile_rect.bottom_left();
-  gfx::PointF top_left = tile_rect.origin();
-  gfx::PointF top_right = tile_rect.top_right();
+  gfx::RectF tile_rect = quad->visible_rect;
+  gfx::QuadF tile_quad(tile_rect);
+
+  if (clip_region) {
+    if (quad->material != DrawQuad::RENDER_PASS) {
+      tile_quad = *clip_region;
+    } else {
+      GetScaledRegion(quad->rect, clip_region, &tile_quad);
+    }
+  }
+
+  gfx::PointF bottom_right = tile_quad.p3();
+  gfx::PointF bottom_left = tile_quad.p4();
+  gfx::PointF top_left = tile_quad.p1();
+  gfx::PointF top_right = tile_quad.p2();
   bool clipped = false;
 
   // Map points to device space. We ignore |clipped|, since the result of
@@ -1262,16 +1394,26 @@
   LayerQuad::Edge right_edge(top_right, bottom_right);
 
   // Only apply anti-aliasing to edges not clipped by culling or scissoring.
-  if (quad->IsTopEdge() && tile_rect.y() == quad->rect.y())
+  // If an edge is degenerate we do not want to replace it with a "proper" edge
+  // as that will cause the quad to possibly expand is strange ways.
+  if (!top_edge.degenerate() && is_top(clip_region, quad) &&
+      tile_rect.y() == quad->rect.y()) {
     top_edge = device_layer_edges.top();
-  if (quad->IsLeftEdge() && tile_rect.x() == quad->rect.x())
+  }
+  if (!left_edge.degenerate() && is_left(clip_region, quad) &&
+      tile_rect.x() == quad->rect.x()) {
     left_edge = device_layer_edges.left();
-  if (quad->IsRightEdge() && tile_rect.right() == quad->rect.right())
+  }
+  if (!right_edge.degenerate() && is_right(clip_region, quad) &&
+      tile_rect.right() == quad->rect.right()) {
     right_edge = device_layer_edges.right();
-  if (quad->IsBottomEdge() && tile_rect.bottom() == quad->rect.bottom())
+  }
+  if (!bottom_edge.degenerate() && is_bottom(clip_region, quad) &&
+      tile_rect.bottom() == quad->rect.bottom()) {
     bottom_edge = device_layer_edges.bottom();
+  }
 
-  float sign = gfx::QuadF(tile_rect).IsCounterClockwise() ? -1 : 1;
+  float sign = tile_quad.IsCounterClockwise() ? -1 : 1;
   bottom_edge.scale(sign);
   left_edge.scale(sign);
   top_edge.scale(sign);
@@ -1281,6 +1423,32 @@
   return LayerQuad(left_edge, top_edge, right_edge, bottom_edge).ToQuadF();
 }
 
+float GetTotalQuadError(const gfx::QuadF* clipped_quad,
+                        const gfx::QuadF* ideal_rect) {
+  return (clipped_quad->p1() - ideal_rect->p1()).LengthSquared() +
+         (clipped_quad->p2() - ideal_rect->p2()).LengthSquared() +
+         (clipped_quad->p3() - ideal_rect->p3()).LengthSquared() +
+         (clipped_quad->p4() - ideal_rect->p4()).LengthSquared();
+}
+
+// Attempt to rotate the clipped quad until it lines up the most
+// correctly. This is necessary because we check the edges of this
+// quad against the expected left/right/top/bottom for anti-aliasing.
+void AlignQuadToBoundingBox(gfx::QuadF* clipped_quad) {
+  gfx::QuadF bounding_quad = gfx::QuadF(clipped_quad->BoundingBox());
+  gfx::QuadF best_rotation = *clipped_quad;
+  float least_error_amount = GetTotalQuadError(clipped_quad, &bounding_quad);
+  for (size_t i = 1; i < 4; ++i) {
+    clipped_quad->Realign(1);
+    float new_error = GetTotalQuadError(clipped_quad, &bounding_quad);
+    if (new_error < least_error_amount) {
+      least_error_amount = new_error;
+      best_rotation = *clipped_quad;
+    }
+  }
+  *clipped_quad = best_rotation;
+}
+
 // static
 bool GLRenderer::ShouldAntialiasQuad(const gfx::Transform& device_transform,
                                      const DrawQuad* quad,
@@ -1312,18 +1480,39 @@
 }
 
 // static
-void GLRenderer::SetupQuadForAntialiasing(
+void GLRenderer::SetupQuadForClippingAndAntialiasing(
     const gfx::Transform& device_transform,
     const DrawQuad* quad,
+    bool use_aa,
+    const gfx::QuadF* clip_region,
     gfx::QuadF* local_quad,
     float edge[24]) {
   bool is_render_pass_quad = (quad->material == DrawQuad::RENDER_PASS);
-  gfx::RectF content_rect =
-      is_render_pass_quad ? QuadVertexRect() : quad->visibleContentRect();
+  gfx::QuadF rotated_clip;
+  const gfx::QuadF* local_clip_region = clip_region;
+  if (local_clip_region) {
+    rotated_clip = *clip_region;
+    AlignQuadToBoundingBox(&rotated_clip);
+    local_clip_region = &rotated_clip;
+  }
 
+  gfx::QuadF content_rect = is_render_pass_quad
+                                ? gfx::QuadF(QuadVertexRect())
+                                : gfx::QuadF(quad->visibleContentRect());
+  if (!use_aa) {
+    if (local_clip_region) {
+      if (!is_render_pass_quad) {
+        content_rect = *local_clip_region;
+      } else {
+        GetScaledRegion(quad->rect, local_clip_region, &content_rect);
+      }
+      *local_quad = content_rect;
+    }
+    return;
+  }
   bool clipped = false;
   gfx::QuadF device_layer_quad =
-      MathUtil::MapQuad(device_transform, gfx::QuadF(content_rect), &clipped);
+      MathUtil::MapQuad(device_transform, content_rect, &clipped);
 
   LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox()));
   device_layer_bounds.InflateAntiAliasingDistance();
@@ -1334,16 +1523,25 @@
   device_layer_edges.ToFloatArray(edge);
   device_layer_bounds.ToFloatArray(&edge[12]);
 
+  // If we have a clip region then we are split, and therefore
+  // by necessity, at least one of our edges is not an external
+  // one.
+  bool is_full_rect = quad->visible_rect == quad->rect;
+
+  bool region_contains_all_outside_edges =
+      is_full_rect &&
+      (is_top(local_clip_region, quad) && is_left(local_clip_region, quad) &&
+       is_bottom(local_clip_region, quad) && is_right(local_clip_region, quad));
+
   bool use_aa_on_all_four_edges =
-      is_render_pass_quad ||
-      (quad->IsTopEdge() && quad->IsLeftEdge() && quad->IsBottomEdge() &&
-       quad->IsRightEdge() && quad->visible_rect == quad->rect);
+      !local_clip_region &&
+      (is_render_pass_quad || region_contains_all_outside_edges);
 
   gfx::QuadF device_quad =
       use_aa_on_all_four_edges
           ? device_layer_edges.ToQuadF()
           : GetDeviceQuadWithAntialiasingOnExteriorEdges(
-                device_layer_edges, device_transform, quad);
+                device_layer_edges, device_transform, local_clip_region, quad);
 
   // Map device space quad to local space. device_transform has no 3d
   // component since it was flattened, so we don't need to project.  We should
@@ -1359,7 +1557,8 @@
 }
 
 void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
-                                    const SolidColorDrawQuad* quad) {
+                                    const SolidColorDrawQuad* quad,
+                                    const gfx::QuadF* clip_region) {
   gfx::Rect tile_rect = quad->visible_rect;
 
   SkColor color = quad->color;
@@ -1383,10 +1582,11 @@
   bool use_aa = settings_->allow_antialiasing &&
                 !quad->force_anti_aliasing_off &&
                 ShouldAntialiasQuad(device_transform, quad, force_aa);
+  SetupQuadForClippingAndAntialiasing(device_transform, quad, use_aa,
+                                      clip_region, &local_quad, edge);
 
   SolidColorProgramUniforms uniforms;
   if (use_aa) {
-    SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge);
     SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms);
   } else {
     SolidColorUniformLocation(GetSolidColorProgram(), &uniforms);
@@ -1457,13 +1657,15 @@
 }
 
 void GLRenderer::DrawTileQuad(const DrawingFrame* frame,
-                              const TileDrawQuad* quad) {
-  DrawContentQuad(frame, quad, quad->resource_id);
+                              const TileDrawQuad* quad,
+                              const gfx::QuadF* clip_region) {
+  DrawContentQuad(frame, quad, quad->resource_id, clip_region);
 }
 
 void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
                                  const ContentDrawQuadBase* quad,
-                                 ResourceProvider::ResourceId resource_id) {
+                                 ResourceProvider::ResourceId resource_id,
+                                 const gfx::QuadF* clip_region) {
   gfx::Transform device_transform =
       frame->window_matrix * frame->projection_matrix * quad->quadTransform();
   device_transform.FlattenTo2d();
@@ -1475,15 +1677,16 @@
   // similar to the way DrawContentQuadNoAA works and then consider
   // combining DrawContentQuadAA and DrawContentQuadNoAA into one method.
   if (use_aa)
-    DrawContentQuadAA(frame, quad, resource_id, device_transform);
+    DrawContentQuadAA(frame, quad, resource_id, device_transform, clip_region);
   else
-    DrawContentQuadNoAA(frame, quad, resource_id);
+    DrawContentQuadNoAA(frame, quad, resource_id, clip_region);
 }
 
 void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame,
                                    const ContentDrawQuadBase* quad,
                                    ResourceProvider::ResourceId resource_id,
-                                   const gfx::Transform& device_transform) {
+                                   const gfx::Transform& device_transform,
+                                   const gfx::QuadF* clip_region) {
   if (!device_transform.IsInvertible())
     return;
 
@@ -1528,8 +1731,8 @@
 
   gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
   float edge[24];
-  SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge);
-
+  SetupQuadForClippingAndAntialiasing(device_transform, quad, true, clip_region,
+                                      &local_quad, edge);
   ResourceProvider::ScopedSamplerGL quad_resource_lock(
       resource_provider_, resource_id,
       quad->nearest_neighbor ? GL_NEAREST : GL_LINEAR);
@@ -1607,7 +1810,8 @@
 
 void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame,
                                      const ContentDrawQuadBase* quad,
-                                     ResourceProvider::ResourceId resource_id) {
+                                     ResourceProvider::ResourceId resource_id,
+                                     const gfx::QuadF* clip_region) {
   gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional(
       quad->tex_coord_rect, quad->rect, quad->visible_rect);
   float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width();
@@ -1681,17 +1885,37 @@
   // does, then vertices will match the texture mapping in the vertex buffer.
   // The method SetShaderQuadF() changes the order of vertices and so it's
   // not used here.
-
-  gfx::RectF tile_rect = quad->visible_rect;
+  gfx::QuadF tile_rect(quad->visible_rect);
+  float width = quad->visible_rect.width();
+  float height = quad->visible_rect.height();
+  gfx::PointF top_left = quad->visible_rect.origin();
+  if (clip_region) {
+    tile_rect = *clip_region;
+    float gl_uv[8] = {
+        (tile_rect.p4().x() - top_left.x()) / width,
+        (tile_rect.p4().y() - top_left.y()) / height,
+        (tile_rect.p1().x() - top_left.x()) / width,
+        (tile_rect.p1().y() - top_left.y()) / height,
+        (tile_rect.p2().x() - top_left.x()) / width,
+        (tile_rect.p2().y() - top_left.y()) / height,
+        (tile_rect.p3().x() - top_left.x()) / width,
+        (tile_rect.p3().y() - top_left.y()) / height,
+    };
+    PrepareGeometry(CLIPPED_BINDING);
+    clipped_geometry_->InitializeCustomQuadWithUVs(
+        gfx::QuadF(quad->visible_rect), gl_uv);
+  } else {
+    PrepareGeometry(SHARED_BINDING);
+  }
   float gl_quad[8] = {
-    tile_rect.x(),
-    tile_rect.bottom(),
-    tile_rect.x(),
-    tile_rect.y(),
-    tile_rect.right(),
-    tile_rect.y(),
-    tile_rect.right(),
-    tile_rect.bottom(),
+      tile_rect.p4().x(),
+      tile_rect.p4().y(),
+      tile_rect.p1().x(),
+      tile_rect.p1().y(),
+      tile_rect.p2().x(),
+      tile_rect.p2().y(),
+      tile_rect.p3().x(),
+      tile_rect.p3().y(),
   };
   GLC(gl_, gl_->Uniform2fv(uniforms.quad_location, 4, gl_quad));
 
@@ -1704,7 +1928,8 @@
 }
 
 void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
-                                  const YUVVideoDrawQuad* quad) {
+                                  const YUVVideoDrawQuad* quad,
+                                  const gfx::QuadF* clip_region) {
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
@@ -1844,15 +2069,31 @@
       break;
   }
 
+  // The transform and vertex data are used to figure out the extents that the
+  // un-antialiased quad should have and which vertex this is and the float
+  // quad passed in via uniform is the actual geometry that gets used to draw
+  // it. This is why this centered rect is used and not the original quad_rect.
+  gfx::RectF tile_rect = quad->visible_rect;
   GLC(gl_, gl_->UniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb));
   GLC(gl_, gl_->Uniform3fv(yuv_adj_location, 1, yuv_adjust));
 
   SetShaderOpacity(quad->opacity(), alpha_location);
-  DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, matrix_location);
+  if (!clip_region) {
+    DrawQuadGeometry(frame, quad->quadTransform(), tile_rect, matrix_location);
+  } else {
+    float uvs[8] = {0};
+    GetScaledUVs(quad->visible_rect, clip_region, uvs);
+    gfx::QuadF region_quad = *clip_region;
+    region_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
+    region_quad -= gfx::Vector2dF(0.5f, 0.5f);
+    DrawQuadGeometryClippedByQuadF(frame, quad->quadTransform(), tile_rect,
+                                   region_quad, matrix_location, uvs);
+  }
 }
 
 void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
-                                     const StreamVideoDrawQuad* quad) {
+                                     const StreamVideoDrawQuad* quad,
+                                     const gfx::QuadF* clip_region) {
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
   static float gl_matrix[16];
@@ -1883,10 +2124,19 @@
 
   SetShaderOpacity(quad->opacity(),
                    program->fragment_shader().alpha_location());
-  DrawQuadGeometry(frame,
-                   quad->quadTransform(),
-                   quad->rect,
-                   program->vertex_shader().matrix_location());
+  if (!clip_region) {
+    DrawQuadGeometry(frame, quad->quadTransform(), quad->rect,
+                     program->vertex_shader().matrix_location());
+  } else {
+    gfx::QuadF region_quad(*clip_region);
+    region_quad.Scale(1.0f / quad->rect.width(), 1.0f / quad->rect.height());
+    region_quad -= gfx::Vector2dF(0.5f, 0.5f);
+    float uvs[8] = {0};
+    GetScaledUVs(quad->visible_rect, clip_region, uvs);
+    DrawQuadGeometryClippedByQuadF(
+        frame, quad->quadTransform(), quad->rect, region_quad,
+        program->vertex_shader().matrix_location(), uvs);
+  }
 }
 
 struct TextureProgramBinding {
@@ -1902,6 +2152,7 @@
   int program_id;
   int sampler_location;
   int matrix_location;
+  int transform_location;
   int background_color_location;
 };
 
@@ -1917,11 +2168,13 @@
   int vertex_opacity_location;
 };
 
-void GLRenderer::FlushTextureQuadCache() {
+void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) {
   // Check to see if we have anything to draw.
   if (draw_cache_.program_id == -1)
     return;
 
+  PrepareGeometry(flush_binding);
+
   // Set the correct blending mode.
   SetBlendEnabled(draw_cache_.needs_blending);
 
@@ -1982,10 +2235,26 @@
   draw_cache_.uv_xform_data.resize(0);
   draw_cache_.vertex_opacity_data.resize(0);
   draw_cache_.matrix_data.resize(0);
+
+  // If we had a clipped binding, prepare the shared binding for the
+  // next inserts.
+  if (flush_binding == CLIPPED_BINDING) {
+    PrepareGeometry(SHARED_BINDING);
+  }
 }
 
 void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame,
-                                    const TextureDrawQuad* quad) {
+                                    const TextureDrawQuad* quad,
+                                    const gfx::QuadF* clip_region) {
+  // If we have a clip_region then we have to render the next quad
+  // with dynamic geometry, therefore we must flush all pending
+  // texture quads.
+  if (clip_region) {
+    // We send in false here because we want to flush what's currently in the
+    // queue using the shared_geometry and not clipped_geometry
+    FlushTextureQuadCache(SHARED_BINDING);
+  }
+
   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
       gl_,
       &highp_threshold_cache_,
@@ -2017,7 +2286,7 @@
       draw_cache_.nearest_neighbor != quad->nearest_neighbor ||
       draw_cache_.background_color != quad->background_color ||
       draw_cache_.matrix_data.size() >= 8) {
-    FlushTextureQuadCache();
+    FlushTextureQuadCache(SHARED_BINDING);
     draw_cache_.program_id = binding.program_id;
     draw_cache_.resource_id = resource_id;
     draw_cache_.needs_blending = quad->ShouldDrawWithBlending();
@@ -2032,7 +2301,12 @@
   }
 
   // Generate the uv-transform
-  draw_cache_.uv_xform_data.push_back(UVTransform(quad));
+  if (!clip_region) {
+    draw_cache_.uv_xform_data.push_back(UVTransform(quad));
+  } else {
+    Float4 uv_transform = {{0.0f, 0.0f, 1.0f, 1.0f}};
+    draw_cache_.uv_xform_data.push_back(uv_transform);
+  }
 
   // Generate the vertex opacity
   const float opacity = quad->opacity();
@@ -2049,10 +2323,32 @@
   Float16 m;
   quad_rect_matrix.matrix().asColMajorf(m.data);
   draw_cache_.matrix_data.push_back(m);
+
+  if (clip_region) {
+    gfx::QuadF scaled_region;
+    if (!GetScaledRegion(quad->rect, clip_region, &scaled_region)) {
+      scaled_region = SharedGeometryQuad().BoundingBox();
+    }
+    // Both the scaled region and the SharedGeomtryQuad are in the space
+    // -0.5->0.5. We need to move that to the space 0->1.
+    float uv[8];
+    uv[0] = scaled_region.p1().x() + 0.5f;
+    uv[1] = scaled_region.p1().y() + 0.5f;
+    uv[2] = scaled_region.p2().x() + 0.5f;
+    uv[3] = scaled_region.p2().y() + 0.5f;
+    uv[4] = scaled_region.p3().x() + 0.5f;
+    uv[5] = scaled_region.p3().y() + 0.5f;
+    uv[6] = scaled_region.p4().x() + 0.5f;
+    uv[7] = scaled_region.p4().y() + 0.5f;
+    PrepareGeometry(CLIPPED_BINDING);
+    clipped_geometry_->InitializeCustomQuadWithUVs(scaled_region, uv);
+    FlushTextureQuadCache(CLIPPED_BINDING);
+  }
 }
 
 void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame,
-                                   const IOSurfaceDrawQuad* quad) {
+                                   const IOSurfaceDrawQuad* quad,
+                                   const gfx::QuadF* clip_region) {
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
@@ -2091,8 +2387,15 @@
   DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_));
   GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, lock.texture_id()));
 
-  DrawQuadGeometry(
-      frame, quad->quadTransform(), quad->rect, binding.matrix_location);
+  if (!clip_region) {
+    DrawQuadGeometry(frame, quad->quadTransform(), quad->rect,
+                     binding.matrix_location);
+  } else {
+    float uvs[8] = {0};
+    GetScaledUVs(quad->visible_rect, clip_region, uvs);
+    DrawQuadGeometryClippedByQuadF(frame, quad->quadTransform(), quad->rect,
+                                   *clip_region, binding.matrix_location, uvs);
+  }
 
   GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, 0));
 }
@@ -2113,7 +2416,9 @@
   ScheduleOverlays(frame);
 }
 
-void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); }
+void GLRenderer::FinishDrawingQuadList() {
+  FlushTextureQuadCache(SHARED_BINDING);
+}
 
 bool GLRenderer::FlippedFramebuffer(const DrawingFrame* frame) const {
   if (frame->current_render_pass != frame->root_render_pass)
@@ -2130,7 +2435,7 @@
   if (is_scissor_enabled_)
     return;
 
-  FlushTextureQuadCache();
+  FlushTextureQuadCache(SHARED_BINDING);
   GLC(gl_, gl_->Enable(GL_SCISSOR_TEST));
   is_scissor_enabled_ = true;
 }
@@ -2139,7 +2444,7 @@
   if (!is_scissor_enabled_)
     return;
 
-  FlushTextureQuadCache();
+  FlushTextureQuadCache(SHARED_BINDING);
   GLC(gl_, gl_->Disable(GL_SCISSOR_TEST));
   is_scissor_enabled_ = false;
 }
@@ -2208,10 +2513,34 @@
   program_shadow_ = program;
 }
 
+void GLRenderer::DrawQuadGeometryClippedByQuadF(
+    const DrawingFrame* frame,
+    const gfx::Transform& draw_transform,
+    const gfx::RectF& quad_rect,
+    const gfx::QuadF& clipping_region_quad,
+    int matrix_location,
+    const float* uvs) {
+  PrepareGeometry(CLIPPED_BINDING);
+  if (uvs) {
+    clipped_geometry_->InitializeCustomQuadWithUVs(clipping_region_quad, uvs);
+  } else {
+    clipped_geometry_->InitializeCustomQuad(clipping_region_quad);
+  }
+  gfx::Transform quad_rect_matrix;
+  QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect);
+  static float gl_matrix[16];
+  ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad_rect_matrix);
+  GLC(gl_, gl_->UniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0]));
+
+  GLC(gl_, gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
+                             reinterpret_cast<const void*>(0)));
+}
+
 void GLRenderer::DrawQuadGeometry(const DrawingFrame* frame,
                                   const gfx::Transform& draw_transform,
                                   const gfx::RectF& quad_rect,
                                   int matrix_location) {
+  PrepareGeometry(SHARED_BINDING);
   gfx::Transform quad_rect_matrix;
   QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect);
   static float gl_matrix[16];
@@ -2274,6 +2603,7 @@
     output_surface_->context_provider()->DeleteCachedResources();
     GLC(gl_, gl_->Flush());
   }
+  PrepareGeometry(NO_BINDING);
 }
 
 void GLRenderer::DiscardBackbuffer() {
@@ -2605,7 +2935,7 @@
     return;
 
   scissor_rect_ = scissor_rect;
-  FlushTextureQuadCache();
+  FlushTextureQuadCache(SHARED_BINDING);
   GLC(gl_,
       gl_->Scissor(scissor_rect.x(),
                    scissor_rect.y(),
@@ -2630,8 +2960,27 @@
   // Create an FBO for doing offscreen rendering.
   GLC(gl_, gl_->GenFramebuffers(1, &offscreen_framebuffer_id_));
 
-  shared_geometry_ = make_scoped_ptr(
-      new GeometryBinding(gl_, QuadVertexRect()));
+  shared_geometry_ =
+      make_scoped_ptr(new StaticGeometryBinding(gl_, QuadVertexRect()));
+  clipped_geometry_ = make_scoped_ptr(new DynamicGeometryBinding(gl_));
+}
+
+void GLRenderer::PrepareGeometry(BoundGeometry binding) {
+  if (binding == bound_geometry_) {
+    return;
+  }
+
+  switch (binding) {
+    case SHARED_BINDING:
+      shared_geometry_->PrepareForDraw();
+      break;
+    case CLIPPED_BINDING:
+      clipped_geometry_->PrepareForDraw();
+      break;
+    case NO_BINDING:
+      break;
+  }
+  bound_geometry_ = binding;
 }
 
 const GLRenderer::TileCheckerboardProgram*
@@ -3111,8 +3460,8 @@
 
 void GLRenderer::RestoreGLState() {
   // This restores the current GLRenderer state to the GL context.
-
-  shared_geometry_->PrepareForDraw();
+  bound_geometry_ = NO_BINDING;
+  PrepareGeometry(SHARED_BINDING);
 
   GLC(gl_, gl_->Disable(GL_DEPTH_TEST));
   GLC(gl_, gl_->Disable(GL_CULL_FACE));
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 01668ab..27f2c42 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -39,7 +39,8 @@
 class StreamVideoDrawQuad;
 class TextureDrawQuad;
 class TextureMailboxDeleter;
-class GeometryBinding;
+class StaticGeometryBinding;
+class DynamicGeometryBinding;
 class ScopedEnsureFramebufferAllocation;
 
 // Class that handles drawing of composited render layers using GL.
@@ -85,7 +86,7 @@
   bool IsBackbufferDiscarded() const { return is_backbuffer_discarded_; }
 
   const gfx::QuadF& SharedGeometryQuad() const { return shared_geometry_quad_; }
-  const GeometryBinding* SharedGeometry() const {
+  const StaticGeometryBinding* SharedGeometry() const {
     return shared_geometry_.get();
   }
 
@@ -96,7 +97,8 @@
                              ResourceFormat texture_format,
                              const gfx::Rect& device_rect);
   void ReleaseRenderPassTextures();
-
+  enum BoundGeometry { NO_BINDING, SHARED_BINDING, CLIPPED_BINDING };
+  void PrepareGeometry(BoundGeometry geometry_to_bind);
   void SetStencilEnabled(bool enabled);
   bool stencil_enabled() const { return stencil_shadow_; }
   void SetBlendEnabled(bool enabled);
@@ -112,7 +114,9 @@
                      bool draw_rect_covers_full_surface) override;
   void ClearFramebuffer(DrawingFrame* frame,
                         bool has_external_stencil_test) override;
-  void DoDrawQuad(DrawingFrame* frame, const class DrawQuad*) override;
+  void DoDrawQuad(DrawingFrame* frame,
+                  const class DrawQuad*,
+                  const gfx::QuadF* draw_region) override;
   void BeginDrawingFrame(DrawingFrame* frame) override;
   void FinishDrawingFrame(DrawingFrame* frame) override;
   bool FlippedFramebuffer(const DrawingFrame* frame) const override;
@@ -132,10 +136,13 @@
   // Inflate the quad and fill edge array for fragment shader.
   // |local_quad| is set to inflated quad. |edge| array is filled with
   // inflated quad's edge data.
-  static void SetupQuadForAntialiasing(const gfx::Transform& device_transform,
-                                       const DrawQuad* quad,
-                                       gfx::QuadF* local_quad,
-                                       float edge[24]);
+  static void SetupQuadForClippingAndAntialiasing(
+      const gfx::Transform& device_transform,
+      const DrawQuad* quad,
+      bool use_aa,
+      const gfx::QuadF* clip_region,
+      gfx::QuadF* local_quad,
+      float edge[24]);
 
  private:
   friend class GLRendererShaderPixelTest;
@@ -144,7 +151,8 @@
   static void ToGLMatrix(float* gl_matrix, const gfx::Transform& transform);
 
   void DrawCheckerboardQuad(const DrawingFrame* frame,
-                            const CheckerboardDrawQuad* quad);
+                            const CheckerboardDrawQuad* quad,
+                            const gfx::QuadF* clip_region);
   void DrawDebugBorderQuad(const DrawingFrame* frame,
                            const DebugBorderDrawQuad* quad);
   static bool IsDefaultBlendMode(SkXfermode::Mode blend_mode) {
@@ -158,6 +166,7 @@
       DrawingFrame* frame,
       const RenderPassDrawQuad* quad,
       const gfx::Transform& contents_device_transform,
+      const gfx::QuadF* clip_region,
       bool use_aa);
   scoped_ptr<ScopedResource> GetBackdropTexture(const gfx::Rect& bounding_rect);
 
@@ -168,34 +177,56 @@
       const RenderPassDrawQuad* quad,
       ScopedResource* background_texture);
 
-  void DrawRenderPassQuad(DrawingFrame* frame, const RenderPassDrawQuad* quad);
+  void DrawRenderPassQuad(DrawingFrame* frame,
+                          const RenderPassDrawQuad* quadi,
+                          const gfx::QuadF* clip_region);
   void DrawSolidColorQuad(const DrawingFrame* frame,
-                          const SolidColorDrawQuad* quad);
+                          const SolidColorDrawQuad* quad,
+                          const gfx::QuadF* clip_region);
   void DrawStreamVideoQuad(const DrawingFrame* frame,
-                           const StreamVideoDrawQuad* quad);
+                           const StreamVideoDrawQuad* quad,
+                           const gfx::QuadF* clip_region);
+  void DrawTextureQuad(const DrawingFrame* frame,
+                       const TextureDrawQuad* quad,
+                       const gfx::QuadF* clip_region);
   void EnqueueTextureQuad(const DrawingFrame* frame,
-                          const TextureDrawQuad* quad);
-  void FlushTextureQuadCache();
+                          const TextureDrawQuad* quad,
+                          const gfx::QuadF* clip_region);
+  void FlushTextureQuadCache(BoundGeometry flush_binding);
   void DrawIOSurfaceQuad(const DrawingFrame* frame,
-                         const IOSurfaceDrawQuad* quad);
-  void DrawTileQuad(const DrawingFrame* frame, const TileDrawQuad* quad);
+                         const IOSurfaceDrawQuad* quad,
+                         const gfx::QuadF* clip_region);
+  void DrawTileQuad(const DrawingFrame* frame,
+                    const TileDrawQuad* quad,
+                    const gfx::QuadF* clip_region);
   void DrawContentQuad(const DrawingFrame* frame,
                        const ContentDrawQuadBase* quad,
-                       ResourceProvider::ResourceId resource_id);
+                       ResourceProvider::ResourceId resource_id,
+                       const gfx::QuadF* clip_region);
   void DrawContentQuadAA(const DrawingFrame* frame,
                          const ContentDrawQuadBase* quad,
                          ResourceProvider::ResourceId resource_id,
-                         const gfx::Transform& device_transform);
+                         const gfx::Transform& device_transform,
+                         const gfx::QuadF* clip_region);
   void DrawContentQuadNoAA(const DrawingFrame* frame,
                            const ContentDrawQuadBase* quad,
-                           ResourceProvider::ResourceId resource_id);
+                           ResourceProvider::ResourceId resource_id,
+                           const gfx::QuadF* clip_region);
   void DrawYUVVideoQuad(const DrawingFrame* frame,
-                        const YUVVideoDrawQuad* quad);
+                        const YUVVideoDrawQuad* quad,
+                        const gfx::QuadF* clip_region);
   void DrawPictureQuad(const DrawingFrame* frame,
-                       const PictureDrawQuad* quad);
+                       const PictureDrawQuad* quad,
+                       const gfx::QuadF* clip_region);
 
   void SetShaderOpacity(float opacity, int alpha_location);
   void SetShaderQuadF(const gfx::QuadF& quad, int quad_location);
+  void DrawQuadGeometryClippedByQuadF(const DrawingFrame* frame,
+                                      const gfx::Transform& draw_transform,
+                                      const gfx::RectF& quad_rect,
+                                      const gfx::QuadF& clipping_region_quad,
+                                      int matrix_location,
+                                      const float uv[8]);
   void DrawQuadGeometry(const DrawingFrame* frame,
                         const gfx::Transform& draw_transform,
                         const gfx::RectF& quad_rect,
@@ -237,7 +268,8 @@
 
   unsigned offscreen_framebuffer_id_;
 
-  scoped_ptr<GeometryBinding> shared_geometry_;
+  scoped_ptr<StaticGeometryBinding> shared_geometry_;
+  scoped_ptr<DynamicGeometryBinding> clipped_geometry_;
   gfx::QuadF shared_geometry_quad_;
 
   // This block of bindings defines all of the programs used by the compositor
@@ -480,7 +512,7 @@
 
   SkBitmap on_demand_tile_raster_bitmap_;
   ResourceProvider::ResourceId on_demand_tile_raster_resource_id_;
-
+  BoundGeometry bound_geometry_;
   DISALLOW_COPY_AND_ASSIGN(GLRenderer);
 };
 
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 5590ec3..9090621 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -775,7 +775,10 @@
                    0),
         expect_overlays_(false) {}
 
-  MOCK_METHOD2(DoDrawQuad, void(DrawingFrame* frame, const DrawQuad* quad));
+  MOCK_METHOD3(DoDrawQuad,
+               void(DrawingFrame* frame,
+                    const DrawQuad* quad,
+                    const gfx::QuadF* draw_region));
 
   using GLRenderer::BeginDrawingFrame;
 
@@ -875,7 +878,7 @@
 
   // Candidate pass was taken out and extra skipped pass added,
   // so only draw 2 quads.
-  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2);
+  EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(2);
   EXPECT_CALL(scheduler_,
               Schedule(1,
                        gfx::OVERLAY_TRANSFORM_NONE,
@@ -913,7 +916,7 @@
   pass_list.push_back(pass.Pass());
 
   // 3 quads in the pass, all should draw.
-  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
+  EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3);
   EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
   renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
 
@@ -946,7 +949,7 @@
   pass_list.push_back(pass.Pass());
 
   // Should see no overlays.
-  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
+  EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3);
   EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
   renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
 
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index 81ad842..ebda8d6 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -110,6 +110,52 @@
                FilterOperations());  // background filters
 }
 
+void CreateTestTwoColoredTextureDrawQuad(const gfx::Rect& rect,
+                                         SkColor texel_color,
+                                         SkColor texel_stripe_color,
+                                         SkColor background_color,
+                                         bool premultiplied_alpha,
+                                         const SharedQuadState* shared_state,
+                                         ResourceProvider* resource_provider,
+                                         RenderPass* render_pass) {
+  SkPMColor pixel_color = premultiplied_alpha
+                              ? SkPreMultiplyColor(texel_color)
+                              : SkPackARGB32NoCheck(SkColorGetA(texel_color),
+                                                    SkColorGetR(texel_color),
+                                                    SkColorGetG(texel_color),
+                                                    SkColorGetB(texel_color));
+  SkPMColor pixel_stripe_color =
+      premultiplied_alpha
+          ? SkPreMultiplyColor(texel_stripe_color)
+          : SkPackARGB32NoCheck(SkColorGetA(texel_stripe_color),
+                                SkColorGetR(texel_stripe_color),
+                                SkColorGetG(texel_stripe_color),
+                                SkColorGetB(texel_stripe_color));
+  std::vector<uint32_t> pixels(rect.size().GetArea(), pixel_color);
+  for (int i = rect.height() / 4; i < (rect.height() * 3 / 4); ++i) {
+    for (int k = rect.width() / 4; k < (rect.width() * 3 / 4); ++k) {
+      pixels[i * rect.width() + k] = pixel_stripe_color;
+    }
+  }
+  ResourceProvider::ResourceId resource = resource_provider->CreateResource(
+      rect.size(), GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
+      RGBA_8888);
+  resource_provider->SetPixels(resource,
+                               reinterpret_cast<uint8_t*>(&pixels.front()),
+                               rect, rect, gfx::Vector2d());
+
+  float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+  const gfx::PointF uv_top_left(0.0f, 0.0f);
+  const gfx::PointF uv_bottom_right(1.0f, 1.0f);
+  const bool flipped = false;
+  const bool nearest_neighbor = false;
+  TextureDrawQuad* quad =
+      render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
+  quad->SetNew(shared_state, rect, gfx::Rect(), rect, resource,
+               premultiplied_alpha, uv_top_left, uv_bottom_right,
+               background_color, vertex_opacity, flipped, nearest_neighbor);
+}
+
 void CreateTestTextureDrawQuad(const gfx::Rect& rect,
                                SkColor texel_color,
                                SkColor background_color,
@@ -134,20 +180,216 @@
 
   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
 
+  const gfx::PointF uv_top_left(0.0f, 0.0f);
+  const gfx::PointF uv_bottom_right(1.0f, 1.0f);
+  const bool flipped = false;
+  const bool nearest_neighbor = false;
   TextureDrawQuad* quad =
       render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
-  quad->SetNew(shared_state,
-               rect,
-               gfx::Rect(),
-               rect,
-               resource,
-               premultiplied_alpha,
-               gfx::PointF(0.0f, 0.0f),  // uv_top_left
-               gfx::PointF(1.0f, 1.0f),  // uv_bottom_right
-               background_color,
-               vertex_opacity,
-               false,   // flipped
-               false);  // nearest_neighbor
+  quad->SetNew(shared_state, rect, gfx::Rect(), rect, resource,
+               premultiplied_alpha, uv_top_left, uv_bottom_right,
+               background_color, vertex_opacity, flipped, nearest_neighbor);
+}
+
+void CreateTestYUVVideoDrawQuad_FromVideoFrame(
+    const SharedQuadState* shared_state,
+    scoped_refptr<media::VideoFrame> video_frame,
+    uint8 alpha_value,
+    const gfx::RectF& tex_coord_rect,
+    RenderPass* render_pass,
+    VideoResourceUpdater* video_resource_updater,
+    const gfx::Rect& rect,
+    ResourceProvider* resource_provider) {
+  const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A);
+  const YUVVideoDrawQuad::ColorSpace color_space =
+      (video_frame->format() == media::VideoFrame::YV12J
+           ? YUVVideoDrawQuad::JPEG
+           : YUVVideoDrawQuad::REC_601);
+  const gfx::Rect opaque_rect(0, 0, 0, 0);
+
+  if (with_alpha) {
+    memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value,
+           video_frame->stride(media::VideoFrame::kAPlane) *
+               video_frame->rows(media::VideoFrame::kAPlane));
+  }
+
+  VideoFrameExternalResources resources =
+      video_resource_updater->CreateExternalResourcesFromVideoFrame(
+          video_frame);
+
+  EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
+  EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
+            resources.mailboxes.size());
+  EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
+            resources.release_callbacks.size());
+
+  ResourceProvider::ResourceId y_resource =
+      resource_provider->CreateResourceFromTextureMailbox(
+          resources.mailboxes[media::VideoFrame::kYPlane],
+          SingleReleaseCallbackImpl::Create(
+              resources.release_callbacks[media::VideoFrame::kYPlane]));
+  ResourceProvider::ResourceId u_resource =
+      resource_provider->CreateResourceFromTextureMailbox(
+          resources.mailboxes[media::VideoFrame::kUPlane],
+          SingleReleaseCallbackImpl::Create(
+              resources.release_callbacks[media::VideoFrame::kUPlane]));
+  ResourceProvider::ResourceId v_resource =
+      resource_provider->CreateResourceFromTextureMailbox(
+          resources.mailboxes[media::VideoFrame::kVPlane],
+          SingleReleaseCallbackImpl::Create(
+              resources.release_callbacks[media::VideoFrame::kVPlane]));
+  ResourceProvider::ResourceId a_resource = 0;
+  if (with_alpha) {
+    a_resource = resource_provider->CreateResourceFromTextureMailbox(
+        resources.mailboxes[media::VideoFrame::kAPlane],
+        SingleReleaseCallbackImpl::Create(
+            resources.release_callbacks[media::VideoFrame::kAPlane]));
+  }
+
+  YUVVideoDrawQuad* yuv_quad =
+      render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
+  yuv_quad->SetNew(shared_state, rect, opaque_rect, rect, tex_coord_rect,
+                   video_frame->coded_size(), y_resource, u_resource,
+                   v_resource, a_resource, color_space);
+}
+
+void CreateTestYUVVideoDrawQuad_Striped(
+    const SharedQuadState* shared_state,
+    media::VideoFrame::Format format,
+    bool is_transparent,
+    const gfx::RectF& tex_coord_rect,
+    RenderPass* render_pass,
+    VideoResourceUpdater* video_resource_updater,
+    const gfx::Rect& rect,
+    ResourceProvider* resource_provider) {
+  scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
+      format, rect.size(), rect, rect.size(), base::TimeDelta());
+
+  // YUV values representing a striped pattern, for validating texture
+  // coordinates for sampling.
+  uint8_t y_value = 0;
+  uint8_t u_value = 0;
+  uint8_t v_value = 0;
+  for (int i = 0; i < video_frame->rows(media::VideoFrame::kYPlane); ++i) {
+    uint8_t* y_row = video_frame->data(media::VideoFrame::kYPlane) +
+                     video_frame->stride(media::VideoFrame::kYPlane) * i;
+    for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kYPlane);
+         ++j) {
+      y_row[j] = (y_value += 1);
+    }
+  }
+  for (int i = 0; i < video_frame->rows(media::VideoFrame::kUPlane); ++i) {
+    uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) +
+                     video_frame->stride(media::VideoFrame::kUPlane) * i;
+    uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) +
+                     video_frame->stride(media::VideoFrame::kVPlane) * i;
+    for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane);
+         ++j) {
+      u_row[j] = (u_value += 3);
+      v_row[j] = (v_value += 5);
+    }
+  }
+  uint8 alpha_value = is_transparent ? 0 : 128;
+  CreateTestYUVVideoDrawQuad_FromVideoFrame(
+      shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
+      video_resource_updater, rect, resource_provider);
+}
+
+// Creates a video frame of size background_size filled with yuv_background,
+// and then draws a foreground rectangle in a different color on top of
+// that. The foreground rectangle must have coordinates that are divisible
+// by 2 because YUV is a block format.
+void CreateTestYUVVideoDrawQuad_TwoColor(
+    const SharedQuadState* shared_state,
+    media::VideoFrame::Format format,
+    bool is_transparent,
+    const gfx::RectF& tex_coord_rect,
+    const gfx::Size& background_size,
+    uint8 y_background,
+    uint8 u_background,
+    uint8 v_background,
+    const gfx::Rect& foreground_rect,
+    uint8 y_foreground,
+    uint8 u_foreground,
+    uint8 v_foreground,
+    RenderPass* render_pass,
+    VideoResourceUpdater* video_resource_updater,
+    ResourceProvider* resource_provider) {
+  const gfx::Rect rect(background_size);
+
+  scoped_refptr<media::VideoFrame> video_frame =
+      media::VideoFrame::CreateFrame(format, background_size, foreground_rect,
+                                     foreground_rect.size(), base::TimeDelta());
+
+  int planes[] = {media::VideoFrame::kYPlane,
+                  media::VideoFrame::kUPlane,
+                  media::VideoFrame::kVPlane};
+  uint8 yuv_background[] = {y_background, u_background, v_background};
+  uint8 yuv_foreground[] = {y_foreground, u_foreground, v_foreground};
+  int sample_size[] = {1, 2, 2};
+
+  for (int i = 0; i < 3; ++i) {
+    memset(video_frame->data(planes[i]), yuv_background[i],
+           video_frame->stride(planes[i]) * video_frame->rows(planes[i]));
+  }
+
+  for (int i = 0; i < 3; ++i) {
+    // Since yuv encoding uses block encoding, widths have to be divisible
+    // by the sample size in order for this function to behave properly.
+    DCHECK_EQ(foreground_rect.x() % sample_size[i], 0);
+    DCHECK_EQ(foreground_rect.y() % sample_size[i], 0);
+    DCHECK_EQ(foreground_rect.width() % sample_size[i], 0);
+    DCHECK_EQ(foreground_rect.height() % sample_size[i], 0);
+
+    gfx::Rect sample_rect(foreground_rect.x() / sample_size[i],
+                          foreground_rect.y() / sample_size[i],
+                          foreground_rect.width() / sample_size[i],
+                          foreground_rect.height() / sample_size[i]);
+    for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) {
+      for (int x = sample_rect.x(); x < sample_rect.right(); ++x) {
+        size_t offset = y * video_frame->stride(planes[i]) + x;
+        video_frame->data(planes[i])[offset] = yuv_foreground[i];
+      }
+    }
+  }
+
+  uint8 alpha_value = 255;
+  CreateTestYUVVideoDrawQuad_FromVideoFrame(
+      shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
+      video_resource_updater, rect, resource_provider);
+}
+
+void CreateTestYUVVideoDrawQuad_Solid(
+    const SharedQuadState* shared_state,
+    media::VideoFrame::Format format,
+    bool is_transparent,
+    const gfx::RectF& tex_coord_rect,
+    uint8 y,
+    uint8 u,
+    uint8 v,
+    RenderPass* render_pass,
+    VideoResourceUpdater* video_resource_updater,
+    const gfx::Rect& rect,
+    ResourceProvider* resource_provider) {
+  scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
+      format, rect.size(), rect, rect.size(), base::TimeDelta());
+
+  // YUV values of a solid, constant, color. Useful for testing that color
+  // space/color range are being handled properly.
+  memset(video_frame->data(media::VideoFrame::kYPlane), y,
+         video_frame->stride(media::VideoFrame::kYPlane) *
+             video_frame->rows(media::VideoFrame::kYPlane));
+  memset(video_frame->data(media::VideoFrame::kUPlane), u,
+         video_frame->stride(media::VideoFrame::kUPlane) *
+             video_frame->rows(media::VideoFrame::kUPlane));
+  memset(video_frame->data(media::VideoFrame::kVPlane), v,
+         video_frame->stride(media::VideoFrame::kVPlane) *
+             video_frame->rows(media::VideoFrame::kVPlane));
+
+  uint8 alpha_value = is_transparent ? 0 : 128;
+  CreateTestYUVVideoDrawQuad_FromVideoFrame(
+      shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
+      video_resource_updater, rect, resource_provider);
 }
 
 typedef ::testing::Types<GLRenderer,
@@ -322,6 +564,278 @@
       FuzzyPixelOffByOneComparator(true)));
 }
 
+template <typename QuadType>
+static const base::FilePath::CharType* IntersectingQuadImage() {
+  return FILE_PATH_LITERAL("intersecting_blue_green_squares.png");
+}
+template <>
+const base::FilePath::CharType* IntersectingQuadImage<SolidColorDrawQuad>() {
+  return FILE_PATH_LITERAL("intersecting_blue_green.png");
+}
+template <>
+const base::FilePath::CharType* IntersectingQuadImage<YUVVideoDrawQuad>() {
+  return FILE_PATH_LITERAL("intersecting_blue_green_squares_video.png");
+}
+
+template <typename TypeParam>
+class IntersectingQuadPixelTest : public RendererPixelTest<TypeParam> {
+ protected:
+  void SetupQuadStateAndRenderPass() {
+    // This sets up a pair of draw quads. They are both rotated
+    // relative to the root plane, they are also rotated relative to each other.
+    // The intersect in the middle at a non-perpendicular angle so that any
+    // errors are hopefully magnified.
+    // The quads should intersect correctly, as in the front quad should only
+    // be partially in front of the back quad, and partially behind.
+
+    viewport_rect_ = gfx::Rect(this->device_viewport_size_);
+    quad_rect_ = gfx::Rect(0, 0, this->device_viewport_size_.width(),
+                           this->device_viewport_size_.height() / 2.0);
+
+    RenderPassId id(1, 1);
+    render_pass_ = CreateTestRootRenderPass(id, viewport_rect_);
+
+    // Create the front quad rotated on the Z and Y axis.
+    gfx::Transform trans;
+    trans.Translate3d(0, 0, 0.707 * this->device_viewport_size_.width() / 2.0);
+    trans.RotateAboutZAxis(45.0);
+    trans.RotateAboutYAxis(45.0);
+    front_quad_state_ =
+        CreateTestSharedQuadState(trans, viewport_rect_, render_pass_.get());
+    front_quad_state_->clip_rect = quad_rect_;
+    // Make sure they end up in a 3d sorting context.
+    front_quad_state_->sorting_context_id = 1;
+
+    // Create the back quad, and rotate on just the y axis. This will intersect
+    // the first quad partially.
+    trans = gfx::Transform();
+    trans.Translate3d(0, 0, -0.707 * this->device_viewport_size_.width() / 2.0);
+    trans.RotateAboutYAxis(-45.0);
+    back_quad_state_ =
+        CreateTestSharedQuadState(trans, viewport_rect_, render_pass_.get());
+    back_quad_state_->sorting_context_id = 1;
+    back_quad_state_->clip_rect = quad_rect_;
+  }
+  template <typename T>
+  void AppendBackgroundAndRunTest(const PixelComparator& comparator) {
+    SharedQuadState* background_quad_state = CreateTestSharedQuadState(
+        gfx::Transform(), viewport_rect_, render_pass_.get());
+    SolidColorDrawQuad* background_quad =
+        render_pass_->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+    background_quad->SetNew(background_quad_state, viewport_rect_,
+                            viewport_rect_, SK_ColorWHITE, false);
+    pass_list_.push_back(render_pass_.Pass());
+    const base::FilePath::CharType* fileName = IntersectingQuadImage<T>();
+    EXPECT_TRUE(
+        this->RunPixelTest(&pass_list_, base::FilePath(fileName), comparator));
+  }
+  template <typename T>
+  T* CreateAndAppendDrawQuad() {
+    return render_pass_->CreateAndAppendDrawQuad<T>();
+  }
+
+  scoped_ptr<RenderPass> render_pass_;
+  gfx::Rect viewport_rect_;
+  SharedQuadState* front_quad_state_;
+  SharedQuadState* back_quad_state_;
+  gfx::Rect quad_rect_;
+  RenderPassList pass_list_;
+};
+
+template <typename TypeParam>
+class IntersectingQuadGLPixelTest
+    : public IntersectingQuadPixelTest<TypeParam> {
+ public:
+  void SetUp() override {
+    IntersectingQuadPixelTest<TypeParam>::SetUp();
+    video_resource_updater_.reset(
+        new VideoResourceUpdater(this->output_surface_->context_provider(),
+                                 this->resource_provider_.get()));
+    video_resource_updater2_.reset(
+        new VideoResourceUpdater(this->output_surface_->context_provider(),
+                                 this->resource_provider_.get()));
+  }
+
+ protected:
+  scoped_ptr<VideoResourceUpdater> video_resource_updater_;
+  scoped_ptr<VideoResourceUpdater> video_resource_updater2_;
+};
+
+template <typename TypeParam>
+class IntersectingQuadSoftwareTest
+    : public IntersectingQuadPixelTest<TypeParam> {};
+
+typedef ::testing::Types<SoftwareRenderer, SoftwareRendererWithExpandedViewport>
+    SoftwareRendererTypes;
+typedef ::testing::Types<GLRenderer, GLRendererWithExpandedViewport>
+    GLRendererTypes;
+
+TYPED_TEST_CASE(IntersectingQuadPixelTest, RendererTypes);
+TYPED_TEST_CASE(IntersectingQuadGLPixelTest, GLRendererTypes);
+TYPED_TEST_CASE(IntersectingQuadSoftwareTest, SoftwareRendererTypes);
+
+TYPED_TEST(IntersectingQuadPixelTest, SolidColorQuads) {
+  this->SetupQuadStateAndRenderPass();
+
+  SolidColorDrawQuad* quad =
+      this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+  SolidColorDrawQuad* quad2 =
+      this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+
+  quad->SetNew(this->front_quad_state_, this->quad_rect_, this->quad_rect_,
+               SK_ColorBLUE, false);
+  quad2->SetNew(this->back_quad_state_, this->quad_rect_, this->quad_rect_,
+                SK_ColorGREEN, false);
+  SCOPED_TRACE("IntersectingSolidColorQuads");
+  this->template AppendBackgroundAndRunTest<SolidColorDrawQuad>(
+      FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
+}
+
+template <typename TypeParam>
+SkColor GetColor(const SkColor& color) {
+  return color;
+}
+
+template <>
+SkColor GetColor<GLRenderer>(const SkColor& color) {
+  return SkColorSetARGB(SkColorGetA(color), SkColorGetB(color),
+                        SkColorGetG(color), SkColorGetR(color));
+}
+template <>
+SkColor GetColor<GLRendererWithExpandedViewport>(const SkColor& color) {
+  return GetColor<GLRenderer>(color);
+}
+
+TYPED_TEST(IntersectingQuadPixelTest, TexturedQuads) {
+  this->SetupQuadStateAndRenderPass();
+  CreateTestTwoColoredTextureDrawQuad(
+      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
+      true, this->front_quad_state_, this->resource_provider_.get(),
+      this->render_pass_.get());
+  CreateTestTwoColoredTextureDrawQuad(
+      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
+      true, this->back_quad_state_, this->resource_provider_.get(),
+      this->render_pass_.get());
+
+  SCOPED_TRACE("IntersectingTexturedQuads");
+  this->template AppendBackgroundAndRunTest<TextureDrawQuad>(
+      FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
+}
+
+TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) {
+  this->SetupQuadStateAndRenderPass();
+  gfx::RectF outer_rect(this->quad_rect_);
+  gfx::RectF inner_rect(this->quad_rect_.x() + (this->quad_rect_.width() / 4),
+                        this->quad_rect_.y() + (this->quad_rect_.height() / 4),
+                        this->quad_rect_.width() / 2,
+                        this->quad_rect_.height() / 2);
+
+  SkPaint black_paint;
+  black_paint.setColor(SK_ColorBLACK);
+  SkPaint blue_paint;
+  blue_paint.setColor(SK_ColorBLUE);
+  SkPaint green_paint;
+  green_paint.setColor(SK_ColorGREEN);
+
+  scoped_ptr<FakePicturePile> blue_recording =
+      FakePicturePile::CreateFilledPile(gfx::Size(1000, 1000),
+                                        this->quad_rect_.size());
+  blue_recording->add_draw_rect_with_paint(outer_rect, black_paint);
+  blue_recording->add_draw_rect_with_paint(inner_rect, blue_paint);
+  blue_recording->RerecordPile();
+  scoped_refptr<FakePicturePileImpl> blue_pile =
+      FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr);
+
+  PictureDrawQuad* blue_quad =
+      this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
+
+  blue_quad->SetNew(this->front_quad_state_, this->quad_rect_, gfx::Rect(),
+                    this->quad_rect_, this->quad_rect_, this->quad_rect_.size(),
+                    false, RGBA_8888, this->quad_rect_, 1.f, blue_pile);
+
+  scoped_ptr<FakePicturePile> green_recording =
+      FakePicturePile::CreateFilledPile(this->quad_rect_.size(),
+                                        this->quad_rect_.size());
+  green_recording->add_draw_rect_with_paint(outer_rect, green_paint);
+  green_recording->add_draw_rect_with_paint(inner_rect, black_paint);
+  green_recording->RerecordPile();
+  scoped_refptr<FakePicturePileImpl> green_pile =
+      FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
+
+  PictureDrawQuad* green_quad =
+      this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
+  green_quad->SetNew(this->back_quad_state_, this->quad_rect_, gfx::Rect(),
+                     this->quad_rect_, this->quad_rect_,
+                     this->quad_rect_.size(), false, RGBA_8888,
+                     this->quad_rect_, 1.f, green_pile);
+  SCOPED_TRACE("IntersectingPictureQuadsPass");
+  this->template AppendBackgroundAndRunTest<PictureDrawQuad>(
+      FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
+}
+
+TYPED_TEST(IntersectingQuadPixelTest, RenderPassQuads) {
+  this->SetupQuadStateAndRenderPass();
+  RenderPassId child_pass_id1(2, 2);
+  RenderPassId child_pass_id2(2, 3);
+  scoped_ptr<RenderPass> child_pass1 =
+      CreateTestRenderPass(child_pass_id1, this->quad_rect_, gfx::Transform());
+  SharedQuadState* child1_quad_state = CreateTestSharedQuadState(
+      gfx::Transform(), this->quad_rect_, child_pass1.get());
+  scoped_ptr<RenderPass> child_pass2 =
+      CreateTestRenderPass(child_pass_id2, this->quad_rect_, gfx::Transform());
+  SharedQuadState* child2_quad_state = CreateTestSharedQuadState(
+      gfx::Transform(), this->quad_rect_, child_pass2.get());
+
+  CreateTestTwoColoredTextureDrawQuad(
+      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
+      true, child1_quad_state, this->resource_provider_.get(),
+      child_pass1.get());
+  CreateTestTwoColoredTextureDrawQuad(
+      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
+      true, child2_quad_state, this->resource_provider_.get(),
+      child_pass2.get());
+
+  CreateTestRenderPassDrawQuad(this->front_quad_state_, this->quad_rect_,
+                               child_pass_id1, this->render_pass_.get());
+  CreateTestRenderPassDrawQuad(this->back_quad_state_, this->quad_rect_,
+                               child_pass_id2, this->render_pass_.get());
+
+  this->pass_list_.push_back(child_pass1.Pass());
+  this->pass_list_.push_back(child_pass2.Pass());
+  SCOPED_TRACE("IntersectingRenderQuadsPass");
+  this->template AppendBackgroundAndRunTest<RenderPassDrawQuad>(
+      FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
+}
+
+TYPED_TEST(IntersectingQuadGLPixelTest, YUVVideoQuads) {
+  this->SetupQuadStateAndRenderPass();
+  gfx::Rect inner_rect(
+      ((this->quad_rect_.x() + (this->quad_rect_.width() / 4)) & ~0xF),
+      ((this->quad_rect_.y() + (this->quad_rect_.height() / 4)) & ~0xF),
+      (this->quad_rect_.width() / 2) & ~0xF,
+      (this->quad_rect_.height() / 2) & ~0xF);
+
+  CreateTestYUVVideoDrawQuad_TwoColor(
+      this->front_quad_state_, media::VideoFrame::YV12J, false,
+      gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(), 0, 128, 128,
+      inner_rect, 29, 255, 107, this->render_pass_.get(),
+      this->video_resource_updater_.get(), this->resource_provider_.get());
+
+  CreateTestYUVVideoDrawQuad_TwoColor(
+      this->back_quad_state_, media::VideoFrame::YV12J, false,
+      gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(), 149, 43, 21,
+      inner_rect, 0, 128, 128, this->render_pass_.get(),
+      this->video_resource_updater2_.get(), this->resource_provider_.get());
+
+  SCOPED_TRACE("IntersectingVideoQuads");
+  this->template AppendBackgroundAndRunTest<YUVVideoDrawQuad>(
+      FuzzyPixelOffByOneComparator(false));
+}
+
 // TODO(skaslev): The software renderer does not support non-premultplied alpha.
 TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithoutBackground) {
   gfx::Rect rect(this->device_viewport_size_);
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index a4b5428..19c4fa3 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -25,6 +25,7 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
 #include "third_party/skia/include/core/SkMatrix.h"
+#include "third_party/skia/include/core/SkPoint.h"
 #include "third_party/skia/include/core/SkShader.h"
 #include "third_party/skia/include/effects/SkLayerRasterizer.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -235,7 +236,13 @@
   return false;
 }
 
-void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) {
+void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame,
+                                  const DrawQuad* quad,
+                                  const gfx::QuadF* draw_region) {
+  if (draw_region) {
+    current_canvas_->save();
+  }
+
   TRACE_EVENT0("cc", "SoftwareRenderer::DoDrawQuad");
   gfx::Transform quad_rect_matrix;
   QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect);
@@ -270,9 +277,31 @@
     current_paint_.setXfermodeMode(SkXfermode::kSrc_Mode);
   }
 
+  if (draw_region) {
+    gfx::QuadF local_draw_region(*draw_region);
+    SkPath draw_region_clip_path;
+    local_draw_region -=
+        gfx::Vector2dF(quad->visible_rect.x(), quad->visible_rect.y());
+    local_draw_region.Scale(1.0f / quad->visible_rect.width(),
+                            1.0f / quad->visible_rect.height());
+    local_draw_region -= gfx::Vector2dF(0.5f, 0.5f);
+
+    SkPoint clip_points[4];
+    QuadFToSkPoints(local_draw_region, clip_points);
+    draw_region_clip_path.addPoly(clip_points, 4, true);
+
+    current_canvas_->clipPath(draw_region_clip_path, SkRegion::kIntersect_Op,
+                              false);
+  }
+
   switch (quad->material) {
     case DrawQuad::CHECKERBOARD:
-      DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad));
+      // TODO(enne) For now since checkerboards shouldn't be part of a 3D
+      // context, clipping regions aren't supported so we skip drawing them
+      // if this becomes the case.
+      if (!draw_region) {
+        DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad));
+      }
       break;
     case DrawQuad::DEBUG_BORDER:
       DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad));
@@ -307,6 +336,9 @@
   }
 
   current_canvas_->resetMatrix();
+  if (draw_region) {
+    current_canvas_->restore();
+  }
 }
 
 void SoftwareRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
diff --git a/cc/output/software_renderer.h b/cc/output/software_renderer.h
index 99868c3..dc8e2fb 100644
--- a/cc/output/software_renderer.h
+++ b/cc/output/software_renderer.h
@@ -52,7 +52,10 @@
                      bool draw_rect_covers_full_surface) override;
   void ClearFramebuffer(DrawingFrame* frame,
                         bool has_external_stencil_test) override;
-  void DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) override;
+
+  void DoDrawQuad(DrawingFrame* frame,
+                  const DrawQuad* quad,
+                  const gfx::QuadF* draw_region) override;
   void BeginDrawingFrame(DrawingFrame* frame) override;
   void FinishDrawingFrame(DrawingFrame* frame) override;
   bool FlippedFramebuffer(const DrawingFrame* frame) const override;
diff --git a/cc/output/static_geometry_binding.cc b/cc/output/static_geometry_binding.cc
new file mode 100644
index 0000000..683db2d
--- /dev/null
+++ b/cc/output/static_geometry_binding.cc
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/output/static_geometry_binding.h"
+
+#include "cc/output/gl_renderer.h"  // For the GLC() macro.
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace cc {
+
+StaticGeometryBinding::StaticGeometryBinding(gpu::gles2::GLES2Interface* gl,
+                                             const gfx::RectF& quad_vertex_rect)
+    : gl_(gl), quad_vertices_vbo_(0), quad_elements_vbo_(0) {
+  GeometryBindingQuad quads[8];
+  GeometryBindingQuadIndex quad_indices[8];
+
+  static_assert(sizeof(GeometryBindingQuad) == 24 * sizeof(float),
+                "struct Quad should be densely packed");
+  static_assert(sizeof(GeometryBindingQuadIndex) == 6 * sizeof(uint16_t),
+                "struct QuadIndex should be densely packed");
+
+  for (size_t i = 0; i < 8; i++) {
+    GeometryBindingVertex v0 = {
+        {quad_vertex_rect.x(), quad_vertex_rect.bottom(), 0.0f},
+        {0.0f, 1.0f},
+        i * 4.0f + 0.0f};
+    GeometryBindingVertex v1 = {
+        {quad_vertex_rect.x(), quad_vertex_rect.y(), 0.0f},
+        {0.0f, 0.0f},
+        i * 4.0f + 1.0f};
+    GeometryBindingVertex v2 = {
+        {quad_vertex_rect.right(), quad_vertex_rect.y(), 0.0f},
+        {1.0f, 0.0f},
+        i * 4.0f + 2.0f};
+    GeometryBindingVertex v3 = {
+        {quad_vertex_rect.right(), quad_vertex_rect.bottom(), 0.0f},
+        {1.0f, 1.0f},
+        i * 4.0f + 3.0f};
+    GeometryBindingQuad x(v0, v1, v2, v3);
+    quads[i] = x;
+    GeometryBindingQuadIndex y(
+        static_cast<uint16>(0 + 4 * i), static_cast<uint16>(1 + 4 * i),
+        static_cast<uint16>(2 + 4 * i), static_cast<uint16>(3 + 4 * i),
+        static_cast<uint16>(0 + 4 * i), static_cast<uint16>(2 + 4 * i));
+    quad_indices[i] = y;
+  }
+
+  GLC(gl_, gl_->GenBuffers(1, &quad_vertices_vbo_));
+  GLC(gl_, gl_->GenBuffers(1, &quad_elements_vbo_));
+
+  GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
+  GLC(gl_, gl_->BufferData(GL_ARRAY_BUFFER, sizeof(GeometryBindingQuad) * 8,
+                           quads, GL_STATIC_DRAW));
+
+  GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
+  GLC(gl_, gl_->BufferData(GL_ELEMENT_ARRAY_BUFFER,
+                           sizeof(GeometryBindingQuadIndex) * 8, &quad_indices,
+                           GL_STATIC_DRAW));
+}
+
+StaticGeometryBinding::~StaticGeometryBinding() {
+  gl_->DeleteBuffers(1, &quad_vertices_vbo_);
+  gl_->DeleteBuffers(1, &quad_elements_vbo_);
+}
+
+void StaticGeometryBinding::PrepareForDraw() {
+  SetupGLContext(gl_, quad_elements_vbo_, quad_vertices_vbo_);
+}
+
+}  // namespace cc
diff --git a/cc/output/static_geometry_binding.h b/cc/output/static_geometry_binding.h
new file mode 100644
index 0000000..bd6bfcc
--- /dev/null
+++ b/cc/output/static_geometry_binding.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 CC_OUTPUT_STATIC_GEOMETRY_BINDING_H_
+#define CC_OUTPUT_STATIC_GEOMETRY_BINDING_H_
+
+#include "cc/output/geometry_binding.h"
+
+using gpu::gles2::GLES2Interface;
+
+namespace cc {
+
+class StaticGeometryBinding {
+ public:
+  StaticGeometryBinding(gpu::gles2::GLES2Interface* gl,
+                        const gfx::RectF& quad_vertex_rect);
+  ~StaticGeometryBinding();
+
+  void PrepareForDraw();
+
+ private:
+  gpu::gles2::GLES2Interface* gl_;
+
+  GLuint quad_vertices_vbo_;
+  GLuint quad_elements_vbo_;
+
+  DISALLOW_COPY_AND_ASSIGN(StaticGeometryBinding);
+};
+
+}  // namespace cc
+
+#endif  // CC_OUTPUT_STATIC_GEOMETRY_BINDING_H_
diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h
index 8dcd2b9..f80e06c 100644
--- a/cc/quads/content_draw_quad_base.h
+++ b/cc/quads/content_draw_quad_base.h
@@ -8,7 +8,6 @@
 #include "base/memory/scoped_ptr.h"
 #include "cc/base/cc_export.h"
 #include "cc/quads/draw_quad.h"
-#include "third_party/khronos/GLES2/gl2.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/size.h"
 
diff --git a/cc/quads/draw_polygon.cc b/cc/quads/draw_polygon.cc
index 026be2c..6544b64 100644
--- a/cc/quads/draw_polygon.cc
+++ b/cc/quads/draw_polygon.cc
@@ -12,7 +12,7 @@
 namespace {
 // This allows for some imperfection in the normal comparison when checking if
 // two pieces of geometry are coplanar.
-static const float coplanar_dot_epsilon = 0.01f;
+static const float coplanar_dot_epsilon = 0.001f;
 // This threshold controls how "thick" a plane is. If a point's distance is
 // <= |compare_threshold|, then it is considered on the plane. Only when this
 // boundary is crossed do we consider doing splitting.
@@ -25,21 +25,23 @@
 // points that SHOULD be intersecting the "thick plane", but actually fail to
 // test positively for it because |split_threshold| allowed them to be outside
 // this range.
+// This is really supposd to be compare_threshold / 2.0f, but that would
+// create another static initializer.
 static const float split_threshold = 0.5f;
+
+static const float normalized_threshold = 0.001f;
 }  // namespace
 
 namespace cc {
 
-gfx::Vector3dF DrawPolygon::default_normal = gfx::Vector3dF(0.0f, 0.0f, -1.0f);
-
 DrawPolygon::DrawPolygon() {
 }
 
-DrawPolygon::DrawPolygon(DrawQuad* original,
+DrawPolygon::DrawPolygon(const DrawQuad* original,
                          const std::vector<gfx::Point3F>& in_points,
                          const gfx::Vector3dF& normal,
                          int draw_order_index)
-    : order_index_(draw_order_index), original_ref_(original) {
+    : order_index_(draw_order_index), original_ref_(original), is_split_(true) {
   for (size_t i = 0; i < in_points.size(); i++) {
     points_.push_back(in_points[i]);
   }
@@ -49,12 +51,14 @@
 // This takes the original DrawQuad that this polygon should be based on,
 // a visible content rect to make the 4 corner points from, and a transformation
 // to move it and its normal into screen space.
-DrawPolygon::DrawPolygon(DrawQuad* original_ref,
+DrawPolygon::DrawPolygon(const DrawQuad* original_ref,
                          const gfx::RectF& visible_content_rect,
                          const gfx::Transform& transform,
                          int draw_order_index)
-    : order_index_(draw_order_index), original_ref_(original_ref) {
-  normal_ = default_normal;
+    : normal_(0.0f, 0.0f, 1.0f),
+      order_index_(draw_order_index),
+      original_ref_(original_ref),
+      is_split_(false) {
   gfx::Point3F points[8];
   int num_vertices_in_clipped_quad;
   gfx::QuadF send_quad(visible_content_rect);
@@ -97,6 +101,9 @@
 // Assumes that layers are split and there are no intersecting planes.
 BspCompareResult DrawPolygon::SideCompare(const DrawPolygon& a,
                                           const DrawPolygon& b) {
+  // Let's make sure that both of these are normalized.
+  DCHECK_GE(normalized_threshold, std::abs(a.normal_.LengthSquared() - 1.0f));
+  DCHECK_GE(normalized_threshold, std::abs(b.normal_.LengthSquared() - 1.0f));
   // Right away let's check if they're coplanar
   double dot = gfx::DotProduct(a.normal_, b.normal_);
   float sign = 0.0f;
@@ -105,7 +112,7 @@
   if (std::abs(dot) >= 1.0f - coplanar_dot_epsilon) {
     normal_match = true;
     // The normals are matching enough that we only have to test one point.
-    sign = gfx::DotProduct(a.points_[0] - b.points_[0], b.normal_);
+    sign = b.SignedPointDistance(a.points_[0]);
     // Is it on either side of the splitter?
     if (sign < -compare_threshold) {
       return BSP_BACK;
@@ -168,7 +175,7 @@
 
   // The case where one vertex lies on the thick-plane and the other
   // is outside of it.
-  if (std::abs(start_distance) < distance_threshold &&
+  if (std::abs(start_distance) <= distance_threshold &&
       std::abs(end_distance) > distance_threshold) {
     intersection->SetPoint(line_start.x(), line_start.y(), line_start.z());
     return true;
@@ -270,7 +277,7 @@
         break;
       }
     }
-    if (current_vertex++ > points_size) {
+    if (current_vertex++ > (points_size)) {
       break;
     }
   }
@@ -284,6 +291,7 @@
 
   // First polygon.
   out_points[0].push_back(intersections[0]);
+  DCHECK_GE(vertex_before[1], start1);
   for (size_t i = start1; i <= vertex_before[1]; i++) {
     out_points[0].push_back(points_[i]);
     --points_remaining;
@@ -306,6 +314,9 @@
   scoped_ptr<DrawPolygon> poly2(
       new DrawPolygon(original_ref_, out_points[1], normal_, order_index_));
 
+  DCHECK_GE(poly1->points().size(), 3u);
+  DCHECK_GE(poly2->points().size(), 3u);
+
   if (SideCompare(*poly1, splitter) == BSP_FRONT) {
     *front = poly1.Pass();
     *back = poly2.Pass();
diff --git a/cc/quads/draw_polygon.h b/cc/quads/draw_polygon.h
index 32643ee..b94ff1e 100644
--- a/cc/quads/draw_polygon.h
+++ b/cc/quads/draw_polygon.h
@@ -24,11 +24,11 @@
   DrawPolygon();
   ~DrawPolygon();
 
-  DrawPolygon(DrawQuad* original_ref,
+  DrawPolygon(const DrawQuad* original_ref,
               const std::vector<gfx::Point3F>& in_points,
               const gfx::Vector3dF& normal,
               int draw_order_index = 0);
-  DrawPolygon(DrawQuad* original_ref,
+  DrawPolygon(const DrawQuad* original_ref,
               const gfx::RectF& visible_content_rect,
               const gfx::Transform& transform,
               int draw_order_index = 0);
@@ -56,11 +56,9 @@
   const gfx::Vector3dF& normal() const { return normal_; }
   const DrawQuad* original_ref() const { return original_ref_; }
   int order_index() const { return order_index_; }
-
+  bool is_split() const { return is_split_; }
   scoped_ptr<DrawPolygon> CreateCopy();
 
-  static gfx::Vector3dF default_normal;
-
  private:
   void ApplyTransform(const gfx::Transform& transform);
   void ApplyTransformToNormal(const gfx::Transform& transform);
@@ -76,7 +74,8 @@
   // we need.
   // This DrawQuad is owned by the caller and its lifetime must be preserved
   // as long as this DrawPolygon is alive.
-  DrawQuad* original_ref_;
+  const DrawQuad* original_ref_;
+  bool is_split_;
 };
 
 }  // namespace cc
diff --git a/cc/quads/draw_quad.cc b/cc/quads/draw_quad.cc
index 8b8fd78..ac1b43e 100644
--- a/cc/quads/draw_quad.cc
+++ b/cc/quads/draw_quad.cc
@@ -25,9 +25,7 @@
 namespace cc {
 
 DrawQuad::DrawQuad()
-    : material(INVALID),
-      needs_blending(false),
-      shared_quad_state() {
+    : material(INVALID), needs_blending(false), shared_quad_state(0) {
 }
 
 void DrawQuad::SetAll(const SharedQuadState* shared_quad_state,
diff --git a/cc/quads/tile_draw_quad.cc b/cc/quads/tile_draw_quad.cc
index fbdae88..aa8f748 100644
--- a/cc/quads/tile_draw_quad.cc
+++ b/cc/quads/tile_draw_quad.cc
@@ -7,7 +7,6 @@
 #include "base/logging.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "base/values.h"
-#include "third_party/khronos/GLES2/gl2.h"
 
 namespace cc {
 
diff --git a/cc/resources/display_item_list.cc b/cc/resources/display_item_list.cc
index ac6ab57..48f8c66 100644
--- a/cc/resources/display_item_list.cc
+++ b/cc/resources/display_item_list.cc
@@ -10,8 +10,12 @@
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/picture_debug_util.h"
+#include "cc/debug/traced_picture.h"
+#include "cc/debug/traced_value.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkDrawPictureCallback.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/utils/SkPictureUtils.h"
 #include "ui/gfx/skia_util.h"
 
 namespace cc {
@@ -30,12 +34,46 @@
 void DisplayItemList::Raster(SkCanvas* canvas,
                              SkDrawPictureCallback* callback,
                              float contents_scale) const {
-  canvas->save();
-  canvas->scale(contents_scale, contents_scale);
-  for (size_t i = 0; i < items_.size(); ++i) {
-    items_[i]->Raster(canvas, callback);
+  if (!picture_) {
+    canvas->save();
+    canvas->scale(contents_scale, contents_scale);
+    for (size_t i = 0; i < items_.size(); ++i) {
+      items_[i]->Raster(canvas, callback);
+    }
+    canvas->restore();
+  } else {
+    DCHECK(picture_);
+
+    canvas->save();
+    canvas->scale(contents_scale, contents_scale);
+    if (callback) {
+      // If we have a callback, we need to call |draw()|, |drawPicture()|
+      // doesn't take a callback.  This is used by |AnalysisCanvas| to early
+      // out.
+      picture_->playback(canvas, callback);
+    } else {
+      // Prefer to call |drawPicture()| on the canvas since it could place the
+      // entire picture on the canvas instead of parsing the skia operations.
+      canvas->drawPicture(picture_.get());
+    }
+    canvas->restore();
   }
-  canvas->restore();
+}
+
+void DisplayItemList::CreateAndCacheSkPicture() {
+  // Convert to an SkPicture for faster rasterization. Code is identical to
+  // that in Picture::Record.
+  SkRTreeFactory factory;
+  SkPictureRecorder recorder;
+  skia::RefPtr<SkCanvas> canvas;
+  canvas = skia::SharePtr(recorder.beginRecording(
+      layer_rect_.width(), layer_rect_.height(), &factory));
+  canvas->translate(-layer_rect_.x(), -layer_rect_.y());
+  canvas->clipRect(gfx::RectToSkRect(layer_rect_));
+  for (size_t i = 0; i < items_.size(); ++i)
+    items_[i]->Raster(canvas.get(), NULL);
+  picture_ = skia::AdoptRef(recorder.endRecording());
+  DCHECK(picture_);
 }
 
 void DisplayItemList::AppendItem(scoped_ptr<DisplayItem> item) {
@@ -62,6 +100,9 @@
     total_size += item->PictureMemoryUsage();
   }
 
+  if (picture_)
+    total_size += SkPictureUtils::ApproximateBytesUsed(picture_.get());
+
   return total_size;
 }
 
diff --git a/cc/resources/display_item_list.h b/cc/resources/display_item_list.h
index e16b8b8..39694d7 100644
--- a/cc/resources/display_item_list.h
+++ b/cc/resources/display_item_list.h
@@ -11,6 +11,8 @@
 #include "cc/base/cc_export.h"
 #include "cc/base/scoped_ptr_vector.h"
 #include "cc/resources/display_item.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkPicture.h"
 #include "ui/gfx/geometry/rect.h"
 
 class SkCanvas;
@@ -32,6 +34,8 @@
   void set_layer_rect(gfx::Rect layer_rect) { layer_rect_ = layer_rect; }
   gfx::Rect layer_rect() const { return layer_rect_; }
 
+  void CreateAndCacheSkPicture();
+
   bool IsSuitableForGpuRasterization() const;
   int ApproximateOpCount() const;
   size_t PictureMemoryUsage() const;
@@ -44,6 +48,8 @@
   DisplayItemList();
   ~DisplayItemList();
   ScopedPtrVector<DisplayItem> items_;
+  skia::RefPtr<SkPicture> picture_;
+
   gfx::Rect layer_rect_;
   bool is_suitable_for_gpu_rasterization_;
   int approximate_op_count_;
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc
index 8d2dc3e..367b23d 100644
--- a/cc/resources/display_list_recording_source.cc
+++ b/cc/resources/display_list_recording_source.cc
@@ -112,6 +112,9 @@
 
   DetermineIfSolidColor();
   display_list_->EmitTraceSnapshot();
+
+  display_list_->CreateAndCacheSkPicture();
+
   return true;
 }
 
diff --git a/cc/resources/gpu_rasterizer.cc b/cc/resources/gpu_rasterizer.cc
index 6e318ed..d810386 100644
--- a/cc/resources/gpu_rasterizer.cc
+++ b/cc/resources/gpu_rasterizer.cc
@@ -120,9 +120,16 @@
     write_lock->InitSkSurface(use_worker_context, use_distance_field_text,
                               raster_source->CanUseLCDText(),
                               msaa_sample_count_);
+
+    SkSurface* sk_surface = write_lock->sk_surface();
+
+    // Allocating an SkSurface will fail after a lost context.  Pretend we
+    // rasterized, as the contents of the resource don't matter anymore.
+    if (!sk_surface)
+      return;
+
     SkMultiPictureDraw multi_picture_draw;
-    multi_picture_draw.add(write_lock->sk_surface()->getCanvas(),
-                           picture.get());
+    multi_picture_draw.add(sk_surface->getCanvas(), picture.get());
     multi_picture_draw.draw(msaa_sample_count_ > 0);
     write_lock->ReleaseSkSurface();
   }
@@ -169,6 +176,9 @@
                       msaa_sample_count_);
 
   SkSurface* sk_surface = lock->sk_surface();
+
+  // Allocating an SkSurface will fail after a lost context.  Pretend we
+  // rasterized, as the contents of the resource don't matter anymore.
   if (!sk_surface)
     return;
 
diff --git a/cc/resources/layer_quad.cc b/cc/resources/layer_quad.cc
index 38ec7b3..ba92314 100644
--- a/cc/resources/layer_quad.cc
+++ b/cc/resources/layer_quad.cc
@@ -10,8 +10,11 @@
 namespace cc {
 
 LayerQuad::Edge::Edge(const gfx::PointF& p, const gfx::PointF& q) {
-  DCHECK(p != q);
-
+  if (p == q) {
+    degenerate_ = true;
+    return;
+  }
+  degenerate_ = false;
   gfx::Vector2dF tangent(p.y() - q.y(), q.x() - p.x());
   float cross2 = p.x() * q.y() - q.x() * p.y();
 
@@ -43,6 +46,22 @@
       bottom_(bottom) {}
 
 gfx::QuadF LayerQuad::ToQuadF() const {
+  if (left_.degenerate()) {
+    return gfx::QuadF(top_.Intersect(bottom_), top_.Intersect(right_),
+                      right_.Intersect(bottom_), bottom_.Intersect(top_));
+  }
+  if (right_.degenerate()) {
+    return gfx::QuadF(left_.Intersect(top_), top_.Intersect(bottom_),
+                      bottom_.Intersect(top_), bottom_.Intersect(left_));
+  }
+  if (top_.degenerate()) {
+    return gfx::QuadF(left_.Intersect(right_), right_.Intersect(left_),
+                      right_.Intersect(bottom_), bottom_.Intersect(left_));
+  }
+  if (bottom_.degenerate()) {
+    return gfx::QuadF(left_.Intersect(top_), top_.Intersect(right_),
+                      right_.Intersect(left_), left_.Intersect(right_));
+  }
   return gfx::QuadF(left_.Intersect(top_),
                     top_.Intersect(right_),
                     right_.Intersect(bottom_),
@@ -50,18 +69,42 @@
 }
 
 void LayerQuad::ToFloatArray(float flattened[12]) const {
-  flattened[0] = left_.x();
-  flattened[1] = left_.y();
-  flattened[2] = left_.z();
-  flattened[3] = top_.x();
-  flattened[4] = top_.y();
-  flattened[5] = top_.z();
-  flattened[6] = right_.x();
-  flattened[7] = right_.y();
-  flattened[8] = right_.z();
-  flattened[9] = bottom_.x();
-  flattened[10] = bottom_.y();
-  flattened[11] = bottom_.z();
+  if (left_.degenerate()) {
+    flattened[0] = bottom_.x();
+    flattened[1] = bottom_.y();
+    flattened[2] = bottom_.z();
+  } else {
+    flattened[0] = left_.x();
+    flattened[1] = left_.y();
+    flattened[2] = left_.z();
+  }
+  if (top_.degenerate()) {
+    flattened[3] = left_.x();
+    flattened[4] = left_.y();
+    flattened[5] = left_.z();
+  } else {
+    flattened[3] = top_.x();
+    flattened[4] = top_.y();
+    flattened[5] = top_.z();
+  }
+  if (right_.degenerate()) {
+    flattened[6] = top_.x();
+    flattened[7] = top_.y();
+    flattened[8] = top_.z();
+  } else {
+    flattened[6] = right_.x();
+    flattened[7] = right_.y();
+    flattened[8] = right_.z();
+  }
+  if (bottom_.degenerate()) {
+    flattened[9] = right_.x();
+    flattened[10] = right_.y();
+    flattened[11] = right_.z();
+  } else {
+    flattened[9] = bottom_.x();
+    flattened[10] = bottom_.y();
+    flattened[11] = bottom_.z();
+  }
 }
 
 }  // namespace cc
diff --git a/cc/resources/layer_quad.h b/cc/resources/layer_quad.h
index ed1db10..7433645 100644
--- a/cc/resources/layer_quad.h
+++ b/cc/resources/layer_quad.h
@@ -22,7 +22,7 @@
  public:
   class Edge {
    public:
-    Edge() : x_(0), y_(0), z_(0) {}
+    Edge() : x_(0), y_(0), z_(0), degenerate_(false) {}
     Edge(const gfx::PointF& p, const gfx::PointF& q);
 
     float x() const { return x_; }
@@ -57,6 +57,8 @@
     }
     void scale(float s) { scale(s, s, s); }
 
+    bool degenerate() const { return degenerate_; }
+
     gfx::PointF Intersect(const Edge& e) const {
       return gfx::PointF(
           (y() * e.z() - e.y() * z()) / (x() * e.y() - e.x() * y()),
@@ -67,6 +69,7 @@
     float x_;
     float y_;
     float z_;
+    bool degenerate_;
   };
 
   LayerQuad(const Edge& left,
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index 30c5845..867a86a 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -4,9 +4,8 @@
 
 #include "cc/resources/picture.h"
 
-#include <algorithm>
-#include <limits>
 #include <set>
+#include <string>
 
 #include "base/base64.h"
 #include "base/trace_event/trace_event.h"
@@ -59,18 +58,18 @@
     const gfx::Size& tile_grid_size,
     bool gather_pixel_refs,
     RecordingSource::RecordingMode recording_mode) {
-  scoped_refptr<Picture> picture = make_scoped_refptr(new Picture(layer_rect));
+  scoped_refptr<Picture> picture =
+      make_scoped_refptr(new Picture(layer_rect, tile_grid_size));
 
-  picture->Record(client, tile_grid_size, recording_mode);
+  picture->Record(client, recording_mode);
   if (gather_pixel_refs)
-    picture->GatherPixelRefs(tile_grid_size);
+    picture->GatherPixelRefs();
 
   return picture;
 }
 
-Picture::Picture(const gfx::Rect& layer_rect)
-  : layer_rect_(layer_rect),
-    cell_size_(layer_rect.size()) {
+Picture::Picture(const gfx::Rect& layer_rect, const gfx::Size& tile_grid_size)
+    : layer_rect_(layer_rect), pixel_refs_(tile_grid_size) {
   // Instead of recording a trace event for object creation here, we wait for
   // the picture to be recorded in Picture::Record.
 }
@@ -127,16 +126,13 @@
 Picture::Picture(SkPicture* picture, const gfx::Rect& layer_rect)
     : layer_rect_(layer_rect),
       picture_(skia::AdoptRef(picture)),
-      cell_size_(layer_rect.size()) {
+      pixel_refs_(layer_rect.size()) {
 }
 
 Picture::Picture(const skia::RefPtr<SkPicture>& picture,
                  const gfx::Rect& layer_rect,
-                 const PixelRefMap& pixel_refs) :
-    layer_rect_(layer_rect),
-    picture_(picture),
-    pixel_refs_(pixel_refs),
-    cell_size_(layer_rect.size()) {
+                 const PixelRefMap& pixel_refs)
+    : layer_rect_(layer_rect), picture_(picture), pixel_refs_(pixel_refs) {
 }
 
 Picture::~Picture() {
@@ -169,7 +165,6 @@
 }
 
 void Picture::Record(ContentLayerClient* painter,
-                     const gfx::Size& tile_grid_size,
                      RecordingSource::RecordingMode recording_mode) {
   TRACE_EVENT2("cc",
                "Picture::Record",
@@ -179,9 +174,7 @@
                recording_mode);
 
   DCHECK(!picture_);
-  DCHECK(!tile_grid_size.IsEmpty());
 
-  // TODO(mtklein): If SkRTree sticks, clean up tile_grid_info.  skbug.com/3085
   SkRTreeFactory factory;
   SkPictureRecorder recorder;
 
@@ -235,7 +228,7 @@
   EmitTraceSnapshot();
 }
 
-void Picture::GatherPixelRefs(const gfx::Size& tile_grid_size) {
+void Picture::GatherPixelRefs() {
   TRACE_EVENT2("cc", "Picture::GatherPixelRefs",
                "width", layer_rect_.width(),
                "height", layer_rect_.height());
@@ -244,46 +237,8 @@
   DCHECK(pixel_refs_.empty());
   if (!WillPlayBackBitmaps())
     return;
-  cell_size_ = tile_grid_size;
-  DCHECK_GT(cell_size_.width(), 0);
-  DCHECK_GT(cell_size_.height(), 0);
 
-  int min_x = std::numeric_limits<int>::max();
-  int min_y = std::numeric_limits<int>::max();
-  int max_x = 0;
-  int max_y = 0;
-
-  skia::DiscardablePixelRefList pixel_refs;
-  skia::PixelRefUtils::GatherDiscardablePixelRefs(picture_.get(), &pixel_refs);
-  for (skia::DiscardablePixelRefList::const_iterator it = pixel_refs.begin();
-       it != pixel_refs.end();
-       ++it) {
-    gfx::Point min(
-        RoundDown(static_cast<int>(it->pixel_ref_rect.x()),
-                  cell_size_.width()),
-        RoundDown(static_cast<int>(it->pixel_ref_rect.y()),
-                  cell_size_.height()));
-    gfx::Point max(
-        RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.right())),
-                  cell_size_.width()),
-        RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())),
-                  cell_size_.height()));
-
-    for (int y = min.y(); y <= max.y(); y += cell_size_.height()) {
-      for (int x = min.x(); x <= max.x(); x += cell_size_.width()) {
-        PixelRefMapKey key(x, y);
-        pixel_refs_[key].push_back(it->pixel_ref);
-      }
-    }
-
-    min_x = std::min(min_x, min.x());
-    min_y = std::min(min_y, min.y());
-    max_x = std::max(max_x, max.x());
-    max_y = std::max(max_y, max.y());
-  }
-
-  min_pixel_cell_ = gfx::Point(min_x, min_y);
-  max_pixel_cell_ = gfx::Point(max_x, max_y);
+  pixel_refs_.GatherPixelRefsFromPicture(picture_.get());
 }
 
 int Picture::Raster(SkCanvas* canvas,
@@ -361,104 +316,9 @@
       TracedPicture::AsTraceablePictureAlias(original));
 }
 
-base::LazyInstance<Picture::PixelRefs>
-    Picture::PixelRefIterator::empty_pixel_refs_;
-
-Picture::PixelRefIterator::PixelRefIterator()
-    : picture_(NULL),
-      current_pixel_refs_(empty_pixel_refs_.Pointer()),
-      current_index_(0),
-      min_point_(-1, -1),
-      max_point_(-1, -1),
-      current_x_(0),
-      current_y_(0) {
-}
-
-Picture::PixelRefIterator::PixelRefIterator(
-    const gfx::Rect& rect,
-    const Picture* picture)
-    : picture_(picture),
-      current_pixel_refs_(empty_pixel_refs_.Pointer()),
-      current_index_(0) {
-  gfx::Rect layer_rect = picture->layer_rect_;
-  gfx::Size cell_size = picture->cell_size_;
-  DCHECK(!cell_size.IsEmpty());
-
-  gfx::Rect query_rect(rect);
-  // Early out if the query rect doesn't intersect this picture.
-  if (!query_rect.Intersects(layer_rect)) {
-    min_point_ = gfx::Point(0, 0);
-    max_point_ = gfx::Point(0, 0);
-    current_x_ = 1;
-    current_y_ = 1;
-    return;
-  }
-
-  // First, subtract the layer origin as cells are stored in layer space.
-  query_rect.Offset(-layer_rect.OffsetFromOrigin());
-
-  // We have to find a cell_size aligned point that corresponds to
-  // query_rect. Point is a multiple of cell_size.
-  min_point_ = gfx::Point(
-      RoundDown(query_rect.x(), cell_size.width()),
-      RoundDown(query_rect.y(), cell_size.height()));
-  max_point_ = gfx::Point(
-      RoundDown(query_rect.right() - 1, cell_size.width()),
-      RoundDown(query_rect.bottom() - 1, cell_size.height()));
-
-  // Limit the points to known pixel ref boundaries.
-  min_point_ = gfx::Point(
-      std::max(min_point_.x(), picture->min_pixel_cell_.x()),
-      std::max(min_point_.y(), picture->min_pixel_cell_.y()));
-  max_point_ = gfx::Point(
-      std::min(max_point_.x(), picture->max_pixel_cell_.x()),
-      std::min(max_point_.y(), picture->max_pixel_cell_.y()));
-
-  // Make the current x be cell_size.width() less than min point, so that
-  // the first increment will point at min_point_.
-  current_x_ = min_point_.x() - cell_size.width();
-  current_y_ = min_point_.y();
-  if (current_y_ <= max_point_.y())
-    ++(*this);
-}
-
-Picture::PixelRefIterator::~PixelRefIterator() {
-}
-
-Picture::PixelRefIterator& Picture::PixelRefIterator::operator++() {
-  ++current_index_;
-  // If we're not at the end of the list, then we have the next item.
-  if (current_index_ < current_pixel_refs_->size())
-    return *this;
-
-  DCHECK(current_y_ <= max_point_.y());
-  while (true) {
-    gfx::Size cell_size = picture_->cell_size_;
-
-    // Advance the current grid cell.
-    current_x_ += cell_size.width();
-    if (current_x_ > max_point_.x()) {
-      current_y_ += cell_size.height();
-      current_x_ = min_point_.x();
-      if (current_y_ > max_point_.y()) {
-        current_pixel_refs_ = empty_pixel_refs_.Pointer();
-        current_index_ = 0;
-        break;
-      }
-    }
-
-    // If there are no pixel refs at this grid cell, keep incrementing.
-    PixelRefMapKey key(current_x_, current_y_);
-    PixelRefMap::const_iterator iter = picture_->pixel_refs_.find(key);
-    if (iter == picture_->pixel_refs_.end())
-      continue;
-
-    // We found a non-empty list: store it and get the first pixel ref.
-    current_pixel_refs_ = &iter->second;
-    current_index_ = 0;
-    break;
-  }
-  return *this;
+PixelRefMap::Iterator Picture::GetPixelRefMapIterator(
+    const gfx::Rect& layer_rect) const {
+  return PixelRefMap::Iterator(layer_rect, this);
 }
 
 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/cc/resources/picture.h b/cc/resources/picture.h
index 089838c..ecbbaee 100644
--- a/cc/resources/picture.h
+++ b/cc/resources/picture.h
@@ -5,10 +5,6 @@
 #ifndef CC_RESOURCES_PICTURE_H_
 #define CC_RESOURCES_PICTURE_H_
 
-#include <string>
-#include <utility>
-#include <vector>
-
 #include "base/basictypes.h"
 #include "base/containers/hash_tables.h"
 #include "base/lazy_instance.h"
@@ -18,6 +14,7 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/base/cc_export.h"
 #include "cc/base/region.h"
+#include "cc/resources/pixel_ref_map.h"
 #include "cc/resources/recording_source.h"
 #include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkPicture.h"
@@ -40,10 +37,6 @@
 class CC_EXPORT Picture
     : public base::RefCountedThreadSafe<Picture> {
  public:
-  typedef std::pair<int, int> PixelRefMapKey;
-  typedef std::vector<SkPixelRef*> PixelRefs;
-  typedef base::hash_map<PixelRefMapKey, PixelRefs> PixelRefMap;
-
   static scoped_refptr<Picture> Create(
       const gfx::Rect& layer_rect,
       ContentLayerClient* client,
@@ -79,49 +72,16 @@
 
   scoped_ptr<base::Value> AsValue() const;
 
-  // This iterator imprecisely returns the set of pixel refs that are needed to
-  // raster this layer rect from this picture.  Internally, pixel refs are
-  // clumped into tile grid buckets, so there may be false positives.
-  class CC_EXPORT PixelRefIterator {
-   public:
-    PixelRefIterator();
-    PixelRefIterator(const gfx::Rect& layer_rect, const Picture* picture);
-    ~PixelRefIterator();
-
-    SkPixelRef* operator->() const {
-      DCHECK_LT(current_index_, current_pixel_refs_->size());
-      return (*current_pixel_refs_)[current_index_];
-    }
-
-    SkPixelRef* operator*() const {
-      DCHECK_LT(current_index_, current_pixel_refs_->size());
-      return (*current_pixel_refs_)[current_index_];
-    }
-
-    PixelRefIterator& operator++();
-    operator bool() const {
-      return current_index_ < current_pixel_refs_->size();
-    }
-
-   private:
-    static base::LazyInstance<PixelRefs> empty_pixel_refs_;
-    const Picture* picture_;
-    const PixelRefs* current_pixel_refs_;
-    unsigned current_index_;
-
-    gfx::Point min_point_;
-    gfx::Point max_point_;
-    int current_x_;
-    int current_y_;
-  };
-
   void EmitTraceSnapshot() const;
   void EmitTraceSnapshotAlias(Picture* original) const;
 
   bool WillPlayBackBitmaps() const { return picture_->willPlayBackBitmaps(); }
 
+  PixelRefMap::Iterator GetPixelRefMapIterator(
+      const gfx::Rect& layer_rect) const;
+
  private:
-  explicit Picture(const gfx::Rect& layer_rect);
+  Picture(const gfx::Rect& layer_rect, const gfx::Size& tile_grid_size);
   // This constructor assumes SkPicture is already ref'd and transfers
   // ownership to this picture.
   Picture(const skia::RefPtr<SkPicture>&,
@@ -134,19 +94,15 @@
   // Record a paint operation. To be able to safely use this SkPicture for
   // playback on a different thread this can only be called once.
   void Record(ContentLayerClient* client,
-              const gfx::Size& tile_grid_size,
               RecordingSource::RecordingMode recording_mode);
 
   // Gather pixel refs from recording.
-  void GatherPixelRefs(const gfx::Size& tile_grid_info);
+  void GatherPixelRefs();
 
   gfx::Rect layer_rect_;
   skia::RefPtr<SkPicture> picture_;
 
   PixelRefMap pixel_refs_;
-  gfx::Point min_pixel_cell_;
-  gfx::Point max_pixel_cell_;
-  gfx::Size cell_size_;
 
   scoped_refptr<base::trace_event::ConvertableToTraceFormat>
     AsTraceableRasterData(float scale) const;
@@ -154,7 +110,7 @@
     AsTraceableRecordData() const;
 
   friend class base::RefCountedThreadSafe<Picture>;
-  friend class PixelRefIterator;
+  friend class PixelRefMap::Iterator;
   DISALLOW_COPY_AND_ASSIGN(Picture);
 };
 
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc
index a9bad90..e5f217b 100644
--- a/cc/resources/picture_pile_impl.cc
+++ b/cc/resources/picture_pile_impl.cc
@@ -455,7 +455,7 @@
       continue;
 
     processed_pictures_.insert(picture);
-    pixel_ref_iterator_ = Picture::PixelRefIterator(layer_rect_, picture);
+    pixel_ref_iterator_ = picture->GetPixelRefMapIterator(layer_rect_);
     if (pixel_ref_iterator_)
       break;
   }
diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h
index c35dd0f..b144a79 100644
--- a/cc/resources/picture_pile_impl.h
+++ b/cc/resources/picture_pile_impl.h
@@ -13,6 +13,7 @@
 #include "cc/base/cc_export.h"
 #include "cc/debug/rendering_stats_instrumentation.h"
 #include "cc/resources/picture_pile.h"
+#include "cc/resources/pixel_ref_map.h"
 #include "cc/resources/raster_source.h"
 #include "skia/ext/analysis_canvas.h"
 #include "skia/ext/refptr.h"
@@ -87,7 +88,7 @@
     const PicturePileImpl* picture_pile_;
     gfx::Rect layer_rect_;
     TilingData::Iterator tile_iterator_;
-    Picture::PixelRefIterator pixel_ref_iterator_;
+    PixelRefMap::Iterator pixel_ref_iterator_;
     std::set<const void*> processed_pictures_;
   };
 
diff --git a/cc/resources/picture_unittest.cc b/cc/resources/picture_unittest.cc
index 1e2ba44..b53765c 100644
--- a/cc/resources/picture_unittest.cc
+++ b/cc/resources/picture_unittest.cc
@@ -85,269 +85,6 @@
   EXPECT_EQ(0, memcmp(two_rect_buffer, two_rect_buffer_check, 4 * 100 * 100));
 }
 
-TEST(PictureTest, PixelRefIterator) {
-  gfx::Rect layer_rect(2048, 2048);
-
-  gfx::Size tile_grid_size(512, 512);
-
-  FakeContentLayerClient content_layer_client;
-
-  // Discardable pixel refs are found in the following grids:
-  // |---|---|---|---|
-  // |   | x |   | x |
-  // |---|---|---|---|
-  // | x |   | x |   |
-  // |---|---|---|---|
-  // |   | x |   | x |
-  // |---|---|---|---|
-  // | x |   | x |   |
-  // |---|---|---|---|
-  SkBitmap discardable_bitmap[4][4];
-  for (int y = 0; y < 4; ++y) {
-    for (int x = 0; x < 4; ++x) {
-      if ((x + y) & 1) {
-        CreateBitmap(
-            gfx::Size(500, 500), "discardable", &discardable_bitmap[y][x]);
-        SkPaint paint;
-        content_layer_client.add_draw_bitmap(
-            discardable_bitmap[y][x],
-            gfx::Point(x * 512 + 6, y * 512 + 6), paint);
-      }
-    }
-  }
-
-  scoped_refptr<Picture> picture =
-      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
-                      RecordingSource::RECORD_NORMALLY);
-
-  // Default iterator does not have any pixel refs
-  {
-    Picture::PixelRefIterator iterator;
-    EXPECT_FALSE(iterator);
-  }
-  for (int y = 0; y < 4; ++y) {
-    for (int x = 0; x < 4; ++x) {
-      Picture::PixelRefIterator iterator(gfx::Rect(x * 512, y * 512, 500, 500),
-                                         picture.get());
-      if ((x + y) & 1) {
-        EXPECT_TRUE(iterator) << x << " " << y;
-        EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef()) << x <<
-            " " << y;
-        EXPECT_FALSE(++iterator) << x << " " << y;
-      } else {
-        EXPECT_FALSE(iterator) << x << " " << y;
-      }
-    }
-  }
-  // Capture 4 pixel refs.
-  {
-    Picture::PixelRefIterator iterator(gfx::Rect(512, 512, 2048, 2048),
-                                       picture.get());
-    EXPECT_TRUE(iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
-    EXPECT_FALSE(++iterator);
-  }
-
-  // Copy test.
-  Picture::PixelRefIterator iterator(gfx::Rect(512, 512, 2048, 2048),
-                                     picture.get());
-  EXPECT_TRUE(iterator);
-  EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
-  EXPECT_TRUE(++iterator);
-  EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
-
-  // copy now points to the same spot as iterator,
-  // but both can be incremented independently.
-  Picture::PixelRefIterator copy = iterator;
-  EXPECT_TRUE(++iterator);
-  EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
-  EXPECT_TRUE(++iterator);
-  EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
-  EXPECT_FALSE(++iterator);
-
-  EXPECT_TRUE(copy);
-  EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef());
-  EXPECT_TRUE(++copy);
-  EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef());
-  EXPECT_TRUE(++copy);
-  EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef());
-  EXPECT_FALSE(++copy);
-}
-
-TEST(PictureTest, PixelRefIteratorNonZeroLayer) {
-  gfx::Rect layer_rect(1024, 0, 2048, 2048);
-
-  gfx::Size tile_grid_size(512, 512);
-
-  FakeContentLayerClient content_layer_client;
-
-  // Discardable pixel refs are found in the following grids:
-  // |---|---|---|---|
-  // |   | x |   | x |
-  // |---|---|---|---|
-  // | x |   | x |   |
-  // |---|---|---|---|
-  // |   | x |   | x |
-  // |---|---|---|---|
-  // | x |   | x |   |
-  // |---|---|---|---|
-  SkBitmap discardable_bitmap[4][4];
-  for (int y = 0; y < 4; ++y) {
-    for (int x = 0; x < 4; ++x) {
-      if ((x + y) & 1) {
-        CreateBitmap(
-            gfx::Size(500, 500), "discardable", &discardable_bitmap[y][x]);
-        SkPaint paint;
-        content_layer_client.add_draw_bitmap(
-            discardable_bitmap[y][x],
-            gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint);
-      }
-    }
-  }
-
-  scoped_refptr<Picture> picture =
-      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
-                      RecordingSource::RECORD_NORMALLY);
-
-  // Default iterator does not have any pixel refs
-  {
-    Picture::PixelRefIterator iterator;
-    EXPECT_FALSE(iterator);
-  }
-  for (int y = 0; y < 4; ++y) {
-    for (int x = 0; x < 4; ++x) {
-      Picture::PixelRefIterator iterator(
-          gfx::Rect(1024 + x * 512, y * 512, 500, 500), picture.get());
-      if ((x + y) & 1) {
-        EXPECT_TRUE(iterator) << x << " " << y;
-        EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef());
-        EXPECT_FALSE(++iterator) << x << " " << y;
-      } else {
-        EXPECT_FALSE(iterator) << x << " " << y;
-      }
-    }
-  }
-  // Capture 4 pixel refs.
-  {
-    Picture::PixelRefIterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048),
-                                       picture.get());
-    EXPECT_TRUE(iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
-    EXPECT_FALSE(++iterator);
-  }
-
-  // Copy test.
-  {
-    Picture::PixelRefIterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048),
-                                       picture.get());
-    EXPECT_TRUE(iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
-
-    // copy now points to the same spot as iterator,
-    // but both can be incremented independently.
-    Picture::PixelRefIterator copy = iterator;
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
-    EXPECT_FALSE(++iterator);
-
-    EXPECT_TRUE(copy);
-    EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef());
-    EXPECT_TRUE(++copy);
-    EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef());
-    EXPECT_TRUE(++copy);
-    EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef());
-    EXPECT_FALSE(++copy);
-  }
-
-  // Non intersecting rects
-  {
-    Picture::PixelRefIterator iterator(gfx::Rect(0, 0, 1000, 1000),
-                                       picture.get());
-    EXPECT_FALSE(iterator);
-  }
-  {
-    Picture::PixelRefIterator iterator(gfx::Rect(3500, 0, 1000, 1000),
-                                       picture.get());
-    EXPECT_FALSE(iterator);
-  }
-  {
-    Picture::PixelRefIterator iterator(gfx::Rect(0, 1100, 1000, 1000),
-                                       picture.get());
-    EXPECT_FALSE(iterator);
-  }
-  {
-    Picture::PixelRefIterator iterator(gfx::Rect(3500, 1100, 1000, 1000),
-                                       picture.get());
-    EXPECT_FALSE(iterator);
-  }
-}
-
-TEST(PictureTest, PixelRefIteratorOnePixelQuery) {
-  gfx::Rect layer_rect(2048, 2048);
-
-  gfx::Size tile_grid_size(512, 512);
-
-  FakeContentLayerClient content_layer_client;
-
-  // Discardable pixel refs are found in the following grids:
-  // |---|---|---|---|
-  // |   | x |   | x |
-  // |---|---|---|---|
-  // | x |   | x |   |
-  // |---|---|---|---|
-  // |   | x |   | x |
-  // |---|---|---|---|
-  // | x |   | x |   |
-  // |---|---|---|---|
-  SkBitmap discardable_bitmap[4][4];
-  for (int y = 0; y < 4; ++y) {
-    for (int x = 0; x < 4; ++x) {
-      if ((x + y) & 1) {
-        CreateBitmap(
-            gfx::Size(500, 500), "discardable", &discardable_bitmap[y][x]);
-        SkPaint paint;
-        content_layer_client.add_draw_bitmap(
-            discardable_bitmap[y][x],
-            gfx::Point(x * 512 + 6, y * 512 + 6), paint);
-      }
-    }
-  }
-
-  scoped_refptr<Picture> picture =
-      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
-                      RecordingSource::RECORD_NORMALLY);
-
-  for (int y = 0; y < 4; ++y) {
-    for (int x = 0; x < 4; ++x) {
-      Picture::PixelRefIterator iterator(
-          gfx::Rect(x * 512, y * 512 + 256, 1, 1), picture.get());
-      if ((x + y) & 1) {
-        EXPECT_TRUE(iterator) << x << " " << y;
-        EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef());
-        EXPECT_FALSE(++iterator) << x << " " << y;
-      } else {
-        EXPECT_FALSE(iterator) << x << " " << y;
-      }
-    }
-  }
-}
-
 TEST(PictureTest, CreateFromSkpValue) {
   SkGraphics::Init();
 
diff --git a/cc/resources/pixel_ref_map.cc b/cc/resources/pixel_ref_map.cc
new file mode 100644
index 0000000..dc50851
--- /dev/null
+++ b/cc/resources/pixel_ref_map.cc
@@ -0,0 +1,158 @@
+// 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 "cc/resources/pixel_ref_map.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "cc/base/util.h"
+#include "cc/resources/picture.h"
+#include "skia/ext/pixel_ref_utils.h"
+
+namespace cc {
+
+PixelRefMap::PixelRefMap(const gfx::Size& cell_size) : cell_size_(cell_size) {
+  DCHECK(!cell_size.IsEmpty());
+}
+
+PixelRefMap::~PixelRefMap() {
+}
+
+void PixelRefMap::GatherPixelRefsFromPicture(SkPicture* picture) {
+  DCHECK(picture);
+
+  int min_x = std::numeric_limits<int>::max();
+  int min_y = std::numeric_limits<int>::max();
+  int max_x = 0;
+  int max_y = 0;
+
+  skia::DiscardablePixelRefList pixel_refs;
+  skia::PixelRefUtils::GatherDiscardablePixelRefs(picture, &pixel_refs);
+  for (skia::DiscardablePixelRefList::const_iterator it = pixel_refs.begin();
+       it != pixel_refs.end(); ++it) {
+    gfx::Point min(
+        RoundDown(static_cast<int>(it->pixel_ref_rect.x()), cell_size_.width()),
+        RoundDown(static_cast<int>(it->pixel_ref_rect.y()),
+                  cell_size_.height()));
+    gfx::Point max(
+        RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.right())),
+                  cell_size_.width()),
+        RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())),
+                  cell_size_.height()));
+
+    for (int y = min.y(); y <= max.y(); y += cell_size_.height()) {
+      for (int x = min.x(); x <= max.x(); x += cell_size_.width()) {
+        PixelRefMapKey key(x, y);
+        data_hash_map_[key].push_back(it->pixel_ref);
+      }
+    }
+
+    min_x = std::min(min_x, min.x());
+    min_y = std::min(min_y, min.y());
+    max_x = std::max(max_x, max.x());
+    max_y = std::max(max_y, max.y());
+  }
+
+  min_pixel_cell_ = gfx::Point(min_x, min_y);
+  max_pixel_cell_ = gfx::Point(max_x, max_y);
+}
+
+base::LazyInstance<PixelRefs> PixelRefMap::Iterator::empty_pixel_refs_;
+
+PixelRefMap::Iterator::Iterator()
+    : target_pixel_ref_map_(NULL),
+      current_pixel_refs_(empty_pixel_refs_.Pointer()),
+      current_index_(0),
+      min_point_(-1, -1),
+      max_point_(-1, -1),
+      current_x_(0),
+      current_y_(0) {
+}
+
+PixelRefMap::Iterator::Iterator(const gfx::Rect& rect, const Picture* picture)
+    : target_pixel_ref_map_(&(picture->pixel_refs_)),
+      current_pixel_refs_(empty_pixel_refs_.Pointer()),
+      current_index_(0) {
+  gfx::Rect layer_rect = picture->layer_rect_;
+  gfx::Size cell_size = target_pixel_ref_map_->cell_size_;
+  DCHECK(!cell_size.IsEmpty());
+  gfx::Rect query_rect(rect);
+  // Early out if the query rect doesn't intersect this picture.
+  if (!query_rect.Intersects(layer_rect)) {
+    min_point_ = gfx::Point(0, 0);
+    max_point_ = gfx::Point(0, 0);
+    current_x_ = 1;
+    current_y_ = 1;
+    return;
+  }
+
+  // First, subtract the layer origin as cells are stored in layer space.
+  query_rect.Offset(-layer_rect.OffsetFromOrigin());
+
+  // We have to find a cell_size aligned point that corresponds to
+  // query_rect. Point is a multiple of cell_size.
+  min_point_ = gfx::Point(RoundDown(query_rect.x(), cell_size.width()),
+                          RoundDown(query_rect.y(), cell_size.height()));
+  max_point_ =
+      gfx::Point(RoundDown(query_rect.right() - 1, cell_size.width()),
+                 RoundDown(query_rect.bottom() - 1, cell_size.height()));
+
+  // Limit the points to known pixel ref boundaries.
+  min_point_ = gfx::Point(
+      std::max(min_point_.x(), target_pixel_ref_map_->min_pixel_cell_.x()),
+      std::max(min_point_.y(), target_pixel_ref_map_->min_pixel_cell_.y()));
+  max_point_ = gfx::Point(
+      std::min(max_point_.x(), target_pixel_ref_map_->max_pixel_cell_.x()),
+      std::min(max_point_.y(), target_pixel_ref_map_->max_pixel_cell_.y()));
+
+  // Make the current x be cell_size.width() less than min point, so that
+  // the first increment will point at min_point_.
+  current_x_ = min_point_.x() - cell_size.width();
+  current_y_ = min_point_.y();
+  if (current_y_ <= max_point_.y())
+    ++(*this);
+}
+
+PixelRefMap::Iterator::~Iterator() {
+}
+
+PixelRefMap::Iterator& PixelRefMap::Iterator::operator++() {
+  ++current_index_;
+  // If we're not at the end of the list, then we have the next item.
+  if (current_index_ < current_pixel_refs_->size())
+    return *this;
+
+  DCHECK(current_y_ <= max_point_.y());
+  while (true) {
+    gfx::Size cell_size = target_pixel_ref_map_->cell_size_;
+
+    // Advance the current grid cell.
+    current_x_ += cell_size.width();
+    if (current_x_ > max_point_.x()) {
+      current_y_ += cell_size.height();
+      current_x_ = min_point_.x();
+      if (current_y_ > max_point_.y()) {
+        current_pixel_refs_ = empty_pixel_refs_.Pointer();
+        current_index_ = 0;
+        break;
+      }
+    }
+
+    // If there are no pixel refs at this grid cell, keep incrementing.
+    PixelRefMapKey key(current_x_, current_y_);
+    PixelRefHashmap::const_iterator iter =
+        target_pixel_ref_map_->data_hash_map_.find(key);
+    if (iter == target_pixel_ref_map_->data_hash_map_.end())
+      continue;
+
+    // We found a non-empty list: store it and get the first pixel ref.
+    current_pixel_refs_ = &iter->second;
+    current_index_ = 0;
+    break;
+  }
+  return *this;
+}
+
+}  // namespace cc
diff --git a/cc/resources/pixel_ref_map.h b/cc/resources/pixel_ref_map.h
new file mode 100644
index 0000000..f50a841
--- /dev/null
+++ b/cc/resources/pixel_ref_map.h
@@ -0,0 +1,90 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RESOURCES_PIXEL_REF_MAP_H_
+#define CC_RESOURCES_PIXEL_REF_MAP_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "cc/base/cc_export.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+class SkPixelRef;
+
+namespace cc {
+
+class Picture;
+
+typedef std::pair<int, int> PixelRefMapKey;
+typedef std::vector<SkPixelRef*> PixelRefs;
+typedef base::hash_map<PixelRefMapKey, PixelRefs> PixelRefHashmap;
+
+// This class is used and owned by cc Picture class. It is used to gather pixel
+// refs which would happen after record. It takes in |cell_size| to decide how
+// big each grid cell should be.
+class CC_EXPORT PixelRefMap {
+ public:
+  explicit PixelRefMap(const gfx::Size& cell_size);
+  ~PixelRefMap();
+  void GatherPixelRefsFromPicture(SkPicture* picture);
+
+  bool empty() const { return data_hash_map_.empty(); }
+
+  // This iterator imprecisely returns the set of pixel refs that are needed to
+  // raster this layer rect from this picture.  Internally, pixel refs are
+  // clumped into tile grid buckets, so there may be false positives.
+  class CC_EXPORT Iterator {
+   public:
+    // Default iterator constructor that is used as place holder for invalid
+    // Iterator.
+    Iterator();
+    Iterator(const gfx::Rect& layer_rect, const Picture* picture);
+    ~Iterator();
+
+    SkPixelRef* operator->() const {
+      DCHECK_LT(current_index_, current_pixel_refs_->size());
+      return (*current_pixel_refs_)[current_index_];
+    }
+
+    SkPixelRef* operator*() const {
+      DCHECK_LT(current_index_, current_pixel_refs_->size());
+      return (*current_pixel_refs_)[current_index_];
+    }
+
+    Iterator& operator++();
+    operator bool() const {
+      return current_index_ < current_pixel_refs_->size();
+    }
+
+   private:
+    static base::LazyInstance<PixelRefs> empty_pixel_refs_;
+    const PixelRefMap* target_pixel_ref_map_;
+    const PixelRefs* current_pixel_refs_;
+    unsigned current_index_;
+
+    gfx::Rect layer_rect_;
+
+    gfx::Point min_point_;
+    gfx::Point max_point_;
+    int current_x_;
+    int current_y_;
+  };
+
+ private:
+  gfx::Point min_pixel_cell_;
+  gfx::Point max_pixel_cell_;
+  gfx::Size cell_size_;
+
+  PixelRefHashmap data_hash_map_;
+};
+
+}  // namespace cc
+
+#endif  // CC_RESOURCES_PIXEL_REF_MAP_H_
diff --git a/cc/resources/pixel_ref_map_unittest.cc b/cc/resources/pixel_ref_map_unittest.cc
new file mode 100644
index 0000000..4c40336
--- /dev/null
+++ b/cc/resources/pixel_ref_map_unittest.cc
@@ -0,0 +1,292 @@
+// 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 "cc/resources/pixel_ref_map.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "cc/resources/picture.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/skia_common.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkGraphics.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/skia_util.h"
+
+namespace cc {
+namespace {
+
+TEST(PixelRefMapTest, PixelRefMapIterator) {
+  gfx::Rect layer_rect(2048, 2048);
+
+  gfx::Size tile_grid_size(512, 512);
+
+  FakeContentLayerClient content_layer_client;
+
+  // Discardable pixel refs are found in the following grids:
+  // |---|---|---|---|
+  // |   | x |   | x |
+  // |---|---|---|---|
+  // | x |   | x |   |
+  // |---|---|---|---|
+  // |   | x |   | x |
+  // |---|---|---|---|
+  // | x |   | x |   |
+  // |---|---|---|---|
+  SkBitmap discardable_bitmap[4][4];
+  for (int y = 0; y < 4; ++y) {
+    for (int x = 0; x < 4; ++x) {
+      if ((x + y) & 1) {
+        CreateBitmap(gfx::Size(500, 500), "discardable",
+                     &discardable_bitmap[y][x]);
+        SkPaint paint;
+        content_layer_client.add_draw_bitmap(
+            discardable_bitmap[y][x], gfx::Point(x * 512 + 6, y * 512 + 6),
+            paint);
+      }
+    }
+  }
+
+  scoped_refptr<Picture> picture =
+      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
+                      RecordingSource::RECORD_NORMALLY);
+
+  // Default iterator does not have any pixel refs.
+  {
+    PixelRefMap::Iterator iterator;
+    EXPECT_FALSE(iterator);
+  }
+
+  for (int y = 0; y < 4; ++y) {
+    for (int x = 0; x < 4; ++x) {
+      PixelRefMap::Iterator iterator(gfx::Rect(x * 512, y * 512, 500, 500),
+                                     picture.get());
+      if ((x + y) & 1) {
+        EXPECT_TRUE(iterator) << x << " " << y;
+        EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef())
+            << x << " " << y;
+        EXPECT_FALSE(++iterator) << x << " " << y;
+      } else {
+        EXPECT_FALSE(iterator) << x << " " << y;
+      }
+    }
+  }
+  // Capture 4 pixel refs.
+  {
+    PixelRefMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048),
+                                   picture.get());
+    EXPECT_TRUE(iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
+    EXPECT_FALSE(++iterator);
+  }
+
+  // Copy test.
+  PixelRefMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048),
+                                 picture.get());
+  EXPECT_TRUE(iterator);
+  EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
+  EXPECT_TRUE(++iterator);
+  EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
+
+  // copy now points to the same spot as iterator,
+  // but both can be incremented independently.
+  PixelRefMap::Iterator copy = iterator;
+  EXPECT_TRUE(++iterator);
+  EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
+  EXPECT_TRUE(++iterator);
+  EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
+  EXPECT_FALSE(++iterator);
+
+  EXPECT_TRUE(copy);
+  EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef());
+  EXPECT_TRUE(++copy);
+  EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef());
+  EXPECT_TRUE(++copy);
+  EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef());
+  EXPECT_FALSE(++copy);
+}
+
+TEST(PixelRefMapTest, PixelRefMapIteratorNonZeroLayer) {
+  gfx::Rect layer_rect(1024, 0, 2048, 2048);
+
+  gfx::Size tile_grid_size(512, 512);
+
+  FakeContentLayerClient content_layer_client;
+
+  // Discardable pixel refs are found in the following grids:
+  // |---|---|---|---|
+  // |   | x |   | x |
+  // |---|---|---|---|
+  // | x |   | x |   |
+  // |---|---|---|---|
+  // |   | x |   | x |
+  // |---|---|---|---|
+  // | x |   | x |   |
+  // |---|---|---|---|
+  SkBitmap discardable_bitmap[4][4];
+  for (int y = 0; y < 4; ++y) {
+    for (int x = 0; x < 4; ++x) {
+      if ((x + y) & 1) {
+        CreateBitmap(gfx::Size(500, 500), "discardable",
+                     &discardable_bitmap[y][x]);
+        SkPaint paint;
+        content_layer_client.add_draw_bitmap(
+            discardable_bitmap[y][x],
+            gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint);
+      }
+    }
+  }
+
+  scoped_refptr<Picture> picture =
+      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
+                      RecordingSource::RECORD_NORMALLY);
+
+  // Default iterator does not have any pixel refs.
+  {
+    PixelRefMap::Iterator iterator;
+    EXPECT_FALSE(iterator);
+  }
+
+  for (int y = 0; y < 4; ++y) {
+    for (int x = 0; x < 4; ++x) {
+      PixelRefMap::Iterator iterator(
+          gfx::Rect(1024 + x * 512, y * 512, 500, 500), picture.get());
+      if ((x + y) & 1) {
+        EXPECT_TRUE(iterator) << x << " " << y;
+        EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef());
+        EXPECT_FALSE(++iterator) << x << " " << y;
+      } else {
+        EXPECT_FALSE(iterator) << x << " " << y;
+      }
+    }
+  }
+  // Capture 4 pixel refs.
+  {
+    PixelRefMap::Iterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048),
+                                   picture.get());
+    EXPECT_TRUE(iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
+    EXPECT_FALSE(++iterator);
+  }
+
+  // Copy test.
+  {
+    PixelRefMap::Iterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048),
+                                   picture.get());
+    EXPECT_TRUE(iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
+
+    // copy now points to the same spot as iterator,
+    // but both can be incremented independently.
+    PixelRefMap::Iterator copy = iterator;
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
+    EXPECT_TRUE(++iterator);
+    EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
+    EXPECT_FALSE(++iterator);
+
+    EXPECT_TRUE(copy);
+    EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef());
+    EXPECT_TRUE(++copy);
+    EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef());
+    EXPECT_TRUE(++copy);
+    EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef());
+    EXPECT_FALSE(++copy);
+  }
+
+  // Non intersecting rects
+  {
+    PixelRefMap::Iterator iterator(gfx::Rect(0, 0, 1000, 1000), picture.get());
+    EXPECT_FALSE(iterator);
+  }
+  {
+    PixelRefMap::Iterator iterator(gfx::Rect(3500, 0, 1000, 1000),
+                                   picture.get());
+    EXPECT_FALSE(iterator);
+  }
+  {
+    PixelRefMap::Iterator iterator(gfx::Rect(0, 1100, 1000, 1000),
+                                   picture.get());
+    EXPECT_FALSE(iterator);
+  }
+  {
+    PixelRefMap::Iterator iterator(gfx::Rect(3500, 1100, 1000, 1000),
+                                   picture.get());
+    EXPECT_FALSE(iterator);
+  }
+}
+
+TEST(PixelRefMapTest, PixelRefMapIteratorOnePixelQuery) {
+  gfx::Rect layer_rect(2048, 2048);
+
+  gfx::Size tile_grid_size(512, 512);
+
+  FakeContentLayerClient content_layer_client;
+
+  // Discardable pixel refs are found in the following grids:
+  // |---|---|---|---|
+  // |   | x |   | x |
+  // |---|---|---|---|
+  // | x |   | x |   |
+  // |---|---|---|---|
+  // |   | x |   | x |
+  // |---|---|---|---|
+  // | x |   | x |   |
+  // |---|---|---|---|
+  SkBitmap discardable_bitmap[4][4];
+  for (int y = 0; y < 4; ++y) {
+    for (int x = 0; x < 4; ++x) {
+      if ((x + y) & 1) {
+        CreateBitmap(gfx::Size(500, 500), "discardable",
+                     &discardable_bitmap[y][x]);
+        SkPaint paint;
+        content_layer_client.add_draw_bitmap(
+            discardable_bitmap[y][x], gfx::Point(x * 512 + 6, y * 512 + 6),
+            paint);
+      }
+    }
+  }
+
+  scoped_refptr<Picture> picture =
+      Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
+                      RecordingSource::RECORD_NORMALLY);
+
+  // Default iterator does not have any pixel refs.
+  {
+    PixelRefMap::Iterator iterator;
+    EXPECT_FALSE(iterator);
+  }
+
+  for (int y = 0; y < 4; ++y) {
+    for (int x = 0; x < 4; ++x) {
+      PixelRefMap::Iterator iterator(gfx::Rect(x * 512, y * 512 + 256, 1, 1),
+                                     picture.get());
+      if ((x + y) & 1) {
+        EXPECT_TRUE(iterator) << x << " " << y;
+        EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef());
+        EXPECT_FALSE(++iterator) << x << " " << y;
+      } else {
+        EXPECT_FALSE(iterator) << x << " " << y;
+      }
+    }
+  }
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/cc/resources/platform_color.h b/cc/resources/platform_color.h
index 4945dcc..17eddc1 100644
--- a/cc/resources/platform_color.h
+++ b/cc/resources/platform_color.h
@@ -8,8 +8,6 @@
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "cc/resources/resource_format.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
 #include "third_party/skia/include/core/SkTypes.h"
 
 namespace cc {
diff --git a/cc/resources/resource.h b/cc/resources/resource.h
index 707d77e..edafaef 100644
--- a/cc/resources/resource.h
+++ b/cc/resources/resource.h
@@ -7,7 +7,6 @@
 
 #include "cc/base/cc_export.h"
 #include "cc/resources/resource_provider.h"
-#include "third_party/khronos/GLES2/gl2.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace cc {
diff --git a/cc/resources/tile.cc b/cc/resources/tile.cc
index 1576047..f86330e 100644
--- a/cc/resources/tile.cc
+++ b/cc/resources/tile.cc
@@ -10,7 +10,6 @@
 #include "cc/base/math_util.h"
 #include "cc/debug/traced_value.h"
 #include "cc/resources/tile_manager.h"
-#include "third_party/khronos/GLES2/gl2.h"
 
 namespace cc {
 
diff --git a/cc/resources/tile_task_worker_pool_unittest.cc b/cc/resources/tile_task_worker_pool_unittest.cc
index d7cb155..72f9d20 100644
--- a/cc/resources/tile_task_worker_pool_unittest.cc
+++ b/cc/resources/tile_task_worker_pool_unittest.cc
@@ -28,6 +28,7 @@
 #include "cc/test/test_gpu_memory_buffer_manager.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_web_graphics_context_3d.h"
+#include "gpu/GLES2/gl2extchromium.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -275,6 +276,14 @@
     return completed_tasks_;
   }
 
+  void LoseContext(ContextProvider* context_provider) {
+    if (!context_provider)
+      return;
+    context_provider->ContextGL()->LoseContextCHROMIUM(
+        GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
+    context_provider->ContextGL()->Flush();
+  }
+
  private:
   void Create3dOutputSurfaceAndResourceProvider() {
     output_surface_ = FakeOutputSurface::Create3d(
@@ -404,6 +413,21 @@
   RunMessageLoopUntilAllTasksHaveCompleted();
 }
 
+TEST_P(TileTaskWorkerPoolTest, LostContext) {
+  LoseContext(output_surface_->context_provider());
+  LoseContext(output_surface_->worker_context_provider());
+
+  AppendTask(0u);
+  AppendTask(1u);
+  ScheduleTasks();
+
+  RunMessageLoopUntilAllTasksHaveCompleted();
+
+  ASSERT_EQ(2u, completed_tasks().size());
+  EXPECT_FALSE(completed_tasks()[0].canceled);
+  EXPECT_FALSE(completed_tasks()[1].canceled);
+}
+
 INSTANTIATE_TEST_CASE_P(
     TileTaskWorkerPoolTests,
     TileTaskWorkerPoolTest,
diff --git a/cc/resources/tiling_set_raster_queue_all.cc b/cc/resources/tiling_set_raster_queue_all.cc
index c4d949c..2ccba67 100644
--- a/cc/resources/tiling_set_raster_queue_all.cc
+++ b/cc/resources/tiling_set_raster_queue_all.cc
@@ -112,6 +112,137 @@
   }
 }
 
+// OnePriorityRectIterator
+TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator()
+    : tile_(nullptr), tiling_(nullptr), tiling_data_(nullptr) {
+}
+
+TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator(
+    PictureLayerTiling* tiling,
+    TilingData* tiling_data)
+    : tile_(nullptr), tiling_(tiling), tiling_data_(tiling_data) {
+}
+
+template <typename TilingIteratorType>
+void TilingSetRasterQueueAll::OnePriorityRectIterator::AdvanceToNextTile(
+    TilingIteratorType* iterator) {
+  tile_ = nullptr;
+  while (!tile_ || !TileNeedsRaster(tile_)) {
+    ++(*iterator);
+    if (!(*iterator)) {
+      tile_ = nullptr;
+      return;
+    }
+    tile_ = tiling_->TileAt(iterator->index_x(), iterator->index_y());
+  }
+  tiling_->UpdateTileAndTwinPriority(tile_);
+}
+
+template <typename TilingIteratorType>
+bool TilingSetRasterQueueAll::OnePriorityRectIterator::
+    GetFirstTileAndCheckIfValid(TilingIteratorType* iterator) {
+  tile_ = tiling_->TileAt(iterator->index_x(), iterator->index_y());
+  if (!tile_ || !TileNeedsRaster(tile_)) {
+    tile_ = nullptr;
+    return false;
+  }
+  tiling_->UpdateTileAndTwinPriority(tile_);
+  return true;
+}
+
+// VisibleTilingIterator.
+TilingSetRasterQueueAll::VisibleTilingIterator::VisibleTilingIterator(
+    PictureLayerTiling* tiling,
+    TilingData* tiling_data)
+    : OnePriorityRectIterator(tiling, tiling_data) {
+  if (!tiling_->has_visible_rect_tiles())
+    return;
+  iterator_ =
+      TilingData::Iterator(tiling_data_, tiling_->current_visible_rect(),
+                           false /* include_borders */);
+  if (!iterator_)
+    return;
+  if (!GetFirstTileAndCheckIfValid(&iterator_))
+    ++(*this);
+}
+
+TilingSetRasterQueueAll::VisibleTilingIterator&
+    TilingSetRasterQueueAll::VisibleTilingIterator::
+    operator++() {
+  AdvanceToNextTile(&iterator_);
+  return *this;
+}
+
+// SkewportTilingIterator.
+TilingSetRasterQueueAll::SkewportTilingIterator::SkewportTilingIterator(
+    PictureLayerTiling* tiling,
+    TilingData* tiling_data)
+    : OnePriorityRectIterator(tiling, tiling_data) {
+  if (!tiling_->has_skewport_rect_tiles())
+    return;
+  iterator_ = TilingData::SpiralDifferenceIterator(
+      tiling_data_, tiling_->current_skewport_rect(),
+      tiling_->current_visible_rect(), tiling_->current_visible_rect());
+  if (!iterator_)
+    return;
+  if (!GetFirstTileAndCheckIfValid(&iterator_))
+    ++(*this);
+}
+
+TilingSetRasterQueueAll::SkewportTilingIterator&
+    TilingSetRasterQueueAll::SkewportTilingIterator::
+    operator++() {
+  AdvanceToNextTile(&iterator_);
+  return *this;
+}
+
+// SoonBorderTilingIterator.
+TilingSetRasterQueueAll::SoonBorderTilingIterator::SoonBorderTilingIterator(
+    PictureLayerTiling* tiling,
+    TilingData* tiling_data)
+    : OnePriorityRectIterator(tiling, tiling_data) {
+  if (!tiling_->has_soon_border_rect_tiles())
+    return;
+  iterator_ = TilingData::SpiralDifferenceIterator(
+      tiling_data_, tiling_->current_soon_border_rect(),
+      tiling_->current_skewport_rect(), tiling_->current_visible_rect());
+  if (!iterator_)
+    return;
+  if (!GetFirstTileAndCheckIfValid(&iterator_))
+    ++(*this);
+}
+
+TilingSetRasterQueueAll::SoonBorderTilingIterator&
+    TilingSetRasterQueueAll::SoonBorderTilingIterator::
+    operator++() {
+  AdvanceToNextTile(&iterator_);
+  return *this;
+}
+
+// EventuallyTilingIterator.
+TilingSetRasterQueueAll::EventuallyTilingIterator::EventuallyTilingIterator(
+    PictureLayerTiling* tiling,
+    TilingData* tiling_data)
+    : OnePriorityRectIterator(tiling, tiling_data) {
+  if (!tiling_->has_eventually_rect_tiles())
+    return;
+  iterator_ = TilingData::SpiralDifferenceIterator(
+      tiling_data_, tiling_->current_eventually_rect(),
+      tiling_->current_skewport_rect(), tiling_->current_soon_border_rect());
+  if (!iterator_)
+    return;
+  if (!GetFirstTileAndCheckIfValid(&iterator_))
+    ++(*this);
+}
+
+TilingSetRasterQueueAll::EventuallyTilingIterator&
+    TilingSetRasterQueueAll::EventuallyTilingIterator::
+    operator++() {
+  AdvanceToNextTile(&iterator_);
+  return *this;
+}
+
+// TilingIterator
 TilingSetRasterQueueAll::TilingIterator::TilingIterator()
     : tiling_(NULL), current_tile_(NULL) {
 }
@@ -123,125 +254,80 @@
       tiling_data_(tiling_data),
       phase_(VISIBLE_RECT),
       current_tile_(NULL) {
-  if (!tiling_->has_visible_rect_tiles()) {
+  visible_iterator_ = VisibleTilingIterator(tiling_, tiling_data_);
+  if (visible_iterator_.done()) {
     AdvancePhase();
     return;
   }
-
-  visible_iterator_ =
-      TilingData::Iterator(tiling_data_, tiling_->current_visible_rect(),
-                           false /* include_borders */);
-  if (!visible_iterator_) {
-    AdvancePhase();
-    return;
-  }
-
-  current_tile_ =
-      tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y());
-  if (!current_tile_ || !TileNeedsRaster(current_tile_)) {
-    ++(*this);
-    return;
-  }
-  tiling_->UpdateTileAndTwinPriority(current_tile_);
-}
-
-TilingSetRasterQueueAll::TilingIterator::~TilingIterator() {
+  current_tile_ = *visible_iterator_;
 }
 
 void TilingSetRasterQueueAll::TilingIterator::AdvancePhase() {
   DCHECK_LT(phase_, EVENTUALLY_RECT);
 
-  do {
+  current_tile_ = nullptr;
+  while (!current_tile_ && phase_ < EVENTUALLY_RECT) {
     phase_ = static_cast<Phase>(phase_ + 1);
     switch (phase_) {
       case VISIBLE_RECT:
         NOTREACHED();
         return;
       case SKEWPORT_RECT:
-        if (!tiling_->has_skewport_rect_tiles())
-          continue;
-
-        spiral_iterator_ = TilingData::SpiralDifferenceIterator(
-            tiling_data_, tiling_->current_skewport_rect(),
-            tiling_->current_visible_rect(), tiling_->current_visible_rect());
+        skewport_iterator_ = SkewportTilingIterator(tiling_, tiling_data_);
+        if (!skewport_iterator_.done())
+          current_tile_ = *skewport_iterator_;
         break;
       case SOON_BORDER_RECT:
-        if (!tiling_->has_soon_border_rect_tiles())
-          continue;
-
-        spiral_iterator_ = TilingData::SpiralDifferenceIterator(
-            tiling_data_, tiling_->current_soon_border_rect(),
-            tiling_->current_skewport_rect(), tiling_->current_visible_rect());
+        soon_border_iterator_ = SoonBorderTilingIterator(tiling_, tiling_data_);
+        if (!soon_border_iterator_.done())
+          current_tile_ = *soon_border_iterator_;
         break;
       case EVENTUALLY_RECT:
-        if (!tiling_->has_eventually_rect_tiles()) {
-          current_tile_ = NULL;
-          return;
-        }
-
-        spiral_iterator_ = TilingData::SpiralDifferenceIterator(
-            tiling_data_, tiling_->current_eventually_rect(),
-            tiling_->current_skewport_rect(),
-            tiling_->current_soon_border_rect());
+        eventually_iterator_ = EventuallyTilingIterator(tiling_, tiling_data_);
+        if (!eventually_iterator_.done())
+          current_tile_ = *eventually_iterator_;
         break;
     }
-
-    while (spiral_iterator_) {
-      current_tile_ = tiling_->TileAt(spiral_iterator_.index_x(),
-                                      spiral_iterator_.index_y());
-      if (current_tile_ && TileNeedsRaster(current_tile_))
-        break;
-      ++spiral_iterator_;
-    }
-
-    if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) {
-      current_tile_ = NULL;
-      break;
-    }
-  } while (!spiral_iterator_);
-
-  if (current_tile_)
-    tiling_->UpdateTileAndTwinPriority(current_tile_);
+  }
 }
 
 TilingSetRasterQueueAll::TilingIterator&
     TilingSetRasterQueueAll::TilingIterator::
     operator++() {
-  current_tile_ = NULL;
-  while (!current_tile_ || !TileNeedsRaster(current_tile_)) {
-    std::pair<int, int> next_index;
-    switch (phase_) {
-      case VISIBLE_RECT:
-        ++visible_iterator_;
-        if (!visible_iterator_) {
-          AdvancePhase();
-          return *this;
-        }
-        next_index = visible_iterator_.index();
-        break;
-      case SKEWPORT_RECT:
-      case SOON_BORDER_RECT:
-        ++spiral_iterator_;
-        if (!spiral_iterator_) {
-          AdvancePhase();
-          return *this;
-        }
-        next_index = spiral_iterator_.index();
-        break;
-      case EVENTUALLY_RECT:
-        ++spiral_iterator_;
-        if (!spiral_iterator_) {
-          current_tile_ = NULL;
-          return *this;
-        }
-        next_index = spiral_iterator_.index();
-        break;
-    }
-    current_tile_ = tiling_->TileAt(next_index.first, next_index.second);
+  switch (phase_) {
+    case VISIBLE_RECT:
+      ++visible_iterator_;
+      if (visible_iterator_.done()) {
+        AdvancePhase();
+        return *this;
+      }
+      current_tile_ = *visible_iterator_;
+      break;
+    case SKEWPORT_RECT:
+      ++skewport_iterator_;
+      if (skewport_iterator_.done()) {
+        AdvancePhase();
+        return *this;
+      }
+      current_tile_ = *skewport_iterator_;
+      break;
+    case SOON_BORDER_RECT:
+      ++soon_border_iterator_;
+      if (soon_border_iterator_.done()) {
+        AdvancePhase();
+        return *this;
+      }
+      current_tile_ = *soon_border_iterator_;
+      break;
+    case EVENTUALLY_RECT:
+      ++eventually_iterator_;
+      if (eventually_iterator_.done()) {
+        current_tile_ = nullptr;
+        return *this;
+      }
+      current_tile_ = *eventually_iterator_;
+      break;
   }
-
-  if (current_tile_)
-    tiling_->UpdateTileAndTwinPriority(current_tile_);
   return *this;
 }
 
diff --git a/cc/resources/tiling_set_raster_queue_all.h b/cc/resources/tiling_set_raster_queue_all.h
index 5577c6c..ebca838 100644
--- a/cc/resources/tiling_set_raster_queue_all.h
+++ b/cc/resources/tiling_set_raster_queue_all.h
@@ -26,12 +26,90 @@
   bool IsEmpty() const;
 
  private:
+  // Helper base class for individual region iterators.
+  class OnePriorityRectIterator {
+   public:
+    OnePriorityRectIterator();
+    OnePriorityRectIterator(PictureLayerTiling* tiling,
+                            TilingData* tiling_data);
+
+    bool done() const { return !tile_; }
+    Tile* operator*() const { return tile_; }
+
+   protected:
+    ~OnePriorityRectIterator() = default;
+    bool TileNeedsRaster(Tile* tile) const {
+      return tile->NeedsRaster() && !tiling_->IsTileOccluded(tile);
+    }
+
+    template <typename TilingIteratorType>
+    void AdvanceToNextTile(TilingIteratorType* iterator);
+    template <typename TilingIteratorType>
+    bool GetFirstTileAndCheckIfValid(TilingIteratorType* iterator);
+
+    Tile* tile_;
+    PictureLayerTiling* tiling_;
+    TilingData* tiling_data_;
+  };
+
+  // Iterates over visible rect only, left to right top to bottom order.
+  class VisibleTilingIterator : public OnePriorityRectIterator {
+   public:
+    VisibleTilingIterator() = default;
+    VisibleTilingIterator(PictureLayerTiling* tiling, TilingData* tiling_data);
+
+    VisibleTilingIterator& operator++();
+
+   private:
+    TilingData::Iterator iterator_;
+  };
+
+  // Iterates over skewport only, spiral around the visible rect.
+  class SkewportTilingIterator : public OnePriorityRectIterator {
+   public:
+    SkewportTilingIterator() = default;
+    SkewportTilingIterator(PictureLayerTiling* tiling, TilingData* tiling_data);
+
+    SkewportTilingIterator& operator++();
+
+   private:
+    TilingData::SpiralDifferenceIterator iterator_;
+  };
+
+  // Iterates over soon border only, spiral around the visible rect.
+  class SoonBorderTilingIterator : public OnePriorityRectIterator {
+   public:
+    SoonBorderTilingIterator() = default;
+    SoonBorderTilingIterator(PictureLayerTiling* tiling,
+                             TilingData* tiling_data);
+
+    SoonBorderTilingIterator& operator++();
+
+   private:
+    TilingData::SpiralDifferenceIterator iterator_;
+  };
+
+  // Iterates over eventually rect only, spiral around the soon rect.
+  class EventuallyTilingIterator : public OnePriorityRectIterator {
+   public:
+    EventuallyTilingIterator() = default;
+    EventuallyTilingIterator(PictureLayerTiling* tiling,
+                             TilingData* tiling_data);
+
+    EventuallyTilingIterator& operator++();
+
+   private:
+    TilingData::SpiralDifferenceIterator iterator_;
+  };
+
+  // Iterates over all of the above phases in the following order: visible,
+  // skewport, soon border, eventually.
   class TilingIterator {
    public:
     TilingIterator();
     explicit TilingIterator(PictureLayerTiling* tiling,
                             TilingData* tiling_data);
-    ~TilingIterator();
+    ~TilingIterator() = default;
 
     bool done() const { return current_tile_ == nullptr; }
     const Tile* operator*() const { return current_tile_; }
@@ -61,9 +139,6 @@
     };
 
     void AdvancePhase();
-    bool TileNeedsRaster(Tile* tile) const {
-      return tile->NeedsRaster() && !tiling_->IsTileOccluded(tile);
-    }
 
     PictureLayerTiling* tiling_;
     TilingData* tiling_data_;
@@ -71,8 +146,10 @@
     Phase phase_;
 
     Tile* current_tile_;
-    TilingData::Iterator visible_iterator_;
-    TilingData::SpiralDifferenceIterator spiral_iterator_;
+    VisibleTilingIterator visible_iterator_;
+    SkewportTilingIterator skewport_iterator_;
+    SoonBorderTilingIterator soon_border_iterator_;
+    EventuallyTilingIterator eventually_iterator_;
   };
 
   enum IteratorType { LOW_RES, HIGH_RES, NUM_ITERATORS };
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h
index 1bccf79..df9951a 100644
--- a/cc/resources/video_resource_updater.h
+++ b/cc/resources/video_resource_updater.h
@@ -61,13 +61,13 @@
   ~VideoFrameExternalResources();
 };
 
-// VideoResourceUpdater is by the video system to produce frame content as
+// VideoResourceUpdater is used by the video system to produce frame content as
 // resources consumable by the compositor.
 class CC_EXPORT VideoResourceUpdater
     : public base::SupportsWeakPtr<VideoResourceUpdater> {
  public:
-  explicit VideoResourceUpdater(ContextProvider* context_provider,
-                                ResourceProvider* resource_provider);
+  VideoResourceUpdater(ContextProvider* context_provider,
+                       ResourceProvider* resource_provider);
   ~VideoResourceUpdater();
 
   VideoFrameExternalResources CreateExternalResourcesFromVideoFrame(
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index a6f15f0..4f00ff3 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -251,12 +251,12 @@
     // Contributing passes aggregated in to the pass list need to take the
     // transform of the surface quad into account to update their transform to
     // the root surface.
-    // TODO(jamesr): Make sure this is sufficient for surfaces nested several
-    // levels deep and add tests.
     copy_pass->transform_to_root_target.ConcatTransform(
         surface_quad->quadTransform());
     copy_pass->transform_to_root_target.ConcatTransform(
         content_to_target_transform);
+    copy_pass->transform_to_root_target.ConcatTransform(
+        dest_pass->transform_to_root_target);
 
     CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
                     gfx::Transform(), ClipData(), copy_pass.get(), surface_id);
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index 1dff7ec..cf54568 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -939,9 +939,13 @@
   }
 
   // Root surface.
-  test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
-                             test::Quad::SurfaceQuad(middle_surface_id, 1.f)};
-  test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
+  test::Quad secondary_quads[] = {
+      test::Quad::SolidColorQuad(1),
+      test::Quad::SurfaceQuad(middle_surface_id, 1.f)};
+  test::Quad root_quads[] = {test::Quad::SolidColorQuad(1)};
+  test::Pass root_passes[] = {
+      test::Pass(secondary_quads, arraysize(secondary_quads)),
+      test::Pass(root_quads, arraysize(root_quads))};
 
   RenderPassList root_pass_list;
   AddPasses(&root_pass_list,
@@ -958,6 +962,8 @@
   root_pass_list.at(0)->quad_list.ElementAt(1)->visible_rect =
       gfx::Rect(0, 0, 8, 100);
 
+  root_pass_list[0]->transform_to_root_target.Translate(10, 5);
+
   scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
   root_pass_list.swap(root_frame_data->render_pass_list);
 
@@ -977,17 +983,19 @@
 
   const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
 
-  ASSERT_EQ(2u, aggregated_pass_list.size());
+  ASSERT_EQ(3u, aggregated_pass_list.size());
 
   ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
 
   // The first pass should have one shared quad state for the one solid color
   // quad.
   EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
-  // The second (root) pass should have just two shared quad states. We'll
+  // The second pass should have just two shared quad states. We'll
   // verify the properties through the quads.
   EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size());
 
+  EXPECT_EQ(1u, aggregated_pass_list[2]->shared_quad_state_list.size());
+
   SharedQuadState* aggregated_first_pass_sqs =
       aggregated_pass_list[0]->shared_quad_state_list.front();
 
@@ -999,8 +1007,9 @@
             aggregated_first_pass_sqs->content_to_target_transform.ToString());
 
   // The first pass's transform to the root target should include the aggregated
-  // transform.
+  // transform, including the transform from the child pass to the root.
   gfx::Transform expected_first_pass_transform_to_root_target;
+  expected_first_pass_transform_to_root_target.Translate(10, 5);
   expected_first_pass_transform_to_root_target.Translate(0, 10);
   expected_first_pass_transform_to_root_target.Scale(2, 3);
   expected_first_pass_transform_to_root_target.Translate(8, 0);
diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc
index 88e166c..ac60271 100644
--- a/cc/surfaces/surface_display_output_surface.cc
+++ b/cc/surfaces/surface_display_output_surface.cc
@@ -25,9 +25,6 @@
   capabilities_.delegated_rendering = true;
   capabilities_.max_frames_pending = 1;
   capabilities_.can_force_reclaim_resources = true;
-  // Frame always needs to be swapped because forced resource reclaiming
-  // destroys the Display's copy.
-  capabilities_.draw_and_swap_full_viewport_every_frame = true;
 }
 
 SurfaceDisplayOutputSurface::~SurfaceDisplayOutputSurface() {
diff --git a/cc/test/data/anti_aliasing.png b/cc/test/data/anti_aliasing.png
index 4abe9e1..eba7436 100644
--- a/cc/test/data/anti_aliasing.png
+++ b/cc/test/data/anti_aliasing.png
Binary files differ
diff --git a/cc/test/data/background_filter_blur_off_axis.png b/cc/test/data/background_filter_blur_off_axis.png
index 5077171..5e9a0c2 100644
--- a/cc/test/data/background_filter_blur_off_axis.png
+++ b/cc/test/data/background_filter_blur_off_axis.png
Binary files differ
diff --git a/cc/test/data/intersecting_blue_green.png b/cc/test/data/intersecting_blue_green.png
new file mode 100644
index 0000000..8262071
--- /dev/null
+++ b/cc/test/data/intersecting_blue_green.png
Binary files differ
diff --git a/cc/test/data/intersecting_blue_green_squares.png b/cc/test/data/intersecting_blue_green_squares.png
new file mode 100644
index 0000000..22da4d3
--- /dev/null
+++ b/cc/test/data/intersecting_blue_green_squares.png
Binary files differ
diff --git a/cc/test/data/intersecting_blue_green_squares_video.png b/cc/test/data/intersecting_blue_green_squares_video.png
new file mode 100644
index 0000000..e1bea4f
--- /dev/null
+++ b/cc/test/data/intersecting_blue_green_squares_video.png
Binary files differ
diff --git a/cc/test/data/mask_of_background_filter.png b/cc/test/data/mask_of_background_filter.png
index 2a96d49..35a9b93 100644
--- a/cc/test/data/mask_of_background_filter.png
+++ b/cc/test/data/mask_of_background_filter.png
Binary files differ
diff --git a/cc/test/data/mask_of_layer_with_blend.png b/cc/test/data/mask_of_layer_with_blend.png
index 35faaba..1f2bedd 100644
--- a/cc/test/data/mask_of_layer_with_blend.png
+++ b/cc/test/data/mask_of_layer_with_blend.png
Binary files differ
diff --git a/cc/test/fake_impl_proxy.h b/cc/test/fake_impl_proxy.h
index b9408c8..69eb5d2 100644
--- a/cc/test/fake_impl_proxy.h
+++ b/cc/test/fake_impl_proxy.h
@@ -12,7 +12,9 @@
 
 class FakeImplProxy : public FakeProxy {
  public:
-  FakeImplProxy() : set_impl_thread_(this) {}
+  FakeImplProxy()
+      : FakeProxy(base::MessageLoopProxy::current(), nullptr),
+        set_impl_thread_(this) {}
 
   explicit FakeImplProxy(
       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
diff --git a/cc/test/fake_proxy.cc b/cc/test/fake_proxy.cc
index b288c07..9c24162 100644
--- a/cc/test/fake_proxy.cc
+++ b/cc/test/fake_proxy.cc
@@ -42,7 +42,4 @@
   return false;
 }
 
-void FakeProxy::AsValueInto(base::trace_event::TracedValue*) const {
-}
-
 }  // namespace cc
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index 2309fef..d5ad313 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -46,7 +46,6 @@
   bool SupportsImplScrolling() const override;
   void SetDebugState(const LayerTreeDebugState& debug_state) override {}
   bool MainFrameWillHappenForTesting() override;
-  void AsValueInto(base::trace_event::TracedValue* state) const override;
   void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override {}
 
   virtual RendererCapabilities& GetRendererCapabilities();
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 9690362..3c6ff57 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -350,7 +350,7 @@
     LayerTreeHostImpl::UpdateAnimationState(start_ready_animations);
     bool has_unfinished_animation = false;
     for (const auto& it :
-         animation_registrar()->active_animation_controllers()) {
+         animation_registrar()->active_animation_controllers_for_testing()) {
       if (it.second->HasActiveAnimation()) {
         has_unfinished_animation = true;
         break;
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc
index bf85ea3..7c9bb2c 100644
--- a/cc/test/test_context_provider.cc
+++ b/cc/test/test_context_provider.cc
@@ -104,6 +104,11 @@
   gl_context->makeCurrent();
   gr_context_ = skia::AdoptRef(GrContext::Create(
       kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(gl_context->gl())));
+
+  // If GlContext is already lost, also abandon the new GrContext.
+  if (IsContextLost())
+    gr_context_->abandonContext();
+
   return gr_context_.get();
 }
 
@@ -151,6 +156,8 @@
   }
   if (!lost_context_callback_.is_null())
     base::ResetAndReturn(&lost_context_callback_).Run();
+  if (gr_context_)
+    gr_context_->abandonContext();
 }
 
 TestWebGraphicsContext3D* TestContextProvider::TestContext3d() {
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc
index 9f20bb8..6d8ccf7 100644
--- a/cc/test/test_web_graphics_context_3d.cc
+++ b/cc/test/test_web_graphics_context_3d.cc
@@ -71,6 +71,7 @@
       bound_buffer_(0),
       weak_ptr_factory_(this) {
   CreateNamespace();
+  set_support_image(true);
 }
 
 TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 1e6d2c7..41aa81b 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -38,7 +38,7 @@
       const TransformNode* clip_transform_node =
           transform_tree.Node(clip_node->data.transform_id);
       const TransformNode* target_node =
-          transform_tree.Node(transform_node->data.target_id);
+          transform_tree.Node(transform_node->data.content_target_id);
 
       gfx::Transform clip_to_target;
       gfx::Transform content_to_target;
diff --git a/cc/trees/layer_sorter.cc b/cc/trees/layer_sorter.cc
deleted file mode 100644
index bde4920..0000000
--- a/cc/trees/layer_sorter.cc
+++ /dev/null
@@ -1,470 +0,0 @@
-// Copyright 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 "cc/trees/layer_sorter.h"
-
-#include <algorithm>
-#include <deque>
-#include <limits>
-#include <vector>
-
-#include "base/logging.h"
-#include "cc/base/math_util.h"
-#include "cc/layers/render_surface_impl.h"
-#include "ui/gfx/transform.h"
-
-namespace cc {
-
-// This epsilon is used to determine if two layers are too close to each other
-// to be able to tell which is in front of the other.  It's a relative epsilon
-// so it is robust to changes in scene scale.  This value was chosen by picking
-// a value near machine epsilon and then increasing it until the flickering on
-// the test scene went away.
-const float k_layer_epsilon = 1e-4f;
-
-inline static float PerpProduct(const gfx::Vector2dF& u,
-                                const gfx::Vector2dF& v) {
-  return u.x() * v.y() - u.y() * v.x();
-}
-
-// Tests if two edges defined by their endpoints (a,b) and (c,d) intersect.
-// Returns true and the point of intersection if they do and false otherwise.
-static bool EdgeEdgeTest(const gfx::PointF& a,
-                         const gfx::PointF& b,
-                         const gfx::PointF& c,
-                         const gfx::PointF& d,
-                         gfx::PointF* r) {
-  gfx::Vector2dF u = b - a;
-  gfx::Vector2dF v = d - c;
-  gfx::Vector2dF w = a - c;
-
-  float denom = PerpProduct(u, v);
-
-  // If denom == 0 then the edges are parallel. While they could be overlapping
-  // we don't bother to check here as the we'll find their intersections from
-  // the corner to quad tests.
-  if (!denom)
-    return false;
-
-  float s = PerpProduct(v, w) / denom;
-  if (s < 0.f || s > 1.f)
-    return false;
-
-  float t = PerpProduct(u, w) / denom;
-  if (t < 0.f || t > 1.f)
-    return false;
-
-  u.Scale(s);
-  *r = a + u;
-  return true;
-}
-
-GraphNode::GraphNode(LayerImpl* layer_impl)
-    : layer(layer_impl),
-      incoming_edge_weight(0.f) {}
-
-GraphNode::~GraphNode() {}
-
-LayerSorter::LayerSorter()
-    : z_range_(0.f) {}
-
-LayerSorter::~LayerSorter() {}
-
-static float CheckFloatingPointNumericAccuracy(float a, float b) {
-  float abs_dif = std::abs(b - a);
-  float abs_max = std::max(std::abs(b), std::abs(a));
-  // Check to see if we've got a result with a reasonable amount of error.
-  return abs_dif / abs_max;
-}
-
-// Checks whether layer "a" draws on top of layer "b". The weight value returned
-// is an indication of the maximum z-depth difference between the layers or zero
-// if the layers are found to be intesecting (some features are in front and
-// some are behind).
-LayerSorter::ABCompareResult LayerSorter::CheckOverlap(LayerShape* a,
-                                                       LayerShape* b,
-                                                       float z_threshold,
-                                                       float* weight) {
-  *weight = 0.f;
-
-  // Early out if the projected bounds don't overlap.
-  if (!a->projected_bounds.Intersects(b->projected_bounds))
-    return NONE;
-
-  gfx::PointF aPoints[4] = { a->projected_quad.p1(),
-                             a->projected_quad.p2(),
-                             a->projected_quad.p3(),
-                             a->projected_quad.p4() };
-  gfx::PointF bPoints[4] = { b->projected_quad.p1(),
-                             b->projected_quad.p2(),
-                             b->projected_quad.p3(),
-                             b->projected_quad.p4() };
-
-  // Make a list of points that inside both layer quad projections.
-  std::vector<gfx::PointF> overlap_points;
-
-  // Check all four corners of one layer against the other layer's quad.
-  for (int i = 0; i < 4; ++i) {
-    if (a->projected_quad.Contains(bPoints[i]))
-      overlap_points.push_back(bPoints[i]);
-    if (b->projected_quad.Contains(aPoints[i]))
-      overlap_points.push_back(aPoints[i]);
-  }
-
-  // Check all the edges of one layer for intersection with the other layer's
-  // edges.
-  gfx::PointF r;
-  for (int ea = 0; ea < 4; ++ea)
-    for (int eb = 0; eb < 4; ++eb)
-      if (EdgeEdgeTest(aPoints[ea], aPoints[(ea + 1) % 4],
-                       bPoints[eb], bPoints[(eb + 1) % 4],
-                       &r))
-        overlap_points.push_back(r);
-
-  if (overlap_points.empty())
-    return NONE;
-
-  // Check the corresponding layer depth value for all overlap points to
-  // determine which layer is in front.
-  float max_positive = 0.f;
-  float max_negative = 0.f;
-
-  // This flag tracks the existance of a numerically accurate seperation
-  // between two layers.  If there is no accurate seperation, the layers
-  // cannot be effectively sorted.
-  bool accurate = false;
-
-  for (size_t o = 0; o < overlap_points.size(); o++) {
-    float za = a->LayerZFromProjectedPoint(overlap_points[o]);
-    float zb = b->LayerZFromProjectedPoint(overlap_points[o]);
-
-    // Here we attempt to avoid numeric issues with layers that are too
-    // close together.  If we have 2-sided quads that are very close
-    // together then we will draw them in document order to avoid
-    // flickering.  The correct solution is for the content maker to turn
-    // on back-face culling or move the quads apart (if they're not two
-    // sides of one object).
-    if (CheckFloatingPointNumericAccuracy(za, zb) > k_layer_epsilon)
-      accurate = true;
-
-    float diff = za - zb;
-    if (diff > max_positive)
-      max_positive = diff;
-    if (diff < max_negative)
-      max_negative = diff;
-  }
-
-  // If we can't tell which should come first, we use document order.
-  if (!accurate)
-    return A_BEFORE_B;
-
-  float max_diff =
-      std::abs(max_positive) > std::abs(max_negative) ?
-          max_positive : max_negative;
-
-  // If the results are inconsistent (and the z difference substantial to rule
-  // out numerical errors) then the layers are intersecting. We will still
-  // return an order based on the maximum depth difference but with an edge
-  // weight of zero these layers will get priority if a graph cycle is present
-  // and needs to be broken.
-  if (max_positive > z_threshold && max_negative < -z_threshold)
-    *weight = 0.f;
-  else
-    *weight = std::abs(max_diff);
-
-  // Maintain relative order if the layers have the same depth at all
-  // intersection points.
-  if (max_diff <= 0.f)
-    return A_BEFORE_B;
-
-  return B_BEFORE_A;
-}
-
-LayerShape::LayerShape() {}
-
-LayerShape::LayerShape(float width,
-                       float height,
-                       const gfx::Transform& draw_transform) {
-  gfx::QuadF layer_quad(gfx::RectF(0.f, 0.f, width, height));
-
-  // Compute the projection of the layer quad onto the z = 0 plane.
-
-  gfx::PointF clipped_quad[8];
-  int num_vertices_in_clipped_quad;
-  MathUtil::MapClippedQuad(draw_transform,
-                           layer_quad,
-                           clipped_quad,
-                           &num_vertices_in_clipped_quad);
-
-  if (num_vertices_in_clipped_quad < 3) {
-    projected_bounds = gfx::RectF();
-    return;
-  }
-
-  projected_bounds =
-      MathUtil::ComputeEnclosingRectOfVertices(clipped_quad,
-                                               num_vertices_in_clipped_quad);
-
-  // NOTE: it will require very significant refactoring and overhead to deal
-  // with generalized polygons or multiple quads per layer here. For the sake of
-  // layer sorting it is equally correct to take a subsection of the polygon
-  // that can be made into a quad. This will only be incorrect in the case of
-  // intersecting layers, which are not supported yet anyway.
-  projected_quad.set_p1(clipped_quad[0]);
-  projected_quad.set_p2(clipped_quad[1]);
-  projected_quad.set_p3(clipped_quad[2]);
-  if (num_vertices_in_clipped_quad >= 4) {
-    projected_quad.set_p4(clipped_quad[3]);
-  } else {
-    // This will be a degenerate quad that is actually a triangle.
-    projected_quad.set_p4(clipped_quad[2]);
-  }
-
-  // Compute the normal of the layer's plane.
-  bool clipped = false;
-  gfx::Point3F c1 =
-      MathUtil::MapPoint(draw_transform, gfx::Point3F(0.f, 0.f, 0.f), &clipped);
-  gfx::Point3F c2 =
-      MathUtil::MapPoint(draw_transform, gfx::Point3F(0.f, 1.f, 0.f), &clipped);
-  gfx::Point3F c3 =
-      MathUtil::MapPoint(draw_transform, gfx::Point3F(1.f, 0.f, 0.f), &clipped);
-  // TODO(shawnsingh): Deal with clipping.
-  gfx::Vector3dF c12 = c2 - c1;
-  gfx::Vector3dF c13 = c3 - c1;
-  layer_normal = gfx::CrossProduct(c13, c12);
-
-  transform_origin = c1;
-}
-
-LayerShape::~LayerShape() {}
-
-// Returns the Z coordinate of a point on the layer that projects
-// to point p which lies on the z = 0 plane. It does it by computing the
-// intersection of a line starting from p along the Z axis and the plane
-// of the layer.
-float LayerShape::LayerZFromProjectedPoint(const gfx::PointF& p) const {
-  gfx::Vector3dF z_axis(0.f, 0.f, 1.f);
-  gfx::Vector3dF w = gfx::Point3F(p) - transform_origin;
-
-  float d = gfx::DotProduct(layer_normal, z_axis);
-  float n = -gfx::DotProduct(layer_normal, w);
-
-  // Check if layer is parallel to the z = 0 axis which will make it
-  // invisible and hence returning zero is fine.
-  if (!d)
-    return 0.f;
-
-  // The intersection point would be given by:
-  // p + (n / d) * u  but since we are only interested in the
-  // z coordinate and p's z coord is zero, all we need is the value of n/d.
-  return n / d;
-}
-
-void LayerSorter::CreateGraphNodes(LayerImplList::iterator first,
-                                   LayerImplList::iterator last) {
-  DVLOG(2) << "Creating graph nodes:";
-  float min_z = FLT_MAX;
-  float max_z = -FLT_MAX;
-  for (LayerImplList::const_iterator it = first; it < last; it++) {
-    nodes_.push_back(GraphNode(*it));
-    GraphNode& node = nodes_.at(nodes_.size() - 1);
-    RenderSurfaceImpl* render_surface = node.layer->render_surface();
-    if (!node.layer->DrawsContent() && !render_surface)
-      continue;
-
-    DVLOG(2) << "Layer " << node.layer->id() <<
-        " (" << node.layer->bounds().width() <<
-        " x " << node.layer->bounds().height() << ")";
-
-    gfx::Transform draw_transform;
-    float layer_width, layer_height;
-    if (render_surface) {
-      draw_transform = render_surface->draw_transform();
-      layer_width = render_surface->content_rect().width();
-      layer_height = render_surface->content_rect().height();
-    } else {
-      draw_transform = node.layer->draw_transform();
-      layer_width = node.layer->content_bounds().width();
-      layer_height = node.layer->content_bounds().height();
-    }
-
-    node.shape = LayerShape(layer_width, layer_height, draw_transform);
-
-    max_z = std::max(max_z, node.shape.transform_origin.z());
-    min_z = std::min(min_z, node.shape.transform_origin.z());
-  }
-
-  z_range_ = std::abs(max_z - min_z);
-}
-
-void LayerSorter::CreateGraphEdges() {
-  DVLOG(2) << "Edges:";
-  // Fraction of the total z_range below which z differences
-  // are not considered reliable.
-  const float z_threshold_factor = 0.01f;
-  float z_threshold = z_range_ * z_threshold_factor;
-
-  for (size_t na = 0; na < nodes_.size(); na++) {
-    GraphNode& node_a = nodes_[na];
-    if (!node_a.layer->DrawsContent() && !node_a.layer->render_surface())
-      continue;
-    for (size_t nb = na + 1; nb < nodes_.size(); nb++) {
-      GraphNode& node_b = nodes_[nb];
-      if (!node_b.layer->DrawsContent() && !node_b.layer->render_surface())
-        continue;
-      float weight = 0.f;
-      ABCompareResult overlap_result = CheckOverlap(&node_a.shape,
-                                                    &node_b.shape,
-                                                    z_threshold,
-                                                    &weight);
-      GraphNode* start_node = NULL;
-      GraphNode* end_node = NULL;
-      if (overlap_result == A_BEFORE_B) {
-        start_node = &node_a;
-        end_node = &node_b;
-      } else if (overlap_result == B_BEFORE_A) {
-        start_node = &node_b;
-        end_node = &node_a;
-      }
-
-      if (start_node) {
-        DVLOG(2) << start_node->layer->id() << " -> " << end_node->layer->id();
-        edges_.push_back(GraphEdge(start_node, end_node, weight));
-      }
-    }
-  }
-
-  for (size_t i = 0; i < edges_.size(); i++) {
-    GraphEdge& edge = edges_[i];
-    active_edges_[&edge] = &edge;
-    edge.from->outgoing.push_back(&edge);
-    edge.to->incoming.push_back(&edge);
-    edge.to->incoming_edge_weight += edge.weight;
-  }
-}
-
-// Finds and removes an edge from the list by doing a swap with the
-// last element of the list.
-void LayerSorter::RemoveEdgeFromList(GraphEdge* edge,
-                                     std::vector<GraphEdge*>* list) {
-  std::vector<GraphEdge*>::iterator iter =
-      std::find(list->begin(), list->end(), edge);
-  DCHECK(iter != list->end());
-  list->erase(iter);
-}
-
-// Sorts the given list of layers such that they can be painted in a
-// back-to-front order. Sorting produces correct results for non-intersecting
-// layers that don't have cyclical order dependencies. Cycles and intersections
-// are broken (somewhat) aribtrarily. Sorting of layers is done via a
-// topological sort of a directed graph whose nodes are the layers themselves.
-// An edge from node A to node B signifies that layer A needs to be drawn before
-// layer B. If A and B have no dependency between each other, then we preserve
-// the ordering of those layers as they were in the original list.
-//
-// The draw order between two layers is determined by projecting the two
-// triangles making up each layer quad to the Z = 0 plane, finding points of
-// intersection between the triangles and backprojecting those points to the
-// plane of the layer to determine the corresponding Z coordinate. The layer
-// with the lower Z coordinate (farther from the eye) needs to be rendered
-// first.
-//
-// If the layer projections don't intersect, then no edges (dependencies) are
-// created between them in the graph. HOWEVER, in this case we still need to
-// preserve the ordering of the original list of layers, since that list should
-// already have proper z-index ordering of layers.
-//
-void LayerSorter::Sort(LayerImplList::iterator first,
-                       LayerImplList::iterator last) {
-  DVLOG(2) << "Sorting start ----";
-  CreateGraphNodes(first, last);
-
-  CreateGraphEdges();
-
-  std::vector<GraphNode*> sorted_list;
-  std::deque<GraphNode*> no_incoming_edge_node_list;
-
-  // Find all the nodes that don't have incoming edges.
-  for (NodeList::iterator la = nodes_.begin(); la < nodes_.end(); la++) {
-    if (!la->incoming.size())
-      no_incoming_edge_node_list.push_back(&(*la));
-  }
-
-  DVLOG(2) << "Sorted list: ";
-  while (active_edges_.size() || no_incoming_edge_node_list.size()) {
-    while (no_incoming_edge_node_list.size()) {
-      // It is necessary to preserve the existing ordering of layers, when there
-      // are no explicit dependencies (because this existing ordering has
-      // correct z-index/layout ordering). To preserve this ordering, we process
-      // Nodes in the same order that they were added to the list.
-      GraphNode* from_node = no_incoming_edge_node_list.front();
-      no_incoming_edge_node_list.pop_front();
-
-      // Add it to the final list.
-      sorted_list.push_back(from_node);
-
-      DVLOG(2) << from_node->layer->id() << ", ";
-
-      // Remove all its outgoing edges from the graph.
-      for (size_t i = 0; i < from_node->outgoing.size(); i++) {
-        GraphEdge* outgoing_edge = from_node->outgoing[i];
-
-        active_edges_.erase(outgoing_edge);
-        RemoveEdgeFromList(outgoing_edge, &outgoing_edge->to->incoming);
-        outgoing_edge->to->incoming_edge_weight -= outgoing_edge->weight;
-
-        if (!outgoing_edge->to->incoming.size())
-          no_incoming_edge_node_list.push_back(outgoing_edge->to);
-      }
-      from_node->outgoing.clear();
-    }
-
-    if (!active_edges_.size())
-      break;
-
-    // If there are still active edges but the list of nodes without incoming
-    // edges is empty then we have run into a cycle. Break the cycle by finding
-    // the node with the smallest overall incoming edge weight and use it. This
-    // will favor nodes that have zero-weight incoming edges i.e. layers that
-    // are being occluded by a layer that intersects them.
-    float min_incoming_edge_weight = FLT_MAX;
-    GraphNode* next_node = NULL;
-    for (size_t i = 0; i < nodes_.size(); i++) {
-      if (nodes_[i].incoming.size() &&
-          nodes_[i].incoming_edge_weight < min_incoming_edge_weight) {
-        min_incoming_edge_weight = nodes_[i].incoming_edge_weight;
-        next_node = &nodes_[i];
-      }
-    }
-    DCHECK(next_node);
-    // Remove all its incoming edges.
-    for (size_t e = 0; e < next_node->incoming.size(); e++) {
-      GraphEdge* incoming_edge = next_node->incoming[e];
-
-      active_edges_.erase(incoming_edge);
-      RemoveEdgeFromList(incoming_edge, &incoming_edge->from->outgoing);
-    }
-    next_node->incoming.clear();
-    next_node->incoming_edge_weight = 0.f;
-    no_incoming_edge_node_list.push_back(next_node);
-    DVLOG(2) << "Breaking cycle by cleaning up incoming edges from " <<
-        next_node->layer->id() <<
-        " (weight = " << min_incoming_edge_weight << ")";
-  }
-
-  // Note: The original elements of the list are in no danger of having their
-  // ref count go to zero here as they are all nodes of the layer hierarchy and
-  // are kept alive by their parent nodes.
-  int count = 0;
-  for (LayerImplList::iterator it = first; it < last; it++)
-    *it = sorted_list[count++]->layer;
-
-  DVLOG(2) << "Sorting end ----";
-
-  nodes_.clear();
-  edges_.clear();
-  active_edges_.clear();
-}
-
-}  // namespace cc
diff --git a/cc/trees/layer_sorter.h b/cc/trees/layer_sorter.h
deleted file mode 100644
index 4cfa8fe..0000000
--- a/cc/trees/layer_sorter.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 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 CC_TREES_LAYER_SORTER_H_
-#define CC_TREES_LAYER_SORTER_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#include "cc/base/cc_export.h"
-#include "cc/layers/layer_impl.h"
-#include "ui/gfx/geometry/point3_f.h"
-#include "ui/gfx/geometry/quad_f.h"
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/geometry/vector3d_f.h"
-
-namespace gfx {
-class Transform;
-}
-
-namespace cc {
-struct GraphEdge;
-
-// Holds various useful properties derived from a layer's 3D outline.
-struct CC_EXPORT LayerShape {
-  LayerShape();
-  LayerShape(float width, float height, const gfx::Transform& draw_transform);
-  ~LayerShape();
-
-  float LayerZFromProjectedPoint(const gfx::PointF& p) const;
-
-  gfx::Vector3dF layer_normal;
-  gfx::Point3F transform_origin;
-  gfx::QuadF projected_quad;
-  gfx::RectF projected_bounds;
-};
-
-struct GraphNode {
-  explicit GraphNode(LayerImpl* layer_impl);
-  ~GraphNode();
-
-  LayerImpl* layer;
-  LayerShape shape;
-  std::vector<GraphEdge*> incoming;
-  std::vector<GraphEdge*> outgoing;
-  float incoming_edge_weight;
-};
-
-struct GraphEdge {
-  GraphEdge(GraphNode* from_node, GraphNode* to_node, float weight)
-      : from(from_node),
-        to(to_node),
-        weight(weight) {}
-
-  GraphNode* from;
-  GraphNode* to;
-  float weight;
-};
-
-
-
-class CC_EXPORT LayerSorter {
- public:
-  LayerSorter();
-  ~LayerSorter();
-
-  void Sort(LayerImplList::iterator first, LayerImplList::iterator last);
-
-  enum ABCompareResult { A_BEFORE_B, B_BEFORE_A, NONE };
-
-  static ABCompareResult CheckOverlap(LayerShape* a,
-                                      LayerShape* b,
-                                      float z_threshold,
-                                      float* weight);
-
- private:
-  typedef std::vector<GraphNode> NodeList;
-  typedef std::vector<GraphEdge> EdgeList;
-  NodeList nodes_;
-  EdgeList edges_;
-  float z_range_;
-
-  typedef base::hash_map<GraphEdge*, GraphEdge*> EdgeMap;
-  EdgeMap active_edges_;
-
-  void CreateGraphNodes(LayerImplList::iterator first,
-                        LayerImplList::iterator last);
-  void CreateGraphEdges();
-  void RemoveEdgeFromList(GraphEdge* graph, std::vector<GraphEdge*>* list);
-
-  DISALLOW_COPY_AND_ASSIGN(LayerSorter);
-};
-
-}  // namespace cc
-#endif  // CC_TREES_LAYER_SORTER_H_
diff --git a/cc/trees/layer_sorter_unittest.cc b/cc/trees/layer_sorter_unittest.cc
deleted file mode 100644
index 74d3cf5..0000000
--- a/cc/trees/layer_sorter_unittest.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 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 "cc/trees/layer_sorter.h"
-
-#include "cc/base/math_util.h"
-#include "cc/layers/layer_impl.h"
-#include "cc/test/fake_impl_proxy.h"
-#include "cc/test/fake_layer_tree_host_impl.h"
-#include "cc/test/test_shared_bitmap_manager.h"
-#include "cc/trees/single_thread_proxy.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/transform.h"
-
-namespace cc {
-namespace {
-
-// Note: In the following overlap tests, the "camera" is looking down the
-// negative Z axis, meaning that layers with smaller z values (more negative)
-// are further from the camera and therefore must be drawn before layers with
-// higher z values.
-
-TEST(LayerSorterTest, BasicOverlap) {
-  LayerSorter::ABCompareResult overlap_result;
-  const float z_threshold = 0.1f;
-  float weight = 0.f;
-
-  // Trivial test, with one layer directly obscuring the other.
-  gfx::Transform neg4_translate;
-  neg4_translate.Translate3d(0.0, 0.0, -4.0);
-  LayerShape front(2.f, 2.f, neg4_translate);
-
-  gfx::Transform neg5_translate;
-  neg5_translate.Translate3d(0.0, 0.0, -5.0);
-  LayerShape back(2.f, 2.f, neg5_translate);
-
-  overlap_result =
-      LayerSorter::CheckOverlap(&front, &back, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::B_BEFORE_A, overlap_result);
-  EXPECT_EQ(1.f, weight);
-
-  overlap_result =
-      LayerSorter::CheckOverlap(&back, &front, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result);
-  EXPECT_EQ(1.f, weight);
-
-  // One layer translated off to the right. No overlap should be detected.
-  gfx::Transform right_translate;
-  right_translate.Translate3d(10.0, 0.0, -5.0);
-  LayerShape back_right(2.f, 2.f, right_translate);
-  overlap_result =
-      LayerSorter::CheckOverlap(&front, &back_right, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::NONE, overlap_result);
-
-  // When comparing a layer with itself, z difference is always 0.
-  overlap_result =
-      LayerSorter::CheckOverlap(&front, &front, z_threshold, &weight);
-  EXPECT_EQ(0.f, weight);
-}
-
-TEST(LayerSorterTest, RightAngleOverlap) {
-  LayerSorter::ABCompareResult overlap_result;
-  const float z_threshold = 0.1f;
-  float weight = 0.f;
-
-  gfx::Transform perspective_matrix;
-  perspective_matrix.ApplyPerspectiveDepth(1000.0);
-
-  // Two layers forming a right angle with a perspective viewing transform.
-  gfx::Transform left_face_matrix;
-  left_face_matrix.Translate3d(-1.0, 0.0, -5.0);
-  left_face_matrix.RotateAboutYAxis(-90.0);
-  left_face_matrix.Translate(-1.0, -1.0);
-  LayerShape left_face(2.f, 2.f, perspective_matrix * left_face_matrix);
-  gfx::Transform front_face_matrix;
-  front_face_matrix.Translate3d(0.0, 0.0, -4.0);
-  front_face_matrix.Translate(-1.0, -1.0);
-  LayerShape front_face(2.f, 2.f, perspective_matrix * front_face_matrix);
-
-  overlap_result =
-      LayerSorter::CheckOverlap(&front_face, &left_face, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::B_BEFORE_A, overlap_result);
-}
-
-TEST(LayerSorterTest, IntersectingLayerOverlap) {
-  LayerSorter::ABCompareResult overlap_result;
-  const float z_threshold = 0.1f;
-  float weight = 0.f;
-
-  gfx::Transform perspective_matrix;
-  perspective_matrix.ApplyPerspectiveDepth(1000.0);
-
-  // Intersecting layers. An explicit order will be returned based on relative z
-  // values at the overlapping features but the weight returned should be zero.
-  gfx::Transform front_face_matrix;
-  front_face_matrix.Translate3d(0.0, 0.0, -4.0);
-  front_face_matrix.Translate(-1.0, -1.0);
-  LayerShape front_face(2.f, 2.f, perspective_matrix * front_face_matrix);
-
-  gfx::Transform through_matrix;
-  through_matrix.Translate3d(0.0, 0.0, -4.0);
-  through_matrix.RotateAboutYAxis(45.0);
-  through_matrix.Translate(-1.0, -1.0);
-  LayerShape rotated_face(2.f, 2.f, perspective_matrix * through_matrix);
-  overlap_result = LayerSorter::CheckOverlap(&front_face,
-                                             &rotated_face,
-                                             z_threshold,
-                                             &weight);
-  EXPECT_NE(LayerSorter::NONE, overlap_result);
-  EXPECT_EQ(0.f, weight);
-}
-
-TEST(LayerSorterTest, LayersAtAngleOverlap) {
-  LayerSorter::ABCompareResult overlap_result;
-  const float z_threshold = 0.1f;
-  float weight = 0.f;
-
-  // Trickier test with layers at an angle.
-  //
-  //   -x . . . . 0 . . . . +x
-  // -z             /
-  //  :            /----B----
-  //  0           C
-  //  : ----A----/
-  // +z         /
-  //
-  // C is in front of A and behind B (not what you'd expect by comparing
-  // centers). A and B don't overlap, so they're incomparable.
-
-  gfx::Transform transform_a;
-  transform_a.Translate3d(-6.0, 0.0, 1.0);
-  transform_a.Translate(-4.0, -10.0);
-  LayerShape layer_a(8.f, 20.f, transform_a);
-
-  gfx::Transform transform_b;
-  transform_b.Translate3d(6.0, 0.0, -1.0);
-  transform_b.Translate(-4.0, -10.0);
-  LayerShape layer_b(8.f, 20.f, transform_b);
-
-  gfx::Transform transform_c;
-  transform_c.RotateAboutYAxis(40.0);
-  transform_c.Translate(-4.0, -10.0);
-  LayerShape layer_c(8.f, 20.f, transform_c);
-
-  overlap_result =
-      LayerSorter::CheckOverlap(&layer_a, &layer_c, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result);
-  overlap_result =
-      LayerSorter::CheckOverlap(&layer_c, &layer_b, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result);
-  overlap_result =
-      LayerSorter::CheckOverlap(&layer_a, &layer_b, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::NONE, overlap_result);
-}
-
-TEST(LayerSorterTest, LayersUnderPathologicalPerspectiveTransform) {
-  LayerSorter::ABCompareResult overlap_result;
-  const float z_threshold = 0.1f;
-  float weight = 0.f;
-
-  // On perspective projection, if w becomes negative, the re-projected point
-  // will be invalid and un-usable. Correct code needs to clip away portions of
-  // the geometry where w < 0. If the code uses the invalid value, it will think
-  // that a layer has different bounds than it really does, which can cause
-  // things to sort incorrectly.
-
-  gfx::Transform perspective_matrix;
-  perspective_matrix.ApplyPerspectiveDepth(1);
-
-  gfx::Transform transform_a;
-  transform_a.Translate3d(-15.0, 0.0, -2.0);
-  transform_a.Translate(-5.0, -5.0);
-  LayerShape layer_a(10.f, 10.f, perspective_matrix * transform_a);
-
-  // With this sequence of transforms, when layer B is correctly clipped, it
-  // will be visible on the left half of the projection plane, in front of
-  // layer_a. When it is not clipped, its bounds will actually incorrectly
-  // appear much smaller and the correct sorting dependency will not be found.
-  gfx::Transform transform_b;
-  transform_b.Translate3d(0.f, 0.f, 0.7f);
-  transform_b.RotateAboutYAxis(45.0);
-  transform_b.Translate(-5.0, -5.0);
-  LayerShape layer_b(10.f, 10.f, perspective_matrix * transform_b);
-
-  // Sanity check that the test case actually covers the intended scenario,
-  // where part of layer B go behind the w = 0 plane.
-  gfx::QuadF test_quad = gfx::QuadF(gfx::RectF(-0.5f, -0.5f, 1.f, 1.f));
-  bool clipped = false;
-  MathUtil::MapQuad(perspective_matrix * transform_b, test_quad, &clipped);
-  ASSERT_TRUE(clipped);
-
-  overlap_result =
-      LayerSorter::CheckOverlap(&layer_a, &layer_b, z_threshold, &weight);
-  EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result);
-}
-
-TEST(LayerSorterTest, VerifyExistingOrderingPreservedWhenNoZDiff) {
-  // If there is no reason to re-sort the layers (i.e. no 3d z difference), then
-  // the existing ordering provided on input should be retained. This test
-  // covers the fix in https://bugs.webkit.org/show_bug.cgi?id=75046. Before
-  // this fix, ordering was accidentally reversed, causing bugs in z-index
-  // ordering on websites when preserves3D triggered the LayerSorter.
-
-  // Input list of layers: [1, 2, 3, 4, 5].
-  // Expected output: [3, 4, 1, 2, 5].
-  //    - 1, 2, and 5 do not have a 3d z difference, and therefore their
-  //      relative ordering should be retained.
-  //    - 3 and 4 do not have a 3d z difference, and therefore their relative
-  //      ordering should be retained.
-  //    - 3 and 4 should be re-sorted so they are in front of 1, 2, and 5.
-
-  FakeImplProxy proxy;
-  TestSharedBitmapManager shared_bitmap_manager;
-  FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager);
-
-  scoped_ptr<LayerImpl> layer1 = LayerImpl::Create(host_impl.active_tree(), 1);
-  scoped_ptr<LayerImpl> layer2 = LayerImpl::Create(host_impl.active_tree(), 2);
-  scoped_ptr<LayerImpl> layer3 = LayerImpl::Create(host_impl.active_tree(), 3);
-  scoped_ptr<LayerImpl> layer4 = LayerImpl::Create(host_impl.active_tree(), 4);
-  scoped_ptr<LayerImpl> layer5 = LayerImpl::Create(host_impl.active_tree(), 5);
-
-  gfx::Transform BehindMatrix;
-  BehindMatrix.Translate3d(0.0, 0.0, 2.0);
-  gfx::Transform FrontMatrix;
-  FrontMatrix.Translate3d(0.0, 0.0, 1.0);
-
-  layer1->SetBounds(gfx::Size(10, 10));
-  layer1->SetContentBounds(gfx::Size(10, 10));
-  layer1->draw_properties().target_space_transform = BehindMatrix;
-  layer1->SetDrawsContent(true);
-
-  layer2->SetBounds(gfx::Size(20, 20));
-  layer2->SetContentBounds(gfx::Size(20, 20));
-  layer2->draw_properties().target_space_transform = BehindMatrix;
-  layer2->SetDrawsContent(true);
-
-  layer3->SetBounds(gfx::Size(30, 30));
-  layer3->SetContentBounds(gfx::Size(30, 30));
-  layer3->draw_properties().target_space_transform = FrontMatrix;
-  layer3->SetDrawsContent(true);
-
-  layer4->SetBounds(gfx::Size(40, 40));
-  layer4->SetContentBounds(gfx::Size(40, 40));
-  layer4->draw_properties().target_space_transform = FrontMatrix;
-  layer4->SetDrawsContent(true);
-
-  layer5->SetBounds(gfx::Size(50, 50));
-  layer5->SetContentBounds(gfx::Size(50, 50));
-  layer5->draw_properties().target_space_transform = BehindMatrix;
-  layer5->SetDrawsContent(true);
-
-  LayerImplList layer_list;
-  layer_list.push_back(layer1.get());
-  layer_list.push_back(layer2.get());
-  layer_list.push_back(layer3.get());
-  layer_list.push_back(layer4.get());
-  layer_list.push_back(layer5.get());
-
-  ASSERT_EQ(5u, layer_list.size());
-  EXPECT_EQ(1, layer_list[0]->id());
-  EXPECT_EQ(2, layer_list[1]->id());
-  EXPECT_EQ(3, layer_list[2]->id());
-  EXPECT_EQ(4, layer_list[3]->id());
-  EXPECT_EQ(5, layer_list[4]->id());
-
-  LayerSorter layer_sorter;
-  layer_sorter.Sort(layer_list.begin(), layer_list.end());
-
-  ASSERT_EQ(5u, layer_list.size());
-  EXPECT_EQ(3, layer_list[0]->id());
-  EXPECT_EQ(4, layer_list[1]->id());
-  EXPECT_EQ(1, layer_list[2]->id());
-  EXPECT_EQ(2, layer_list[3]->id());
-  EXPECT_EQ(5, layer_list[4]->id());
-}
-
-TEST(LayerSorterTest, VerifyConcidentLayerPrecisionLossResultsInDocumentOrder) {
-  FakeImplProxy proxy;
-  TestSharedBitmapManager shared_bitmap_manager;
-  FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager);
-
-  scoped_ptr<LayerImpl> layer1 = LayerImpl::Create(host_impl.active_tree(), 1);
-  scoped_ptr<LayerImpl> layer2 = LayerImpl::Create(host_impl.active_tree(), 2);
-
-  // Layer 1 should occur before layer 2 in paint.  However, due to numeric
-  // issues in the sorter, it will put the layers in the wrong order
-  // in some situations.  Here we test a patch that results in  document
-  // order rather than calculated order when numeric percision is suspect
-  // in calculated order.
-
-  gfx::Transform BehindMatrix;
-  BehindMatrix.Translate3d(0.f, 0.f, 0.999999f);
-  BehindMatrix.RotateAboutXAxis(38.5);
-  BehindMatrix.RotateAboutYAxis(77.0);
-  gfx::Transform FrontMatrix;
-  FrontMatrix.Translate3d(0, 0, 1.0);
-  FrontMatrix.RotateAboutXAxis(38.5);
-  FrontMatrix.RotateAboutYAxis(77.0);
-
-  layer1->SetBounds(gfx::Size(10, 10));
-  layer1->SetContentBounds(gfx::Size(10, 10));
-  layer1->draw_properties().target_space_transform = BehindMatrix;
-  layer1->SetDrawsContent(true);
-
-  layer2->SetBounds(gfx::Size(10, 10));
-  layer2->SetContentBounds(gfx::Size(10, 10));
-  layer2->draw_properties().target_space_transform = FrontMatrix;
-  layer2->SetDrawsContent(true);
-
-  LayerImplList layer_list;
-  layer_list.push_back(layer1.get());
-  layer_list.push_back(layer2.get());
-
-  ASSERT_EQ(2u, layer_list.size());
-  EXPECT_EQ(1, layer_list[0]->id());
-  EXPECT_EQ(2, layer_list[1]->id());
-
-  LayerSorter layer_sorter;
-  layer_sorter.Sort(layer_list.begin(), layer_list.end());
-
-  ASSERT_EQ(2u, layer_list.size());
-  EXPECT_EQ(1, layer_list[0]->id());
-  EXPECT_EQ(2, layer_list[1]->id());
-}
-
-}  // namespace
-}  // namespace cc
-
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index d893b33..2ac7ebe 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -544,34 +544,7 @@
 void LayerTreeHost::SetAnimationEvents(
     scoped_ptr<AnimationEventsVector> events) {
   DCHECK(proxy_->IsMainThread());
-  for (size_t event_index = 0; event_index < events->size(); ++event_index) {
-    int event_layer_id = (*events)[event_index].layer_id;
-
-    // Use the map of all controllers, not just active ones, since non-active
-    // controllers may still receive events for impl-only animations.
-    const AnimationRegistrar::AnimationControllerMap& animation_controllers =
-        animation_registrar_->all_animation_controllers();
-    auto iter = animation_controllers.find(event_layer_id);
-    if (iter != animation_controllers.end()) {
-      switch ((*events)[event_index].type) {
-        case AnimationEvent::STARTED:
-          (*iter).second->NotifyAnimationStarted((*events)[event_index]);
-          break;
-
-        case AnimationEvent::FINISHED:
-          (*iter).second->NotifyAnimationFinished((*events)[event_index]);
-          break;
-
-        case AnimationEvent::ABORTED:
-          (*iter).second->NotifyAnimationAborted((*events)[event_index]);
-          break;
-
-        case AnimationEvent::PROPERTY_UPDATE:
-          (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]);
-          break;
-      }
-    }
-  }
+  animation_registrar_->SetAnimationEvents(events.Pass());
 }
 
 void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
@@ -1165,26 +1138,12 @@
                  animate));
 }
 
-void LayerTreeHost::AsValueInto(base::trace_event::TracedValue* state) const {
-  state->BeginDictionary("proxy");
-  proxy_->AsValueInto(state);
-  state->EndDictionary();
-}
-
 void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) {
-  if (!settings_.accelerated_animation_enabled ||
-      animation_registrar_->active_animation_controllers().empty())
+  if (!settings_.accelerated_animation_enabled)
     return;
 
-  TRACE_EVENT0("cc", "LayerTreeHost::AnimateLayers");
-
-  AnimationRegistrar::AnimationControllerMap active_controllers_copy =
-      animation_registrar_->active_animation_controllers();
-  for (auto& it : active_controllers_copy) {
-    it.second->Animate(monotonic_time);
-    bool start_ready_animations = true;
-    it.second->UpdateState(start_ready_animations, NULL);
-  }
+  if (animation_registrar_->AnimateLayers(monotonic_time))
+    animation_registrar_->UpdateAnimationState(true, NULL);
 }
 
 UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) {
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index e677f89..840a4fa 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -272,9 +272,6 @@
     return animation_registrar_.get();
   }
 
-  // Obtains a thorough dump of the LayerTreeHost as a value.
-  void AsValueInto(base::trace_event::TracedValue* value) const;
-
   bool in_paint_layer_contents() const { return in_paint_layer_contents_; }
 
   // CreateUIResource creates a resource given a bitmap.  The bitmap is
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index e468c07..064e91e 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -15,7 +15,6 @@
 #include "cc/layers/render_surface.h"
 #include "cc/layers/render_surface_impl.h"
 #include "cc/trees/draw_property_utils.h"
-#include "cc/trees/layer_sorter.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -31,20 +30,6 @@
 
 ScrollAndScaleSet::~ScrollAndScaleSet() {}
 
-static void SortLayers(LayerList::iterator first,
-                       LayerList::iterator end,
-                       void* layer_sorter) {
-  NOTREACHED();
-}
-
-static void SortLayers(LayerImplList::iterator first,
-                       LayerImplList::iterator end,
-                       LayerSorter* layer_sorter) {
-  DCHECK(layer_sorter);
-  TRACE_EVENT0("cc", "LayerTreeHostCommon::SortLayers");
-  layer_sorter->Sort(first, end);
-}
-
 template <typename LayerType>
 static gfx::Vector2dF GetEffectiveScrollDelta(LayerType* layer) {
   // Layer's scroll offset can have an integer part and fractional part.
@@ -1128,6 +1113,8 @@
     int current_render_surface_layer_list_id) {
   layer->draw_properties().last_drawn_render_surface_layer_list_id =
       current_render_surface_layer_list_id;
+  layer->draw_properties().layer_or_descendant_is_drawn =
+      !!current_render_surface_layer_list_id;
 }
 
 template <typename LayerTypePtr>
@@ -1200,8 +1187,7 @@
         data.layer_or_descendant_has_copy_request;
     layer_or_descendant_has_input_handler |=
         data.layer_or_descendant_has_input_handler;
-    num_unclipped_descendants +=
-        data.num_unclipped_descendants;
+    num_unclipped_descendants += data.num_unclipped_descendants;
   }
 };
 
@@ -1233,6 +1219,7 @@
 
   layer->draw_properties().sorted_for_recursion = false;
   layer->draw_properties().has_child_with_a_scroll_parent = false;
+  layer->draw_properties().layer_or_descendant_is_drawn = false;
   layer->draw_properties().visited = false;
 
   if (!HasInvertibleOrAnimatedTransform(layer)) {
@@ -1279,7 +1266,6 @@
 
 template <typename LayerType>
 struct SubtreeGlobals {
-  LayerSorter* layer_sorter;
   int max_texture_size;
   float device_scale_factor;
   float page_scale_factor;
@@ -1814,8 +1800,6 @@
   // layer's "screen space" and local content space.
   layer_draw_properties.screen_space_transform =
       data_from_ancestor.full_hierarchy_matrix;
-  if (layer->should_flatten_transform())
-    layer_draw_properties.screen_space_transform.FlattenTo2d();
   layer_draw_properties.screen_space_transform.PreconcatTransform
       (layer_draw_properties.target_space_transform);
 
@@ -1934,6 +1918,10 @@
     data_for_children.full_hierarchy_matrix.PreconcatTransform(
         render_surface->draw_transform());
 
+    // A render surface inherently acts as a flattening point for the content of
+    // its descendants.
+    data_for_children.full_hierarchy_matrix.FlattenTo2d();
+
     if (layer->mask_layer()) {
       DrawProperties<LayerType>& mask_layer_draw_properties =
           layer->mask_layer()->draw_properties();
@@ -2212,6 +2200,8 @@
         render_surface_layer_list->size() -
         child->draw_properties()
             .index_of_first_render_surface_layer_list_addition;
+    layer_draw_properties.layer_or_descendant_is_drawn |=
+        child->draw_properties().layer_or_descendant_is_drawn;
   }
 
   // Add the unsorted layer list contributions, if necessary.
@@ -2365,17 +2355,6 @@
     return;
   }
 
-  // If preserves-3d then sort all the descendants in 3D so that they can be
-  // drawn from back to front. If the preserves-3d property is also set on the
-  // parent then skip the sorting as the parent will sort all the descendants
-  // anyway.
-  if (globals.layer_sorter && descendants.size() && layer->Is3dSorted() &&
-      !LayerIsInExisting3DRenderingContext(layer)) {
-    SortLayers(descendants.begin() + sorting_start_index,
-               descendants.end(),
-               globals.layer_sorter);
-  }
-
   UpdateAccumulatedSurfaceState<LayerType>(
       layer, local_drawable_content_rect_of_subtree, accumulated_surface_state);
 
@@ -2413,7 +2392,6 @@
   scaled_device_transform.Scale(inputs.device_scale_factor,
                                 inputs.device_scale_factor);
 
-  globals->layer_sorter = NULL;
   globals->max_texture_size = inputs.max_texture_size;
   globals->device_scale_factor =
       inputs.device_scale_factor * device_transform_scale;
@@ -2577,9 +2555,6 @@
   DataForRecursion<LayerImpl> data_for_recursion;
   ProcessCalcDrawPropsInputs(*inputs, &globals, &data_for_recursion);
 
-  LayerSorter layer_sorter;
-  globals.layer_sorter = &layer_sorter;
-
   PreCalculateMetaInformationRecursiveData recursive_data;
   PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
   std::vector<AccumulatedSurfaceState<LayerImpl>> accumulated_surface_state;
diff --git a/cc/trees/layer_tree_host_common_perftest.cc b/cc/trees/layer_tree_host_common_perftest.cc
index 73d5c1d..1732e55 100644
--- a/cc/trees/layer_tree_host_common_perftest.cc
+++ b/cc/trees/layer_tree_host_common_perftest.cc
@@ -25,7 +25,6 @@
 #include "cc/test/layer_tree_json_parser.h"
 #include "cc/test/layer_tree_test.h"
 #include "cc/test/paths.h"
-#include "cc/trees/layer_sorter.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "testing/perf/perf_test.h"
 
@@ -162,55 +161,7 @@
   }
 };
 
-class LayerSorterMainTest : public CalcDrawPropsImplTest {
- public:
-  void RunSortLayers() { RunTest(false, false, false); }
-
-  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
-
-  void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
-    LayerTreeImpl* active_tree = host_impl->active_tree();
-    // First build the tree and then we'll start running tests on layersorter
-    // itself
-    bool can_render_to_separate_surface = true;
-    int max_texture_size = 8096;
-    DoCalcDrawPropertiesImpl(can_render_to_separate_surface,
-                             max_texture_size,
-                             active_tree,
-                             host_impl);
-
-    // Behaviour of this test is different from that of sorting in practice.
-    // In this case, all layers that exist in any 3D context are put into a list
-    // and are sorted as one big 3D context instead of several smaller ones.
-    BuildLayerImplList(active_tree->root_layer(), &base_list_);
-    timer_.Reset();
-    do {
-      // Here we'll move the layers into a LayerImpl list of their own to be
-      // sorted so we don't have a sorted list for every run after the first
-      LayerImplList test_list = base_list_;
-      layer_sorter_.Sort(test_list.begin(), test_list.end());
-      timer_.NextLap();
-    } while (!timer_.HasTimeLimitExpired());
-
-    EndTest();
-  }
-
-  void BuildLayerImplList(LayerImpl* layer, LayerImplList* list) {
-    if (layer->Is3dSorted()) {
-      list->push_back(layer);
-    }
-
-    for (size_t i = 0; i < layer->children().size(); i++) {
-      BuildLayerImplList(layer->children()[i], list);
-    }
-  }
-
- private:
-  LayerImplList base_list_;
-  LayerSorter layer_sorter_;
-};
-
-class BspTreePerfTest : public LayerSorterMainTest {
+class BspTreePerfTest : public CalcDrawPropsImplTest {
  public:
   void RunSortLayers() { RunTest(false, false, false); }
 
@@ -261,7 +212,18 @@
     EndTest();
   }
 
+  void BuildLayerImplList(LayerImpl* layer, LayerImplList* list) {
+    if (layer->Is3dSorted()) {
+      list->push_back(layer);
+    }
+
+    for (size_t i = 0; i < layer->children().size(); i++) {
+      BuildLayerImplList(layer->children()[i], list);
+    }
+  }
+
  private:
+  LayerImplList base_list_;
   int num_duplicates_;
 };
 
@@ -313,13 +275,13 @@
   RunCalcDrawProps();
 }
 
-TEST_F(LayerSorterMainTest, LayerSorterCubes) {
+TEST_F(BspTreePerfTest, LayerSorterCubes) {
   SetTestName("layer_sort_cubes");
   ReadTestFile("layer_sort_cubes");
   RunSortLayers();
 }
 
-TEST_F(LayerSorterMainTest, LayerSorterRubik) {
+TEST_F(BspTreePerfTest, LayerSorterRubik) {
   SetTestName("layer_sort_rubik");
   ReadTestFile("layer_sort_rubik");
   // TODO(vollick): Remove verify_property_trees setting after
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 6234d87..d2c473e 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -1478,6 +1478,74 @@
   }
 }
 
+TEST_F(LayerTreeHostCommonTest, RenderSurfacesFlattenScreenSpaceTransform) {
+  // Render surfaces act as a flattening point for their subtree, so should
+  // always flatten the target-to-screen space transform seen by descendants.
+
+  scoped_refptr<Layer> root = Layer::Create();
+  scoped_refptr<Layer> parent = Layer::Create();
+  scoped_refptr<LayerWithForcedDrawsContent> child =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+  scoped_refptr<LayerWithForcedDrawsContent> grand_child =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+
+  gfx::Transform rotation_about_y_axis;
+  rotation_about_y_axis.RotateAboutYAxis(30.0);
+  // Make |parent| have a render surface.
+  parent->SetOpacity(0.9f);
+
+  const gfx::Transform identity_matrix;
+  SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(100, 100), true, false);
+  SetLayerPropertiesForTesting(parent.get(), rotation_about_y_axis,
+                               gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+                               true, false);
+  SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(10, 10), true, false);
+  SetLayerPropertiesForTesting(grand_child.get(), identity_matrix,
+                               gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+                               true, false);
+
+  root->AddChild(parent);
+  parent->AddChild(child);
+  child->AddChild(grand_child);
+
+  grand_child->SetShouldFlattenTransform(false);
+
+  scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost());
+  host->SetRootLayer(root);
+
+  // Only grand_child should preserve 3d.
+  EXPECT_TRUE(root->should_flatten_transform());
+  EXPECT_TRUE(parent->should_flatten_transform());
+  EXPECT_TRUE(child->should_flatten_transform());
+  EXPECT_FALSE(grand_child->should_flatten_transform());
+
+  gfx::Transform expected_child_draw_transform = identity_matrix;
+  gfx::Transform expected_grand_child_draw_transform = identity_matrix;
+
+  gfx::Transform flattened_rotation_about_y = rotation_about_y_axis;
+  flattened_rotation_about_y.FlattenTo2d();
+
+  ExecuteCalculateDrawProperties(root.get());
+
+  EXPECT_TRUE(parent->render_surface());
+  EXPECT_FALSE(child->render_surface());
+  EXPECT_FALSE(grand_child->render_surface());
+
+  EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, child->draw_transform());
+  EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
+                                  grand_child->draw_transform());
+
+  // The screen-space transform inherited by |child| and |grand_child| should
+  // have been flattened at their render target. In particular, the fact that
+  // |grand_child| happens to preserve 3d shouldn't affect this flattening.
+  EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_y,
+                                  child->screen_space_transform());
+  EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_y,
+                                  grand_child->screen_space_transform());
+}
+
 TEST_F(LayerTreeHostCommonTest, ClipRectCullsRenderSurfaces) {
   // The entire subtree of layers that are outside the clip rect should be
   // culled away, and should not affect the render_surface_layer_list.
@@ -2975,78 +3043,6 @@
   EXPECT_FALSE(child->draw_properties().sorted_for_recursion);
 }
 
-TEST_F(LayerTreeHostCommonTest, WillSortAtContextBoundary) {
-  // Creates a layer tree that looks as follows:
-  // * root (sorting-context-id1)
-  //   * parent (sorting-context-id2)
-  //     * child1 (sorting-context-id2)
-  //     * child2 (sorting-context-id2)
-  //
-  // This test ensures that we sort at |parent| even though both it and root are
-  // set to be 3d sorted.
-  FakeImplProxy proxy;
-  TestSharedBitmapManager shared_bitmap_manager;
-  FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager);
-
-  scoped_ptr<LayerImpl> root_ptr(LayerImpl::Create(host_impl.active_tree(), 1));
-  LayerImpl* root = root_ptr.get();
-  scoped_ptr<LayerImpl> parent_ptr(
-      LayerImpl::Create(host_impl.active_tree(), 2));
-  LayerImpl* parent = parent_ptr.get();
-  scoped_ptr<LayerImpl> child1_ptr(
-      LayerImpl::Create(host_impl.active_tree(), 3));
-  LayerImpl* child1 = child1_ptr.get();
-  scoped_ptr<LayerImpl> child2_ptr(
-      LayerImpl::Create(host_impl.active_tree(), 4));
-  LayerImpl* child2 = child2_ptr.get();
-
-  gfx::Transform identity_matrix;
-  gfx::Transform below_matrix;
-  below_matrix.Translate3d(0.f, 0.f, -10.f);
-  gfx::Transform above_matrix;
-  above_matrix.Translate3d(0.f, 0.f, 10.f);
-
-  SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
-                               gfx::PointF(), gfx::Size(100, 100), true, true,
-                               true);
-  SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
-                               gfx::PointF(), gfx::Size(50, 50), true, true,
-                               true);
-  SetLayerPropertiesForTesting(child1, above_matrix, gfx::Point3F(),
-                               gfx::PointF(), gfx::Size(50, 50), true, true,
-                               false);
-  SetLayerPropertiesForTesting(child2, below_matrix, gfx::Point3F(),
-                               gfx::PointF(), gfx::Size(50, 50), true, true,
-                               false);
-
-  root->Set3dSortingContextId(3);
-  root->SetDrawsContent(true);
-  parent->Set3dSortingContextId(7);
-  parent->SetDrawsContent(true);
-  child1->Set3dSortingContextId(7);
-  child1->SetDrawsContent(true);
-  child2->Set3dSortingContextId(7);
-  child2->SetDrawsContent(true);
-
-  parent->AddChild(child1_ptr.Pass());
-  parent->AddChild(child2_ptr.Pass());
-  root->AddChild(parent_ptr.Pass());
-
-  LayerImplList render_surface_layer_list;
-  LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root_ptr.get(), root->bounds(), &render_surface_layer_list);
-  inputs.can_adjust_raster_scales = true;
-  LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
-  EXPECT_TRUE(root->render_surface());
-  EXPECT_EQ(2u, render_surface_layer_list.size());
-
-  EXPECT_EQ(3u, parent->render_surface()->layer_list().size());
-  EXPECT_EQ(child2->id(), parent->render_surface()->layer_list().at(0)->id());
-  EXPECT_EQ(parent->id(), parent->render_surface()->layer_list().at(1)->id());
-  EXPECT_EQ(child1->id(), parent->render_surface()->layer_list().at(2)->id());
-}
-
 TEST_F(LayerTreeHostCommonTest,
        SingularNonAnimatingTransformDoesNotPreventClearingDrawProperties) {
   scoped_refptr<Layer> root = Layer::Create();
@@ -7592,110 +7588,6 @@
   EXPECT_TRUE(render_surface_layer_list.at(2)->render_surface());
 }
 
-TEST_F(LayerTreeHostCommonTest, DoNotClobberSorting) {
-  // We rearrange layer list contributions if we have to visit children out of
-  // order, but it should be a 'stable' rearrangement. That is, the layer list
-  // additions for a single layer should not be reordered, though their position
-  // wrt to the contributions due to a sibling may vary.
-  //
-  // + root
-  //   + scroll_child
-  //     + top_content
-  //     + bottom_content
-  //   + scroll_parent_border
-  //     + scroll_parent_clip
-  //       + scroll_parent
-  //
-  FakeImplProxy proxy;
-  TestSharedBitmapManager shared_bitmap_manager;
-  FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager);
-  host_impl.CreatePendingTree();
-  scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1);
-  scoped_ptr<LayerImpl> scroll_parent_border =
-      LayerImpl::Create(host_impl.active_tree(), 2);
-  scoped_ptr<LayerImpl> scroll_parent_clip =
-      LayerImpl::Create(host_impl.active_tree(), 3);
-  scoped_ptr<LayerImpl> scroll_parent =
-      LayerImpl::Create(host_impl.active_tree(), 4);
-  scoped_ptr<LayerImpl> scroll_child =
-      LayerImpl::Create(host_impl.active_tree(), 5);
-  scoped_ptr<LayerImpl> bottom_content =
-      LayerImpl::Create(host_impl.active_tree(), 6);
-  scoped_ptr<LayerImpl> top_content =
-      LayerImpl::Create(host_impl.active_tree(), 7);
-
-  scroll_parent_clip->SetMasksToBounds(true);
-
-  scroll_child->SetScrollParent(scroll_parent.get());
-  scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
-  scroll_children->insert(scroll_child.get());
-  scroll_parent->SetScrollChildren(scroll_children.release());
-
-  scroll_child->SetDrawsContent(true);
-  scroll_parent->SetDrawsContent(true);
-  top_content->SetDrawsContent(true);
-  bottom_content->SetDrawsContent(true);
-
-  gfx::Transform identity_transform;
-  gfx::Transform top_transform;
-  top_transform.Translate3d(0.0, 0.0, 5.0);
-  gfx::Transform bottom_transform;
-  bottom_transform.Translate3d(0.0, 0.0, 3.0);
-
-  SetLayerPropertiesForTesting(root.get(), identity_transform, gfx::Point3F(),
-                               gfx::PointF(), gfx::Size(50, 50), true, false,
-                               true);
-  SetLayerPropertiesForTesting(scroll_parent_border.get(), identity_transform,
-                               gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40),
-                               true, false, false);
-  SetLayerPropertiesForTesting(scroll_parent_clip.get(), identity_transform,
-                               gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
-                               true, false, false);
-  SetLayerPropertiesForTesting(scroll_parent.get(), identity_transform,
-                               gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50),
-                               true, false, false);
-  SetLayerPropertiesForTesting(scroll_child.get(), identity_transform,
-                               gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50),
-                               true, false, false);
-  SetLayerPropertiesForTesting(top_content.get(), top_transform, gfx::Point3F(),
-                               gfx::PointF(), gfx::Size(50, 50), false, true,
-                               true);
-  SetLayerPropertiesForTesting(bottom_content.get(), bottom_transform,
-                               gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50),
-                               false, true, true);
-
-  scroll_child->SetShouldFlattenTransform(false);
-  scroll_child->Set3dSortingContextId(1);
-
-  scroll_child->AddChild(top_content.Pass());
-  scroll_child->AddChild(bottom_content.Pass());
-  root->AddChild(scroll_child.Pass());
-
-  scroll_parent_clip->AddChild(scroll_parent.Pass());
-  scroll_parent_border->AddChild(scroll_parent_clip.Pass());
-  root->AddChild(scroll_parent_border.Pass());
-
-  LayerImplList render_surface_layer_list;
-  LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root.get(), root->bounds(), &render_surface_layer_list);
-
-  LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
-  EXPECT_TRUE(root->render_surface());
-
-  // If we don't sort by depth and let the layers get added in the order they
-  // would normally be visited in, then layers 6 and 7 will be out of order. In
-  // other words, although we've had to shift 5, 6, and 7 to appear before 4
-  // in the list (because of the scroll parent relationship), this should not
-  // have an effect on the the order of 5, 6, and 7 (which had been reordered
-  // due to layer sorting).
-  EXPECT_EQ(4u, root->render_surface()->layer_list().size());
-  EXPECT_EQ(5, root->render_surface()->layer_list().at(0)->id());
-  EXPECT_EQ(6, root->render_surface()->layer_list().at(1)->id());
-  EXPECT_EQ(7, root->render_surface()->layer_list().at(2)->id());
-  EXPECT_EQ(4, root->render_surface()->layer_list().at(3)->id());
-}
-
 TEST_F(LayerTreeHostCommonTest, ScrollCompensationWithRounding) {
   // This test verifies that a scrolling layer that gets snapped to
   // integer coordinates doesn't move a fixed position child.
@@ -8850,5 +8742,59 @@
             grandchild->visible_rect_from_property_trees());
 }
 
+TEST_F(LayerTreeHostCommonTest, CombineClipsUsingContentTarget) {
+  // In the following layer tree, the layer |box|'s render target is |surface|.
+  // |surface| also creates a transform node. We want to combine clips for |box|
+  // in the space of its target (i.e., |surface|), not its target's target. This
+  // test ensures that happens.
+
+  gfx::Transform rotate;
+  rotate.Rotate(5);
+  gfx::Transform identity;
+
+  scoped_refptr<Layer> root = Layer::Create();
+  SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(2500, 1500), true,
+                               false);
+
+  scoped_refptr<Layer> frame_clip = Layer::Create();
+  SetLayerPropertiesForTesting(frame_clip.get(), identity, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(2500, 1500), true,
+                               false);
+  frame_clip->SetMasksToBounds(true);
+
+  scoped_refptr<Layer> rotated = Layer::Create();
+  SetLayerPropertiesForTesting(rotated.get(), rotate,
+                               gfx::Point3F(1250, 250, 0), gfx::PointF(),
+                               gfx::Size(2500, 500), true, false);
+
+  scoped_refptr<Layer> surface = Layer::Create();
+  SetLayerPropertiesForTesting(surface.get(), rotate, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(2500, 500), true,
+                               false);
+  surface->SetOpacity(0.5);
+
+  scoped_refptr<LayerWithForcedDrawsContent> container =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+  SetLayerPropertiesForTesting(container.get(), identity, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(300, 300), true, false);
+
+  scoped_refptr<LayerWithForcedDrawsContent> box =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+  SetLayerPropertiesForTesting(box.get(), identity, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(100, 100), true, false);
+
+  root->AddChild(frame_clip);
+  frame_clip->AddChild(rotated);
+  rotated->AddChild(surface);
+  surface->AddChild(container);
+  surface->AddChild(box);
+
+  scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost());
+  host->SetRootLayer(root);
+
+  ExecuteCalculateDrawProperties(root.get());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 2f4d9a9..f81a3b1 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -708,10 +708,11 @@
     return DRAW_SUCCESS;
   }
 
-  TRACE_EVENT1("cc",
-               "LayerTreeHostImpl::CalculateRenderPasses",
-               "render_surface_layer_list.size()",
-               static_cast<uint64>(frame->render_surface_layer_list->size()));
+  TRACE_EVENT_BEGIN2(
+      "cc", "LayerTreeHostImpl::CalculateRenderPasses",
+      "render_surface_layer_list.size()",
+      static_cast<uint64>(frame->render_surface_layer_list->size()),
+      "RequiresHighResToDraw", RequiresHighResToDraw());
 
   // Create the render passes in dependency order.
   for (int surface_index = frame->render_surface_layer_list->size() - 1;
@@ -754,9 +755,6 @@
   // due to an impl-animation, we drop the frame to avoid flashing due to the
   // texture suddenly appearing in the future.
   DrawResult draw_result = DRAW_SUCCESS;
-  // When we have a copy request for a layer, we need to draw no matter
-  // what, as the layer may disappear after this frame.
-  bool have_copy_request = false;
 
   int layers_drawn = 0;
 
@@ -764,6 +762,8 @@
 
   int num_missing_tiles = 0;
   int num_incomplete_tiles = 0;
+  bool have_copy_request = false;
+  bool have_missing_animated_tiles = false;
 
   auto end = LayerIterator<LayerImpl>::End(frame->render_surface_layer_list);
   for (auto it =
@@ -848,18 +848,34 @@
           it->screen_space_transform_is_animating() ||
           it->draw_transform_is_animating();
       if (layer_has_animating_transform)
-        draw_result = DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
-    }
-
-    if (append_quads_data.num_incomplete_tiles ||
-        append_quads_data.num_missing_tiles) {
-      if (RequiresHighResToDraw())
-        draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
+        have_missing_animated_tiles = true;
     }
   }
 
-  if (have_copy_request ||
-      output_surface_->capabilities().draw_and_swap_full_viewport_every_frame)
+  if (have_missing_animated_tiles)
+    draw_result = DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
+
+  // When we have a copy request for a layer, we need to draw even if there
+  // would be animating checkerboards, because failing under those conditions
+  // triggers a new main frame, which may cause the copy request layer to be
+  // destroyed.
+  // TODO(danakj): Leaking scheduler internals into LayerTreeHostImpl here.
+  if (have_copy_request)
+    draw_result = DRAW_SUCCESS;
+
+  // When we require high res to draw, abort the draw (almost) always. This does
+  // not cause the scheduler to do a main frame, instead it will continue to try
+  // drawing until we finally complete, so the copy request will not be lost.
+  if (num_incomplete_tiles || num_missing_tiles) {
+    if (RequiresHighResToDraw())
+      draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
+  }
+
+  // When this capability is set we don't have control over the surface the
+  // compositor draws to, so even though the frame may not be complete, the
+  // previous frame has already been potentially lost, so an incomplete frame is
+  // better than nothing, so this takes highest precidence.
+  if (output_surface_->capabilities().draw_and_swap_full_viewport_every_frame)
     draw_result = DRAW_SUCCESS;
 
 #if DCHECK_IS_ON()
@@ -910,6 +926,10 @@
          frame->render_passes.size() == 1u)
       << frame->render_passes.size();
 
+  TRACE_EVENT_END2("cc", "LayerTreeHostImpl::CalculateRenderPasses",
+                   "draw_result", draw_result, "missing tiles",
+                   num_missing_tiles);
+
   return draw_result;
 }
 
@@ -1055,7 +1075,7 @@
   // This will cause NotifyTileStateChanged() to be called for any visible tiles
   // that completed, which will add damage to the frame for them so they appear
   // as part of the current frame being drawn.
-  if (settings().impl_side_painting)
+  if (tile_manager_)
     tile_manager_->UpdateVisibleTiles(global_tile_state_);
 
   frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList();
@@ -1528,7 +1548,7 @@
 
   if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) {
     bool disable_picture_quad_image_filtering =
-        IsActivelyScrolling() || needs_animate_layers();
+        IsActivelyScrolling() || animation_registrar_->needs_animate_layers();
 
     scoped_ptr<SoftwareRenderer> temp_software_renderer =
         SoftwareRenderer::Create(this, &settings_.renderer_settings,
@@ -1656,6 +1676,18 @@
   if (!inner_container)
     return;
 
+  // TODO(bokan): This code is currently specific to top controls. It should be
+  // made general. crbug.com/464814.
+  if (!TopControlsHeight()) {
+    if (outer_container)
+      outer_container->SetBoundsDelta(gfx::Vector2dF());
+
+    inner_container->SetBoundsDelta(gfx::Vector2dF());
+    active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(gfx::Vector2dF());
+
+    return;
+  }
+
   ViewportAnchor anchor(InnerViewportScrollLayer(),
                         OuterViewportScrollLayer());
 
@@ -1693,7 +1725,8 @@
 void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() {
   // Only valid for the single-threaded non-scheduled/synchronous case
   // using the zero copy raster worker pool.
-  single_thread_synchronous_task_graph_runner_->RunUntilIdle();
+  if (tile_manager_)
+    single_thread_synchronous_task_graph_runner_->RunUntilIdle();
 }
 
 void LayerTreeHostImpl::DidLoseOutputSurface() {
@@ -2057,6 +2090,11 @@
     }
   }
 
+  // Synchronous single-threaded mode depends on tiles being ready to
+  // draw when raster is complete.  Therefore, it must use one of zero
+  // copy, software raster, or GPU raster (in the branches above).
+  DCHECK(!IsSynchronousSingleThreaded());
+
   *resource_pool = ResourcePool::Create(
       resource_provider_.get(), GL_TEXTURE_2D);
 
@@ -2119,7 +2157,7 @@
 
   CreateAndSetRenderer();
 
-  if (settings_.impl_side_painting)
+  if (settings_.impl_side_painting && settings_.raster_enabled)
     CreateAndSetTileManager();
   RecreateTreeResources();
 
@@ -3112,52 +3150,35 @@
 }
 
 void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) {
-  if (!settings_.accelerated_animation_enabled ||
-      !needs_animate_layers() ||
-      !active_tree_->root_layer())
+  if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer())
     return;
 
-  TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers");
-  AnimationRegistrar::AnimationControllerMap controllers_copy =
-      animation_registrar_->active_animation_controllers();
-  for (auto& it : controllers_copy)
-    it.second->Animate(monotonic_time);
-
-  SetNeedsAnimate();
+  if (animation_registrar_->AnimateLayers(monotonic_time))
+    SetNeedsAnimate();
 }
 
 void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
-  if (!settings_.accelerated_animation_enabled || !needs_animate_layers() ||
-      !active_tree_->root_layer())
+  if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer())
     return;
 
-  TRACE_EVENT0("cc", "LayerTreeHostImpl::UpdateAnimationState");
   scoped_ptr<AnimationEventsVector> events =
-      make_scoped_ptr(new AnimationEventsVector);
-  AnimationRegistrar::AnimationControllerMap active_controllers_copy =
-      animation_registrar_->active_animation_controllers();
-  for (auto& it : active_controllers_copy)
-    it.second->UpdateState(start_ready_animations, events.get());
+      animation_registrar_->CreateEvents();
+  const bool has_active_animations = animation_registrar_->UpdateAnimationState(
+      start_ready_animations, events.get());
 
-  if (!events->empty()) {
+  if (!events->empty())
     client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass());
-  }
 
-  SetNeedsAnimate();
+  if (has_active_animations)
+    SetNeedsAnimate();
 }
 
 void LayerTreeHostImpl::ActivateAnimations() {
-  if (!settings_.accelerated_animation_enabled || !needs_animate_layers() ||
-      !active_tree_->root_layer())
+  if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer())
     return;
 
-  TRACE_EVENT0("cc", "LayerTreeHostImpl::ActivateAnimations");
-  AnimationRegistrar::AnimationControllerMap active_controllers_copy =
-      animation_registrar_->active_animation_controllers();
-  for (auto& it : active_controllers_copy)
-    it.second->ActivateAnimations();
-
-  SetNeedsAnimate();
+  if (animation_registrar_->ActivateAnimations())
+    SetNeedsAnimate();
 }
 
 std::string LayerTreeHostImpl::LayerTreeAsJson() const {
@@ -3234,11 +3255,6 @@
 }
 
 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
-LayerTreeHostImpl::AsValue() const {
-  return AsValueWithFrame(NULL);
-}
-
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
 LayerTreeHostImpl::AsValueWithFrame(FrameData* frame) const {
   scoped_refptr<base::trace_event::TracedValue> state =
       new base::trace_event::TracedValue();
@@ -3246,11 +3262,6 @@
   return state;
 }
 
-void LayerTreeHostImpl::AsValueInto(
-    base::trace_event::TracedValue* value) const {
-  return AsValueWithFrameInto(NULL, value);
-}
-
 void LayerTreeHostImpl::AsValueWithFrameInto(
     FrameData* frame,
     base::trace_event::TracedValue* state) const {
@@ -3299,14 +3310,6 @@
   }
 }
 
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
-LayerTreeHostImpl::ActivationStateAsValue() const {
-  scoped_refptr<base::trace_event::TracedValue> state =
-      new base::trace_event::TracedValue();
-  ActivationStateAsValueInto(state.get());
-  return state;
-}
-
 void LayerTreeHostImpl::ActivationStateAsValueInto(
     base::trace_event::TracedValue* state) const {
   TracedValue::SetIDRef(this, state, "lthi");
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 73ed039..94012e0 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -380,10 +380,6 @@
 
   scoped_ptr<ScrollAndScaleSet> ProcessScrollDeltas();
 
-  bool needs_animate_layers() const {
-    return !animation_registrar_->active_animation_controllers().empty();
-  }
-
   void set_max_memory_needed_bytes(size_t bytes) {
     max_memory_needed_bytes_ = bytes;
   }
@@ -454,14 +450,10 @@
     return begin_impl_frame_interval_;
   }
 
-  void AsValueInto(base::trace_event::TracedValue* value) const;
   void AsValueWithFrameInto(FrameData* frame,
                             base::trace_event::TracedValue* value) const;
-  scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
   scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValueWithFrame(
       FrameData* frame) const;
-  scoped_refptr<base::trace_event::ConvertableToTraceFormat>
-  ActivationStateAsValue() const;
   void ActivationStateAsValueInto(base::trace_event::TracedValue* value) const;
 
   bool page_scale_animation_active() const { return !!page_scale_animation_; }
@@ -614,6 +606,7 @@
 
   // |resource_provider_| and |tile_manager_| can be NULL, e.g. when using tile-
   // free rendering - see OutputSurface::ForcedDrawToSoftwareDevice().
+  // |tile_manager_| can also be NULL when raster_enabled is false.
   scoped_ptr<ResourceProvider> resource_provider_;
   scoped_ptr<TileManager> tile_manager_;
   bool use_gpu_rasterization_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 7ffa683..4e3230b 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1558,192 +1558,160 @@
   base::TimeTicks fake_current_physical_time_;
 };
 
-#define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST()                            \
-  gfx::Size viewport_size(10, 10);                                             \
-  gfx::Size content_size(100, 100);                                            \
-                                                                               \
-  LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =             \
-      new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_,       \
-                                                shared_bitmap_manager_.get(),  \
-                                                &stats_instrumentation_);      \
-  host_impl_ = make_scoped_ptr(host_impl_override_time);                       \
-  host_impl_->InitializeRenderer(CreateOutputSurface());                       \
-  host_impl_->SetViewportSize(viewport_size);                                  \
-                                                                               \
-  scoped_ptr<LayerImpl> root =                                                 \
-      LayerImpl::Create(host_impl_->active_tree(), 1);                         \
-  root->SetBounds(viewport_size);                                              \
-                                                                               \
-  scoped_ptr<LayerImpl> scroll =                                               \
-      LayerImpl::Create(host_impl_->active_tree(), 2);                         \
-  scroll->SetScrollClipLayer(root->id());                                      \
-  scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());                 \
-  root->SetBounds(viewport_size);                                              \
-  scroll->SetBounds(content_size);                                             \
-  scroll->SetContentBounds(content_size);                                      \
-  scroll->SetIsContainerForFixedPositionLayers(true);                          \
-                                                                               \
-  scoped_ptr<LayerImpl> contents =                                             \
-      LayerImpl::Create(host_impl_->active_tree(), 3);                         \
-  contents->SetDrawsContent(true);                                             \
-  contents->SetBounds(content_size);                                           \
-  contents->SetContentBounds(content_size);                                    \
-                                                                               \
-  scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =                         \
-      SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,       \
-                                           VERTICAL, 10, 0, false, true);      \
-  EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());                                  \
-                                                                               \
-  scroll->AddChild(contents.Pass());                                           \
-  root->AddChild(scroll.Pass());                                               \
-  root->SetHasRenderSurface(true);                                             \
-  scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);                            \
-  root->AddChild(scrollbar.Pass());                                            \
-                                                                               \
-  host_impl_->active_tree()->SetRootLayer(root.Pass());                        \
-  host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, \
-                                                      Layer::INVALID_ID);      \
-  host_impl_->active_tree()->DidBecomeActive();                                \
-  DrawFrame();
+class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
+ protected:
+  void SetupLayers(LayerTreeSettings settings) {
+    gfx::Size viewport_size(10, 10);
+    gfx::Size content_size(100, 100);
 
-TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
-  LayerTreeSettings settings;
-  settings.scrollbar_animator = LayerTreeSettings::LINEAR_FADE;
-  settings.scrollbar_fade_delay_ms = 20;
-  settings.scrollbar_fade_duration_ms = 20;
+    LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
+        new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_,
+                                                  shared_bitmap_manager_.get(),
+                                                  &stats_instrumentation_);
+    host_impl_ = make_scoped_ptr(host_impl_override_time);
+    host_impl_->InitializeRenderer(CreateOutputSurface());
+    host_impl_->SetViewportSize(viewport_size);
 
-  SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
+    scoped_ptr<LayerImpl> root =
+        LayerImpl::Create(host_impl_->active_tree(), 1);
+    root->SetBounds(viewport_size);
 
-  base::TimeTicks fake_now = gfx::FrameTime::Now();
+    scoped_ptr<LayerImpl> scroll =
+        LayerImpl::Create(host_impl_->active_tree(), 2);
+    scroll->SetScrollClipLayer(root->id());
+    scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
+    root->SetBounds(viewport_size);
+    scroll->SetBounds(content_size);
+    scroll->SetContentBounds(content_size);
+    scroll->SetIsContainerForFixedPositionLayers(true);
 
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_FALSE(did_request_redraw_);
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+    scoped_ptr<LayerImpl> contents =
+        LayerImpl::Create(host_impl_->active_tree(), 3);
+    contents->SetDrawsContent(true);
+    contents->SetBounds(content_size);
+    contents->SetContentBounds(content_size);
 
-  // If no scroll happened during a scroll gesture, it should have no effect.
-  host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
-  host_impl_->ScrollEnd();
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_FALSE(did_request_redraw_);
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+    scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
+        SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,
+                                             VERTICAL, 10, 0, false, true);
+    EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
 
-  // After a scroll, a fade animation should be scheduled about 20ms from now.
-  host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
-  host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_TRUE(did_request_redraw_);
-  did_request_redraw_ = false;
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+    scroll->AddChild(contents.Pass());
+    root->AddChild(scroll.Pass());
+    root->SetHasRenderSurface(true);
+    scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
+    root->AddChild(scrollbar.Pass());
 
-  host_impl_->ScrollEnd();
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_FALSE(did_request_redraw_);
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_);
-  EXPECT_FALSE(animation_task_.Equals(base::Closure()));
+    host_impl_->active_tree()->SetRootLayer(root.Pass());
+    host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
+                                                        Layer::INVALID_ID);
+    host_impl_->active_tree()->DidBecomeActive();
+    DrawFrame();
+  }
 
-  fake_now += requested_animation_delay_;
-  requested_animation_delay_ = base::TimeDelta();
-  animation_task_.Run();
-  animation_task_ = base::Closure();
-  EXPECT_TRUE(did_request_animate_);
-  did_request_animate_ = false;
-  EXPECT_FALSE(did_request_redraw_);
+  void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
+    LayerTreeSettings settings;
+    settings.scrollbar_animator = animator;
+    settings.scrollbar_fade_delay_ms = 20;
+    settings.scrollbar_fade_duration_ms = 20;
 
-  // After the fade begins, we should start getting redraws instead of a
-  // scheduled animation.
-  host_impl_->Animate(fake_now);
-  EXPECT_TRUE(did_request_animate_);
-  did_request_animate_ = false;
-  EXPECT_TRUE(did_request_redraw_);
-  did_request_redraw_ = false;
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+    SetupLayers(settings);
 
-  // Setting the scroll offset outside a scroll should also cause the scrollbar
-  // to appear and to schedule a fade.
-  host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
-      gfx::ScrollOffset(5, 5));
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_FALSE(did_request_redraw_);
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_);
-  EXPECT_FALSE(animation_task_.Equals(base::Closure()));
-  requested_animation_delay_ = base::TimeDelta();
-  animation_task_ = base::Closure();
+    base::TimeTicks fake_now = gfx::FrameTime::Now();
 
-  // Unnecessarily Fade animation of solid color scrollbar is not triggered.
-  host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
-  host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_TRUE(did_request_redraw_);
-  did_request_redraw_ = false;
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_FALSE(did_request_redraw_);
+    EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
+    EXPECT_TRUE(animation_task_.Equals(base::Closure()));
 
-  host_impl_->ScrollEnd();
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_FALSE(did_request_redraw_);
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+    // If no scroll happened during a scroll gesture, it should have no effect.
+    host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
+    host_impl_->ScrollEnd();
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_FALSE(did_request_redraw_);
+    EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
+    EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+
+    // After a scroll, a scrollbar animation should be scheduled about 20ms from
+    // now.
+    host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
+    host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_TRUE(did_request_redraw_);
+    did_request_redraw_ = false;
+    EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
+    EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+
+    host_impl_->ScrollEnd();
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_FALSE(did_request_redraw_);
+    EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
+              requested_animation_delay_);
+    EXPECT_FALSE(animation_task_.Equals(base::Closure()));
+
+    fake_now += requested_animation_delay_;
+    requested_animation_delay_ = base::TimeDelta();
+    animation_task_.Run();
+    animation_task_ = base::Closure();
+    EXPECT_TRUE(did_request_animate_);
+    did_request_animate_ = false;
+    EXPECT_FALSE(did_request_redraw_);
+
+    // After the scrollbar animation begins, we should start getting redraws.
+    host_impl_->Animate(fake_now);
+    EXPECT_TRUE(did_request_animate_);
+    did_request_animate_ = false;
+    EXPECT_TRUE(did_request_redraw_);
+    did_request_redraw_ = false;
+    EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
+    EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+
+    // Setting the scroll offset outside a scroll should also cause the
+    // scrollbar to appear and to schedule a scrollbar animation.
+    host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
+        gfx::ScrollOffset(5, 5));
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_FALSE(did_request_redraw_);
+    EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
+              requested_animation_delay_);
+    EXPECT_FALSE(animation_task_.Equals(base::Closure()));
+    requested_animation_delay_ = base::TimeDelta();
+    animation_task_ = base::Closure();
+
+    // Scrollbar animation is not triggered unnecessarily.
+    host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
+    host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_TRUE(did_request_redraw_);
+    did_request_redraw_ = false;
+    EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
+    EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+
+    host_impl_->ScrollEnd();
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_FALSE(did_request_redraw_);
+    EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
+    EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+
+    // Changing page scale triggers scrollbar animation.
+    host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
+    host_impl_->SetPageScaleOnActiveTree(1.1f);
+    EXPECT_FALSE(did_request_animate_);
+    EXPECT_FALSE(did_request_redraw_);
+    EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
+              requested_animation_delay_);
+    EXPECT_FALSE(animation_task_.Equals(base::Closure()));
+    requested_animation_delay_ = base::TimeDelta();
+    animation_task_ = base::Closure();
+  }
+};
+
+TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
+  RunTest(LayerTreeSettings::LINEAR_FADE);
 }
 
-TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
-  LayerTreeSettings settings;
-  settings.scrollbar_animator = LayerTreeSettings::LINEAR_FADE;
-  settings.scrollbar_fade_delay_ms = 20;
-  settings.scrollbar_fade_duration_ms = 20;
-  settings.use_pinch_zoom_scrollbars = true;
-
-  SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
-
-  base::TimeTicks fake_now = gfx::FrameTime::Now();
-
-  host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
-
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_FALSE(did_request_animate_);
-
-  // If no scroll happened during a scroll gesture, it should have no effect.
-  host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
-  host_impl_->ScrollEnd();
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_FALSE(did_request_animate_);
-  EXPECT_TRUE(animation_task_.Equals(base::Closure()));
-
-  // After a scroll, no fade animation should be scheduled.
-  host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
-  host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
-  host_impl_->ScrollEnd();
-  did_request_redraw_ = false;
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_FALSE(did_request_animate_);
-  requested_animation_delay_ = base::TimeDelta();
-
-  // We should not see any draw requests.
-  fake_now += base::TimeDelta::FromMilliseconds(25);
-  EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
-  EXPECT_FALSE(did_request_animate_);
-
-  // Make page scale > min so that subsequent scrolls will trigger fades.
-  host_impl_->SetPageScaleOnActiveTree(1.1f);
-
-  // After a scroll, a fade animation should be scheduled about 20ms from now.
-  host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
-  host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
-  host_impl_->ScrollEnd();
-  did_request_redraw_ = false;
-  EXPECT_LT(base::TimeDelta::FromMilliseconds(19), requested_animation_delay_);
-  EXPECT_FALSE(did_request_animate_);
-  requested_animation_delay_ = base::TimeDelta();
-  animation_task_.Run();
-
-  // After the fade begins, we should start getting redraws instead of a
-  // scheduled animation.
-  fake_now += base::TimeDelta::FromMilliseconds(25);
-  host_impl_->Animate(fake_now);
-  EXPECT_TRUE(did_request_animate_);
+TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
+  RunTest(LayerTreeSettings::THINNING);
 }
 
 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
@@ -1960,6 +1928,16 @@
     did_draw_called_ = false;
   }
 
+  static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
+
+  void AddCopyRequest() {
+    ScopedPtrVector<CopyOutputRequest> requests;
+    requests.push_back(
+        CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
+    SetHasRenderSurface(true);
+    PassCopyRequests(&requests);
+  }
+
  protected:
   DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
       : LayerImpl(tree_impl, id),
@@ -2189,60 +2167,219 @@
   bool had_incomplete_tile_;
 };
 
-TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) {
+struct PrepareToDrawSuccessTestCase {
+  struct State {
+    bool has_missing_tile = false;
+    bool has_incomplete_tile = false;
+    bool is_animating = false;
+    bool has_copy_request = false;
+  };
+  bool high_res_required = false;
+  State layer_before;
+  State layer_between;
+  State layer_after;
+  DrawResult expected_result;
+
+  explicit PrepareToDrawSuccessTestCase(DrawResult result)
+      : expected_result(result) {}
+};
+
+TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
+  std::vector<PrepareToDrawSuccessTestCase> cases;
+
+  // 0. Default case.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  // 1. Animated layer first.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_before.is_animating = true;
+  // 2. Animated layer between.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_between.is_animating = true;
+  // 3. Animated layer last.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_after.is_animating = true;
+  // 4. Missing tile first.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_before.has_missing_tile = true;
+  // 5. Missing tile between.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_between.has_missing_tile = true;
+  // 6. Missing tile last.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_after.has_missing_tile = true;
+  // 7. Incomplete tile first.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_before.has_incomplete_tile = true;
+  // 8. Incomplete tile between.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_between.has_incomplete_tile = true;
+  // 9. Incomplete tile last.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_after.has_incomplete_tile = true;
+  // 10. Animation with missing tile.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_between.is_animating = true;
+  // 11. Animation with missing tile and copy request after. Must succeed
+  // because the animation checkerboard means we'll get a new frame and the copy
+  // request's layer may be destroyed.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_between.is_animating = true;
+  cases.back().layer_after.has_copy_request = true;
+  // 12. Animation with missing tile and copy request before. Must succeed
+  // because the animation checkerboard means we'll get a new frame and the copy
+  // request's layer may be destroyed.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_between.is_animating = true;
+  cases.back().layer_before.has_copy_request = true;
+  // 13. Animation with incomplete tile.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_between.has_incomplete_tile = true;
+  cases.back().layer_between.is_animating = true;
+
+  // 14. High res required.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().high_res_required = true;
+  // 15. High res required with incomplete tile.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_incomplete_tile = true;
+  // 16. High res required with missing tile.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_missing_tile = true;
+
+  // 17. High res required is higher priority than animating missing tiles.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_after.has_missing_tile = true;
+  cases.back().layer_after.is_animating = true;
+  // 18. High res required is higher priority than animating missing tiles.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_before.has_missing_tile = true;
+  cases.back().layer_before.is_animating = true;
+
+  // 19. High res required is higher priority than copy requests.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_after.has_copy_request = true;
+  // 20. High res required is higher priority than copy requests.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_before.has_copy_request = true;
+  // 21. High res required is higher priority than copy requests.
+  cases.push_back(
+      PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_between.has_copy_request = true;
+
   host_impl_->active_tree()->SetRootLayer(
       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   DidDrawCheckLayer* root =
       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   root->SetHasRenderSurface(true);
-  bool tile_missing = false;
-  bool had_incomplete_tile = false;
-  bool is_animating = false;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           2,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
 
   LayerTreeHostImpl::FrameData frame;
-
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
   host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
   host_impl_->DidDrawAllLayers(frame);
+  host_impl_->SwapBuffers(frame);
+
+  for (size_t i = 0; i < cases.size(); ++i) {
+    const auto& testcase = cases[i];
+    std::vector<LayerImpl*> to_remove;
+    for (auto* child : root->children())
+      to_remove.push_back(child);
+    for (auto* child : to_remove)
+      root->RemoveChild(child);
+
+    std::ostringstream scope;
+    scope << "Test case: " << i;
+    SCOPED_TRACE(scope.str());
+
+    root->AddChild(MissingTextureAnimatingLayer::Create(
+        host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
+        testcase.layer_before.has_incomplete_tile,
+        testcase.layer_before.is_animating, host_impl_->resource_provider()));
+    DidDrawCheckLayer* before =
+        static_cast<DidDrawCheckLayer*>(root->children().back());
+    if (testcase.layer_before.has_copy_request)
+      before->AddCopyRequest();
+
+    root->AddChild(MissingTextureAnimatingLayer::Create(
+        host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
+        testcase.layer_between.has_incomplete_tile,
+        testcase.layer_between.is_animating, host_impl_->resource_provider()));
+    DidDrawCheckLayer* between =
+        static_cast<DidDrawCheckLayer*>(root->children().back());
+    if (testcase.layer_between.has_copy_request)
+      between->AddCopyRequest();
+
+    root->AddChild(MissingTextureAnimatingLayer::Create(
+        host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
+        testcase.layer_after.has_incomplete_tile,
+        testcase.layer_after.is_animating, host_impl_->resource_provider()));
+    DidDrawCheckLayer* after =
+        static_cast<DidDrawCheckLayer*>(root->children().back());
+    if (testcase.layer_after.has_copy_request)
+      after->AddCopyRequest();
+
+    if (testcase.high_res_required)
+      host_impl_->SetRequiresHighResToDraw();
+
+    LayerTreeHostImpl::FrameData frame;
+    EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
+    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+    host_impl_->DidDrawAllLayers(frame);
+    host_impl_->SwapBuffers(frame);
+  }
 }
 
-TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
+TEST_F(LayerTreeHostImplTest,
+       PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
+  CreateHostImpl(DefaultSettings(),
+                 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
+  EXPECT_TRUE(host_impl_->output_surface()
+                  ->capabilities()
+                  .draw_and_swap_full_viewport_every_frame);
+
+  std::vector<PrepareToDrawSuccessTestCase> cases;
+
+  // 0. Default case.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  // 1. Animation with missing tile.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().layer_between.has_missing_tile = true;
+  cases.back().layer_between.is_animating = true;
+  // 2. High res required with incomplete tile.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_incomplete_tile = true;
+  // 3. High res required with missing tile.
+  cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
+  cases.back().high_res_required = true;
+  cases.back().layer_between.has_missing_tile = true;
+
   host_impl_->active_tree()->SetRootLayer(
       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   DidDrawCheckLayer* root =
       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   root->SetHasRenderSurface(true);
-  bool tile_missing = false;
-  bool had_incomplete_tile = false;
-  bool is_animating = true;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           2,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-
-  LayerTreeHostImpl::FrameData frame;
-
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
-  host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame);
-}
-
-TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) {
-  host_impl_->active_tree()->SetRootLayer(
-      DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
-  DidDrawCheckLayer* root =
-      static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
-  root->SetHasRenderSurface(true);
 
   LayerTreeHostImpl::FrameData frame;
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
@@ -2250,204 +2387,54 @@
   host_impl_->DidDrawAllLayers(frame);
   host_impl_->SwapBuffers(frame);
 
-  bool tile_missing = true;
-  bool had_incomplete_tile = false;
-  bool is_animating = false;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           4,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-  LayerTreeHostImpl::FrameData frame2;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
-  host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame2);
-}
+  for (size_t i = 0; i < cases.size(); ++i) {
+    const auto& testcase = cases[i];
+    std::vector<LayerImpl*> to_remove;
+    for (auto* child : root->children())
+      to_remove.push_back(child);
+    for (auto* child : to_remove)
+      root->RemoveChild(child);
 
-TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) {
-  host_impl_->active_tree()->SetRootLayer(
-      DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
-  DidDrawCheckLayer* root =
-      static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
-  root->SetHasRenderSurface(true);
+    std::ostringstream scope;
+    scope << "Test case: " << i;
+    SCOPED_TRACE(scope.str());
 
-  LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
-  host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame);
-  host_impl_->SwapBuffers(frame);
+    root->AddChild(MissingTextureAnimatingLayer::Create(
+        host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
+        testcase.layer_before.has_incomplete_tile,
+        testcase.layer_before.is_animating, host_impl_->resource_provider()));
+    DidDrawCheckLayer* before =
+        static_cast<DidDrawCheckLayer*>(root->children().back());
+    if (testcase.layer_before.has_copy_request)
+      before->AddCopyRequest();
 
-  bool tile_missing = false;
-  bool had_incomplete_tile = true;
-  bool is_animating = false;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           4,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-  LayerTreeHostImpl::FrameData frame2;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
-  host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame2);
-}
+    root->AddChild(MissingTextureAnimatingLayer::Create(
+        host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
+        testcase.layer_between.has_incomplete_tile,
+        testcase.layer_between.is_animating, host_impl_->resource_provider()));
+    DidDrawCheckLayer* between =
+        static_cast<DidDrawCheckLayer*>(root->children().back());
+    if (testcase.layer_between.has_copy_request)
+      between->AddCopyRequest();
 
-TEST_F(LayerTreeHostImplTest,
-       PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) {
-  host_impl_->active_tree()->SetRootLayer(
-      DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
-  DidDrawCheckLayer* root =
-      static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
-  root->SetHasRenderSurface(true);
+    root->AddChild(MissingTextureAnimatingLayer::Create(
+        host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
+        testcase.layer_after.has_incomplete_tile,
+        testcase.layer_after.is_animating, host_impl_->resource_provider()));
+    DidDrawCheckLayer* after =
+        static_cast<DidDrawCheckLayer*>(root->children().back());
+    if (testcase.layer_after.has_copy_request)
+      after->AddCopyRequest();
 
-  LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
-  host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame);
-  host_impl_->SwapBuffers(frame);
+    if (testcase.high_res_required)
+      host_impl_->SetRequiresHighResToDraw();
 
-  bool tile_missing = true;
-  bool had_incomplete_tile = false;
-  bool is_animating = true;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           6,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-  LayerTreeHostImpl::FrameData frame2;
-  EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
-            host_impl_->PrepareToDraw(&frame2));
-  host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame2);
-}
-
-TEST_F(LayerTreeHostImplTest,
-       PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) {
-  host_impl_->active_tree()->SetRootLayer(
-      DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
-  DidDrawCheckLayer* root =
-      static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
-  root->SetHasRenderSurface(true);
-
-  LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
-  host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame);
-  host_impl_->SwapBuffers(frame);
-
-  bool tile_missing = false;
-  bool had_incomplete_tile = true;
-  bool is_animating = true;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           6,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-  LayerTreeHostImpl::FrameData frame2;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
-  host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame2);
-}
-
-TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) {
-  host_impl_->active_tree()->SetRootLayer(
-      DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
-  DidDrawCheckLayer* root =
-      static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
-  root->SetHasRenderSurface(true);
-
-  LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
-  host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame);
-  host_impl_->SwapBuffers(frame);
-
-  bool tile_missing = false;
-  bool had_incomplete_tile = false;
-  bool is_animating = false;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           8,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-  host_impl_->SetRequiresHighResToDraw();
-  LayerTreeHostImpl::FrameData frame2;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
-  host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame2);
-}
-
-TEST_F(LayerTreeHostImplTest,
-       PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) {
-  host_impl_->active_tree()->SetRootLayer(
-      DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
-  DidDrawCheckLayer* root =
-      static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
-  root->SetHasRenderSurface(true);
-
-  LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
-  host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame);
-  host_impl_->SwapBuffers(frame);
-
-  bool tile_missing = false;
-  bool had_incomplete_tile = true;
-  bool is_animating = false;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           8,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-  host_impl_->SetRequiresHighResToDraw();
-  LayerTreeHostImpl::FrameData frame2;
-  EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
-            host_impl_->PrepareToDraw(&frame2));
-  host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame2);
-}
-
-TEST_F(LayerTreeHostImplTest,
-       PrepareToDrawFailsWhenHighResRequiredAndMissingTile) {
-  host_impl_->active_tree()->SetRootLayer(
-      DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
-  DidDrawCheckLayer* root =
-      static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
-  root->SetHasRenderSurface(true);
-
-  LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
-  host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame);
-  host_impl_->SwapBuffers(frame);
-
-  bool tile_missing = true;
-  bool had_incomplete_tile = false;
-  bool is_animating = false;
-  root->AddChild(
-      MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
-                                           8,
-                                           tile_missing,
-                                           had_incomplete_tile,
-                                           is_animating,
-                                           host_impl_->resource_provider()));
-  host_impl_->SetRequiresHighResToDraw();
-  LayerTreeHostImpl::FrameData frame2;
-  EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
-            host_impl_->PrepareToDraw(&frame2));
-  host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
-  host_impl_->DidDrawAllLayers(frame2);
+    LayerTreeHostImpl::FrameData frame;
+    EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
+    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+    host_impl_->DidDrawAllLayers(frame);
+    host_impl_->SwapBuffers(frame);
+  }
 }
 
 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
@@ -6530,9 +6517,10 @@
   EXPECT_EQ(1, software_device->frames_began_);
   EXPECT_EQ(1, software_device->frames_ended_);
 
-  // Call other API methods that are likely to hit NULL pointer in this mode.
-  EXPECT_TRUE(host_impl_->AsValue().get());
-  EXPECT_TRUE(host_impl_->ActivationStateAsValue().get());
+  // Call another API method that is likely to hit nullptr in this mode.
+  scoped_refptr<base::trace_event::TracedValue> state =
+      make_scoped_refptr(new base::trace_event::TracedValue());
+  host_impl_->ActivationStateAsValueInto(state.get());
 }
 
 TEST_F(LayerTreeHostImplTest,
@@ -7117,7 +7105,7 @@
             host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
 }
 
-TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
+TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
   gfx::Size content_size(100, 100);
   SetupScrollAndContentsLayers(content_size);
 
@@ -7141,13 +7129,50 @@
   // any layer that is a drawn RSLL member, then we can ignore the hit.
   //
   // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
-  // started overscrolling the inner viewport.
+  // started scrolling the inner viewport.
   EXPECT_EQ(InputHandler::SCROLL_STARTED,
             host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
 
   EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
 }
 
+TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
+  gfx::Size content_size(100, 100);
+  SetupScrollAndContentsLayers(content_size);
+
+  LayerImpl* root = host_impl_->active_tree()->LayerById(1);
+  LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
+
+  scoped_ptr<LayerImpl> invisible_scroll_layer =
+      CreateScrollableLayer(7, content_size, root);
+  invisible_scroll_layer->SetDrawsContent(false);
+
+  scoped_ptr<LayerImpl> child_layer =
+      LayerImpl::Create(host_impl_->active_tree(), 8);
+  child_layer->SetDrawsContent(false);
+
+  scoped_ptr<LayerImpl> grand_child_layer =
+      LayerImpl::Create(host_impl_->active_tree(), 9);
+  grand_child_layer->SetDrawsContent(true);
+  grand_child_layer->SetBounds(content_size);
+  grand_child_layer->SetContentBounds(content_size);
+  // Move the grand child so it's not hit by our test point.
+  grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
+
+  child_layer->AddChild(grand_child_layer.Pass());
+  invisible_scroll_layer->AddChild(child_layer.Pass());
+  root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
+
+  DrawFrame();
+
+  // We should have scrolled |invisible_scroll_layer| as it was hit and it has
+  // a descendant which is a drawn RSLL member.
+  EXPECT_EQ(InputHandler::SCROLL_STARTED,
+            host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
+
+  EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
+}
+
 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
   // This test case is very similar to the one above with one key difference:
   // the invisible scroller has a scroll child that is indeed draw contents.
@@ -7193,12 +7218,9 @@
 
   DrawFrame();
 
-  // We should not have scrolled |child_scroll| even though we technically "hit"
-  // it. The reason for this is that if the scrolling the scroll would not move
-  // any layer that is a drawn RSLL member, then we can ignore the hit.
-  //
-  // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
-  // started overscrolling the inner viewport.
+  // We should have scrolled |child_scroll| even though it is invisible.
+  // The reason for this is that if the scrolling the scroll would move a layer
+  // that is a drawn RSLL member, then we should accept this hit.
   EXPECT_EQ(InputHandler::SCROLL_STARTED,
             host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
 
@@ -7495,7 +7517,8 @@
   float offset = top_controls_height_ - residue;
   EXPECT_TRUE(
       host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
-  EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(-offset,
+                  host_impl_->top_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF().ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
@@ -7554,7 +7577,8 @@
   float offset = top_controls_height_ - residue;
   EXPECT_TRUE(
       host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
-  EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(-offset,
+                  host_impl_->top_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF().ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
@@ -7624,7 +7648,8 @@
   float offset = top_controls_height_ - residue;
   EXPECT_TRUE(
       host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
-  EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(-offset,
+                  host_impl_->top_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
@@ -7687,7 +7712,8 @@
   float offset = top_controls_height_ - residue;
   EXPECT_TRUE(
       host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
-  EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(-offset,
+                  host_impl_->top_controls_manager()->ControlsTopOffset());
   EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index 76acaa8..dd3cf73 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -97,8 +97,8 @@
 }
 
 TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) {
-  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
-      gfx::Rect(200, 200), SK_ColorWHITE);
+  scoped_refptr<SolidColorLayer> background =
+      CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorTRANSPARENT);
 
   // This verifies that the perspective of the clear layer (with black border)
   // does not influence the blending of the green box behind it. Also verifies
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 7b0e53b..b9491bb 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -12,6 +12,9 @@
 
 #if !defined(OS_ANDROID)
 
+// TODO(enne): these time out on Windows.  http://crbug.com/435632
+#if !defined(OS_WIN)
+
 namespace cc {
 namespace {
 
@@ -57,9 +60,6 @@
   gfx::Size bounds_;
 };
 
-// TODO(enne): these time out on Windows.  http://crbug.com/435632
-#if !defined(OS_WIN)
-
 TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayer) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(200, 200), SK_ColorWHITE);
@@ -280,8 +280,6 @@
                            "mask_of_replica_of_clipped_layer.png")));
 }
 
-#endif  // !defined(OS_WIN)
-
 class CheckerContentLayerClient : public ContentLayerClient {
  public:
   CheckerContentLayerClient(const gfx::Size& bounds,
@@ -397,8 +395,8 @@
 
   float percentage_pixels_large_error = 2.5f;  // 2.5%, ~1600px / (256*256)
   float percentage_pixels_small_error = 0.0f;
-  float average_error_allowed_in_bad_pixels = 60.0f;
-  int large_error_allowed = 100;
+  float average_error_allowed_in_bad_pixels = 100.0f;
+  int large_error_allowed = 256;
   int small_error_allowed = 0;
   pixel_comparator_.reset(new FuzzyPixelComparator(
       true,  // discard_alpha
@@ -467,4 +465,5 @@
 }  // namespace
 }  // namespace cc
 
-#endif  // OS_ANDROID
+#endif  // !defined(OS_WIN)
+#endif  // !defined(OS_ANDROID)
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 1be61a5..2ec6e66 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2099,6 +2099,7 @@
     proxy->SetMaxPartialTextureUpdates(5);
 
     LayerTreeSettings settings;
+    settings.impl_side_painting = false;
     settings.max_partial_texture_updates = 10;
 
     LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
@@ -2116,6 +2117,7 @@
     proxy->SetMaxPartialTextureUpdates(5);
 
     LayerTreeSettings settings;
+    settings.impl_side_painting = false;
     settings.max_partial_texture_updates = 10;
 
     LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
@@ -2133,6 +2135,7 @@
     proxy->SetMaxPartialTextureUpdates(20);
 
     LayerTreeSettings settings;
+    settings.impl_side_painting = false;
     settings.max_partial_texture_updates = 10;
 
     LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
@@ -2147,6 +2150,7 @@
   LayerTreeSettings settings;
   settings.max_partial_texture_updates = 4;
   settings.single_thread_proxy_scheduler = false;
+  settings.impl_side_painting = false;
 
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
       new TestSharedBitmapManager());
@@ -2170,6 +2174,7 @@
   LayerTreeSettings settings;
   settings.max_partial_texture_updates = 4;
   settings.single_thread_proxy_scheduler = false;
+  settings.impl_side_painting = false;
 
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
       new TestSharedBitmapManager());
@@ -2193,6 +2198,7 @@
   LayerTreeSettings settings;
   settings.max_partial_texture_updates = 4;
   settings.single_thread_proxy_scheduler = false;
+  settings.impl_side_painting = false;
 
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
       new TestSharedBitmapManager());
@@ -2217,6 +2223,7 @@
   LayerTreeSettings settings;
   settings.max_partial_texture_updates = 4;
   settings.single_thread_proxy_scheduler = false;
+  settings.impl_side_painting = false;
 
   scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
       new TestSharedBitmapManager());
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index c1da07e..e9b877d 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -196,7 +196,7 @@
   void AnimateLayers(LayerTreeHostImpl* host_impl,
                      base::TimeTicks monotonic_time) override {
     bool have_animations = !host_impl->animation_registrar()
-                                ->active_animation_controllers()
+                                ->active_animation_controllers_for_testing()
                                 .empty();
     if (!started_animating_ && have_animations) {
       started_animating_ = true;
@@ -1243,7 +1243,8 @@
     // start times.
     num_swap_buffers_++;
     AnimationRegistrar::AnimationControllerMap controllers_copy =
-        host_impl->animation_registrar()->active_animation_controllers();
+        host_impl->animation_registrar()
+            ->active_animation_controllers_for_testing();
     if (controllers_copy.size() == 2u) {
       EndTest();
       EXPECT_GE(num_swap_buffers_, 3);
diff --git a/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
index 06b3674..622143d 100644
--- a/cc/trees/layer_tree_host_unittest_no_message_loop.cc
+++ b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
@@ -104,6 +104,7 @@
     LayerTreeSettings settings;
     settings.single_thread_proxy_scheduler = false;
     settings.verify_property_trees = true;
+    settings.raster_enabled = false;
     layer_tree_host_ = LayerTreeHost::CreateSingleThreaded(
         this, this, nullptr, nullptr, settings, nullptr, nullptr);
     layer_tree_host_->SetViewportSize(size_);
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 5114fdc..a27630e 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1430,15 +1430,16 @@
 static bool ScrollsAnyDrawnRenderSurfaceLayerListMember(LayerImpl* layer) {
   if (!layer->scrollable())
     return false;
-  if (layer->IsDrawnRenderSurfaceLayerListMember())
+  if (layer->draw_properties().layer_or_descendant_is_drawn)
     return true;
+
   if (!layer->scroll_children())
     return false;
   for (std::set<LayerImpl*>::const_iterator it =
            layer->scroll_children()->begin();
        it != layer->scroll_children()->end();
        ++it) {
-    if ((*it)->IsDrawnRenderSurfaceLayerListMember())
+    if ((*it)->draw_properties().layer_or_descendant_is_drawn)
       return true;
   }
   return false;
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index 67f98e6..06df3c2 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -920,14 +920,6 @@
   ASSERT_TRUE(grand_child1);
   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
 
-  RenderSurfaceImpl* root_render_surface =
-      host_impl().active_tree()->root_layer()->render_surface();
-  ASSERT_EQ(4u, root_render_surface->layer_list().size());
-  ASSERT_EQ(3, root_render_surface->layer_list().at(0)->id());
-  ASSERT_EQ(1, root_render_surface->layer_list().at(1)->id());
-  ASSERT_EQ(2, root_render_surface->layer_list().at(2)->id());
-  ASSERT_EQ(4, root_render_surface->layer_list().at(3)->id());
-
   // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
   // the root layer.
   gfx::Point test_point = gfx::Point(1, 1);
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 0088e91..213ad28 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -15,6 +15,7 @@
 
 LayerTreeSettings::LayerTreeSettings()
     : impl_side_painting(false),
+      raster_enabled(true),
       throttle_frame_production(true),
       single_thread_proxy_scheduler(true),
       use_external_begin_frame_source(false),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index ce8d856..373f704 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -21,6 +21,7 @@
 
   RendererSettings renderer_settings;
   bool impl_side_painting;
+  bool raster_enabled;
   bool throttle_frame_production;
   bool single_thread_proxy_scheduler;
   bool use_external_begin_frame_source;
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc
index 388eb6e..0f0ce15 100644
--- a/cc/trees/occlusion_tracker.cc
+++ b/cc/trees/occlusion_tracker.cc
@@ -155,7 +155,7 @@
   return layer->Is3dSorted();
 }
 static inline bool LayerIsInUnsorted3dRenderingContext(const LayerImpl* layer) {
-  return false;
+  return layer->Is3dSorted();
 }
 
 template <typename LayerType>
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index e3639ad..f3f2185 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -1540,56 +1540,6 @@
   }
 };
 
-// This test requires accumulating occlusion of 3d layers, which are skipped by
-// the occlusion tracker on the main thread. So this test should run on the impl
-// thread.
-IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
-
-template <class Types>
-class OcclusionTrackerTestLargePixelsOccludeInsideClipRect
-    : public OcclusionTrackerTest<Types> {
- protected:
-  explicit OcclusionTrackerTestLargePixelsOccludeInsideClipRect(
-      bool opaque_layers)
-      : OcclusionTrackerTest<Types>(opaque_layers) {}
-  void RunMyTest() override {
-    gfx::Transform transform;
-    transform.Translate(50.0, 50.0);
-    transform.ApplyPerspectiveDepth(100.0);
-    transform.Translate3d(0.0, 0.0, 99.0);
-    transform.Translate(-50.0, -50.0);
-
-    typename Types::ContentLayerType* parent = this->CreateRoot(
-        this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
-    parent->SetMasksToBounds(true);
-    typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
-        parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
-    parent->SetShouldFlattenTransform(false);
-    parent->Set3dSortingContextId(1);
-    layer->SetShouldFlattenTransform(false);
-    layer->Set3dSortingContextId(1);
-    this->CalcDrawEtc(parent);
-
-    TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
-        gfx::Rect(0, 0, 1000, 1000));
-
-    // This is very close to the camera, so pixels in its visible_content_rect()
-    // will actually go outside of the layer's clip rect.  Ensure that those
-    // pixels don't occlude things outside the clip rect.
-    this->VisitLayer(layer, &occlusion);
-    this->EnterLayer(parent, &occlusion);
-    EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
-              occlusion.occlusion_from_inside_target().ToString());
-    EXPECT_EQ(gfx::Rect().ToString(),
-              occlusion.occlusion_from_outside_target().ToString());
-  }
-};
-
-// This test requires accumulating occlusion of 3d layers, which are skipped by
-// the occlusion tracker on the main thread. So this test should run on the impl
-// thread.
-IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect);
-
 template <class Types>
 class OcclusionTrackerTestAnimationOpacity1OnMainThread
     : public OcclusionTrackerTest<Types> {
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 95e4366..8e8ef50 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -43,7 +43,8 @@
       ancestors_are_invertible(true),
       is_animated(false),
       to_screen_is_animated(false),
-      flattens(false),
+      flattens_inherited_transform(false),
+      flattens_local_transform(false),
       scrolls(false),
       needs_sublayer_scale(false),
       layer_scale_factor(1.0f) {
@@ -190,7 +191,8 @@
     node->data.to_screen = node->data.to_parent;
     node->data.ancestors_are_invertible = true;
     node->data.to_screen_is_animated = false;
-  } else if (parent_node->data.flattens) {
+  } else if (parent_node->data.flattens_local_transform ||
+             node->data.flattens_inherited_transform) {
     // Flattening is tricky. Once a layer is drawn into its render target, it
     // cannot escape, so we only need to consider transforms between the layer
     // and its target when flattening (i.e., its draw transform). To compute the
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index 404f498..cb00e8a 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -69,7 +69,13 @@
   bool is_animated;
   bool to_screen_is_animated;
 
-  bool flattens;
+  // We don't necessarily create a transform node to apply flattening. If we've
+  // skipped flattening for an ancestor, we must flatten the transform we
+  // inherit, but we don't necessarily need to flatten our local transform. We
+  // must therefore use two values to describe the flattening required for the
+  // local and inherited transforms.
+  bool flattens_inherited_transform;
+  bool flattens_local_transform;
   bool scrolls;
 
   bool needs_sublayer_scale;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 6f3f792..8352ab8 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -33,6 +33,7 @@
   float page_scale_factor;
   float device_scale_factor;
   bool in_subtree_of_page_scale_application_layer;
+  bool should_flatten;
   const gfx::Transform* device_transform;
 };
 
@@ -124,13 +125,9 @@
 
   const bool has_surface = !!layer->render_surface();
 
-  const bool flattening_change = layer->parent() &&
-                                 layer->should_flatten_transform() &&
-                                 !layer->parent()->should_flatten_transform();
-
   bool requires_node = is_root || is_scrollable || has_significant_transform ||
                        has_animated_transform || has_surface ||
-                       is_page_scale_application_layer || flattening_change;
+                       is_page_scale_application_layer;
 
   Layer* transform_parent = GetTransformParent(data_from_ancestor, layer);
 
@@ -172,6 +169,7 @@
   data_for_children->transform_tree_parent = layer;
 
   if (!requires_node) {
+    data_for_children->should_flatten |= layer->should_flatten_transform();
     gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
                                   layer->transform().To2dTranslation();
     layer->set_offset_to_transform_parent(parent_offset + local_offset);
@@ -189,7 +187,9 @@
   layer->set_transform_tree_index(node->id);
 
   node->data.scrolls = is_scrollable;
-  node->data.flattens = layer->should_flatten_transform();
+  node->data.flattens_inherited_transform = data_for_children->should_flatten;
+  node->data.flattens_local_transform = layer->should_flatten_transform();
+  data_for_children->should_flatten = false;
   node->data.target_id =
       data_from_ancestor.render_target->transform_tree_index();
   node->data.content_target_id =
@@ -316,6 +316,7 @@
   data_for_recursion.page_scale_factor = page_scale_factor;
   data_for_recursion.device_scale_factor = device_scale_factor;
   data_for_recursion.in_subtree_of_page_scale_application_layer = false;
+  data_for_recursion.should_flatten = false;
   data_for_recursion.device_transform = &device_transform;
 
   ClipNode root_clip;
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 539effe..945e547 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -80,9 +80,8 @@
 
   virtual void NotifyInputThrottledUntilCommit() = 0;
 
-  // Defers commits until it is reset. It is only supported when in threaded
-  // mode. It's an error to make a sync call like CompositeAndReadback while
-  // commits are deferred.
+  // Defers commits until it is reset. It is only supported when using a
+  // scheduler.
   virtual void SetDeferCommits(bool defer_commits) = 0;
 
   virtual void MainThreadHasStoppedFlinging() = 0;
@@ -103,8 +102,6 @@
 
   virtual bool SupportsImplScrolling() const = 0;
 
-  virtual void AsValueInto(base::trace_event::TracedValue* value) const = 0;
-
   virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0;
 
   virtual void SetChildrenNeedBeginFrames(bool children_need_begin_frames) = 0;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 401a4b8..81c70f0 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -549,18 +549,6 @@
   }
 }
 
-void SingleThreadProxy::AsValueInto(
-    base::trace_event::TracedValue* state) const {
-  // The following line casts away const modifiers because it is just
-  // setting debug state. We still want the AsValue() function and its
-  // call chain to be const throughout.
-  DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
-
-  state->BeginDictionary("layer_tree_host_impl");
-  layer_tree_host_impl_->AsValueInto(state);
-  state->EndDictionary();
-}
-
 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
   {
     DebugScopedSetImplThread impl(this);
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 2612a4d..5bc6d3d 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -59,7 +59,6 @@
   size_t MaxPartialTextureUpdates() const override;
   void ForceSerializeOnSwapBuffers() override;
   bool SupportsImplScrolling() const override;
-  void AsValueInto(base::trace_event::TracedValue* state) const override;
   bool MainFrameWillHappenForTesting() override;
   void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
 
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 8c766f2..7452520 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -1252,31 +1252,6 @@
 
 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
 
-void ThreadProxy::AsValueInto(base::trace_event::TracedValue* state) const {
-  CompletionEvent completion;
-  {
-    DebugScopedSetMainThreadBlocked main_thread_blocked(
-        const_cast<ThreadProxy*>(this));
-    scoped_refptr<base::trace_event::TracedValue> state_refptr(state);
-    Proxy::ImplThreadTaskRunner()->PostTask(
-        FROM_HERE,
-        base::Bind(&ThreadProxy::AsValueOnImplThread,
-                   impl_thread_weak_ptr_,
-                   &completion,
-                   state_refptr));
-    completion.Wait();
-  }
-}
-
-void ThreadProxy::AsValueOnImplThread(
-    CompletionEvent* completion,
-    base::trace_event::TracedValue* state) const {
-  state->BeginDictionary("layer_tree_host_impl");
-  impl().layer_tree_host_impl->AsValueInto(state);
-  state->EndDictionary();
-  completion->Signal();
-}
-
 bool ThreadProxy::MainFrameWillHappenForTesting() {
   DCHECK(IsMainThread());
   CompletionEvent completion;
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index c2dd348..927caab 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -175,7 +175,6 @@
   void ForceSerializeOnSwapBuffers() override;
   bool SupportsImplScrolling() const override;
   void SetDebugState(const LayerTreeDebugState& debug_state) override;
-  void AsValueInto(base::trace_event::TracedValue* value) const override;
   bool MainFrameWillHappenForTesting() override;
   void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
 
@@ -279,8 +278,6 @@
   void ForceSerializeOnSwapBuffersOnImplThread(CompletionEvent* completion);
   void MainFrameWillHappenOnImplThreadForTesting(CompletionEvent* completion,
                                                  bool* main_frame_will_happen);
-  void AsValueOnImplThread(CompletionEvent* completion,
-                           base::trace_event::TracedValue* state) const;
   void SetSwapUsedIncompleteTileOnImplThread(bool used_incomplete_tile);
   void MainThreadHasStoppedFlingingOnImplThread();
   void SetInputThrottledUntilCommitOnImplThread(bool is_throttled);
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 6f011f7..502bc0a 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -33,6 +33,7 @@
 # gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings => //gpu/skia_bindings
 
 import("//testing/test.gni")
+import("//build/config/ui.gni")
 
 component("gpu") {
   public_deps = [
@@ -183,6 +184,7 @@
     "command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc",
     "command_buffer/service/gles2_cmd_decoder_unittest_base.cc",
     "command_buffer/service/gles2_cmd_decoder_unittest_base.h",
+    "command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc",
     "command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc",
     "command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc",
     "command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc",
@@ -259,6 +261,7 @@
     "//base",
     "//base/test:test_support",
     "//gpu/command_buffer/service",
+    "//testing/gmock",
     "//testing/gtest",
     "//testing/perf",
     "//ui/gfx/geometry",
@@ -280,3 +283,25 @@
     "//third_party/angle:translator_static",
   ]
 }
+
+if (is_linux && !is_chromeos && target_cpu != "arm" && use_x11) {
+  executable("compositor_model_bench") {
+    sources = [
+      "tools/compositor_model_bench/compositor_model_bench.cc",
+      "tools/compositor_model_bench/forward_render_model.cc",
+      "tools/compositor_model_bench/render_model_utils.cc",
+      "tools/compositor_model_bench/render_models.cc",
+      "tools/compositor_model_bench/render_tree.cc",
+      "tools/compositor_model_bench/shaders.cc",
+    ]
+
+    libs = [ "GL" ]
+
+    configs += [ "//build/config/linux:x11" ]
+
+    deps = [
+      "//base",
+      "//ui/gl",
+    ]
+  }
+}
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index 60404dc..c425c52 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -69,6 +69,7 @@
 #define glDisableVertexAttribArray GLES2_GET_FUN(DisableVertexAttribArray)
 #define glDrawArrays GLES2_GET_FUN(DrawArrays)
 #define glDrawElements GLES2_GET_FUN(DrawElements)
+#define glDrawRangeElements GLES2_GET_FUN(DrawRangeElements)
 #define glEnable GLES2_GET_FUN(Enable)
 #define glEnableVertexAttribArray GLES2_GET_FUN(EnableVertexAttribArray)
 #define glFenceSync GLES2_GET_FUN(FenceSync)
@@ -256,6 +257,8 @@
 #define glUnmapBufferCHROMIUM GLES2_GET_FUN(UnmapBufferCHROMIUM)
 #define glMapBufferSubDataCHROMIUM GLES2_GET_FUN(MapBufferSubDataCHROMIUM)
 #define glUnmapBufferSubDataCHROMIUM GLES2_GET_FUN(UnmapBufferSubDataCHROMIUM)
+#define glMapBufferRange GLES2_GET_FUN(MapBufferRange)
+#define glUnmapBuffer GLES2_GET_FUN(UnmapBuffer)
 #define glMapTexSubImage2DCHROMIUM GLES2_GET_FUN(MapTexSubImage2DCHROMIUM)
 #define glUnmapTexSubImage2DCHROMIUM GLES2_GET_FUN(UnmapTexSubImage2DCHROMIUM)
 #define glResizeCHROMIUM GLES2_GET_FUN(ResizeCHROMIUM)
diff --git a/gpu/blink/webgraphicscontext3d_impl.cc b/gpu/blink/webgraphicscontext3d_impl.cc
index 581e102..e469532 100644
--- a/gpu/blink/webgraphicscontext3d_impl.cc
+++ b/gpu/blink/webgraphicscontext3d_impl.cc
@@ -19,6 +19,21 @@
 #endif
 #include "third_party/khronos/GLES2/gl2ext.h"
 
+using blink::WGC3Dbitfield;
+using blink::WGC3Dboolean;
+using blink::WGC3Dbyte;
+using blink::WGC3Dchar;
+using blink::WGC3Dclampf;
+using blink::WGC3Denum;
+using blink::WGC3Dfloat;
+using blink::WGC3Dint;
+using blink::WGC3Dintptr;
+using blink::WGC3Dsizei;
+using blink::WGC3Dsizeiptr;
+using blink::WGC3Duint64;
+using blink::WGC3Duint;
+using blink::WebGLId;
+
 namespace gpu_blink {
 
 namespace {
@@ -361,11 +376,12 @@
       program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length);
   if (max_name_length < 0)
     return false;
-  scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
-  if (!name) {
-    synthesizeGLError(GL_OUT_OF_MEMORY);
+  if (max_name_length == 0) {
+    // No active attributes exist.
+    synthesizeGLError(GL_INVALID_VALUE);
     return false;
   }
+  scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
   GLsizei length = 0;
   GLint size = -1;
   GLenum type = 0;
@@ -387,11 +403,12 @@
       program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length);
   if (max_name_length < 0)
     return false;
-  scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
-  if (!name) {
-    synthesizeGLError(GL_OUT_OF_MEMORY);
+  if (max_name_length == 0) {
+    // No active uniforms exist.
+    synthesizeGLError(GL_INVALID_VALUE);
     return false;
   }
+  scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
   GLsizei length = 0;
   GLint size = -1;
   GLenum type = 0;
diff --git a/gpu/blink/webgraphicscontext3d_impl.h b/gpu/blink/webgraphicscontext3d_impl.h
index a0d1461..a232d06 100644
--- a/gpu/blink/webgraphicscontext3d_impl.h
+++ b/gpu/blink/webgraphicscontext3d_impl.h
@@ -23,22 +23,6 @@
 }
 }
 
-using blink::WebGLId;
-
-using blink::WGC3Dbyte;
-using blink::WGC3Dchar;
-using blink::WGC3Denum;
-using blink::WGC3Dboolean;
-using blink::WGC3Dbitfield;
-using blink::WGC3Dint;
-using blink::WGC3Dsizei;
-using blink::WGC3Duint;
-using blink::WGC3Dfloat;
-using blink::WGC3Dclampf;
-using blink::WGC3Dintptr;
-using blink::WGC3Dsizeiptr;
-using blink::WGC3Duint64;
-
 namespace gpu_blink {
 
 class WebGraphicsContext3DErrorMessageCallback;
@@ -56,7 +40,8 @@
   virtual unsigned int insertSyncPoint();
   virtual void waitSyncPoint(unsigned int sync_point);
 
-  virtual void loseContextCHROMIUM(WGC3Denum current, WGC3Denum other);
+  virtual void loseContextCHROMIUM(blink::WGC3Denum current,
+                                   blink::WGC3Denum other);
 
   virtual void reshapeWithScaleFactor(
       int width, int height, float scale_factor);
@@ -64,368 +49,442 @@
   virtual void prepareTexture();
   virtual void postSubBufferCHROMIUM(int x, int y, int width, int height);
 
-  virtual void activeTexture(WGC3Denum texture);
-  virtual void attachShader(WebGLId program, WebGLId shader);
-  virtual void bindAttribLocation(WebGLId program, WGC3Duint index,
-                                  const WGC3Dchar* name);
-  virtual void bindBuffer(WGC3Denum target, WebGLId buffer);
-  virtual void bindFramebuffer(WGC3Denum target, WebGLId framebuffer);
-  virtual void bindRenderbuffer(WGC3Denum target, WebGLId renderbuffer);
-  virtual void bindTexture(WGC3Denum target, WebGLId texture);
-  virtual void blendColor(WGC3Dclampf red, WGC3Dclampf green,
-                          WGC3Dclampf blue, WGC3Dclampf alpha);
-  virtual void blendEquation(WGC3Denum mode);
-  virtual void blendEquationSeparate(WGC3Denum modeRGB,
-                                     WGC3Denum modeAlpha);
-  virtual void blendFunc(WGC3Denum sfactor, WGC3Denum dfactor);
-  virtual void blendFuncSeparate(WGC3Denum srcRGB,
-                                 WGC3Denum dstRGB,
-                                 WGC3Denum srcAlpha,
-                                 WGC3Denum dstAlpha);
+  virtual void activeTexture(blink::WGC3Denum texture);
+  virtual void attachShader(blink::WebGLId program, blink::WebGLId shader);
+  virtual void bindAttribLocation(blink::WebGLId program,
+                                  blink::WGC3Duint index,
+                                  const blink::WGC3Dchar* name);
+  virtual void bindBuffer(blink::WGC3Denum target, blink::WebGLId buffer);
+  virtual void bindFramebuffer(blink::WGC3Denum target,
+                               blink::WebGLId framebuffer);
+  virtual void bindRenderbuffer(blink::WGC3Denum target,
+                                blink::WebGLId renderbuffer);
+  virtual void bindTexture(blink::WGC3Denum target, blink::WebGLId texture);
+  virtual void blendColor(blink::WGC3Dclampf red,
+                          blink::WGC3Dclampf green,
+                          blink::WGC3Dclampf blue,
+                          blink::WGC3Dclampf alpha);
+  virtual void blendEquation(blink::WGC3Denum mode);
+  virtual void blendEquationSeparate(blink::WGC3Denum modeRGB,
+                                     blink::WGC3Denum modeAlpha);
+  virtual void blendFunc(blink::WGC3Denum sfactor, blink::WGC3Denum dfactor);
+  virtual void blendFuncSeparate(blink::WGC3Denum srcRGB,
+                                 blink::WGC3Denum dstRGB,
+                                 blink::WGC3Denum srcAlpha,
+                                 blink::WGC3Denum dstAlpha);
 
-  virtual void bufferData(WGC3Denum target, WGC3Dsizeiptr size,
-                          const void* data, WGC3Denum usage);
-  virtual void bufferSubData(WGC3Denum target, WGC3Dintptr offset,
-                             WGC3Dsizeiptr size, const void* data);
+  virtual void bufferData(blink::WGC3Denum target,
+                          blink::WGC3Dsizeiptr size,
+                          const void* data,
+                          blink::WGC3Denum usage);
+  virtual void bufferSubData(blink::WGC3Denum target,
+                             blink::WGC3Dintptr offset,
+                             blink::WGC3Dsizeiptr size,
+                             const void* data);
 
-  virtual WGC3Denum checkFramebufferStatus(WGC3Denum target);
-  virtual void clear(WGC3Dbitfield mask);
-  virtual void clearColor(WGC3Dclampf red, WGC3Dclampf green,
-                          WGC3Dclampf blue, WGC3Dclampf alpha);
-  virtual void clearDepth(WGC3Dclampf depth);
-  virtual void clearStencil(WGC3Dint s);
-  virtual void colorMask(WGC3Dboolean red, WGC3Dboolean green,
-                         WGC3Dboolean blue, WGC3Dboolean alpha);
-  virtual void compileShader(WebGLId shader);
+  virtual blink::WGC3Denum checkFramebufferStatus(blink::WGC3Denum target);
+  virtual void clear(blink::WGC3Dbitfield mask);
+  virtual void clearColor(blink::WGC3Dclampf red,
+                          blink::WGC3Dclampf green,
+                          blink::WGC3Dclampf blue,
+                          blink::WGC3Dclampf alpha);
+  virtual void clearDepth(blink::WGC3Dclampf depth);
+  virtual void clearStencil(blink::WGC3Dint s);
+  virtual void colorMask(blink::WGC3Dboolean red,
+                         blink::WGC3Dboolean green,
+                         blink::WGC3Dboolean blue,
+                         blink::WGC3Dboolean alpha);
+  virtual void compileShader(blink::WebGLId shader);
 
-  virtual void compressedTexImage2D(WGC3Denum target,
-                                    WGC3Dint level,
-                                    WGC3Denum internalformat,
-                                    WGC3Dsizei width,
-                                    WGC3Dsizei height,
-                                    WGC3Dint border,
-                                    WGC3Dsizei imageSize,
+  virtual void compressedTexImage2D(blink::WGC3Denum target,
+                                    blink::WGC3Dint level,
+                                    blink::WGC3Denum internalformat,
+                                    blink::WGC3Dsizei width,
+                                    blink::WGC3Dsizei height,
+                                    blink::WGC3Dint border,
+                                    blink::WGC3Dsizei imageSize,
                                     const void* data);
-  virtual void compressedTexSubImage2D(WGC3Denum target,
-                                       WGC3Dint level,
-                                       WGC3Dint xoffset,
-                                       WGC3Dint yoffset,
-                                       WGC3Dsizei width,
-                                       WGC3Dsizei height,
-                                       WGC3Denum format,
-                                       WGC3Dsizei imageSize,
+  virtual void compressedTexSubImage2D(blink::WGC3Denum target,
+                                       blink::WGC3Dint level,
+                                       blink::WGC3Dint xoffset,
+                                       blink::WGC3Dint yoffset,
+                                       blink::WGC3Dsizei width,
+                                       blink::WGC3Dsizei height,
+                                       blink::WGC3Denum format,
+                                       blink::WGC3Dsizei imageSize,
                                        const void* data);
-  virtual void copyTexImage2D(WGC3Denum target,
-                              WGC3Dint level,
-                              WGC3Denum internalformat,
-                              WGC3Dint x,
-                              WGC3Dint y,
-                              WGC3Dsizei width,
-                              WGC3Dsizei height,
-                              WGC3Dint border);
-  virtual void copyTexSubImage2D(WGC3Denum target,
-                                 WGC3Dint level,
-                                 WGC3Dint xoffset,
-                                 WGC3Dint yoffset,
-                                 WGC3Dint x,
-                                 WGC3Dint y,
-                                 WGC3Dsizei width,
-                                 WGC3Dsizei height);
-  virtual void cullFace(WGC3Denum mode);
-  virtual void depthFunc(WGC3Denum func);
-  virtual void depthMask(WGC3Dboolean flag);
-  virtual void depthRange(WGC3Dclampf zNear, WGC3Dclampf zFar);
-  virtual void detachShader(WebGLId program, WebGLId shader);
-  virtual void disable(WGC3Denum cap);
-  virtual void disableVertexAttribArray(WGC3Duint index);
-  virtual void drawArrays(WGC3Denum mode, WGC3Dint first, WGC3Dsizei count);
-  virtual void drawElements(WGC3Denum mode,
-                            WGC3Dsizei count,
-                            WGC3Denum type,
-                            WGC3Dintptr offset);
+  virtual void copyTexImage2D(blink::WGC3Denum target,
+                              blink::WGC3Dint level,
+                              blink::WGC3Denum internalformat,
+                              blink::WGC3Dint x,
+                              blink::WGC3Dint y,
+                              blink::WGC3Dsizei width,
+                              blink::WGC3Dsizei height,
+                              blink::WGC3Dint border);
+  virtual void copyTexSubImage2D(blink::WGC3Denum target,
+                                 blink::WGC3Dint level,
+                                 blink::WGC3Dint xoffset,
+                                 blink::WGC3Dint yoffset,
+                                 blink::WGC3Dint x,
+                                 blink::WGC3Dint y,
+                                 blink::WGC3Dsizei width,
+                                 blink::WGC3Dsizei height);
+  virtual void cullFace(blink::WGC3Denum mode);
+  virtual void depthFunc(blink::WGC3Denum func);
+  virtual void depthMask(blink::WGC3Dboolean flag);
+  virtual void depthRange(blink::WGC3Dclampf zNear, blink::WGC3Dclampf zFar);
+  virtual void detachShader(blink::WebGLId program, blink::WebGLId shader);
+  virtual void disable(blink::WGC3Denum cap);
+  virtual void disableVertexAttribArray(blink::WGC3Duint index);
+  virtual void drawArrays(blink::WGC3Denum mode,
+                          blink::WGC3Dint first,
+                          blink::WGC3Dsizei count);
+  virtual void drawElements(blink::WGC3Denum mode,
+                            blink::WGC3Dsizei count,
+                            blink::WGC3Denum type,
+                            blink::WGC3Dintptr offset);
 
-  virtual void enable(WGC3Denum cap);
-  virtual void enableVertexAttribArray(WGC3Duint index);
+  virtual void enable(blink::WGC3Denum cap);
+  virtual void enableVertexAttribArray(blink::WGC3Duint index);
   virtual void finish();
   virtual void flush();
-  virtual void framebufferRenderbuffer(WGC3Denum target,
-                                       WGC3Denum attachment,
-                                       WGC3Denum renderbuffertarget,
-                                       WebGLId renderbuffer);
-  virtual void framebufferTexture2D(WGC3Denum target,
-                                    WGC3Denum attachment,
-                                    WGC3Denum textarget,
-                                    WebGLId texture,
-                                    WGC3Dint level);
-  virtual void frontFace(WGC3Denum mode);
-  virtual void generateMipmap(WGC3Denum target);
+  virtual void framebufferRenderbuffer(blink::WGC3Denum target,
+                                       blink::WGC3Denum attachment,
+                                       blink::WGC3Denum renderbuffertarget,
+                                       blink::WebGLId renderbuffer);
+  virtual void framebufferTexture2D(blink::WGC3Denum target,
+                                    blink::WGC3Denum attachment,
+                                    blink::WGC3Denum textarget,
+                                    blink::WebGLId texture,
+                                    blink::WGC3Dint level);
+  virtual void frontFace(blink::WGC3Denum mode);
+  virtual void generateMipmap(blink::WGC3Denum target);
 
-  virtual bool getActiveAttrib(WebGLId program,
-                               WGC3Duint index,
+  virtual bool getActiveAttrib(blink::WebGLId program,
+                               blink::WGC3Duint index,
                                ActiveInfo&);
-  virtual bool getActiveUniform(WebGLId program,
-                                WGC3Duint index,
+  virtual bool getActiveUniform(blink::WebGLId program,
+                                blink::WGC3Duint index,
                                 ActiveInfo&);
 
-  virtual void getAttachedShaders(WebGLId program,
-                                  WGC3Dsizei maxCount,
-                                  WGC3Dsizei* count,
-                                  WebGLId* shaders);
+  virtual void getAttachedShaders(blink::WebGLId program,
+                                  blink::WGC3Dsizei maxCount,
+                                  blink::WGC3Dsizei* count,
+                                  blink::WebGLId* shaders);
 
-  virtual WGC3Dint  getAttribLocation(WebGLId program, const WGC3Dchar* name);
+  virtual blink::WGC3Dint getAttribLocation(blink::WebGLId program,
+                                            const blink::WGC3Dchar* name);
 
-  virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value);
+  virtual void getBooleanv(blink::WGC3Denum pname, blink::WGC3Dboolean* value);
 
-  virtual void getBufferParameteriv(WGC3Denum target,
-                                    WGC3Denum pname,
-                                    WGC3Dint* value);
+  virtual void getBufferParameteriv(blink::WGC3Denum target,
+                                    blink::WGC3Denum pname,
+                                    blink::WGC3Dint* value);
 
-  virtual WGC3Denum getError();
+  virtual blink::WGC3Denum getError();
 
-  virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value);
+  virtual void getFloatv(blink::WGC3Denum pname, blink::WGC3Dfloat* value);
 
-  virtual void getFramebufferAttachmentParameteriv(WGC3Denum target,
-                                                   WGC3Denum attachment,
-                                                   WGC3Denum pname,
-                                                   WGC3Dint* value);
+  virtual void getFramebufferAttachmentParameteriv(blink::WGC3Denum target,
+                                                   blink::WGC3Denum attachment,
+                                                   blink::WGC3Denum pname,
+                                                   blink::WGC3Dint* value);
 
-  virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value);
+  virtual void getIntegerv(blink::WGC3Denum pname, blink::WGC3Dint* value);
 
-  virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value);
+  virtual void getProgramiv(blink::WebGLId program,
+                            blink::WGC3Denum pname,
+                            blink::WGC3Dint* value);
 
-  virtual blink::WebString getProgramInfoLog(WebGLId program);
+  virtual blink::WebString getProgramInfoLog(blink::WebGLId program);
 
-  virtual void getRenderbufferParameteriv(WGC3Denum target,
-                                          WGC3Denum pname,
-                                          WGC3Dint* value);
+  virtual void getRenderbufferParameteriv(blink::WGC3Denum target,
+                                          blink::WGC3Denum pname,
+                                          blink::WGC3Dint* value);
 
-  virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value);
+  virtual void getShaderiv(blink::WebGLId shader,
+                           blink::WGC3Denum pname,
+                           blink::WGC3Dint* value);
 
-  virtual blink::WebString getShaderInfoLog(WebGLId shader);
+  virtual blink::WebString getShaderInfoLog(blink::WebGLId shader);
 
-  virtual void getShaderPrecisionFormat(WGC3Denum shadertype,
-                                        WGC3Denum precisiontype,
-                                        WGC3Dint* range,
-                                        WGC3Dint* precision);
+  virtual void getShaderPrecisionFormat(blink::WGC3Denum shadertype,
+                                        blink::WGC3Denum precisiontype,
+                                        blink::WGC3Dint* range,
+                                        blink::WGC3Dint* precision);
 
-  virtual blink::WebString getShaderSource(WebGLId shader);
-  virtual blink::WebString getString(WGC3Denum name);
+  virtual blink::WebString getShaderSource(blink::WebGLId shader);
+  virtual blink::WebString getString(blink::WGC3Denum name);
 
-  virtual void getTexParameterfv(WGC3Denum target,
-                                 WGC3Denum pname,
-                                 WGC3Dfloat* value);
-  virtual void getTexParameteriv(WGC3Denum target,
-                                 WGC3Denum pname,
-                                 WGC3Dint* value);
+  virtual void getTexParameterfv(blink::WGC3Denum target,
+                                 blink::WGC3Denum pname,
+                                 blink::WGC3Dfloat* value);
+  virtual void getTexParameteriv(blink::WGC3Denum target,
+                                 blink::WGC3Denum pname,
+                                 blink::WGC3Dint* value);
 
-  virtual void getUniformfv(WebGLId program,
-                            WGC3Dint location,
-                            WGC3Dfloat* value);
-  virtual void getUniformiv(WebGLId program,
-                            WGC3Dint location,
-                            WGC3Dint* value);
+  virtual void getUniformfv(blink::WebGLId program,
+                            blink::WGC3Dint location,
+                            blink::WGC3Dfloat* value);
+  virtual void getUniformiv(blink::WebGLId program,
+                            blink::WGC3Dint location,
+                            blink::WGC3Dint* value);
 
-  virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name);
+  virtual blink::WGC3Dint getUniformLocation(blink::WebGLId program,
+                                             const blink::WGC3Dchar* name);
 
-  virtual void getVertexAttribfv(WGC3Duint index, WGC3Denum pname,
-                                 WGC3Dfloat* value);
-  virtual void getVertexAttribiv(WGC3Duint index, WGC3Denum pname,
-                                 WGC3Dint* value);
+  virtual void getVertexAttribfv(blink::WGC3Duint index,
+                                 blink::WGC3Denum pname,
+                                 blink::WGC3Dfloat* value);
+  virtual void getVertexAttribiv(blink::WGC3Duint index,
+                                 blink::WGC3Denum pname,
+                                 blink::WGC3Dint* value);
 
-  virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index, WGC3Denum pname);
+  virtual blink::WGC3Dsizeiptr getVertexAttribOffset(blink::WGC3Duint index,
+                                                     blink::WGC3Denum pname);
 
-  virtual void hint(WGC3Denum target, WGC3Denum mode);
-  virtual WGC3Dboolean isBuffer(WebGLId buffer);
-  virtual WGC3Dboolean isEnabled(WGC3Denum cap);
-  virtual WGC3Dboolean isFramebuffer(WebGLId framebuffer);
-  virtual WGC3Dboolean isProgram(WebGLId program);
-  virtual WGC3Dboolean isRenderbuffer(WebGLId renderbuffer);
-  virtual WGC3Dboolean isShader(WebGLId shader);
-  virtual WGC3Dboolean isTexture(WebGLId texture);
-  virtual void lineWidth(WGC3Dfloat);
-  virtual void linkProgram(WebGLId program);
-  virtual void pixelStorei(WGC3Denum pname, WGC3Dint param);
-  virtual void polygonOffset(WGC3Dfloat factor, WGC3Dfloat units);
+  virtual void hint(blink::WGC3Denum target, blink::WGC3Denum mode);
+  virtual blink::WGC3Dboolean isBuffer(blink::WebGLId buffer);
+  virtual blink::WGC3Dboolean isEnabled(blink::WGC3Denum cap);
+  virtual blink::WGC3Dboolean isFramebuffer(blink::WebGLId framebuffer);
+  virtual blink::WGC3Dboolean isProgram(blink::WebGLId program);
+  virtual blink::WGC3Dboolean isRenderbuffer(blink::WebGLId renderbuffer);
+  virtual blink::WGC3Dboolean isShader(blink::WebGLId shader);
+  virtual blink::WGC3Dboolean isTexture(blink::WebGLId texture);
+  virtual void lineWidth(blink::WGC3Dfloat);
+  virtual void linkProgram(blink::WebGLId program);
+  virtual void pixelStorei(blink::WGC3Denum pname, blink::WGC3Dint param);
+  virtual void polygonOffset(blink::WGC3Dfloat factor, blink::WGC3Dfloat units);
 
-  virtual void readPixels(WGC3Dint x,
-                          WGC3Dint y,
-                          WGC3Dsizei width,
-                          WGC3Dsizei height,
-                          WGC3Denum format,
-                          WGC3Denum type,
+  virtual void readPixels(blink::WGC3Dint x,
+                          blink::WGC3Dint y,
+                          blink::WGC3Dsizei width,
+                          blink::WGC3Dsizei height,
+                          blink::WGC3Denum format,
+                          blink::WGC3Denum type,
                           void* pixels);
 
   virtual void releaseShaderCompiler();
-  virtual void renderbufferStorage(WGC3Denum target,
-                                   WGC3Denum internalformat,
-                                   WGC3Dsizei width,
-                                   WGC3Dsizei height);
-  virtual void sampleCoverage(WGC3Dfloat value, WGC3Dboolean invert);
-  virtual void scissor(WGC3Dint x, WGC3Dint y,
-                       WGC3Dsizei width, WGC3Dsizei height);
-  virtual void shaderSource(WebGLId shader, const WGC3Dchar* string);
-  virtual void stencilFunc(WGC3Denum func, WGC3Dint ref, WGC3Duint mask);
-  virtual void stencilFuncSeparate(WGC3Denum face,
-                                   WGC3Denum func,
-                                   WGC3Dint ref,
-                                   WGC3Duint mask);
-  virtual void stencilMask(WGC3Duint mask);
-  virtual void stencilMaskSeparate(WGC3Denum face, WGC3Duint mask);
-  virtual void stencilOp(WGC3Denum fail,
-                         WGC3Denum zfail,
-                         WGC3Denum zpass);
-  virtual void stencilOpSeparate(WGC3Denum face,
-                                 WGC3Denum fail,
-                                 WGC3Denum zfail,
-                                 WGC3Denum zpass);
+  virtual void renderbufferStorage(blink::WGC3Denum target,
+                                   blink::WGC3Denum internalformat,
+                                   blink::WGC3Dsizei width,
+                                   blink::WGC3Dsizei height);
+  virtual void sampleCoverage(blink::WGC3Dfloat value,
+                              blink::WGC3Dboolean invert);
+  virtual void scissor(blink::WGC3Dint x,
+                       blink::WGC3Dint y,
+                       blink::WGC3Dsizei width,
+                       blink::WGC3Dsizei height);
+  virtual void shaderSource(blink::WebGLId shader,
+                            const blink::WGC3Dchar* string);
+  virtual void stencilFunc(blink::WGC3Denum func,
+                           blink::WGC3Dint ref,
+                           blink::WGC3Duint mask);
+  virtual void stencilFuncSeparate(blink::WGC3Denum face,
+                                   blink::WGC3Denum func,
+                                   blink::WGC3Dint ref,
+                                   blink::WGC3Duint mask);
+  virtual void stencilMask(blink::WGC3Duint mask);
+  virtual void stencilMaskSeparate(blink::WGC3Denum face,
+                                   blink::WGC3Duint mask);
+  virtual void stencilOp(blink::WGC3Denum fail,
+                         blink::WGC3Denum zfail,
+                         blink::WGC3Denum zpass);
+  virtual void stencilOpSeparate(blink::WGC3Denum face,
+                                 blink::WGC3Denum fail,
+                                 blink::WGC3Denum zfail,
+                                 blink::WGC3Denum zpass);
 
-  virtual void texImage2D(WGC3Denum target,
-                          WGC3Dint level,
-                          WGC3Denum internalformat,
-                          WGC3Dsizei width,
-                          WGC3Dsizei height,
-                          WGC3Dint border,
-                          WGC3Denum format,
-                          WGC3Denum type,
+  virtual void texImage2D(blink::WGC3Denum target,
+                          blink::WGC3Dint level,
+                          blink::WGC3Denum internalformat,
+                          blink::WGC3Dsizei width,
+                          blink::WGC3Dsizei height,
+                          blink::WGC3Dint border,
+                          blink::WGC3Denum format,
+                          blink::WGC3Denum type,
                           const void* pixels);
 
-  virtual void texParameterf(WGC3Denum target,
-                             WGC3Denum pname,
-                             WGC3Dfloat param);
-  virtual void texParameteri(WGC3Denum target,
-                             WGC3Denum pname,
-                             WGC3Dint param);
+  virtual void texParameterf(blink::WGC3Denum target,
+                             blink::WGC3Denum pname,
+                             blink::WGC3Dfloat param);
+  virtual void texParameteri(blink::WGC3Denum target,
+                             blink::WGC3Denum pname,
+                             blink::WGC3Dint param);
 
-  virtual void texSubImage2D(WGC3Denum target,
-                             WGC3Dint level,
-                             WGC3Dint xoffset,
-                             WGC3Dint yoffset,
-                             WGC3Dsizei width,
-                             WGC3Dsizei height,
-                             WGC3Denum format,
-                             WGC3Denum type,
+  virtual void texSubImage2D(blink::WGC3Denum target,
+                             blink::WGC3Dint level,
+                             blink::WGC3Dint xoffset,
+                             blink::WGC3Dint yoffset,
+                             blink::WGC3Dsizei width,
+                             blink::WGC3Dsizei height,
+                             blink::WGC3Denum format,
+                             blink::WGC3Denum type,
                              const void* pixels);
 
-  virtual void uniform1f(WGC3Dint location, WGC3Dfloat x);
-  virtual void uniform1fv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dfloat* v);
-  virtual void uniform1i(WGC3Dint location, WGC3Dint x);
-  virtual void uniform1iv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dint* v);
-  virtual void uniform2f(WGC3Dint location, WGC3Dfloat x, WGC3Dfloat y);
-  virtual void uniform2fv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dfloat* v);
-  virtual void uniform2i(WGC3Dint location, WGC3Dint x, WGC3Dint y);
-  virtual void uniform2iv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dint* v);
-  virtual void uniform3f(WGC3Dint location,
-                         WGC3Dfloat x, WGC3Dfloat y, WGC3Dfloat z);
-  virtual void uniform3fv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dfloat* v);
-  virtual void uniform3i(WGC3Dint location,
-                         WGC3Dint x, WGC3Dint y, WGC3Dint z);
-  virtual void uniform3iv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dint* v);
-  virtual void uniform4f(WGC3Dint location,
-                         WGC3Dfloat x, WGC3Dfloat y,
-                         WGC3Dfloat z, WGC3Dfloat w);
-  virtual void uniform4fv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dfloat* v);
-  virtual void uniform4i(WGC3Dint location,
-                         WGC3Dint x, WGC3Dint y, WGC3Dint z, WGC3Dint w);
-  virtual void uniform4iv(WGC3Dint location,
-                          WGC3Dsizei count, const WGC3Dint* v);
-  virtual void uniformMatrix2fv(WGC3Dint location,
-                                WGC3Dsizei count,
-                                WGC3Dboolean transpose,
-                                const WGC3Dfloat* value);
-  virtual void uniformMatrix3fv(WGC3Dint location,
-                                WGC3Dsizei count,
-                                WGC3Dboolean transpose,
-                                const WGC3Dfloat* value);
-  virtual void uniformMatrix4fv(WGC3Dint location,
-                                WGC3Dsizei count,
-                                WGC3Dboolean transpose,
-                                const WGC3Dfloat* value);
+  virtual void uniform1f(blink::WGC3Dint location, blink::WGC3Dfloat x);
+  virtual void uniform1fv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dfloat* v);
+  virtual void uniform1i(blink::WGC3Dint location, blink::WGC3Dint x);
+  virtual void uniform1iv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dint* v);
+  virtual void uniform2f(blink::WGC3Dint location,
+                         blink::WGC3Dfloat x,
+                         blink::WGC3Dfloat y);
+  virtual void uniform2fv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dfloat* v);
+  virtual void uniform2i(blink::WGC3Dint location,
+                         blink::WGC3Dint x,
+                         blink::WGC3Dint y);
+  virtual void uniform2iv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dint* v);
+  virtual void uniform3f(blink::WGC3Dint location,
+                         blink::WGC3Dfloat x,
+                         blink::WGC3Dfloat y,
+                         blink::WGC3Dfloat z);
+  virtual void uniform3fv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dfloat* v);
+  virtual void uniform3i(blink::WGC3Dint location,
+                         blink::WGC3Dint x,
+                         blink::WGC3Dint y,
+                         blink::WGC3Dint z);
+  virtual void uniform3iv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dint* v);
+  virtual void uniform4f(blink::WGC3Dint location,
+                         blink::WGC3Dfloat x,
+                         blink::WGC3Dfloat y,
+                         blink::WGC3Dfloat z,
+                         blink::WGC3Dfloat w);
+  virtual void uniform4fv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dfloat* v);
+  virtual void uniform4i(blink::WGC3Dint location,
+                         blink::WGC3Dint x,
+                         blink::WGC3Dint y,
+                         blink::WGC3Dint z,
+                         blink::WGC3Dint w);
+  virtual void uniform4iv(blink::WGC3Dint location,
+                          blink::WGC3Dsizei count,
+                          const blink::WGC3Dint* v);
+  virtual void uniformMatrix2fv(blink::WGC3Dint location,
+                                blink::WGC3Dsizei count,
+                                blink::WGC3Dboolean transpose,
+                                const blink::WGC3Dfloat* value);
+  virtual void uniformMatrix3fv(blink::WGC3Dint location,
+                                blink::WGC3Dsizei count,
+                                blink::WGC3Dboolean transpose,
+                                const blink::WGC3Dfloat* value);
+  virtual void uniformMatrix4fv(blink::WGC3Dint location,
+                                blink::WGC3Dsizei count,
+                                blink::WGC3Dboolean transpose,
+                                const blink::WGC3Dfloat* value);
 
-  virtual void useProgram(WebGLId program);
-  virtual void validateProgram(WebGLId program);
+  virtual void useProgram(blink::WebGLId program);
+  virtual void validateProgram(blink::WebGLId program);
 
-  virtual void vertexAttrib1f(WGC3Duint index, WGC3Dfloat x);
-  virtual void vertexAttrib1fv(WGC3Duint index, const WGC3Dfloat* values);
-  virtual void vertexAttrib2f(WGC3Duint index, WGC3Dfloat x, WGC3Dfloat y);
-  virtual void vertexAttrib2fv(WGC3Duint index, const WGC3Dfloat* values);
-  virtual void vertexAttrib3f(WGC3Duint index,
-                              WGC3Dfloat x, WGC3Dfloat y, WGC3Dfloat z);
-  virtual void vertexAttrib3fv(WGC3Duint index, const WGC3Dfloat* values);
-  virtual void vertexAttrib4f(WGC3Duint index,
-                              WGC3Dfloat x, WGC3Dfloat y,
-                              WGC3Dfloat z, WGC3Dfloat w);
-  virtual void vertexAttrib4fv(WGC3Duint index, const WGC3Dfloat* values);
-  virtual void vertexAttribPointer(WGC3Duint index,
-                                   WGC3Dint size,
-                                   WGC3Denum type,
-                                   WGC3Dboolean normalized,
-                                   WGC3Dsizei stride,
-                                   WGC3Dintptr offset);
+  virtual void vertexAttrib1f(blink::WGC3Duint index, blink::WGC3Dfloat x);
+  virtual void vertexAttrib1fv(blink::WGC3Duint index,
+                               const blink::WGC3Dfloat* values);
+  virtual void vertexAttrib2f(blink::WGC3Duint index,
+                              blink::WGC3Dfloat x,
+                              blink::WGC3Dfloat y);
+  virtual void vertexAttrib2fv(blink::WGC3Duint index,
+                               const blink::WGC3Dfloat* values);
+  virtual void vertexAttrib3f(blink::WGC3Duint index,
+                              blink::WGC3Dfloat x,
+                              blink::WGC3Dfloat y,
+                              blink::WGC3Dfloat z);
+  virtual void vertexAttrib3fv(blink::WGC3Duint index,
+                               const blink::WGC3Dfloat* values);
+  virtual void vertexAttrib4f(blink::WGC3Duint index,
+                              blink::WGC3Dfloat x,
+                              blink::WGC3Dfloat y,
+                              blink::WGC3Dfloat z,
+                              blink::WGC3Dfloat w);
+  virtual void vertexAttrib4fv(blink::WGC3Duint index,
+                               const blink::WGC3Dfloat* values);
+  virtual void vertexAttribPointer(blink::WGC3Duint index,
+                                   blink::WGC3Dint size,
+                                   blink::WGC3Denum type,
+                                   blink::WGC3Dboolean normalized,
+                                   blink::WGC3Dsizei stride,
+                                   blink::WGC3Dintptr offset);
 
-  virtual void viewport(WGC3Dint x, WGC3Dint y,
-                        WGC3Dsizei width, WGC3Dsizei height);
+  virtual void viewport(blink::WGC3Dint x,
+                        blink::WGC3Dint y,
+                        blink::WGC3Dsizei width,
+                        blink::WGC3Dsizei height);
 
-  virtual WebGLId createBuffer();
-  virtual WebGLId createFramebuffer();
-  virtual WebGLId createRenderbuffer();
-  virtual WebGLId createTexture();
+  virtual blink::WebGLId createBuffer();
+  virtual blink::WebGLId createFramebuffer();
+  virtual blink::WebGLId createRenderbuffer();
+  virtual blink::WebGLId createTexture();
 
-  virtual void deleteBuffer(WebGLId);
-  virtual void deleteFramebuffer(WebGLId);
-  virtual void deleteRenderbuffer(WebGLId);
-  virtual void deleteTexture(WebGLId);
+  virtual void deleteBuffer(blink::WebGLId);
+  virtual void deleteFramebuffer(blink::WebGLId);
+  virtual void deleteRenderbuffer(blink::WebGLId);
+  virtual void deleteTexture(blink::WebGLId);
 
-  virtual WebGLId createProgram();
-  virtual WebGLId createShader(WGC3Denum);
+  virtual blink::WebGLId createProgram();
+  virtual blink::WebGLId createShader(blink::WGC3Denum);
 
-  virtual void deleteProgram(WebGLId);
-  virtual void deleteShader(WebGLId);
+  virtual void deleteProgram(blink::WebGLId);
+  virtual void deleteShader(blink::WebGLId);
 
-  virtual void synthesizeGLError(WGC3Denum);
+  virtual void synthesizeGLError(blink::WGC3Denum);
 
-  virtual void* mapBufferSubDataCHROMIUM(
-      WGC3Denum target, WGC3Dintptr offset,
-      WGC3Dsizeiptr size, WGC3Denum access);
+  virtual void* mapBufferSubDataCHROMIUM(blink::WGC3Denum target,
+                                         blink::WGC3Dintptr offset,
+                                         blink::WGC3Dsizeiptr size,
+                                         blink::WGC3Denum access);
   virtual void unmapBufferSubDataCHROMIUM(const void*);
-  virtual void* mapTexSubImage2DCHROMIUM(
-      WGC3Denum target,
-      WGC3Dint level,
-      WGC3Dint xoffset,
-      WGC3Dint yoffset,
-      WGC3Dsizei width,
-      WGC3Dsizei height,
-      WGC3Denum format,
-      WGC3Denum type,
-      WGC3Denum access);
+  virtual void* mapTexSubImage2DCHROMIUM(blink::WGC3Denum target,
+                                         blink::WGC3Dint level,
+                                         blink::WGC3Dint xoffset,
+                                         blink::WGC3Dint yoffset,
+                                         blink::WGC3Dsizei width,
+                                         blink::WGC3Dsizei height,
+                                         blink::WGC3Denum format,
+                                         blink::WGC3Denum type,
+                                         blink::WGC3Denum access);
   virtual void unmapTexSubImage2DCHROMIUM(const void*);
 
   virtual void setVisibilityCHROMIUM(bool visible);
 
-  virtual void discardFramebufferEXT(WGC3Denum target,
-                                     WGC3Dsizei numAttachments,
-                                     const WGC3Denum* attachments);
-  virtual void copyTextureToParentTextureCHROMIUM(
-      WebGLId texture, WebGLId parentTexture);
+  virtual void discardFramebufferEXT(blink::WGC3Denum target,
+                                     blink::WGC3Dsizei numAttachments,
+                                     const blink::WGC3Denum* attachments);
+  virtual void copyTextureToParentTextureCHROMIUM(blink::WebGLId texture,
+                                                  blink::WebGLId parentTexture);
 
   virtual blink::WebString getRequestableExtensionsCHROMIUM();
   virtual void requestExtensionCHROMIUM(const char*);
 
-  virtual void blitFramebufferCHROMIUM(
-      WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1,
-      WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1,
-      WGC3Dbitfield mask, WGC3Denum filter);
+  virtual void blitFramebufferCHROMIUM(blink::WGC3Dint srcX0,
+                                       blink::WGC3Dint srcY0,
+                                       blink::WGC3Dint srcX1,
+                                       blink::WGC3Dint srcY1,
+                                       blink::WGC3Dint dstX0,
+                                       blink::WGC3Dint dstY0,
+                                       blink::WGC3Dint dstX1,
+                                       blink::WGC3Dint dstY1,
+                                       blink::WGC3Dbitfield mask,
+                                       blink::WGC3Denum filter);
   virtual void renderbufferStorageMultisampleCHROMIUM(
-      WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat,
-      WGC3Dsizei width, WGC3Dsizei height);
+      blink::WGC3Denum target,
+      blink::WGC3Dsizei samples,
+      blink::WGC3Denum internalformat,
+      blink::WGC3Dsizei width,
+      blink::WGC3Dsizei height);
 
-  virtual blink::WebString getTranslatedShaderSourceANGLE(WebGLId shader);
+  virtual blink::WebString getTranslatedShaderSourceANGLE(
+      blink::WebGLId shader);
 
   virtual void setContextLostCallback(
       WebGraphicsContext3D::WebGraphicsContextLostCallback* callback);
@@ -433,291 +492,424 @@
   virtual void setErrorMessageCallback(
       WebGraphicsContext3D::WebGraphicsErrorMessageCallback* callback);
 
-  virtual void texImageIOSurface2DCHROMIUM(
-      WGC3Denum target, WGC3Dint width, WGC3Dint height,
-      WGC3Duint ioSurfaceId, WGC3Duint plane);
+  virtual void texImageIOSurface2DCHROMIUM(blink::WGC3Denum target,
+                                           blink::WGC3Dint width,
+                                           blink::WGC3Dint height,
+                                           blink::WGC3Duint ioSurfaceId,
+                                           blink::WGC3Duint plane);
 
-  virtual void texStorage2DEXT(
-      WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat,
-      WGC3Dint width, WGC3Dint height);
+  virtual void texStorage2DEXT(blink::WGC3Denum target,
+                               blink::WGC3Dint levels,
+                               blink::WGC3Duint internalformat,
+                               blink::WGC3Dint width,
+                               blink::WGC3Dint height);
 
-  virtual WebGLId createQueryEXT();
-  virtual void deleteQueryEXT(WebGLId query);
-  virtual WGC3Dboolean isQueryEXT(WGC3Duint query);
-  virtual void beginQueryEXT(WGC3Denum target, WebGLId query);
-  virtual void endQueryEXT(WGC3Denum target);
-  virtual void getQueryivEXT(
-      WGC3Denum target, WGC3Denum pname, WGC3Dint* params);
-  virtual void getQueryObjectuivEXT(
-      WebGLId query, WGC3Denum pname, WGC3Duint* params);
+  virtual blink::WebGLId createQueryEXT();
+  virtual void deleteQueryEXT(blink::WebGLId query);
+  virtual blink::WGC3Dboolean isQueryEXT(blink::WGC3Duint query);
+  virtual void beginQueryEXT(blink::WGC3Denum target, blink::WebGLId query);
+  virtual void endQueryEXT(blink::WGC3Denum target);
+  virtual void getQueryivEXT(blink::WGC3Denum target,
+                             blink::WGC3Denum pname,
+                             blink::WGC3Dint* params);
+  virtual void getQueryObjectuivEXT(blink::WebGLId query,
+                                    blink::WGC3Denum pname,
+                                    blink::WGC3Duint* params);
 
   // TODO(dshwang): Remove |level| in Blink and then remove it.
-  void copyTextureCHROMIUM(WGC3Denum target,
-                           WebGLId source_id,
-                           WebGLId dest_id,
-                           WGC3Dint level,
-                           WGC3Denum internal_format,
-                           WGC3Denum dest_type) override;
+  void copyTextureCHROMIUM(blink::WGC3Denum target,
+                           blink::WebGLId source_id,
+                           blink::WebGLId dest_id,
+                           blink::WGC3Dint level,
+                           blink::WGC3Denum internal_format,
+                           blink::WGC3Denum dest_type) override;
 
-  void copySubTextureCHROMIUM(WGC3Denum target,
-                              WebGLId source_id,
-                              WebGLId dest_id,
-                              WGC3Dint level,
-                              WGC3Dint xoffset,
-                              WGC3Dint yoffset) override;
+  void copySubTextureCHROMIUM(blink::WGC3Denum target,
+                              blink::WebGLId source_id,
+                              blink::WebGLId dest_id,
+                              blink::WGC3Dint level,
+                              blink::WGC3Dint xoffset,
+                              blink::WGC3Dint yoffset) override;
 
-  virtual void copyTextureCHROMIUM(WGC3Denum target,
-                                   WebGLId source_id,
-                                   WebGLId dest_id,
-                                   WGC3Denum internal_format,
-                                   WGC3Denum dest_type);
+  virtual void copyTextureCHROMIUM(blink::WGC3Denum target,
+                                   blink::WebGLId source_id,
+                                   blink::WebGLId dest_id,
+                                   blink::WGC3Denum internal_format,
+                                   blink::WGC3Denum dest_type);
 
-  virtual void copySubTextureCHROMIUM(WGC3Denum target,
-                                      WebGLId sourceId,
-                                      WebGLId destId,
-                                      WGC3Dint xoffset,
-                                      WGC3Dint yoffset);
+  virtual void copySubTextureCHROMIUM(blink::WGC3Denum target,
+                                      blink::WebGLId sourceId,
+                                      blink::WebGLId destId,
+                                      blink::WGC3Dint xoffset,
+                                      blink::WGC3Dint yoffset);
 
-  virtual void bindUniformLocationCHROMIUM(WebGLId program, WGC3Dint location,
-                                           const WGC3Dchar* uniform);
+  virtual void bindUniformLocationCHROMIUM(blink::WebGLId program,
+                                           blink::WGC3Dint location,
+                                           const blink::WGC3Dchar* uniform);
 
   virtual void shallowFlushCHROMIUM();
   virtual void shallowFinishCHROMIUM();
 
-  virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox);
-  virtual void produceTextureCHROMIUM(WGC3Denum target,
-                                      const WGC3Dbyte* mailbox);
-  virtual void produceTextureDirectCHROMIUM(WebGLId texture, WGC3Denum target,
-                                      const WGC3Dbyte* mailbox);
-  virtual void consumeTextureCHROMIUM(WGC3Denum target,
-                                      const WGC3Dbyte* mailbox);
-  virtual WebGLId createAndConsumeTextureCHROMIUM(WGC3Denum target,
-                                      const WGC3Dbyte* mailbox);
+  virtual void genMailboxCHROMIUM(blink::WGC3Dbyte* mailbox);
+  virtual void produceTextureCHROMIUM(blink::WGC3Denum target,
+                                      const blink::WGC3Dbyte* mailbox);
+  virtual void produceTextureDirectCHROMIUM(blink::WebGLId texture,
+                                            blink::WGC3Denum target,
+                                            const blink::WGC3Dbyte* mailbox);
+  virtual void consumeTextureCHROMIUM(blink::WGC3Denum target,
+                                      const blink::WGC3Dbyte* mailbox);
+  virtual blink::WebGLId createAndConsumeTextureCHROMIUM(
+      blink::WGC3Denum target,
+      const blink::WGC3Dbyte* mailbox);
 
-  virtual void genValuebuffersCHROMIUM(WGC3Dsizei count, WebGLId* ids);
-  virtual WebGLId createValuebufferCHROMIUM();
-  virtual void deleteValuebuffersCHROMIUM(WGC3Dsizei count, WebGLId* ids);
-  virtual void deleteValuebufferCHROMIUM(WebGLId);
-  virtual void bindValuebufferCHROMIUM(WGC3Denum target, WebGLId valuebuffer);
-  virtual WGC3Dboolean isValuebufferCHROMIUM(WebGLId renderbuffer);
-  virtual void subscribeValueCHROMIUM(WGC3Denum target, WGC3Denum subscription);
-  virtual void populateSubscribedValuesCHROMIUM(WGC3Denum target);
-  virtual void uniformValuebufferCHROMIUM(WGC3Dint location,
-                                          WGC3Denum target,
-                                          WGC3Denum subscription);
-  virtual void traceBeginCHROMIUM(const WGC3Dchar* category_name,
-                                  const WGC3Dchar* trace_name);
+  virtual void genValuebuffersCHROMIUM(blink::WGC3Dsizei count,
+                                       blink::WebGLId* ids);
+  virtual blink::WebGLId createValuebufferCHROMIUM();
+  virtual void deleteValuebuffersCHROMIUM(blink::WGC3Dsizei count,
+                                          blink::WebGLId* ids);
+  virtual void deleteValuebufferCHROMIUM(blink::WebGLId);
+  virtual void bindValuebufferCHROMIUM(blink::WGC3Denum target,
+                                       blink::WebGLId valuebuffer);
+  virtual blink::WGC3Dboolean isValuebufferCHROMIUM(
+      blink::WebGLId renderbuffer);
+  virtual void subscribeValueCHROMIUM(blink::WGC3Denum target,
+                                      blink::WGC3Denum subscription);
+  virtual void populateSubscribedValuesCHROMIUM(blink::WGC3Denum target);
+  virtual void uniformValuebufferCHROMIUM(blink::WGC3Dint location,
+                                          blink::WGC3Denum target,
+                                          blink::WGC3Denum subscription);
+  virtual void traceBeginCHROMIUM(const blink::WGC3Dchar* category_name,
+                                  const blink::WGC3Dchar* trace_name);
   virtual void traceEndCHROMIUM();
 
-  virtual void insertEventMarkerEXT(const WGC3Dchar* marker);
-  virtual void pushGroupMarkerEXT(const WGC3Dchar* marker);
+  virtual void insertEventMarkerEXT(const blink::WGC3Dchar* marker);
+  virtual void pushGroupMarkerEXT(const blink::WGC3Dchar* marker);
   virtual void popGroupMarkerEXT();
 
   // GL_OES_vertex_array_object
-  virtual WebGLId createVertexArrayOES();
-  virtual void deleteVertexArrayOES(WebGLId array);
-  virtual WGC3Dboolean isVertexArrayOES(WebGLId array);
-  virtual void bindVertexArrayOES(WebGLId array);
+  virtual blink::WebGLId createVertexArrayOES();
+  virtual void deleteVertexArrayOES(blink::WebGLId array);
+  virtual blink::WGC3Dboolean isVertexArrayOES(blink::WebGLId array);
+  virtual void bindVertexArrayOES(blink::WebGLId array);
 
-  virtual void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint image_id);
-  virtual void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint image_id);
+  virtual void bindTexImage2DCHROMIUM(blink::WGC3Denum target,
+                                      blink::WGC3Dint image_id);
+  virtual void releaseTexImage2DCHROMIUM(blink::WGC3Denum target,
+                                         blink::WGC3Dint image_id);
 
-  virtual void* mapBufferCHROMIUM(WGC3Denum target, WGC3Denum access);
-  virtual WGC3Dboolean unmapBufferCHROMIUM(WGC3Denum target);
+  virtual void* mapBufferCHROMIUM(blink::WGC3Denum target,
+                                  blink::WGC3Denum access);
+  virtual blink::WGC3Dboolean unmapBufferCHROMIUM(blink::WGC3Denum target);
 
   // Async pixel transfer functions.
-  virtual void asyncTexImage2DCHROMIUM(
-      WGC3Denum target,
-      WGC3Dint level,
-      WGC3Denum internalformat,
-      WGC3Dsizei width,
-      WGC3Dsizei height,
-      WGC3Dint border,
-      WGC3Denum format,
-      WGC3Denum type,
-      const void* pixels);
-  virtual void asyncTexSubImage2DCHROMIUM(
-      WGC3Denum target,
-      WGC3Dint level,
-      WGC3Dint xoffset,
-      WGC3Dint yoffset,
-      WGC3Dsizei width,
-      WGC3Dsizei height,
-      WGC3Denum format,
-      WGC3Denum type,
-      const void* pixels);
-  virtual void waitAsyncTexImage2DCHROMIUM(WGC3Denum target);
+  virtual void asyncTexImage2DCHROMIUM(blink::WGC3Denum target,
+                                       blink::WGC3Dint level,
+                                       blink::WGC3Denum internalformat,
+                                       blink::WGC3Dsizei width,
+                                       blink::WGC3Dsizei height,
+                                       blink::WGC3Dint border,
+                                       blink::WGC3Denum format,
+                                       blink::WGC3Denum type,
+                                       const void* pixels);
+  virtual void asyncTexSubImage2DCHROMIUM(blink::WGC3Denum target,
+                                          blink::WGC3Dint level,
+                                          blink::WGC3Dint xoffset,
+                                          blink::WGC3Dint yoffset,
+                                          blink::WGC3Dsizei width,
+                                          blink::WGC3Dsizei height,
+                                          blink::WGC3Denum format,
+                                          blink::WGC3Denum type,
+                                          const void* pixels);
+  virtual void waitAsyncTexImage2DCHROMIUM(blink::WGC3Denum target);
 
   // GL_EXT_draw_buffers
-  virtual void drawBuffersEXT(
-      WGC3Dsizei n,
-      const WGC3Denum* bufs);
+  virtual void drawBuffersEXT(blink::WGC3Dsizei n,
+                              const blink::WGC3Denum* bufs);
 
   // GL_ANGLE_instanced_arrays
-  virtual void drawArraysInstancedANGLE(WGC3Denum mode, WGC3Dint first,
-      WGC3Dsizei count, WGC3Dsizei primcount);
-  virtual void drawElementsInstancedANGLE(WGC3Denum mode, WGC3Dsizei count,
-      WGC3Denum type, WGC3Dintptr offset, WGC3Dsizei primcount);
-  virtual void vertexAttribDivisorANGLE(WGC3Duint index, WGC3Duint divisor);
+  virtual void drawArraysInstancedANGLE(blink::WGC3Denum mode,
+                                        blink::WGC3Dint first,
+                                        blink::WGC3Dsizei count,
+                                        blink::WGC3Dsizei primcount);
+  virtual void drawElementsInstancedANGLE(blink::WGC3Denum mode,
+                                          blink::WGC3Dsizei count,
+                                          blink::WGC3Denum type,
+                                          blink::WGC3Dintptr offset,
+                                          blink::WGC3Dsizei primcount);
+  virtual void vertexAttribDivisorANGLE(blink::WGC3Duint index,
+                                        blink::WGC3Duint divisor);
 
   // GL_CHROMIUM_gpu_memory_buffer_image
-  virtual WGC3Duint createGpuMemoryBufferImageCHROMIUM(WGC3Dsizei width,
-                                                       WGC3Dsizei height,
-                                                       WGC3Denum internalformat,
-                                                       WGC3Denum usage);
-  virtual void destroyImageCHROMIUM(WGC3Duint image_id);
+  virtual blink::WGC3Duint createGpuMemoryBufferImageCHROMIUM(
+      blink::WGC3Dsizei width,
+      blink::WGC3Dsizei height,
+      blink::WGC3Denum internalformat,
+      blink::WGC3Denum usage);
+  virtual void destroyImageCHROMIUM(blink::WGC3Duint image_id);
 
   // GL_EXT_multisampled_render_to_texture
-  virtual void framebufferTexture2DMultisampleEXT(WGC3Denum target,
-                                    WGC3Denum attachment,
-                                    WGC3Denum textarget,
-                                    WebGLId texture,
-                                    WGC3Dint level,
-                                    WGC3Dsizei samples);
+  virtual void framebufferTexture2DMultisampleEXT(blink::WGC3Denum target,
+                                                  blink::WGC3Denum attachment,
+                                                  blink::WGC3Denum textarget,
+                                                  blink::WebGLId texture,
+                                                  blink::WGC3Dint level,
+                                                  blink::WGC3Dsizei samples);
   virtual void renderbufferStorageMultisampleEXT(
-      WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat,
-      WGC3Dsizei width, WGC3Dsizei height);
+      blink::WGC3Denum target,
+      blink::WGC3Dsizei samples,
+      blink::WGC3Denum internalformat,
+      blink::WGC3Dsizei width,
+      blink::WGC3Dsizei height);
 
   // OpenGL ES 3.0 functions not represented by pre-existing extensions
-  virtual void beginTransformFeedback(WGC3Denum primitiveMode);
-  virtual void bindBufferBase(WGC3Denum target, WGC3Duint index,
-      WGC3Duint buffer);
-  virtual void bindBufferRange(WGC3Denum target, WGC3Duint index,
-      WGC3Duint buffer, WGC3Dintptr offset, WGC3Dsizeiptr size);
-  virtual void bindSampler(WGC3Duint unit, WebGLId sampler);
-  virtual void bindTransformFeedback(WGC3Denum target,
-      WebGLId transformfeedback);
-  virtual void clearBufferfi(WGC3Denum buffer, WGC3Dint drawbuffer,
-      WGC3Dfloat depth, WGC3Dint stencil);
-  virtual void clearBufferfv(WGC3Denum buffer, WGC3Dint drawbuffer,
-      const WGC3Dfloat *value);
-  virtual void clearBufferiv(WGC3Denum buffer, WGC3Dint drawbuffer,
-      const WGC3Dint *value);
-  virtual void clearBufferuiv(WGC3Denum buffer, WGC3Dint drawbuffer,
-      const WGC3Duint *value);
-  //virtual WGC3Denum clientWaitSync(WebGLId sync, WGC3Dbitfield flags,
-  //    WGC3Duint64 timeout);
-  //virtual void compressedTexImage3D(WGC3Denum target, WGC3Dint level,
-  //    WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height,
-  //    WGC3Dsizei depth, WGC3Dint border, WGC3Dsizei imageSize,
-  //    const void *data);
-  //virtual void compressedTexSubImage3D(WGC3Denum target, WGC3Dint level,
-  //    WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dsizei width,
-  //    WGC3Dsizei height, WGC3Dsizei depth, WGC3Denum format,
+  virtual void beginTransformFeedback(blink::WGC3Denum primitiveMode);
+  virtual void bindBufferBase(blink::WGC3Denum target,
+                              blink::WGC3Duint index,
+                              blink::WGC3Duint buffer);
+  virtual void bindBufferRange(blink::WGC3Denum target,
+                               blink::WGC3Duint index,
+                               blink::WGC3Duint buffer,
+                               blink::WGC3Dintptr offset,
+                               blink::WGC3Dsizeiptr size);
+  virtual void bindSampler(blink::WGC3Duint unit, blink::WebGLId sampler);
+  virtual void bindTransformFeedback(blink::WGC3Denum target,
+                                     blink::WebGLId transformfeedback);
+  virtual void clearBufferfi(blink::WGC3Denum buffer,
+                             blink::WGC3Dint drawbuffer,
+                             blink::WGC3Dfloat depth,
+                             blink::WGC3Dint stencil);
+  virtual void clearBufferfv(blink::WGC3Denum buffer,
+                             blink::WGC3Dint drawbuffer,
+                             const blink::WGC3Dfloat* value);
+  virtual void clearBufferiv(blink::WGC3Denum buffer,
+                             blink::WGC3Dint drawbuffer,
+                             const blink::WGC3Dint* value);
+  virtual void clearBufferuiv(blink::WGC3Denum buffer,
+                              blink::WGC3Dint drawbuffer,
+                              const blink::WGC3Duint* value);
+  // virtual blink::WGC3Denum clientWaitSync(blink::WebGLId sync,
+  //                                         blink::WGC3Dbitfield flags,
+  //                                         blink::WGC3Duint64 timeout);
+  // virtual void compressedTexImage3D(blink::WGC3Denum target, blink::WGC3Dint
+  // level,
+  //    blink::WGC3Denum internalformat, blink::WGC3Dsizei width,
+  //    WGC3Dsizei height, WGC3Dsizei depth, blink::WGC3Dint border,
   //    WGC3Dsizei imageSize, const void *data);
-  virtual void copyBufferSubData(WGC3Denum readTarget, WGC3Denum writeTarget,
-      WGC3Dintptr readOffset, WGC3Dintptr writeOffset, WGC3Dsizeiptr size);
-  virtual void copyTexSubImage3D(WGC3Denum target, WGC3Dint level,
-      WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dint x,
-      WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height);
-  virtual WebGLId createSampler();
-  virtual WebGLId createTransformFeedback();
-  virtual void deleteSampler(WebGLId sampler);
-  //virtual void deleteSync(WebGLId sync);
-  virtual void deleteTransformFeedback(WebGLId transformfeedback);
+  // virtual void compressedTexSubImage3D(blink::WGC3Denum target,
+  //    blink::WGC3Dint level, blink::WGC3Dint xoffset, blink::WGC3Dint yoffset,
+  //    blink::WGC3Dint zoffset,
+  //    blink::WGC3Dsizei width, blink::WGC3Dsizei height,
+  //    blink::WGC3Dsizei depth, blink::WGC3Denum format,
+  //    blink::WGC3Dsizei imageSize, const void *data);
+  virtual void copyBufferSubData(blink::WGC3Denum readTarget,
+                                 blink::WGC3Denum writeTarget,
+                                 blink::WGC3Dintptr readOffset,
+                                 blink::WGC3Dintptr writeOffset,
+                                 blink::WGC3Dsizeiptr size);
+  virtual void copyTexSubImage3D(blink::WGC3Denum target,
+                                 blink::WGC3Dint level,
+                                 blink::WGC3Dint xoffset,
+                                 blink::WGC3Dint yoffset,
+                                 blink::WGC3Dint zoffset,
+                                 blink::WGC3Dint x,
+                                 blink::WGC3Dint y,
+                                 blink::WGC3Dsizei width,
+                                 blink::WGC3Dsizei height);
+  virtual blink::WebGLId createSampler();
+  virtual blink::WebGLId createTransformFeedback();
+  virtual void deleteSampler(blink::WebGLId sampler);
+  // virtual void deleteSync(blink::WebGLId sync);
+  virtual void deleteTransformFeedback(blink::WebGLId transformfeedback);
   virtual void endTransformFeedback(void);
-  //virtual WebGLId fenceSync(WGC3Denum condition, WGC3Dbitfield flags);
-  virtual void framebufferTextureLayer(WGC3Denum target, WGC3Denum attachment,
-      WGC3Duint texture, WGC3Dint level, WGC3Dint layer);
-  virtual void getActiveUniformBlockName(WGC3Duint program,
-      WGC3Duint uniformBlockIndex, WGC3Dsizei bufSize, WGC3Dsizei *length,
-      WGC3Dchar *uniformBlockName);
-  virtual void getActiveUniformBlockiv(WGC3Duint program,
-      WGC3Duint uniformBlockIndex, WGC3Denum pname, WGC3Dint *params);
-  //virtual void getActiveUniformsiv(WGC3Duint program, WGC3Dsizei uniformCount,
-  //    const WGC3Duint *uniformIndices, WGC3Denum pname, WGC3Dint *params);
-  virtual WGC3Dint getFragDataLocation(WGC3Duint program,
-      const WGC3Dchar *name);
-  virtual void getInternalformativ(WGC3Denum target, WGC3Denum internalformat,
-      WGC3Denum pname, WGC3Dsizei bufSize, WGC3Dint *params);
-  virtual void getSamplerParameterfv(WGC3Duint sampler, WGC3Denum pname,
-      WGC3Dfloat *params);
-  virtual void getSamplerParameteriv(WGC3Duint sampler, WGC3Denum pname,
-      WGC3Dint *params);
-  //virtual void getTransformFeedbackVarying(WGC3Duint program, WGC3Duint index,
-  //    WGC3Dsizei bufSize, WGC3Dsizei *length, WGC3Dsizei *size,
-  //    WGC3Denum *type, WGC3Dchar *name);
-  virtual WGC3Duint getUniformBlockIndex(WGC3Duint program,
-      const WGC3Dchar *uniformBlockName);
-  //virtual void getUniformIndices(WGC3Duint program, WGC3Dsizei uniformCount,
-  //    const WGC3Dchar *const*uniformNames, WGC3Duint *uniformIndices);
-  //virtual void getUniformuiv(WGC3Duint program, WGC3Dint location,
-  //    WGC3Duint *params);
-  //virtual void getVertexAttribIiv(WGC3Duint index, WGC3Denum pname,
-  //    WGC3Dint *params);
-  //virtual void getVertexAttribIuiv(WGC3Duint index, WGC3Denum pname,
-  //    WGC3Duint *params);
-  virtual void invalidateFramebuffer(WGC3Denum target,
-      WGC3Dsizei numAttachments, const WGC3Denum *attachments);
-  virtual void invalidateSubFramebuffer(WGC3Denum target,
-      WGC3Dsizei numAttachments, const WGC3Denum *attachments, WGC3Dint x,
-      WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height);
-  virtual WGC3Dboolean isSampler(WebGLId sampler);
-  //virtual WGC3Dboolean isSync(WebGLId sync);
-  virtual WGC3Dboolean isTransformFeedback(WGC3Duint id);
+  // virtual blink::WebGLId fenceSync(blink::WGC3Denum condition,
+  //                                  blink::WGC3Dbitfield flags);
+  virtual void framebufferTextureLayer(blink::WGC3Denum target,
+                                       blink::WGC3Denum attachment,
+                                       blink::WGC3Duint texture,
+                                       blink::WGC3Dint level,
+                                       blink::WGC3Dint layer);
+  virtual void getActiveUniformBlockName(blink::WGC3Duint program,
+                                         blink::WGC3Duint uniformBlockIndex,
+                                         blink::WGC3Dsizei bufSize,
+                                         blink::WGC3Dsizei* length,
+                                         blink::WGC3Dchar* uniformBlockName);
+  virtual void getActiveUniformBlockiv(blink::WGC3Duint program,
+                                       blink::WGC3Duint uniformBlockIndex,
+                                       blink::WGC3Denum pname,
+                                       blink::WGC3Dint* params);
+  // virtual void getActiveUniformsiv(blink::WGC3Duint program,
+  //    blink::WGC3Dsizei uniformCount, const blink::WGC3Duint *uniformIndices,
+  //    blink::WGC3Denum pname, blink::WGC3Dint *params);
+  virtual blink::WGC3Dint getFragDataLocation(blink::WGC3Duint program,
+                                              const blink::WGC3Dchar* name);
+  virtual void getInternalformativ(blink::WGC3Denum target,
+                                   blink::WGC3Denum internalformat,
+                                   blink::WGC3Denum pname,
+                                   blink::WGC3Dsizei bufSize,
+                                   blink::WGC3Dint* params);
+  virtual void getSamplerParameterfv(blink::WGC3Duint sampler,
+                                     blink::WGC3Denum pname,
+                                     blink::WGC3Dfloat* params);
+  virtual void getSamplerParameteriv(blink::WGC3Duint sampler,
+                                     blink::WGC3Denum pname,
+                                     blink::WGC3Dint* params);
+  // virtual void getTransformFeedbackVarying(blink::WGC3Duint program,
+  // blink::WGC3Duint index,
+  //    blink::WGC3Dsizei bufSize, blink::WGC3Dsizei *length,
+  //    blink::WGC3Dsizei *size, blink::WGC3Denum *type,
+  //    blink::WGC3Dchar *name);
+  virtual blink::WGC3Duint getUniformBlockIndex(
+      blink::WGC3Duint program,
+      const blink::WGC3Dchar* uniformBlockName);
+  // virtual void getUniformIndices(blink::WGC3Duint program,
+  //    blink::WGC3Dsizei uniformCount,
+  //    const blink::WGC3Dchar *const*uniformNames,
+  //    blink::WGC3Duint *uniformIndices);
+  // virtual void getUniformuiv(blink::WGC3Duint program, blink::WGC3Dint
+  // location,
+  //    blink::WGC3Duint *params);
+  // virtual void getVertexAttribIiv(blink::WGC3Duint index, blink::WGC3Denum
+  // pname,
+  //    blink::WGC3Dint *params);
+  // virtual void getVertexAttribIuiv(blink::WGC3Duint index, blink::WGC3Denum
+  // pname,
+  //    blink::WGC3Duint *params);
+  virtual void invalidateFramebuffer(blink::WGC3Denum target,
+                                     blink::WGC3Dsizei numAttachments,
+                                     const blink::WGC3Denum* attachments);
+  virtual void invalidateSubFramebuffer(blink::WGC3Denum target,
+                                        blink::WGC3Dsizei numAttachments,
+                                        const blink::WGC3Denum* attachments,
+                                        blink::WGC3Dint x,
+                                        blink::WGC3Dint y,
+                                        blink::WGC3Dsizei width,
+                                        blink::WGC3Dsizei height);
+  virtual blink::WGC3Dboolean isSampler(blink::WebGLId sampler);
+  // virtual blink::WGC3Dboolean isSync(blink::WebGLId sync);
+  virtual blink::WGC3Dboolean isTransformFeedback(blink::WGC3Duint id);
   virtual void pauseTransformFeedback(void);
-  //virtual void programParameteri(WGC3Duint program, WGC3Denum pname,
-  //    WGC3Dint value);
-  virtual void readBuffer(WGC3Denum src);
+  // virtual void programParameteri(blink::WGC3Duint program, blink::WGC3Denum
+  // pname,
+  //    blink::WGC3Dint value);
+  virtual void readBuffer(blink::WGC3Denum src);
   virtual void resumeTransformFeedback(void);
-  virtual void samplerParameterf(WGC3Duint sampler, WGC3Denum pname,
-      WGC3Dfloat param);
-  virtual void samplerParameterfv(WGC3Duint sampler, WGC3Denum pname,
-      const WGC3Dfloat *param);
-  virtual void samplerParameteri(WGC3Duint sampler, WGC3Denum pname,
-      WGC3Dint param);
-  virtual void samplerParameteriv(WGC3Duint sampler, WGC3Denum pname,
-      const WGC3Dint *param);
-  virtual void texImage3D(WGC3Denum target, WGC3Dint level,
-      WGC3Dint internalformat, WGC3Dsizei width, WGC3Dsizei height,
-      WGC3Dsizei depth, WGC3Dint border, WGC3Denum format, WGC3Denum type,
-      const void *pixels);
-  virtual void texStorage3D(WGC3Denum target, WGC3Dsizei levels,
-      WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height,
-      WGC3Dsizei depth);
-  virtual void texSubImage3D(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset,
-      WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dsizei width, WGC3Dsizei height,
-      WGC3Dsizei depth, WGC3Denum format, WGC3Denum type, const void *pixels);
-  virtual void transformFeedbackVaryings(WGC3Duint program, WGC3Dsizei count,
-      const WGC3Dchar *const*varyings, WGC3Denum bufferMode);
-  virtual void uniform1ui(WGC3Dint location, WGC3Duint x);
-  virtual void uniform1uiv(WGC3Dint location, WGC3Dsizei count,
-      const WGC3Duint *value);
-  virtual void uniform2ui(WGC3Dint location, WGC3Duint x, WGC3Duint y);
-  virtual void uniform2uiv(WGC3Dint location, WGC3Dsizei count,
-      const WGC3Duint *value);
-  virtual void uniform3ui(WGC3Dint location, WGC3Duint x, WGC3Duint y,
-      WGC3Duint z);
-  virtual void uniform3uiv(WGC3Dint location, WGC3Dsizei count,
-      const WGC3Duint *value);
-  virtual void uniform4ui(WGC3Dint location, WGC3Duint x, WGC3Duint y,
-      WGC3Duint z, WGC3Duint w);
-  virtual void uniform4uiv(WGC3Dint location, WGC3Dsizei count,
-      const WGC3Duint *value);
-  virtual void uniformBlockBinding(WGC3Duint program,
-      WGC3Duint uniformBlockIndex, WGC3Duint uniformBlockBinding);
-  virtual void uniformMatrix2x3fv(WGC3Dint location, WGC3Dsizei count,
-      WGC3Dboolean transpose, const WGC3Dfloat* value);
-  virtual void uniformMatrix2x4fv(WGC3Dint location, WGC3Dsizei count,
-      WGC3Dboolean transpose, const WGC3Dfloat* value);
-  virtual void uniformMatrix3x2fv(WGC3Dint location, WGC3Dsizei count,
-      WGC3Dboolean transpose, const WGC3Dfloat* value);
-  virtual void uniformMatrix3x4fv(WGC3Dint location, WGC3Dsizei count,
-      WGC3Dboolean transpose, const WGC3Dfloat* value);
-  virtual void uniformMatrix4x2fv(WGC3Dint location, WGC3Dsizei count,
-      WGC3Dboolean transpose, const WGC3Dfloat* value);
-  virtual void uniformMatrix4x3fv(WGC3Dint location, WGC3Dsizei count,
-      WGC3Dboolean transpose, const WGC3Dfloat* value);
-  virtual void vertexAttribI4i(WGC3Duint index, WGC3Dint x, WGC3Dint y,
-      WGC3Dint z, WGC3Dint w);
-  virtual void vertexAttribI4iv(WGC3Duint index, const WGC3Dint *v);
-  virtual void vertexAttribI4ui(WGC3Duint index, WGC3Duint x, WGC3Duint y,
-      WGC3Duint z, WGC3Duint w);
-  virtual void vertexAttribI4uiv(WGC3Duint index, const WGC3Duint *v);
-  virtual void vertexAttribIPointer(WGC3Duint index, WGC3Dint size,
-      WGC3Denum type, WGC3Dsizei stride, WGC3Dintptr pointer);
-  //virtual void waitSync(WebGLId sync, WGC3Dbitfield flags,
-  //    WGC3Duint64 timeout);
+  virtual void samplerParameterf(blink::WGC3Duint sampler,
+                                 blink::WGC3Denum pname,
+                                 blink::WGC3Dfloat param);
+  virtual void samplerParameterfv(blink::WGC3Duint sampler,
+                                  blink::WGC3Denum pname,
+                                  const blink::WGC3Dfloat* param);
+  virtual void samplerParameteri(blink::WGC3Duint sampler,
+                                 blink::WGC3Denum pname,
+                                 blink::WGC3Dint param);
+  virtual void samplerParameteriv(blink::WGC3Duint sampler,
+                                  blink::WGC3Denum pname,
+                                  const blink::WGC3Dint* param);
+  virtual void texImage3D(blink::WGC3Denum target,
+                          blink::WGC3Dint level,
+                          blink::WGC3Dint internalformat,
+                          blink::WGC3Dsizei width,
+                          blink::WGC3Dsizei height,
+                          blink::WGC3Dsizei depth,
+                          blink::WGC3Dint border,
+                          blink::WGC3Denum format,
+                          blink::WGC3Denum type,
+                          const void* pixels);
+  virtual void texStorage3D(blink::WGC3Denum target,
+                            blink::WGC3Dsizei levels,
+                            blink::WGC3Denum internalformat,
+                            blink::WGC3Dsizei width,
+                            blink::WGC3Dsizei height,
+                            blink::WGC3Dsizei depth);
+  virtual void texSubImage3D(blink::WGC3Denum target,
+                             blink::WGC3Dint level,
+                             blink::WGC3Dint xoffset,
+                             blink::WGC3Dint yoffset,
+                             blink::WGC3Dint zoffset,
+                             blink::WGC3Dsizei width,
+                             blink::WGC3Dsizei height,
+                             blink::WGC3Dsizei depth,
+                             blink::WGC3Denum format,
+                             blink::WGC3Denum type,
+                             const void* pixels);
+  virtual void transformFeedbackVaryings(
+      blink::WGC3Duint program,
+      blink::WGC3Dsizei count,
+      const blink::WGC3Dchar* const* varyings,
+      blink::WGC3Denum bufferMode);
+  virtual void uniform1ui(blink::WGC3Dint location, blink::WGC3Duint x);
+  virtual void uniform1uiv(blink::WGC3Dint location,
+                           blink::WGC3Dsizei count,
+                           const blink::WGC3Duint* value);
+  virtual void uniform2ui(blink::WGC3Dint location,
+                          blink::WGC3Duint x,
+                          blink::WGC3Duint y);
+  virtual void uniform2uiv(blink::WGC3Dint location,
+                           blink::WGC3Dsizei count,
+                           const blink::WGC3Duint* value);
+  virtual void uniform3ui(blink::WGC3Dint location,
+                          blink::WGC3Duint x,
+                          blink::WGC3Duint y,
+                          blink::WGC3Duint z);
+  virtual void uniform3uiv(blink::WGC3Dint location,
+                           blink::WGC3Dsizei count,
+                           const blink::WGC3Duint* value);
+  virtual void uniform4ui(blink::WGC3Dint location,
+                          blink::WGC3Duint x,
+                          blink::WGC3Duint y,
+                          blink::WGC3Duint z,
+                          blink::WGC3Duint w);
+  virtual void uniform4uiv(blink::WGC3Dint location,
+                           blink::WGC3Dsizei count,
+                           const blink::WGC3Duint* value);
+  virtual void uniformBlockBinding(blink::WGC3Duint program,
+                                   blink::WGC3Duint uniformBlockIndex,
+                                   blink::WGC3Duint uniformBlockBinding);
+  virtual void uniformMatrix2x3fv(blink::WGC3Dint location,
+                                  blink::WGC3Dsizei count,
+                                  blink::WGC3Dboolean transpose,
+                                  const blink::WGC3Dfloat* value);
+  virtual void uniformMatrix2x4fv(blink::WGC3Dint location,
+                                  blink::WGC3Dsizei count,
+                                  blink::WGC3Dboolean transpose,
+                                  const blink::WGC3Dfloat* value);
+  virtual void uniformMatrix3x2fv(blink::WGC3Dint location,
+                                  blink::WGC3Dsizei count,
+                                  blink::WGC3Dboolean transpose,
+                                  const blink::WGC3Dfloat* value);
+  virtual void uniformMatrix3x4fv(blink::WGC3Dint location,
+                                  blink::WGC3Dsizei count,
+                                  blink::WGC3Dboolean transpose,
+                                  const blink::WGC3Dfloat* value);
+  virtual void uniformMatrix4x2fv(blink::WGC3Dint location,
+                                  blink::WGC3Dsizei count,
+                                  blink::WGC3Dboolean transpose,
+                                  const blink::WGC3Dfloat* value);
+  virtual void uniformMatrix4x3fv(blink::WGC3Dint location,
+                                  blink::WGC3Dsizei count,
+                                  blink::WGC3Dboolean transpose,
+                                  const blink::WGC3Dfloat* value);
+  virtual void vertexAttribI4i(blink::WGC3Duint index,
+                               blink::WGC3Dint x,
+                               blink::WGC3Dint y,
+                               blink::WGC3Dint z,
+                               blink::WGC3Dint w);
+  virtual void vertexAttribI4iv(blink::WGC3Duint index,
+                                const blink::WGC3Dint* v);
+  virtual void vertexAttribI4ui(blink::WGC3Duint index,
+                                blink::WGC3Duint x,
+                                blink::WGC3Duint y,
+                                blink::WGC3Duint z,
+                                blink::WGC3Duint w);
+  virtual void vertexAttribI4uiv(blink::WGC3Duint index,
+                                 const blink::WGC3Duint* v);
+  virtual void vertexAttribIPointer(blink::WGC3Duint index,
+                                    blink::WGC3Dint size,
+                                    blink::WGC3Denum type,
+                                    blink::WGC3Dsizei stride,
+                                    blink::WGC3Dintptr pointer);
+  // virtual void waitSync(blink::WebGLId sync, blink::WGC3Dbitfield flags,
+  //    blink::WGC3Duint64 timeout);
 
   virtual GrGLInterface* createGrGLInterface();
 
@@ -748,7 +940,7 @@
   bool initialize_failed_;
 
   WebGraphicsContext3D::WebGraphicsContextLostCallback* context_lost_callback_;
-  WGC3Denum context_lost_reason_;
+  blink::WGC3Denum context_lost_reason_;
 
   WebGraphicsContext3D::WebGraphicsErrorMessageCallback*
       error_message_callback_;
@@ -756,7 +948,7 @@
       client_error_message_callback_;
 
   // Errors raised by synthesizeGLError().
-  std::vector<WGC3Denum> synthetic_errors_;
+  std::vector<blink::WGC3Denum> synthetic_errors_;
 
   ::gpu::gles2::GLES2Interface* gl_;
   bool lose_context_when_out_of_memory_;
diff --git a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
index ff83e5a..cc7871c 100644
--- a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
+++ b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -24,6 +24,7 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gl/gl_implementation.h"
 
+using blink::WGC3Denum;
 using gpu::gles2::GLES2Implementation;
 using gpu::GLInProcessContext;
 
diff --git a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h
index 8aba802..32bcbbf 100644
--- a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h
+++ b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h
@@ -63,7 +63,7 @@
   // WebGraphicsContext3D methods
   virtual bool isContextLost();
 
-  virtual WGC3Denum getGraphicsResetStatusARB();
+  virtual blink::WGC3Denum getGraphicsResetStatusARB();
 
   ::gpu::ContextSupport* GetContextSupport();
 
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 5e6d9d9..bf5b19e 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -544,6 +544,7 @@
 # named types are used in 'cmd_buffer_functions.txt'.
 # type: The actual GL type of the named type.
 # valid: The list of values that are valid for both the client and the service.
+# valid_es3: The list of values that are valid in OpenGL ES 3, but not ES 2.
 # invalid: Examples of invalid values for the type. At least these values
 #          should be tested to be invalid.
 # is_complete: The list of valid values of type are final and will not be
@@ -584,6 +585,14 @@
       'GL_ARRAY_BUFFER',
       'GL_ELEMENT_ARRAY_BUFFER',
     ],
+    'valid_es3': [
+      'GL_COPY_READ_BUFFER',
+      'GL_COPY_WRITE_BUFFER',
+      'GL_PIXEL_PACK_BUFFER',
+      'GL_PIXEL_UNPACK_BUFFER',
+      'GL_TRANSFORM_FEEDBACK_BUFFER',
+      'GL_UNIFORM_BUFFER',
+    ],
     'invalid': [
       'GL_RENDERBUFFER',
     ],
@@ -598,6 +607,20 @@
       'GL_RENDERBUFFER',
     ],
   },
+  'MapBufferAccess': {
+    'type': 'GLenum',
+    'valid': [
+      'GL_MAP_READ_BIT',
+      'GL_MAP_WRITE_BIT',
+      'GL_MAP_INVALIDATE_RANGE_BIT',
+      'GL_MAP_INVALIDATE_BUFFER_BIT',
+      'GL_MAP_FLUSH_EXPLICIT_BIT',
+      'GL_MAP_UNSYNCHRONIZED_BIT',
+    ],
+    'invalid': [
+      'GL_SYNC_FLUSH_COMMANDS_BIT',
+    ],
+  },
   'Bufferiv': {
     'type': 'GLenum',
     'valid': [
@@ -1979,6 +2002,11 @@
     'defer_draws': True,
     'trace_level': 2,
   },
+  'DrawRangeElements': {
+    'type': 'Manual',
+    'gen_cmd': 'False',
+    'unsafe': True,
+  },
   'Enable': {
     'decoder_func': 'DoEnable',
     'impl_func': False,
@@ -2494,6 +2522,16 @@
     'client_test': False,
     'pepper_interface': 'ChromiumMapSub',
   },
+  'MapBufferRange': {
+    'type': 'Custom',
+    'data_transfer_methods': ['shm'],
+    'cmd_args': 'GLenumBufferTarget target, GLintptrNotNegative offset, '
+                'GLsizeiptr size, GLbitfieldMapBufferAccess access, '
+                'uint32_t data_shm_id, uint32_t data_shm_offset, '
+                'uint32_t result_shm_id, uint32_t result_shm_offset',
+    'unsafe': True,
+    'result': ['uint32_t'],
+  },
   'PauseTransformFeedback': {
     'unsafe': True,
   },
@@ -2879,6 +2917,10 @@
     'client_test': False,
     'pepper_interface': 'ChromiumMapSub',
   },
+  'UnmapBuffer': {
+    'type': 'Custom',
+    'unsafe': True,
+  },
   'UnmapTexSubImage2DCHROMIUM': {
     'gen_cmd': False,
     'extension': True,
@@ -7507,6 +7549,10 @@
       self.invalid = info['invalid']
     else:
       self.invalid = []
+    if 'valid_es3' in info:
+      self.valid_es3 = info['valid_es3']
+    else:
+      self.valid_es3 = []
 
   def GetType(self):
     return self.info['type']
@@ -7517,6 +7563,9 @@
   def GetValidValues(self):
     return self.valid
 
+  def GetValidValuesES3(self):
+    return self.valid_es3
+
   def IsConstant(self):
     if not 'is_complete' in self.info:
       return False
@@ -9816,6 +9865,13 @@
           file.Write("  %s,\n" % value)
         file.Write("};\n")
         file.Write("\n")
+      if named_type.GetValidValuesES3():
+        file.Write("static const %s valid_%s_table_es3[] = {\n" %
+                   (named_type.GetType(), ToUnderscore(name)))
+        for value in named_type.GetValidValuesES3():
+          file.Write("  %s,\n" % value)
+        file.Write("};\n")
+        file.Write("\n")
     file.Write("Validators::Validators()")
     pre = '    : '
     for count, name in enumerate(names):
@@ -9834,6 +9890,18 @@
       pre = ',\n    '
     file.Write(" {\n");
     file.Write("}\n\n");
+
+    file.Write("void Validators::AddES3Values() {\n")
+    for name in names:
+      named_type = NamedType(_NAMED_TYPE_INFO[name])
+      if named_type.GetValidValuesES3():
+        code = """  %(name)s.AddValues(
+      valid_%(name)s_table_es3, arraysize(valid_%(name)s_table_es3));
+"""
+        file.Write(code % {
+          'name': ToUnderscore(name),
+        })
+    file.Write("}\n\n");
     file.Close()
     self.generated_cpp_filenames.append(file.filename)
 
@@ -9892,9 +9960,13 @@
       if _NAMED_TYPE_INFO[enum]['type'] == 'GLenum':
         file.Write("std::string GLES2Util::GetString%s(uint32_t value) {\n" %
                    enum)
-        if len(_NAMED_TYPE_INFO[enum]['valid']) > 0:
+        valid_list = _NAMED_TYPE_INFO[enum]['valid']
+        if 'valid_es3' in _NAMED_TYPE_INFO[enum]:
+          valid_list = valid_list + _NAMED_TYPE_INFO[enum]['valid_es3']
+        assert len(valid_list) == len(set(valid_list))
+        if len(valid_list) > 0:
           file.Write("  static const EnumToString string_table[] = {\n")
-          for value in _NAMED_TYPE_INFO[enum]['valid']:
+          for value in valid_list:
             file.Write('    { %s, "%s" },\n' % (value, value))
           file.Write("""  };
   return GLES2Util::GetQualifiedEnumString(
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn
index 7e47f24..23d5a8c 100644
--- a/gpu/command_buffer/client/BUILD.gn
+++ b/gpu/command_buffer/client/BUILD.gn
@@ -197,3 +197,23 @@
     "//gpu/command_buffer/common",
   ]
 }
+
+# GYP version: gpu/gpu.gyp:gles2_c_lib_nocheck
+# Same as gles2_c_lib except with no parameter checking. Required for
+# OpenGL ES 2.0 conformance tests.
+component("gles2_c_lib_nocheck") {
+  sources = gles2_c_lib_source_files
+
+  defines = [
+    "GLES2_C_LIB_IMPLEMENTATION",
+    "GLES2_CONFORMANCE_TESTS=1",
+  ]
+  deps = [
+    ":client",
+    ":gles2_implementation_no_check",
+    ":gles2_interface",
+    "//base",
+    "//base/third_party/dynamic_annotations",
+    "//gpu/command_buffer/common",
+  ]
+}
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 7e0da4b..ff3dde1 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -259,6 +259,15 @@
                        const void* indices) {
   gles2::GetGLContext()->DrawElements(mode, count, type, indices);
 }
+void GLES2DrawRangeElements(GLenum mode,
+                            GLuint start,
+                            GLuint end,
+                            GLsizei count,
+                            GLenum type,
+                            const void* indices) {
+  gles2::GetGLContext()->DrawRangeElements(mode, start, end, count, type,
+                                           indices);
+}
 void GLES2Enable(GLenum cap) {
   gles2::GetGLContext()->Enable(cap);
 }
@@ -1065,6 +1074,15 @@
 void GLES2UnmapBufferSubDataCHROMIUM(const void* mem) {
   gles2::GetGLContext()->UnmapBufferSubDataCHROMIUM(mem);
 }
+void* GLES2MapBufferRange(GLenum target,
+                          GLintptr offset,
+                          GLsizeiptr size,
+                          GLbitfield access) {
+  return gles2::GetGLContext()->MapBufferRange(target, offset, size, access);
+}
+GLboolean GLES2UnmapBuffer(GLenum target) {
+  return gles2::GetGLContext()->UnmapBuffer(target);
+}
 void* GLES2MapTexSubImage2DCHROMIUM(GLenum target,
                                     GLint level,
                                     GLint xoffset,
@@ -1557,6 +1575,10 @@
      reinterpret_cast<GLES2FunctionPointer>(glDrawElements),
     },
     {
+     "glDrawRangeElements",
+     reinterpret_cast<GLES2FunctionPointer>(glDrawRangeElements),
+    },
+    {
      "glEnable",
      reinterpret_cast<GLES2FunctionPointer>(glEnable),
     },
@@ -2293,6 +2315,14 @@
      reinterpret_cast<GLES2FunctionPointer>(glUnmapBufferSubDataCHROMIUM),
     },
     {
+     "glMapBufferRange",
+     reinterpret_cast<GLES2FunctionPointer>(glMapBufferRange),
+    },
+    {
+     "glUnmapBuffer",
+     reinterpret_cast<GLES2FunctionPointer>(glUnmapBuffer),
+    },
+    {
      "glMapTexSubImage2DCHROMIUM",
      reinterpret_cast<GLES2FunctionPointer>(glMapTexSubImage2DCHROMIUM),
     },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index ad3eb58..bd40e41 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2226,6 +2226,28 @@
   }
 }
 
+void MapBufferRange(GLenum target,
+                    GLintptr offset,
+                    GLsizeiptr size,
+                    GLbitfield access,
+                    uint32_t data_shm_id,
+                    uint32_t data_shm_offset,
+                    uint32_t result_shm_id,
+                    uint32_t result_shm_offset) {
+  gles2::cmds::MapBufferRange* c = GetCmdSpace<gles2::cmds::MapBufferRange>();
+  if (c) {
+    c->Init(target, offset, size, access, data_shm_id, data_shm_offset,
+            result_shm_id, result_shm_offset);
+  }
+}
+
+void UnmapBuffer(GLenum target) {
+  gles2::cmds::UnmapBuffer* c = GetCmdSpace<gles2::cmds::UnmapBuffer>();
+  if (c) {
+    c->Init(target);
+  }
+}
+
 void ResizeCHROMIUM(GLuint width, GLuint height, GLfloat scale_factor) {
   gles2::cmds::ResizeCHROMIUM* c = GetCmdSpace<gles2::cmds::ResizeCHROMIUM>();
   if (c) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 5938524..fe59c2a 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -222,6 +222,10 @@
     DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]);
   }
 
+  // Release remaining BufferRange mem; This is when a MapBufferRange() is
+  // called but not the UnmapBuffer() pair.
+  ClearMappedBufferRangeMap();
+
   // Release any per-context data in share group.
   share_group_->FreeContext(this);
 
@@ -605,6 +609,11 @@
 }
 
 bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
+  // TODO(zmo): For all the BINDING points, there is a possibility where
+  // resources are shared among multiple contexts, that the cached points
+  // are invalid. It is not a problem for now, but once we allow resource
+  // sharing in WebGL, we need to implement a mechanism to allow correct
+  // client side binding points tracking.  crbug.com/465562.
   switch (pname) {
     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
       *params = capabilities_.max_combined_texture_image_units;
@@ -643,18 +652,12 @@
       *params = capabilities_.num_shader_binary_formats;
       return true;
     case GL_ARRAY_BUFFER_BINDING:
-      if (share_group_->bind_generates_resource()) {
-        *params = bound_array_buffer_id_;
-        return true;
-      }
-      return false;
+      *params = bound_array_buffer_id_;
+      return true;
     case GL_ELEMENT_ARRAY_BUFFER_BINDING:
-      if (share_group_->bind_generates_resource()) {
-        *params =
-            vertex_array_object_manager_->bound_element_array_buffer();
-        return true;
-      }
-      return false;
+      *params =
+          vertex_array_object_manager_->bound_element_array_buffer();
+      return true;
     case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
       *params = bound_pixel_pack_transfer_buffer_id_;
       return true;
@@ -665,43 +668,27 @@
       *params = active_texture_unit_ + GL_TEXTURE0;
       return true;
     case GL_TEXTURE_BINDING_2D:
-      if (share_group_->bind_generates_resource()) {
-        *params = texture_units_[active_texture_unit_].bound_texture_2d;
-        return true;
-      }
-      return false;
+      *params = texture_units_[active_texture_unit_].bound_texture_2d;
+      return true;
     case GL_TEXTURE_BINDING_CUBE_MAP:
-      if (share_group_->bind_generates_resource()) {
-        *params = texture_units_[active_texture_unit_].bound_texture_cube_map;
-        return true;
-      }
-      return false;
+      *params = texture_units_[active_texture_unit_].bound_texture_cube_map;
+      return true;
     case GL_TEXTURE_BINDING_EXTERNAL_OES:
-      if (share_group_->bind_generates_resource()) {
-        *params =
-            texture_units_[active_texture_unit_].bound_texture_external_oes;
-        return true;
-      }
-      return false;
+      *params =
+          texture_units_[active_texture_unit_].bound_texture_external_oes;
+      return true;
     case GL_FRAMEBUFFER_BINDING:
-      if (share_group_->bind_generates_resource()) {
-        *params = bound_framebuffer_;
-        return true;
-      }
-      return false;
+      *params = bound_framebuffer_;
+      return true;
     case GL_READ_FRAMEBUFFER_BINDING:
-      if (IsChromiumFramebufferMultisampleAvailable() &&
-          share_group_->bind_generates_resource()) {
+      if (IsChromiumFramebufferMultisampleAvailable()) {
         *params = bound_read_framebuffer_;
         return true;
       }
       return false;
     case GL_RENDERBUFFER_BINDING:
-      if (share_group_->bind_generates_resource()) {
-        *params = bound_renderbuffer_;
-        return true;
-      }
-      return false;
+      *params = bound_renderbuffer_;
+      return true;
     case GL_MAX_UNIFORM_BUFFER_BINDINGS:
       *params = capabilities_.max_uniform_buffer_bindings;
       return true;
@@ -711,6 +698,7 @@
     case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
       *params = capabilities_.uniform_buffer_offset_alignment;
       return true;
+    // TODO(zmo): Support ES3 pnames.
     default:
       return false;
   }
@@ -828,23 +816,44 @@
       << count << ", "
       << GLES2Util::GetStringIndexType(type) << ", "
       << static_cast<const void*>(indices) << ")");
+  DrawElementsImpl(mode, count, type, indices, "glDrawRangeElements");
+}
+
+void GLES2Implementation::DrawRangeElements(
+    GLenum mode, GLuint start, GLuint end,
+    GLsizei count, GLenum type, const void* indices) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
+      << GLES2Util::GetStringDrawMode(mode) << ", "
+      << start << ", " << end << ", " << count << ", "
+      << GLES2Util::GetStringIndexType(type) << ", "
+      << static_cast<const void*>(indices) << ")");
+  if (end < start) {
+    SetGLError(GL_INVALID_VALUE, "glDrawRangeElements", "end < start");
+    return;
+  }
+  DrawElementsImpl(mode, count, type, indices, "glDrawRangeElements");
+}
+
+void GLES2Implementation::DrawElementsImpl(
+    GLenum mode, GLsizei count, GLenum type, const void* indices,
+    const char* func_name) {
   if (count < 0) {
-    SetGLError(GL_INVALID_VALUE, "glDrawElements", "count less than 0.");
+    SetGLError(GL_INVALID_VALUE, func_name, "count < 0");
     return;
   }
-  if (count == 0) {
-    return;
-  }
-  if (vertex_array_object_manager_->bound_element_array_buffer() != 0 &&
-      !ValidateOffset("glDrawElements", reinterpret_cast<GLintptr>(indices))) {
-    return;
-  }
-  GLuint offset = 0;
   bool simulated = false;
-  if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers(
-      "glDrawElements", this, helper_, count, type, 0, indices,
-      &offset, &simulated)) {
-    return;
+  GLuint offset = ToGLuint(indices);
+  if (count > 0) {
+    if (vertex_array_object_manager_->bound_element_array_buffer() != 0 &&
+        !ValidateOffset(func_name, reinterpret_cast<GLintptr>(indices))) {
+      return;
+    }
+    if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers(
+        func_name, this, helper_, count, type, 0, indices,
+        &offset, &simulated)) {
+      return;
+    }
   }
   helper_->DrawElements(mode, count, type, offset);
   RestoreElementAndArrayBuffers(simulated);
@@ -1384,12 +1393,10 @@
     return;
   }
 
-  if (size == 0) {
-    return;
-  }
+  RemoveMappedBufferRangeByTarget(target);
 
   // If there is no data just send BufferData
-  if (!data) {
+  if (size == 0 || !data) {
     helper_->BufferData(target, size, 0, 0, usage);
     return;
   }
@@ -3291,6 +3298,8 @@
     if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) {
       bound_pixel_unpack_transfer_buffer_id_ = 0;
     }
+
+    RemoveMappedBufferRangeById(buffers[ii]);
   }
 }
 
@@ -3672,6 +3681,133 @@
   CheckGLError();
 }
 
+GLuint GLES2Implementation::GetBoundBufferHelper(GLenum target) {
+  GLenum binding = GLES2Util::MapBufferTargetToBindingEnum(target);
+  GLint id = 0;
+  bool cached = GetHelper(binding, &id);
+  DCHECK(cached);
+  return static_cast<GLuint>(id);
+}
+
+void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target) {
+  GLuint buffer = GetBoundBufferHelper(target);
+  RemoveMappedBufferRangeById(buffer);
+}
+
+void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer) {
+  if (buffer > 0) {
+    auto iter = mapped_buffer_range_map_.find(buffer);
+    if (iter != mapped_buffer_range_map_.end() && iter->second.shm_memory) {
+      mapped_memory_->FreePendingToken(
+          iter->second.shm_memory, helper_->InsertToken());
+      mapped_buffer_range_map_.erase(iter);
+    }
+  }
+}
+
+void GLES2Implementation::ClearMappedBufferRangeMap() {
+  for (auto& buffer_range : mapped_buffer_range_map_) {
+    if (buffer_range.second.shm_memory) {
+      mapped_memory_->FreePendingToken(
+          buffer_range.second.shm_memory, helper_->InsertToken());
+    }
+  }
+  mapped_buffer_range_map_.clear();
+}
+
+void* GLES2Implementation::MapBufferRange(
+    GLenum target, GLintptr offset, GLsizeiptr size, GLbitfield access) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
+      << GLES2Util::GetStringEnum(target) << ", " << offset << ", "
+      << size << ", " << access << ")");
+  if (!ValidateSize("glMapBufferRange", size) ||
+      !ValidateOffset("glMapBufferRange", offset)) {
+    return nullptr;
+  }
+
+  int32 shm_id;
+  unsigned int shm_offset;
+  void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset);
+  if (!mem) {
+    SetGLError(GL_OUT_OF_MEMORY, "glMapBufferRange", "out of memory");
+    return nullptr;
+  }
+
+  typedef cmds::MapBufferRange::Result Result;
+  Result* result = GetResultAs<Result*>();
+  *result = 0;
+  helper_->MapBufferRange(target, offset, size, access, shm_id, shm_offset,
+                          GetResultShmId(), GetResultShmOffset());
+  // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
+  // consider an early return without WaitForCmd(). crbug.com/465804.
+  WaitForCmd();
+  if (*result) {
+    const GLbitfield kInvalidateBits =
+        GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
+    if ((access & kInvalidateBits) != 0) {
+      // We do not read back from the buffer, therefore, we set the client
+      // side memory to zero to avoid uninitialized data.
+      memset(mem, 0, size);
+    }
+    GLuint buffer = GetBoundBufferHelper(target);
+    DCHECK_NE(0u, buffer);
+    // glMapBufferRange fails on an already mapped buffer.
+    DCHECK(mapped_buffer_range_map_.find(buffer) ==
+           mapped_buffer_range_map_.end());
+    auto iter = mapped_buffer_range_map_.insert(std::make_pair(
+        buffer,
+        MappedBuffer(access, shm_id, mem, shm_offset, target, offset, size)));
+    DCHECK(iter.second);
+  } else {
+    mapped_memory_->Free(mem);
+    mem = nullptr;
+  }
+
+  GPU_CLIENT_LOG("  returned " << mem);
+  CheckGLError();
+  return mem;
+}
+
+GLboolean GLES2Implementation::UnmapBuffer(GLenum target) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
+      << GLES2Util::GetStringEnum(target) << ")");
+  switch (target) {
+    case GL_ARRAY_BUFFER:
+    case GL_ELEMENT_ARRAY_BUFFER:
+    case GL_COPY_READ_BUFFER:
+    case GL_COPY_WRITE_BUFFER:
+    case GL_PIXEL_PACK_BUFFER:
+    case GL_PIXEL_UNPACK_BUFFER:
+    case GL_TRANSFORM_FEEDBACK_BUFFER:
+    case GL_UNIFORM_BUFFER:
+      break;
+    default:
+      SetGLError(GL_INVALID_ENUM, "glUnmapBuffer", "invalid target");
+      return GL_FALSE;
+  }
+  GLuint buffer = GetBoundBufferHelper(target);
+  if (buffer == 0) {
+    SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "no buffer bound");
+    return GL_FALSE;
+  }
+  auto iter = mapped_buffer_range_map_.find(buffer);
+  if (iter == mapped_buffer_range_map_.end()) {
+    SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "buffer is unmapped");
+    return GL_FALSE;
+  }
+
+  helper_->UnmapBuffer(target);
+  RemoveMappedBufferRangeById(buffer);
+  // TODO(zmo): There is a rare situation that data might be corrupted and
+  // GL_FALSE should be returned. We lose context on that sitatuon, so we
+  // don't have to WaitForCmd().
+  GPU_CLIENT_LOG("  returned " << GL_TRUE);
+  CheckGLError();
+  return GL_TRUE;
+}
+
 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
      GLenum target,
      GLint level,
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 1ffdf91..39b5870 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -560,6 +560,7 @@
 
   // Helpers for query functions.
   bool GetHelper(GLenum pname, GLint* params);
+  GLuint GetBoundBufferHelper(GLenum target);
   bool GetBooleanvHelper(GLenum pname, GLboolean* params);
   bool GetBufferParameterivHelper(GLenum target, GLenum pname, GLint* params);
   bool GetFloatvHelper(GLenum pname, GLfloat* params);
@@ -659,6 +660,13 @@
   void FailGLError(GLenum /* error */) { }
 #endif
 
+  void RemoveMappedBufferRangeByTarget(GLenum target);
+  void RemoveMappedBufferRangeById(GLuint buffer);
+  void ClearMappedBufferRangeMap();
+
+  void DrawElementsImpl(GLenum mode, GLsizei count, GLenum type,
+                        const void* indices, const char* func_name);
+
   GLES2Util util_;
   GLES2CmdHelper* helper_;
   TransferBufferInterface* transfer_buffer_;
@@ -767,6 +775,10 @@
   typedef std::map<const void*, MappedBuffer> MappedBufferMap;
   MappedBufferMap mapped_buffers_;
 
+  // TODO(zmo): Consolidate |mapped_buffers_| and |mapped_buffer_range_map_|.
+  typedef base::hash_map<GLuint, MappedBuffer> MappedBufferRangeMap;
+  MappedBufferRangeMap mapped_buffer_range_map_;
+
   typedef std::map<const void*, MappedTexture> MappedTextureMap;
   MappedTextureMap mapped_textures_;
 
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 8e032e4..24236bc 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -200,6 +200,13 @@
                   GLenum type,
                   const void* indices) override;
 
+void DrawRangeElements(GLenum mode,
+                       GLuint start,
+                       GLuint end,
+                       GLsizei count,
+                       GLenum type,
+                       const void* indices) override;
+
 void Enable(GLenum cap) override;
 
 GLsync FenceSync(GLenum condition, GLbitfield flags) override;
@@ -800,6 +807,13 @@
 
 void UnmapBufferSubDataCHROMIUM(const void* mem) override;
 
+void* MapBufferRange(GLenum target,
+                     GLintptr offset,
+                     GLsizeiptr size,
+                     GLbitfield access) override;
+
+GLboolean UnmapBuffer(GLenum target) override;
+
 void* MapTexSubImage2DCHROMIUM(GLenum target,
                                GLint level,
                                GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 3af9413..4fecbbc 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -2858,37 +2858,6 @@
       reinterpret_cast<uint8*>(pixels.get()) + offset_to_last, mem2_2.ptr));
 }
 
-// Binds can not be cached with bind_generates_resource = false because
-// our id might not be valid. More specifically if you bind on contextA then
-// delete on contextB the resource is still bound on contextA but GetInterger
-// won't return an id.
-TEST_F(GLES2ImplementationStrictSharedTest, BindsNotCached) {
-  struct PNameValue {
-    GLenum pname;
-    GLint expected;
-  };
-  const PNameValue pairs[] = {{GL_TEXTURE_BINDING_2D, 1, },
-                              {GL_TEXTURE_BINDING_CUBE_MAP, 2, },
-                              {GL_TEXTURE_BINDING_EXTERNAL_OES, 3, },
-                              {GL_FRAMEBUFFER_BINDING, 4, },
-                              {GL_RENDERBUFFER_BINDING, 5, },
-                              {GL_ARRAY_BUFFER_BINDING, 6, },
-                              {GL_ELEMENT_ARRAY_BUFFER_BINDING, 7, }, };
-  size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
-  for (size_t ii = 0; ii < num_pairs; ++ii) {
-    const PNameValue& pv = pairs[ii];
-    GLint v = -1;
-    ExpectedMemoryInfo result1 =
-        GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result));
-    EXPECT_CALL(*command_buffer(), OnFlush())
-        .WillOnce(SetMemory(result1.ptr,
-                            SizedResultHelper<GLuint>(pv.expected)))
-        .RetiresOnSaturation();
-    gl_->GetIntegerv(pv.pname, &v);
-    EXPECT_EQ(pv.expected, v);
-  }
-}
-
 // glGen* Ids must not be reused until glDelete* commands have been
 // flushed by glFlush.
 TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestBuffers) {
@@ -3631,6 +3600,150 @@
   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
 }
 
+TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferWrite) {
+  ExpectedMemoryInfo result =
+      GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(SetMemory(result.ptr, uint32_t(1)))
+      .RetiresOnSaturation();
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
+  EXPECT_TRUE(mem != nullptr);
+
+  EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+}
+
+TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithInvalidateBit) {
+  ExpectedMemoryInfo result =
+      GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(SetMemory(result.ptr, uint32_t(1)))
+      .RetiresOnSaturation();
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  GLsizeiptr kSize = 64;
+  void* mem = gl_->MapBufferRange(
+      GL_ARRAY_BUFFER, 10, kSize,
+      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+  EXPECT_TRUE(mem != nullptr);
+  std::vector<int8_t> zero(kSize);
+  memset(&zero[0], 0, kSize);
+  EXPECT_EQ(0, memcmp(mem, &zero[0], kSize));
+}
+
+TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithGLError) {
+  ExpectedMemoryInfo result =
+      GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+  // Return a result of 0 to indicate an GL error.
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(SetMemory(result.ptr, uint32_t(0)))
+      .RetiresOnSaturation();
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
+  EXPECT_TRUE(mem == nullptr);
+}
+
+TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferRead) {
+  ExpectedMemoryInfo result =
+      GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(SetMemory(result.ptr, uint32_t(1)))
+      .RetiresOnSaturation();
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_READ_BIT);
+  EXPECT_TRUE(mem != nullptr);
+
+  EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+}
+
+TEST_F(GLES2ImplementationTest, MapBufferRangeReadWithGLError) {
+  ExpectedMemoryInfo result =
+      GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+  // Return a result of 0 to indicate an GL error.
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(SetMemory(result.ptr, uint32_t(0)))
+      .RetiresOnSaturation();
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_READ_BIT);
+  EXPECT_TRUE(mem == nullptr);
+}
+
+TEST_F(GLES2ImplementationTest, UnmapBufferFails) {
+  // No bound buffer.
+  EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  // Buffer is unmapped.
+  EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+}
+
+TEST_F(GLES2ImplementationTest, BufferDataUnmapsDataStore) {
+  ExpectedMemoryInfo result =
+      GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(SetMemory(result.ptr, uint32_t(1)))
+      .RetiresOnSaturation();
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
+  EXPECT_TRUE(mem != nullptr);
+
+  std::vector<uint8_t> data(16);
+  // BufferData unmaps the data store.
+  gl_->BufferData(GL_ARRAY_BUFFER, 16, &data[0], GL_STREAM_DRAW);
+
+  EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+}
+
+TEST_F(GLES2ImplementationTest, DeleteBuffersUnmapsDataStore) {
+  ExpectedMemoryInfo result =
+      GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+  EXPECT_CALL(*command_buffer(), OnFlush())
+      .WillOnce(SetMemory(result.ptr, uint32_t(1)))
+      .RetiresOnSaturation();
+
+  const GLuint kBufferId = 123;
+  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+  void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
+  EXPECT_TRUE(mem != nullptr);
+
+  std::vector<uint8_t> data(16);
+  // DeleteBuffers unmaps the data store.
+  gl_->DeleteBuffers(1, &kBufferId);
+
+  EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+}
+
 TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) {
   ContextInitOptions init_options;
   init_options.lose_context_when_out_of_memory = true;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 2d8480a..a0c908f 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -556,6 +556,7 @@
   gl_->DrawArrays(GL_POINTS, 2, 3);
   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
 }
+// TODO(zmo): Implement unit test for DrawRangeElements
 
 TEST_F(GLES2ImplementationTest, EnableVertexAttribArray) {
   struct Cmds {
@@ -2718,6 +2719,8 @@
   EXPECT_TRUE(result);
 }
 // TODO(zmo): Implement unit test for EnableFeatureCHROMIUM
+// TODO(zmo): Implement unit test for MapBufferRange
+// TODO(zmo): Implement unit test for UnmapBuffer
 
 TEST_F(GLES2ImplementationTest, ResizeCHROMIUM) {
   struct Cmds {
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index f93ec07..3da9e22 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -148,6 +148,12 @@
                           GLsizei count,
                           GLenum type,
                           const void* indices) = 0;
+virtual void DrawRangeElements(GLenum mode,
+                               GLuint start,
+                               GLuint end,
+                               GLsizei count,
+                               GLenum type,
+                               const void* indices) = 0;
 virtual void Enable(GLenum cap) = 0;
 virtual void EnableVertexAttribArray(GLuint index) = 0;
 virtual GLsync FenceSync(GLenum condition, GLbitfield flags) = 0;
@@ -583,6 +589,11 @@
                                        GLsizeiptr size,
                                        GLenum access) = 0;
 virtual void UnmapBufferSubDataCHROMIUM(const void* mem) = 0;
+virtual void* MapBufferRange(GLenum target,
+                             GLintptr offset,
+                             GLsizeiptr size,
+                             GLbitfield access) = 0;
+virtual GLboolean UnmapBuffer(GLenum target) = 0;
 virtual void* MapTexSubImage2DCHROMIUM(GLenum target,
                                        GLint level,
                                        GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 0381b32..14ac101 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -145,6 +145,12 @@
                   GLsizei count,
                   GLenum type,
                   const void* indices) override;
+void DrawRangeElements(GLenum mode,
+                       GLuint start,
+                       GLuint end,
+                       GLsizei count,
+                       GLenum type,
+                       const void* indices) override;
 void Enable(GLenum cap) override;
 void EnableVertexAttribArray(GLuint index) override;
 GLsync FenceSync(GLenum condition, GLbitfield flags) override;
@@ -568,6 +574,11 @@
                                GLsizeiptr size,
                                GLenum access) override;
 void UnmapBufferSubDataCHROMIUM(const void* mem) override;
+void* MapBufferRange(GLenum target,
+                     GLintptr offset,
+                     GLsizeiptr size,
+                     GLbitfield access) override;
+GLboolean UnmapBuffer(GLenum target) override;
 void* MapTexSubImage2DCHROMIUM(GLenum target,
                                GLint level,
                                GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index 0f2e5fd..7b9569d 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -226,6 +226,13 @@
                                       GLenum /* type */,
                                       const void* /* indices */) {
 }
+void GLES2InterfaceStub::DrawRangeElements(GLenum /* mode */,
+                                           GLuint /* start */,
+                                           GLuint /* end */,
+                                           GLsizei /* count */,
+                                           GLenum /* type */,
+                                           const void* /* indices */) {
+}
 void GLES2InterfaceStub::Enable(GLenum /* cap */) {
 }
 void GLES2InterfaceStub::EnableVertexAttribArray(GLuint /* index */) {
@@ -987,6 +994,15 @@
 }
 void GLES2InterfaceStub::UnmapBufferSubDataCHROMIUM(const void* /* mem */) {
 }
+void* GLES2InterfaceStub::MapBufferRange(GLenum /* target */,
+                                         GLintptr /* offset */,
+                                         GLsizeiptr /* size */,
+                                         GLbitfield /* access */) {
+  return 0;
+}
+GLboolean GLES2InterfaceStub::UnmapBuffer(GLenum /* target */) {
+  return 0;
+}
 void* GLES2InterfaceStub::MapTexSubImage2DCHROMIUM(GLenum /* target */,
                                                    GLint /* level */,
                                                    GLint /* xoffset */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index 8a9be79..1e5660e 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -145,6 +145,12 @@
                   GLsizei count,
                   GLenum type,
                   const void* indices) override;
+void DrawRangeElements(GLenum mode,
+                       GLuint start,
+                       GLuint end,
+                       GLsizei count,
+                       GLenum type,
+                       const void* indices) override;
 void Enable(GLenum cap) override;
 void EnableVertexAttribArray(GLuint index) override;
 GLsync FenceSync(GLenum condition, GLbitfield flags) override;
@@ -568,6 +574,11 @@
                                GLsizeiptr size,
                                GLenum access) override;
 void UnmapBufferSubDataCHROMIUM(const void* mem) override;
+void* MapBufferRange(GLenum target,
+                     GLintptr offset,
+                     GLsizeiptr size,
+                     GLbitfield access) override;
+GLboolean UnmapBuffer(GLenum target) override;
 void* MapTexSubImage2DCHROMIUM(GLenum target,
                                GLint level,
                                GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index d1479b1..627c90e 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -390,6 +390,16 @@
   gl_->DrawElements(mode, count, type, indices);
 }
 
+void GLES2TraceImplementation::DrawRangeElements(GLenum mode,
+                                                 GLuint start,
+                                                 GLuint end,
+                                                 GLsizei count,
+                                                 GLenum type,
+                                                 const void* indices) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DrawRangeElements");
+  gl_->DrawRangeElements(mode, start, end, count, type, indices);
+}
+
 void GLES2TraceImplementation::Enable(GLenum cap) {
   TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::Enable");
   gl_->Enable(cap);
@@ -1683,6 +1693,19 @@
   gl_->UnmapBufferSubDataCHROMIUM(mem);
 }
 
+void* GLES2TraceImplementation::MapBufferRange(GLenum target,
+                                               GLintptr offset,
+                                               GLsizeiptr size,
+                                               GLbitfield access) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::MapBufferRange");
+  return gl_->MapBufferRange(target, offset, size, access);
+}
+
+GLboolean GLES2TraceImplementation::UnmapBuffer(GLenum target) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UnmapBuffer");
+  return gl_->UnmapBuffer(target);
+}
+
 void* GLES2TraceImplementation::MapTexSubImage2DCHROMIUM(GLenum target,
                                                          GLint level,
                                                          GLint xoffset,
diff --git a/gpu/command_buffer/client/share_group.cc b/gpu/command_buffer/client/share_group.cc
index 6463200..f5c9bf1 100644
--- a/gpu/command_buffer/client/share_group.cc
+++ b/gpu/command_buffer/client/share_group.cc
@@ -60,9 +60,7 @@
     (gl_impl->*delete_fn)(n, ids);
     // We need to ensure that the delete call is evaluated on the service side
     // before any other contexts issue commands using these client ids.
-    // TODO(vmiura): Can remove this by virtualizing internal ids, however
-    // this code only affects PPAPI for now.
-    gl_impl->helper()->CommandBufferHelper::Flush();
+    gl_impl->helper()->CommandBufferHelper::OrderingBarrier();
     return true;
   }
 
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index 140db2c..1dd35fd 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -60,6 +60,7 @@
 GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
 GL_APICALL void         GL_APIENTRY glDrawArrays (GLenumDrawMode mode, GLint first, GLsizei count);
 GL_APICALL void         GL_APIENTRY glDrawElements (GLenumDrawMode mode, GLsizei count, GLenumIndexType type, const void* indices);
+GL_APICALL void         GL_APIENTRY glDrawRangeElements (GLenumDrawMode mode, GLuint start, GLuint end, GLsizei count, GLenumIndexType type, const void* indices);
 GL_APICALL void         GL_APIENTRY glEnable (GLenumCapability cap);
 GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
 GL_APICALL GLsync       GL_APIENTRY glFenceSync (GLenumSyncCondition condition, GLbitfieldSyncFlags flags);
@@ -246,6 +247,8 @@
 GL_APICALL GLboolean    GL_APIENTRY glUnmapBufferCHROMIUM (GLuint target);
 GL_APICALL void*        GL_APIENTRY glMapBufferSubDataCHROMIUM (GLuint target, GLintptrNotNegative offset, GLsizeiptr size, GLenum access);
 GL_APICALL void         GL_APIENTRY glUnmapBufferSubDataCHROMIUM (const void* mem);
+GL_APICALL void*        GL_APIENTRY glMapBufferRange (GLenumBufferTarget target, GLintptrNotNegative offset, GLsizeiptr size, GLbitfieldMapBufferAccess access);
+GL_APICALL GLboolean    GL_APIENTRY glUnmapBuffer (GLenumBufferTarget target);
 GL_APICALL void*        GL_APIENTRY glMapTexSubImage2DCHROMIUM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access);
 GL_APICALL void         GL_APIENTRY glUnmapTexSubImage2DCHROMIUM (const void* mem);
 GL_APICALL void         GL_APIENTRY glResizeCHROMIUM (GLuint width, GLuint height, GLfloat scale_factor);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index d3cb00a..a829dcb 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -10939,6 +10939,118 @@
 static_assert(offsetof(EnableFeatureCHROMIUM, result_shm_offset) == 12,
               "offset of EnableFeatureCHROMIUM result_shm_offset should be 12");
 
+struct MapBufferRange {
+  typedef MapBufferRange ValueType;
+  static const CommandId kCmdId = kMapBufferRange;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+  typedef uint32_t Result;
+
+  static uint32_t ComputeSize() {
+    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(GLenum _target,
+            GLintptr _offset,
+            GLsizeiptr _size,
+            GLbitfield _access,
+            uint32_t _data_shm_id,
+            uint32_t _data_shm_offset,
+            uint32_t _result_shm_id,
+            uint32_t _result_shm_offset) {
+    SetHeader();
+    target = _target;
+    offset = _offset;
+    size = _size;
+    access = _access;
+    data_shm_id = _data_shm_id;
+    data_shm_offset = _data_shm_offset;
+    result_shm_id = _result_shm_id;
+    result_shm_offset = _result_shm_offset;
+  }
+
+  void* Set(void* cmd,
+            GLenum _target,
+            GLintptr _offset,
+            GLsizeiptr _size,
+            GLbitfield _access,
+            uint32_t _data_shm_id,
+            uint32_t _data_shm_offset,
+            uint32_t _result_shm_id,
+            uint32_t _result_shm_offset) {
+    static_cast<ValueType*>(cmd)->Init(_target, _offset, _size, _access,
+                                       _data_shm_id, _data_shm_offset,
+                                       _result_shm_id, _result_shm_offset);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t target;
+  int32_t offset;
+  int32_t size;
+  uint32_t access;
+  uint32_t data_shm_id;
+  uint32_t data_shm_offset;
+  uint32_t result_shm_id;
+  uint32_t result_shm_offset;
+};
+
+static_assert(sizeof(MapBufferRange) == 36,
+              "size of MapBufferRange should be 36");
+static_assert(offsetof(MapBufferRange, header) == 0,
+              "offset of MapBufferRange header should be 0");
+static_assert(offsetof(MapBufferRange, target) == 4,
+              "offset of MapBufferRange target should be 4");
+static_assert(offsetof(MapBufferRange, offset) == 8,
+              "offset of MapBufferRange offset should be 8");
+static_assert(offsetof(MapBufferRange, size) == 12,
+              "offset of MapBufferRange size should be 12");
+static_assert(offsetof(MapBufferRange, access) == 16,
+              "offset of MapBufferRange access should be 16");
+static_assert(offsetof(MapBufferRange, data_shm_id) == 20,
+              "offset of MapBufferRange data_shm_id should be 20");
+static_assert(offsetof(MapBufferRange, data_shm_offset) == 24,
+              "offset of MapBufferRange data_shm_offset should be 24");
+static_assert(offsetof(MapBufferRange, result_shm_id) == 28,
+              "offset of MapBufferRange result_shm_id should be 28");
+static_assert(offsetof(MapBufferRange, result_shm_offset) == 32,
+              "offset of MapBufferRange result_shm_offset should be 32");
+
+struct UnmapBuffer {
+  typedef UnmapBuffer ValueType;
+  static const CommandId kCmdId = kUnmapBuffer;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+  static uint32_t ComputeSize() {
+    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(GLenum _target) {
+    SetHeader();
+    target = _target;
+  }
+
+  void* Set(void* cmd, GLenum _target) {
+    static_cast<ValueType*>(cmd)->Init(_target);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t target;
+};
+
+static_assert(sizeof(UnmapBuffer) == 8, "size of UnmapBuffer should be 8");
+static_assert(offsetof(UnmapBuffer, header) == 0,
+              "offset of UnmapBuffer header should be 0");
+static_assert(offsetof(UnmapBuffer, target) == 4,
+              "offset of UnmapBuffer target should be 4");
+
 struct ResizeCHROMIUM {
   typedef ResizeCHROMIUM ValueType;
   static const CommandId kCmdId = kResizeCHROMIUM;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 3162276..d14f48d 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3778,6 +3778,37 @@
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
+TEST_F(GLES2FormatTest, MapBufferRange) {
+  cmds::MapBufferRange& cmd = *GetBufferAs<cmds::MapBufferRange>();
+  void* next_cmd =
+      cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLintptr>(12),
+              static_cast<GLsizeiptr>(13), static_cast<GLbitfield>(14),
+              static_cast<uint32_t>(15), static_cast<uint32_t>(16),
+              static_cast<uint32_t>(17), static_cast<uint32_t>(18));
+  EXPECT_EQ(static_cast<uint32_t>(cmds::MapBufferRange::kCmdId),
+            cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  EXPECT_EQ(static_cast<GLintptr>(12), cmd.offset);
+  EXPECT_EQ(static_cast<GLsizeiptr>(13), cmd.size);
+  EXPECT_EQ(static_cast<GLbitfield>(14), cmd.access);
+  EXPECT_EQ(static_cast<uint32_t>(15), cmd.data_shm_id);
+  EXPECT_EQ(static_cast<uint32_t>(16), cmd.data_shm_offset);
+  EXPECT_EQ(static_cast<uint32_t>(17), cmd.result_shm_id);
+  EXPECT_EQ(static_cast<uint32_t>(18), cmd.result_shm_offset);
+  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, UnmapBuffer) {
+  cmds::UnmapBuffer& cmd = *GetBufferAs<cmds::UnmapBuffer>();
+  void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11));
+  EXPECT_EQ(static_cast<uint32_t>(cmds::UnmapBuffer::kCmdId),
+            cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+  EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
 TEST_F(GLES2FormatTest, ResizeCHROMIUM) {
   cmds::ResizeCHROMIUM& cmd = *GetBufferAs<cmds::ResizeCHROMIUM>();
   void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 1c739e8..ea62be1 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -243,53 +243,55 @@
   OP(SwapBuffers)                              /* 484 */ \
   OP(GetMaxValueInBufferCHROMIUM)              /* 485 */ \
   OP(EnableFeatureCHROMIUM)                    /* 486 */ \
-  OP(ResizeCHROMIUM)                           /* 487 */ \
-  OP(GetRequestableExtensionsCHROMIUM)         /* 488 */ \
-  OP(RequestExtensionCHROMIUM)                 /* 489 */ \
-  OP(GetProgramInfoCHROMIUM)                   /* 490 */ \
-  OP(GetUniformBlocksCHROMIUM)                 /* 491 */ \
-  OP(GetTransformFeedbackVaryingsCHROMIUM)     /* 492 */ \
-  OP(GetUniformsES3CHROMIUM)                   /* 493 */ \
-  OP(GetTranslatedShaderSourceANGLE)           /* 494 */ \
-  OP(PostSubBufferCHROMIUM)                    /* 495 */ \
-  OP(TexImageIOSurface2DCHROMIUM)              /* 496 */ \
-  OP(CopyTextureCHROMIUM)                      /* 497 */ \
-  OP(CopySubTextureCHROMIUM)                   /* 498 */ \
-  OP(DrawArraysInstancedANGLE)                 /* 499 */ \
-  OP(DrawElementsInstancedANGLE)               /* 500 */ \
-  OP(VertexAttribDivisorANGLE)                 /* 501 */ \
-  OP(GenMailboxCHROMIUM)                       /* 502 */ \
-  OP(ProduceTextureCHROMIUMImmediate)          /* 503 */ \
-  OP(ProduceTextureDirectCHROMIUMImmediate)    /* 504 */ \
-  OP(ConsumeTextureCHROMIUMImmediate)          /* 505 */ \
-  OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 506 */ \
-  OP(BindUniformLocationCHROMIUMBucket)        /* 507 */ \
-  OP(GenValuebuffersCHROMIUMImmediate)         /* 508 */ \
-  OP(DeleteValuebuffersCHROMIUMImmediate)      /* 509 */ \
-  OP(IsValuebufferCHROMIUM)                    /* 510 */ \
-  OP(BindValuebufferCHROMIUM)                  /* 511 */ \
-  OP(SubscribeValueCHROMIUM)                   /* 512 */ \
-  OP(PopulateSubscribedValuesCHROMIUM)         /* 513 */ \
-  OP(UniformValuebufferCHROMIUM)               /* 514 */ \
-  OP(BindTexImage2DCHROMIUM)                   /* 515 */ \
-  OP(ReleaseTexImage2DCHROMIUM)                /* 516 */ \
-  OP(TraceBeginCHROMIUM)                       /* 517 */ \
-  OP(TraceEndCHROMIUM)                         /* 518 */ \
-  OP(AsyncTexSubImage2DCHROMIUM)               /* 519 */ \
-  OP(AsyncTexImage2DCHROMIUM)                  /* 520 */ \
-  OP(WaitAsyncTexImage2DCHROMIUM)              /* 521 */ \
-  OP(WaitAllAsyncTexImage2DCHROMIUM)           /* 522 */ \
-  OP(DiscardFramebufferEXTImmediate)           /* 523 */ \
-  OP(LoseContextCHROMIUM)                      /* 524 */ \
-  OP(InsertSyncPointCHROMIUM)                  /* 525 */ \
-  OP(WaitSyncPointCHROMIUM)                    /* 526 */ \
-  OP(DrawBuffersEXTImmediate)                  /* 527 */ \
-  OP(DiscardBackbufferCHROMIUM)                /* 528 */ \
-  OP(ScheduleOverlayPlaneCHROMIUM)             /* 529 */ \
-  OP(SwapInterval)                             /* 530 */ \
-  OP(MatrixLoadfCHROMIUMImmediate)             /* 531 */ \
-  OP(MatrixLoadIdentityCHROMIUM)               /* 532 */ \
-  OP(BlendBarrierKHR)                          /* 533 */
+  OP(MapBufferRange)                           /* 487 */ \
+  OP(UnmapBuffer)                              /* 488 */ \
+  OP(ResizeCHROMIUM)                           /* 489 */ \
+  OP(GetRequestableExtensionsCHROMIUM)         /* 490 */ \
+  OP(RequestExtensionCHROMIUM)                 /* 491 */ \
+  OP(GetProgramInfoCHROMIUM)                   /* 492 */ \
+  OP(GetUniformBlocksCHROMIUM)                 /* 493 */ \
+  OP(GetTransformFeedbackVaryingsCHROMIUM)     /* 494 */ \
+  OP(GetUniformsES3CHROMIUM)                   /* 495 */ \
+  OP(GetTranslatedShaderSourceANGLE)           /* 496 */ \
+  OP(PostSubBufferCHROMIUM)                    /* 497 */ \
+  OP(TexImageIOSurface2DCHROMIUM)              /* 498 */ \
+  OP(CopyTextureCHROMIUM)                      /* 499 */ \
+  OP(CopySubTextureCHROMIUM)                   /* 500 */ \
+  OP(DrawArraysInstancedANGLE)                 /* 501 */ \
+  OP(DrawElementsInstancedANGLE)               /* 502 */ \
+  OP(VertexAttribDivisorANGLE)                 /* 503 */ \
+  OP(GenMailboxCHROMIUM)                       /* 504 */ \
+  OP(ProduceTextureCHROMIUMImmediate)          /* 505 */ \
+  OP(ProduceTextureDirectCHROMIUMImmediate)    /* 506 */ \
+  OP(ConsumeTextureCHROMIUMImmediate)          /* 507 */ \
+  OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 508 */ \
+  OP(BindUniformLocationCHROMIUMBucket)        /* 509 */ \
+  OP(GenValuebuffersCHROMIUMImmediate)         /* 510 */ \
+  OP(DeleteValuebuffersCHROMIUMImmediate)      /* 511 */ \
+  OP(IsValuebufferCHROMIUM)                    /* 512 */ \
+  OP(BindValuebufferCHROMIUM)                  /* 513 */ \
+  OP(SubscribeValueCHROMIUM)                   /* 514 */ \
+  OP(PopulateSubscribedValuesCHROMIUM)         /* 515 */ \
+  OP(UniformValuebufferCHROMIUM)               /* 516 */ \
+  OP(BindTexImage2DCHROMIUM)                   /* 517 */ \
+  OP(ReleaseTexImage2DCHROMIUM)                /* 518 */ \
+  OP(TraceBeginCHROMIUM)                       /* 519 */ \
+  OP(TraceEndCHROMIUM)                         /* 520 */ \
+  OP(AsyncTexSubImage2DCHROMIUM)               /* 521 */ \
+  OP(AsyncTexImage2DCHROMIUM)                  /* 522 */ \
+  OP(WaitAsyncTexImage2DCHROMIUM)              /* 523 */ \
+  OP(WaitAllAsyncTexImage2DCHROMIUM)           /* 524 */ \
+  OP(DiscardFramebufferEXTImmediate)           /* 525 */ \
+  OP(LoseContextCHROMIUM)                      /* 526 */ \
+  OP(InsertSyncPointCHROMIUM)                  /* 527 */ \
+  OP(WaitSyncPointCHROMIUM)                    /* 528 */ \
+  OP(DrawBuffersEXTImmediate)                  /* 529 */ \
+  OP(DiscardBackbufferCHROMIUM)                /* 530 */ \
+  OP(ScheduleOverlayPlaneCHROMIUM)             /* 531 */ \
+  OP(SwapInterval)                             /* 532 */ \
+  OP(MatrixLoadfCHROMIUMImmediate)             /* 533 */ \
+  OP(MatrixLoadIdentityCHROMIUM)               /* 534 */ \
+  OP(BlendBarrierKHR)                          /* 535 */
 
 enum CommandId {
   kStartPoint = cmd::kLastCommonId,  // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 0950b41..14d6a21 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -870,6 +870,31 @@
   return (v64 << 32) | v32_0;
 }
 
+// static
+uint32_t GLES2Util::MapBufferTargetToBindingEnum(uint32_t target) {
+  switch (target) {
+    case GL_ARRAY_BUFFER:
+      return GL_ARRAY_BUFFER_BINDING;
+    case GL_COPY_READ_BUFFER:
+      return GL_COPY_READ_BUFFER_BINDING;
+    case GL_COPY_WRITE_BUFFER:
+      return GL_COPY_WRITE_BUFFER_BINDING;
+    case GL_ELEMENT_ARRAY_BUFFER:
+      return GL_ELEMENT_ARRAY_BUFFER_BINDING;
+    case GL_PIXEL_PACK_BUFFER:
+      return GL_PIXEL_PACK_BUFFER_BINDING;
+    case GL_PIXEL_UNPACK_BUFFER:
+      return GL_PIXEL_UNPACK_BUFFER_BINDING;
+    case GL_TRANSFORM_FEEDBACK_BUFFER:
+      return GL_TRANSFORM_FEEDBACK_BUFFER_BINDING;
+    case GL_UNIFORM_BUFFER:
+      return GL_UNIFORM_BUFFER_BINDING;
+    default:
+      return 0;
+  }
+}
+
+
 namespace {
 
 // WebGraphicsContext3DCommandBufferImpl configuration attributes. Those in
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 9dd8f28..1661247 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -191,6 +191,8 @@
       uint64_t v64, uint32_t* v32_0, uint32_t* v32_1);
   static uint64_t MapTwoUint32ToUint64(uint32_t v32_0, uint32_t v32_1);
 
+  static uint32_t MapBufferTargetToBindingEnum(uint32_t target);
+
   #include "../common/gles2_cmd_utils_autogen.h"
 
  private:
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
index 76419ce..cd5002d 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -41,6 +41,7 @@
 static std::string GetStringImageUsage(uint32_t value);
 static std::string GetStringIndexType(uint32_t value);
 static std::string GetStringIndexedBufferTarget(uint32_t value);
+static std::string GetStringMapBufferAccess(uint32_t value);
 static std::string GetStringMatrixMode(uint32_t value);
 static std::string GetStringPixelStore(uint32_t value);
 static std::string GetStringPixelType(uint32_t value);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index 899a2f4..52511ed 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -4496,6 +4496,12 @@
   static const EnumToString string_table[] = {
       {GL_ARRAY_BUFFER, "GL_ARRAY_BUFFER"},
       {GL_ELEMENT_ARRAY_BUFFER, "GL_ELEMENT_ARRAY_BUFFER"},
+      {GL_COPY_READ_BUFFER, "GL_COPY_READ_BUFFER"},
+      {GL_COPY_WRITE_BUFFER, "GL_COPY_WRITE_BUFFER"},
+      {GL_PIXEL_PACK_BUFFER, "GL_PIXEL_PACK_BUFFER"},
+      {GL_PIXEL_UNPACK_BUFFER, "GL_PIXEL_UNPACK_BUFFER"},
+      {GL_TRANSFORM_FEEDBACK_BUFFER, "GL_TRANSFORM_FEEDBACK_BUFFER"},
+      {GL_UNIFORM_BUFFER, "GL_UNIFORM_BUFFER"},
   };
   return GLES2Util::GetQualifiedEnumString(string_table,
                                            arraysize(string_table), value);
@@ -4839,6 +4845,19 @@
                                            arraysize(string_table), value);
 }
 
+std::string GLES2Util::GetStringMapBufferAccess(uint32_t value) {
+  static const EnumToString string_table[] = {
+      {GL_MAP_READ_BIT, "GL_MAP_READ_BIT"},
+      {GL_MAP_WRITE_BIT, "GL_MAP_WRITE_BIT"},
+      {GL_MAP_INVALIDATE_RANGE_BIT, "GL_MAP_INVALIDATE_RANGE_BIT"},
+      {GL_MAP_INVALIDATE_BUFFER_BIT, "GL_MAP_INVALIDATE_BUFFER_BIT"},
+      {GL_MAP_FLUSH_EXPLICIT_BIT, "GL_MAP_FLUSH_EXPLICIT_BIT"},
+      {GL_MAP_UNSYNCHRONIZED_BIT, "GL_MAP_UNSYNCHRONIZED_BIT"},
+  };
+  return GLES2Util::GetQualifiedEnumString(string_table,
+                                           arraysize(string_table), value);
+}
+
 std::string GLES2Util::GetStringMatrixMode(uint32_t value) {
   static const EnumToString string_table[] = {
       {GL_PATH_PROJECTION_CHROMIUM, "GL_PATH_PROJECTION_CHROMIUM"},
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index 1f64fd5..c2a0ba5 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -74,6 +74,27 @@
   --buffer_count_;
 }
 
+Buffer::MappedRange::MappedRange(
+    GLintptr offset, GLsizeiptr size, GLenum access, void* pointer,
+    scoped_refptr<gpu::Buffer> shm)
+    : offset(offset),
+      size(size),
+      access(access),
+      pointer(pointer),
+      shm(shm) {
+  DCHECK(pointer);
+  DCHECK(shm.get() && GetShmPointer());
+}
+
+Buffer::MappedRange::~MappedRange() {
+}
+
+void* Buffer::MappedRange::GetShmPointer() const {
+  DCHECK(shm.get());
+  return shm->GetDataAddress(static_cast<unsigned int>(offset),
+                             static_cast<unsigned int>(size));
+}
+
 Buffer::Buffer(BufferManager* manager, GLuint service_id)
     : manager_(manager),
       size_(0),
@@ -119,6 +140,7 @@
       memset(shadow_.get(), 0, size);
     }
   }
+  mapped_range_.reset(nullptr);
 }
 
 bool Buffer::CheckRange(
@@ -397,12 +419,23 @@
 // Since one BufferManager can be shared by multiple decoders, ContextState is
 // passed in each time and not just passed in during initialization.
 Buffer* BufferManager::GetBufferInfoForTarget(
-    ContextState* state, GLenum target) {
-  DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
-  if (target == GL_ARRAY_BUFFER) {
-    return state->bound_array_buffer.get();
-  } else {
-    return state->vertex_attrib_manager->element_array_buffer();
+    ContextState* state, GLenum target) const {
+  switch (target) {
+    case GL_ARRAY_BUFFER:
+      return state->bound_array_buffer.get();
+    case GL_ELEMENT_ARRAY_BUFFER:
+      return state->vertex_attrib_manager->element_array_buffer();
+    case GL_COPY_READ_BUFFER:
+    case GL_COPY_WRITE_BUFFER:
+    case GL_PIXEL_PACK_BUFFER:
+    case GL_PIXEL_UNPACK_BUFFER:
+    case GL_TRANSFORM_FEEDBACK_BUFFER:
+    case GL_UNIFORM_BUFFER:
+      NOTIMPLEMENTED();
+      return nullptr;
+    default:
+      NOTREACHED();
+      return nullptr;
   }
 }
 
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index 22a6e42..29bfaf4 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/common/buffer.h"
 #include "gpu/command_buffer/service/gl_utils.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/gpu_export.h"
@@ -27,6 +28,19 @@
 // Info about Buffers currently in the system.
 class GPU_EXPORT Buffer : public base::RefCounted<Buffer> {
  public:
+  struct MappedRange {
+    GLintptr offset;
+    GLsizeiptr size;
+    GLenum access;
+    void* pointer;  // Pointer returned by driver.
+    scoped_refptr<gpu::Buffer> shm;  // Client side mem.
+
+    MappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
+                void* pointer, scoped_refptr<gpu::Buffer> shm);
+    ~MappedRange();
+    void* GetShmPointer() const;
+  };
+
   Buffer(BufferManager* manager, GLuint service_id);
 
   GLuint service_id() const {
@@ -67,6 +81,19 @@
     return is_client_side_array_;
   }
 
+  void SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
+                      void* pointer, scoped_refptr<gpu::Buffer> shm) {
+    mapped_range_.reset(new MappedRange(offset, size, access, pointer, shm));
+  }
+
+  void RemoveMappedRange() {
+    mapped_range_.reset(nullptr);
+  }
+
+  const MappedRange* GetMappedRange() const {
+    return mapped_range_.get();
+  }
+
  private:
   friend class BufferManager;
   friend class BufferManagerTestBase;
@@ -163,6 +190,9 @@
   // Usage of buffer.
   GLenum usage_;
 
+  // Data cached from last glMapBufferRange call.
+  scoped_ptr<MappedRange> mapped_range_;
+
   // A map of ranges to the highest value in that range of a certain type.
   typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap;
   RangeToMaxValueMap range_set_;
@@ -232,15 +262,16 @@
   // set to a non-zero size.
   bool UseNonZeroSizeForClientSideArrayBuffer();
 
+  Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target) const;
+
  private:
   friend class Buffer;
   friend class TestHelper;  // Needs access to DoBufferData.
   friend class BufferManagerTestBase;  // Needs access to DoBufferSubData.
+
   void StartTracking(Buffer* buffer);
   void StopTracking(Buffer* buffer);
 
-  Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target);
-
   // Does a glBufferSubData and updates the approriate accounting.
   // Assumes the values have already been validated.
   void DoBufferSubData(
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 897afd3..2452954 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -1052,6 +1052,27 @@
 #endif
 }
 
+bool FeatureInfo::IsES3Capable() const {
+  if (gl_version_info_->IsAtLeastGLES(3, 0))
+    return true;
+  // TODO(zmo): For Desktop GL, with anything lower than 4.2, we need to check
+  // the existence of a few extensions to have full WebGL 2 capabilities.
+  if (gl_version_info_->IsAtLeastGL(4, 2))
+    return true;
+#if defined(OS_MACOSX)
+  // TODO(zmo): For experimentation purpose  on MacOSX with core profile,
+  // allow 3.2 or plus for now.
+  if (gl_version_info_->IsAtLeastGL(3, 2))
+    return true;
+#endif
+  return false;
+}
+
+void FeatureInfo::EnableES3Validators() {
+  DCHECK(IsES3Capable());
+  validators_.AddES3Values();
+}
+
 void FeatureInfo::AddExtensionString(const char* s) {
   std::string str(s);
   size_t pos = extensions_.find(str);
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 1a1870d..7816e79 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -130,6 +130,9 @@
     return *(gl_version_info_.get());
   }
 
+  bool IsES3Capable() const;
+  void EnableES3Validators();
+
  private:
   friend class base::RefCounted<FeatureInfo>;
   friend class BufferManagerClientSideArraysTest;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index f76c085..3e568e3 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2474,14 +2474,6 @@
     set_log_commands(true);
   }
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableUnsafeES3APIs) &&
-      attrib_parser.es3_context_required) {
-    // TODO(zmo): We need to implement capabilities check to ensure we can
-    // actually create ES3 contexts.
-    set_unsafe_es3_apis_enabled(true);
-  }
-
   compile_shader_always_succeeds_ =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kCompileShaderAlwaysSucceeds);
@@ -2516,6 +2508,14 @@
   }
   CHECK_GL_ERROR();
 
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableUnsafeES3APIs) &&
+      attrib_parser.es3_context_required &&
+      feature_info_->IsES3Capable()) {
+    feature_info_->EnableES3Validators();
+    set_unsafe_es3_apis_enabled(true);
+  }
+
   disallowed_features_ = disallowed_features;
 
   state_.attrib_values.resize(group_->max_vertex_attribs());
@@ -3113,6 +3113,7 @@
   for (GLsizei ii = 0; ii < n; ++ii) {
     Buffer* buffer = GetBuffer(client_ids[ii]);
     if (buffer && !buffer->IsDeleted()) {
+      buffer->RemoveMappedRange();
       state_.vertex_attrib_manager->Unbind(buffer);
       if (state_.bound_array_buffer.get() == buffer) {
         state_.bound_array_buffer = NULL;
@@ -12288,6 +12289,118 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleMapBufferRange(
+    uint32_t immediate_data_size, const void* cmd_data) {
+  if (!unsafe_es3_apis_enabled()) {
+    return error::kUnknownCommand;
+  }
+  const gles2::cmds::MapBufferRange& c =
+      *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
+  GLenum target = static_cast<GLenum>(c.target);
+  GLbitfield access = static_cast<GLbitfield>(c.access);
+  GLintptr offset = static_cast<GLintptr>(c.offset);
+  GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+
+  typedef cmds::MapBufferRange::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>(
+      c.result_shm_id, c.result_shm_offset, sizeof(*result));
+  if (!result) {
+    return error::kOutOfBounds;
+  }
+  if (*result != 0) {
+    *result = 0;
+    return error::kInvalidArguments;
+  }
+  int8_t* mem =
+      GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
+  if (!mem) {
+    return error::kOutOfBounds;
+  }
+
+  GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
+  if ((access & mask) == mask) {
+    // TODO(zmo): To be on the safe side, always map
+    // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
+    access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
+    access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
+  }
+  // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
+  // undefined behaviors.
+  mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+  if ((access & mask) == mask) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
+                       "incompatible access bits");
+    return error::kNoError;
+  }
+  access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
+  if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
+      (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
+    access = (access | GL_MAP_READ_BIT);
+  }
+  void* ptr = glMapBufferRange(target, offset, size, access);
+  if (ptr == nullptr) {
+    return error::kNoError;
+  }
+  Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
+  DCHECK(buffer);
+  buffer->SetMappedRange(offset, size, access, ptr,
+                         GetSharedMemoryBuffer(c.data_shm_id));
+  if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
+    memcpy(mem, ptr, size);
+  }
+  *result = 1;
+  return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleUnmapBuffer(
+    uint32_t immediate_data_size, const void* cmd_data) {
+  if (!unsafe_es3_apis_enabled()) {
+    return error::kUnknownCommand;
+  }
+  const gles2::cmds::UnmapBuffer& c =
+      *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
+  GLenum target = static_cast<GLenum>(c.target);
+
+  Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
+  if (!buffer) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
+    return error::kNoError;
+  }
+  const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
+  if (!mapped_range) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
+                       "buffer is unmapped");
+    return error::kNoError;
+  }
+  if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
+      (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
+           GL_MAP_FLUSH_EXPLICIT_BIT) {
+    // If we don't need to write back, or explict flush is required, no copying
+    // back is needed.
+  } else {
+    void* mem = mapped_range->GetShmPointer();
+    if (!mem) {
+      return error::kOutOfBounds;
+    }
+    DCHECK(mapped_range->pointer);
+    memcpy(mapped_range->pointer, mem, mapped_range->size);
+  }
+  buffer->RemoveMappedRange();
+  GLboolean rt = glUnmapBuffer(target);
+  if (rt == GL_FALSE) {
+    // At this point, we have already done the necessary validation, so
+    // GL_FALSE indicates data corruption.
+    // TODO(zmo): We could redo the map / copy data / unmap to recover, but
+    // the second unmap could still return GL_FALSE. For now, we simply lose
+    // the contexts in the share group.
+    LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
+    group_->LoseContexts(GL_INNOCENT_CONTEXT_RESET_ARB);
+    reset_status_ = GL_GUILTY_CONTEXT_RESET_ARB;
+    return error::kLostContext;
+  }
+  return error::kNoError;
+}
+
 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
     TextureRef* texture_ref) {
   Texture* texture = texture_ref->texture();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
index 29a55ba..2e153b4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -218,6 +218,10 @@
 // TODO(gman): GetMaxValueInBufferCHROMIUM
 // TODO(gman): EnableFeatureCHROMIUM
 
+// TODO(gman): MapBufferRange
+
+// TODO(gman): UnmapBuffer
+
 // TODO(gman): ResizeCHROMIUM
 // TODO(gman): GetRequestableExtensionsCHROMIUM
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
new file mode 100644
index 0000000..389c78f
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
@@ -0,0 +1,471 @@
+// 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 "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
+
+using ::gfx::MockGLInterface;
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+namespace gpu {
+namespace gles2 {
+
+using namespace cmds;
+
+namespace {
+
+}  // namespace anonymous
+
+TEST_P(GLES2DecoderTest, MapBufferRangeUnmapBufferReadSucceeds) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_READ_BIT;
+
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  std::vector<int8_t> data(kSize);
+  for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
+    data[ii] = static_cast<int8_t>(ii % 255);
+  }
+
+  {  // MapBufferRange
+    EXPECT_CALL(*gl_,
+                MapBufferRange(kTarget, kOffset, kSize, kAccess))
+        .WillOnce(Return(&data[0]))
+        .RetiresOnSaturation();
+
+    typedef MapBufferRange::Result Result;
+    Result* result = GetSharedMemoryAs<Result*>();
+
+    MapBufferRange cmd;
+    cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+             result_shm_id, result_shm_offset);
+    decoder_->set_unsafe_es3_apis_enabled(false);
+    *result = 0;
+    EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+    EXPECT_EQ(0u, *result);
+    decoder_->set_unsafe_es3_apis_enabled(true);
+    *result = 0;
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+    int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+    EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
+    EXPECT_EQ(1u, *result);
+  }
+
+  {  // UnmapBuffer
+    EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
+        .WillOnce(Return(GL_TRUE))
+        .RetiresOnSaturation();
+
+    UnmapBuffer cmd;
+    cmd.Init(kTarget);
+    decoder_->set_unsafe_es3_apis_enabled(false);
+    EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+    decoder_->set_unsafe_es3_apis_enabled(true);
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  }
+
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest, MapBufferRangeUnmapBufferWriteSucceeds) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_WRITE_BIT;
+  const GLbitfield kMappedAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  std::vector<int8_t> data(kSize);
+  for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
+    data[ii] = static_cast<int8_t>(ii % 255);
+  }
+
+  {  // MapBufferRange succeeds
+    EXPECT_CALL(*gl_,
+                MapBufferRange(kTarget, kOffset, kSize, kMappedAccess))
+        .WillOnce(Return(&data[0]))
+        .RetiresOnSaturation();
+
+    typedef MapBufferRange::Result Result;
+    Result* result = GetSharedMemoryAs<Result*>();
+
+    MapBufferRange cmd;
+    cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+             result_shm_id, result_shm_offset);
+    decoder_->set_unsafe_es3_apis_enabled(false);
+    *result = 0;
+    EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+    EXPECT_EQ(0u, *result);
+    decoder_->set_unsafe_es3_apis_enabled(true);
+    *result = 0;
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+    int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+    EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
+    EXPECT_EQ(1u, *result);
+  }
+
+  { // UnmapBuffer succeeds
+    EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
+        .WillOnce(Return(GL_TRUE))
+        .RetiresOnSaturation();
+
+    UnmapBuffer cmd;
+    cmd.Init(kTarget);
+    decoder_->set_unsafe_es3_apis_enabled(false);
+    EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+    decoder_->set_unsafe_es3_apis_enabled(true);
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  }
+
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest, MapBufferRangeNotInitFails) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_READ_BIT;
+  std::vector<int8_t> data(kSize);
+
+  typedef MapBufferRange::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  *result = 1;  // Any value other than 0.
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+
+  MapBufferRange cmd;
+  cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+           result_shm_id, result_shm_offset);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderTest, MapBufferRangeWriteInvalidateRangeSucceeds) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  // With MAP_INVALIDATE_RANGE_BIT, no need to append MAP_READ_BIT.
+  const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  std::vector<int8_t> data(kSize);
+  for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
+    data[ii] = static_cast<int8_t>(ii % 255);
+  }
+  EXPECT_CALL(*gl_,
+              MapBufferRange(kTarget, kOffset, kSize, kAccess))
+      .WillOnce(Return(&data[0]))
+      .RetiresOnSaturation();
+
+  typedef MapBufferRange::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  *result = 0;
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+
+  int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+  memset(mem, 72, kSize);  // Init to a random value other than 0.
+
+  MapBufferRange cmd;
+  cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+           result_shm_id, result_shm_offset);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderTest, MapBufferRangeWriteInvalidateBufferSucceeds) {
+  // Test INVALIDATE_BUFFER_BIT is mapped to INVALIDATE_RANGE_BIT.
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
+  // With MAP_INVALIDATE_BUFFER_BIT, no need to append MAP_READ_BIT.
+  const GLbitfield kFilteredAccess =
+      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  std::vector<int8_t> data(kSize);
+  for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
+    data[ii] = static_cast<int8_t>(ii % 255);
+  }
+  EXPECT_CALL(*gl_,
+              MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
+      .WillOnce(Return(&data[0]))
+      .RetiresOnSaturation();
+
+  typedef MapBufferRange::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  *result = 0;
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+
+  int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+  memset(mem, 72, kSize);  // Init to a random value other than 0.
+
+  MapBufferRange cmd;
+  cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+           result_shm_id, result_shm_offset);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderTest, MapBufferRangeWriteUnsynchronizedBit) {
+  // Test UNSYNCHRONIZED_BIT is filtered out.
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+  const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  std::vector<int8_t> data(kSize);
+  for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
+    data[ii] = static_cast<int8_t>(ii % 255);
+  }
+  EXPECT_CALL(*gl_,
+              MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
+      .WillOnce(Return(&data[0]))
+      .RetiresOnSaturation();
+
+  typedef MapBufferRange::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  *result = 0;
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+
+  int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+  memset(mem, 72, kSize);  // Init to a random value other than 0.
+
+  MapBufferRange cmd;
+  cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+           result_shm_id, result_shm_offset);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
+}
+
+TEST_P(GLES2DecoderTest, MapBufferRangeWithError) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_READ_BIT;
+  std::vector<int8_t> data(kSize);
+  for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
+    data[ii] = static_cast<int8_t>(ii % 255);
+  }
+  EXPECT_CALL(*gl_,
+              MapBufferRange(kTarget, kOffset, kSize, kAccess))
+      .WillOnce(Return(nullptr))  // Return nullptr to indicate a GL error.
+      .RetiresOnSaturation();
+
+  typedef MapBufferRange::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  *result = 0;
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+
+  int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+  memset(mem, 72, kSize);  // Init to a random value other than 0.
+
+  MapBufferRange cmd;
+  cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+           result_shm_id, result_shm_offset);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  memset(&data[0], 72, kSize);
+  // Mem is untouched.
+  EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
+  EXPECT_EQ(0u, *result);
+}
+
+TEST_P(GLES2DecoderTest, MapBufferRangeBadSharedMemoryFails) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_READ_BIT;
+  std::vector<int8_t> data(kSize);
+  for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
+    data[ii] = static_cast<int8_t>(ii % 255);
+  }
+
+  typedef MapBufferRange::Result Result;
+  Result* result = GetSharedMemoryAs<Result*>();
+  *result = 0;
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  MapBufferRange cmd;
+  cmd.Init(kTarget, kOffset, kSize, kAccess,
+           kInvalidSharedMemoryId, data_shm_offset,
+           result_shm_id, result_shm_offset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+  cmd.Init(kTarget, kOffset, kSize, kAccess,
+           data_shm_id, data_shm_offset,
+           kInvalidSharedMemoryId, result_shm_offset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+  cmd.Init(kTarget, kOffset, kSize, kAccess,
+           data_shm_id, kInvalidSharedMemoryOffset,
+           result_shm_id, result_shm_offset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+  cmd.Init(kTarget, kOffset, kSize, kAccess,
+           data_shm_id, data_shm_offset,
+           result_shm_id, kInvalidSharedMemoryOffset);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderTest, UnmapBufferWriteNotMappedFails) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  UnmapBuffer cmd;
+  cmd.Init(kTarget);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest, UnmapBufferWriteNoBoundBufferFails) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+
+  UnmapBuffer cmd;
+  cmd.Init(kTarget);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest, BufferDataDestroysDataStore) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_WRITE_BIT;
+  const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  std::vector<int8_t> data(kSize);
+
+  decoder_->set_unsafe_es3_apis_enabled(true);
+
+  {  // MapBufferRange succeeds
+    EXPECT_CALL(*gl_,
+                MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
+        .WillOnce(Return(&data[0]))
+        .RetiresOnSaturation();
+
+    typedef MapBufferRange::Result Result;
+    Result* result = GetSharedMemoryAs<Result*>();
+
+    MapBufferRange cmd;
+    cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+             result_shm_id, result_shm_offset);
+    *result = 0;
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+    EXPECT_EQ(1u, *result);
+  }
+
+  {  // BufferData unmaps the data store.
+    DoBufferData(kTarget, kSize * 2);
+    EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  }
+
+  {  // UnmapBuffer fails.
+    UnmapBuffer cmd;
+    cmd.Init(kTarget);
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+    EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+  }
+}
+
+TEST_P(GLES2DecoderTest, DeleteBuffersDestroysDataStore) {
+  const GLenum kTarget = GL_ARRAY_BUFFER;
+  const GLintptr kOffset = 10;
+  const GLsizeiptr kSize = 64;
+  const GLbitfield kAccess = GL_MAP_WRITE_BIT;
+  const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+
+  uint32_t result_shm_id = kSharedMemoryId;
+  uint32_t result_shm_offset = kSharedMemoryOffset;
+  uint32_t data_shm_id = kSharedMemoryId;
+  // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+  uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
+  DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+  std::vector<int8_t> data(kSize);
+
+  decoder_->set_unsafe_es3_apis_enabled(true);
+
+  {  // MapBufferRange succeeds
+    EXPECT_CALL(*gl_,
+                MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
+        .WillOnce(Return(&data[0]))
+        .RetiresOnSaturation();
+
+    typedef MapBufferRange::Result Result;
+    Result* result = GetSharedMemoryAs<Result*>();
+
+    MapBufferRange cmd;
+    cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+             result_shm_id, result_shm_offset);
+    *result = 0;
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+    EXPECT_EQ(1u, *result);
+  }
+
+  {  // DeleteBuffers unmaps the data store.
+    DoDeleteBuffer(client_buffer_id_, kServiceBufferId);
+    EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  }
+
+  {  // UnmapBuffer fails.
+    UnmapBuffer cmd;
+    cmd.Init(kTarget);
+    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+    EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+  }
+}
+
+}  // namespace gles2
+}  // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_validation.h b/gpu/command_buffer/service/gles2_cmd_validation.h
index 22ee2da..8ca9861 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation.h
@@ -22,9 +22,7 @@
   ValueValidator() {}
 
   ValueValidator(const T* valid_values, int num_values) {
-    for (int ii = 0; ii < num_values; ++ii) {
-      AddValue(valid_values[ii]);
-    }
+    AddValues(valid_values, num_values);
   }
 
   void AddValue(const T value) {
@@ -33,6 +31,12 @@
     }
   }
 
+  void AddValues(const T* valid_values, int num_values) {
+    for (int ii = 0; ii < num_values; ++ii) {
+      AddValue(valid_values[ii]);
+    }
+  }
+
   bool IsValid(const T value) const {
     return std::find(valid_values_.begin(), valid_values_.end(), value) !=
            valid_values_.end();
@@ -48,6 +52,9 @@
 
 struct Validators {
   Validators();
+
+  void AddES3Values();
+
 #include "gpu/command_buffer/service/gles2_cmd_validation_autogen.h"
 };
 
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index 953c0f9..2a8684a 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -41,6 +41,7 @@
 ValueValidator<GLenum> image_usage;
 ValueValidator<GLenum> index_type;
 ValueValidator<GLenum> indexed_buffer_target;
+ValueValidator<GLenum> map_buffer_access;
 ValueValidator<GLenum> matrix_mode;
 ValueValidator<GLenum> pixel_store;
 ValueValidator<GLint> pixel_store_alignment;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
index 5512be9..2f83240 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -43,6 +43,15 @@
     GL_ELEMENT_ARRAY_BUFFER,
 };
 
+static const GLenum valid_buffer_target_table_es3[] = {
+    GL_COPY_READ_BUFFER,
+    GL_COPY_WRITE_BUFFER,
+    GL_PIXEL_PACK_BUFFER,
+    GL_PIXEL_UNPACK_BUFFER,
+    GL_TRANSFORM_FEEDBACK_BUFFER,
+    GL_UNIFORM_BUFFER,
+};
+
 static const GLenum valid_buffer_usage_table[] = {
     GL_STREAM_DRAW,
     GL_STATIC_DRAW,
@@ -280,6 +289,15 @@
     GL_UNIFORM_BUFFER,
 };
 
+static const GLenum valid_map_buffer_access_table[] = {
+    GL_MAP_READ_BIT,
+    GL_MAP_WRITE_BIT,
+    GL_MAP_INVALIDATE_RANGE_BIT,
+    GL_MAP_INVALIDATE_BUFFER_BIT,
+    GL_MAP_FLUSH_EXPLICIT_BIT,
+    GL_MAP_UNSYNCHRONIZED_BIT,
+};
+
 static const GLenum valid_matrix_mode_table[] = {
     GL_PATH_PROJECTION_CHROMIUM,
     GL_PATH_MODELVIEW_CHROMIUM,
@@ -661,6 +679,8 @@
       index_type(valid_index_type_table, arraysize(valid_index_type_table)),
       indexed_buffer_target(valid_indexed_buffer_target_table,
                             arraysize(valid_indexed_buffer_target_table)),
+      map_buffer_access(valid_map_buffer_access_table,
+                        arraysize(valid_map_buffer_access_table)),
       matrix_mode(valid_matrix_mode_table, arraysize(valid_matrix_mode_table)),
       pixel_store(valid_pixel_store_table, arraysize(valid_pixel_store_table)),
       pixel_store_alignment(valid_pixel_store_alignment_table,
@@ -751,4 +771,9 @@
                      arraysize(valid_vertex_pointer_table)) {
 }
 
+void Validators::AddES3Values() {
+  buffer_target.AddValues(valid_buffer_target_table_es3,
+                          arraysize(valid_buffer_target_table_es3));
+}
+
 #endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gpu_tracer.cc b/gpu/command_buffer/service/gpu_tracer.cc
index 2fbf46c..d00deb0 100644
--- a/gpu/command_buffer/service/gpu_tracer.cc
+++ b/gpu/command_buffer/service/gpu_tracer.cc
@@ -90,7 +90,8 @@
       name_(name),
       outputter_(outputter),
       enabled_(enabled) {
-  if (gpu_timing_client->IsAvailable()) {
+  if (gpu_timing_client->IsAvailable() &&
+      gpu_timing_client->IsTimerOffsetAvailable()) {
     gpu_timer_ = gpu_timing_client->CreateGPUTimer();
   }
 }
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc
index 946d8ae..48a4db9 100644
--- a/gpu/command_buffer/service/gpu_tracer_unittest.cc
+++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -198,7 +198,10 @@
     g_fakeCPUTime = 0;
     const char* gl_version = "3.2";
     const char* extensions = "";
-    if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) {
+    if (GetTimerType() == gfx::GPUTiming::kTimerTypeEXT) {
+      gl_version = "opengl 2.1";
+      extensions = "GL_EXT_timer_query";
+    } else if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) {
       gl_version = "opengl es 3.0";
       extensions = "GL_EXT_disjoint_timer_query";
     } else if (GetTimerType() == gfx::GPUTiming::kTimerTypeARB) {
@@ -231,7 +234,8 @@
   }
 
   void ExpectTraceQueryMocks() {
-    if (GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid) {
+    if (gpu_timing_client_->IsAvailable() &&
+        gpu_timing_client_->IsTimerOffsetAvailable()) {
       // Delegate query APIs used by GPUTrace to a GlFakeQueries
       EXPECT_CALL(*gl_, GenQueriesARB(2, NotNull())).Times(AtLeast(1))
           .WillRepeatedly(
@@ -293,7 +297,8 @@
                             const std::string& name, int64 expect_start_time,
                             int64 expect_end_time) {
     ExpectOutputterBeginMocks(outputter, category, name);
-    bool valid_timer = GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid;
+    bool valid_timer = gpu_timing_client_->IsAvailable() &&
+                       gpu_timing_client_->IsTimerOffsetAvailable();
     ExpectOutputterEndMocks(outputter, category, name, expect_start_time,
                             expect_end_time, valid_timer);
   }
@@ -478,7 +483,8 @@
       std::string source_category = category_name + num_char;
       std::string source_trace_name = trace_name + num_char;
 
-      bool valid_timer = GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid;
+      bool valid_timer = gpu_timing_client_->IsAvailable() &&
+                         gpu_timing_client_->IsTimerOffsetAvailable();
       ExpectOutputterEndMocks(outputter_ref_.get(), source_category,
                               source_trace_name, expect_start_time + i,
                               expect_end_time + i, valid_timer);
@@ -565,6 +571,11 @@
       : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeInvalid) {}
 };
 
+class GpuEXTTimerTracerTest : public BaseGpuTracerTest {
+ public:
+  GpuEXTTimerTracerTest() : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeEXT) {}
+};
+
 class GpuARBTimerTracerTest : public BaseGpuTracerTest {
  public:
   GpuARBTimerTracerTest()
@@ -581,6 +592,10 @@
   DoBasicTracerTest();
 }
 
+TEST_F(GpuEXTTimerTracerTest, EXTTimerBasicTracerTest) {
+  DoBasicTracerTest();
+}
+
 TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerTest) {
   DoBasicTracerTest();
 }
@@ -593,6 +608,10 @@
   DoTracerMarkersTest();
 }
 
+TEST_F(GpuEXTTimerTracerTest, EXTTimerTracerMarkersTest) {
+  DoTracerMarkersTest();
+}
+
 TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerMarkersTest) {
   DoTracerMarkersTest();
 }
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc
index fa07180..55754b7 100644
--- a/gpu/command_buffer/service/shader_manager.cc
+++ b/gpu/command_buffer/service/shader_manager.cc
@@ -27,6 +27,7 @@
 Shader::Shader(GLuint service_id, GLenum shader_type)
       : use_count_(0),
         shader_state_(kShaderStateWaiting),
+        marked_for_deletion_(false),
         service_id_(service_id),
         shader_type_(shader_type),
         source_type_(kANGLE),
@@ -36,6 +37,12 @@
 Shader::~Shader() {
 }
 
+void Shader::Destroy() {
+  if (service_id_) {
+    DeleteServiceID();
+  }
+}
+
 void Shader::RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator,
                             TranslatedShaderSourceType type) {
   shader_state_ = kShaderStateCompileRequested;
@@ -105,6 +112,8 @@
     // We cannot reach here if we are using the shader translator.
     // All invalid shaders must be rejected by the translator.
     // All translated shaders must compile.
+    std::string translator_log = log_info_;
+
     GLint max_len = 0;
     glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
     log_info_.resize(max_len);
@@ -115,9 +124,11 @@
       DCHECK(len == 0 || log_info_[len] == '\0');
       log_info_.resize(len);
     }
+
     LOG_IF(ERROR, translator)
         << "Shader translator allowed/produced an invalid shader "
         << "unless the driver is buggy:"
+        << "\n--Log from shader translator--\n" << translator_log
         << "\n--original-shader--\n" << last_compiled_source_
         << "\n--translated-shader--\n" << source_for_driver
         << "\n--info-log--\n" << log_info_;
@@ -131,13 +142,22 @@
 void Shader::DecUseCount() {
   --use_count_;
   DCHECK_GE(use_count_, 0);
+  if (service_id_ && use_count_ == 0 && marked_for_deletion_) {
+    DeleteServiceID();
+  }
 }
 
-void Shader::Delete() {
-  if (use_count_ > 0) {
-    // If attached, compile the shader before we delete it.
-    DoCompile();
+void Shader::MarkForDeletion() {
+  DCHECK(!marked_for_deletion_);
+  DCHECK_NE(service_id_, 0u);
+
+  marked_for_deletion_ = true;
+  if (use_count_ == 0) {
+    DeleteServiceID();
   }
+}
+
+void Shader::DeleteServiceID() {
   DCHECK_NE(service_id_, 0u);
   glDeleteShader(service_id_);
   service_id_ = 0;
@@ -189,9 +209,7 @@
   while (!shaders_.empty()) {
     if (have_context) {
       Shader* shader = shaders_.begin()->second.get();
-      if (!shader->IsDeleted()) {
-        shader->Delete();
-      }
+      shader->Destroy();
     }
     shaders_.erase(shaders_.begin());
   }
@@ -254,7 +272,7 @@
 void ShaderManager::Delete(Shader* shader) {
   DCHECK(shader);
   DCHECK(IsOwned(shader));
-  shader->Delete();
+  shader->MarkForDeletion();
   RemoveShader(shader);
 }
 
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index 2fbe0dc..0c48b99 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -45,7 +45,7 @@
   }
 
   GLuint service_id() const {
-    return service_id_;
+    return marked_for_deletion_ ? 0 : service_id_;
   }
 
   GLenum shader_type() const {
@@ -97,7 +97,7 @@
   }
 
   bool IsDeleted() const {
-    return service_id_ == 0;
+    return marked_for_deletion_;
   }
 
   bool InUse() const {
@@ -145,15 +145,23 @@
   Shader(GLuint service_id, GLenum shader_type);
   ~Shader();
 
+  // Must be called only if we currently own the context. Forces the deletion
+  // of the underlying shader service id.
+  void Destroy();
+
   void IncUseCount();
   void DecUseCount();
-  void Delete();
+  void MarkForDeletion();
+  void DeleteServiceID();
 
   int use_count_;
 
   // The current state of the shader.
   ShaderState shader_state_;
 
+  // The shader has been marked for deletion.
+  bool marked_for_deletion_;
+
   // The shader this Shader is tracking.
   GLuint service_id_;
 
diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc
index 88f4715..3103e88 100644
--- a/gpu/command_buffer/service/shader_manager_unittest.cc
+++ b/gpu/command_buffer/service/shader_manager_unittest.cc
@@ -82,16 +82,19 @@
   ASSERT_TRUE(shader1.get());
   ASSERT_TRUE(shader2.get());
   manager_.UseShader(shader1.get());
-  EXPECT_CALL(*gl_, DeleteShader(kService1Id))
-      .Times(1)
-      .RetiresOnSaturation();
   manager_.Delete(shader1.get());
+
   EXPECT_CALL(*gl_, DeleteShader(kService2Id))
       .Times(1)
       .RetiresOnSaturation();
   manager_.Delete(shader2.get());
   EXPECT_TRUE(manager_.IsOwned(shader1.get()));
   EXPECT_FALSE(manager_.IsOwned(shader2.get()));
+
+  EXPECT_CALL(*gl_, DeleteShader(kService1Id))
+      .Times(1)
+      .RetiresOnSaturation();
+  manager_.UnuseShader(shader1.get());
 }
 
 TEST_F(ShaderManagerTest, DoCompile) {
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc
index f4a382c..c95ef9f 100644
--- a/gpu/config/gpu_control_list.cc
+++ b/gpu/config/gpu_control_list.cc
@@ -1010,7 +1010,9 @@
   GLType gl_type = kGLTypeNone;
   if (segments.size() > 2 &&
       segments[0] == "OpenGL" && segments[1] == "ES") {
-    number = segments[2];
+    bool full_match = RE2::FullMatch(segments[2], "([\\d.]+).*", &number);
+    DCHECK(full_match);
+
     gl_type = kGLTypeGLES;
     if (segments.size() > 3 &&
         StartsWithASCII(segments[3], "(ANGLE", false)) {
diff --git a/gpu/config/gpu_control_list_entry_unittest.cc b/gpu/config/gpu_control_list_entry_unittest.cc
index 4a26918..5587446 100644
--- a/gpu/config/gpu_control_list_entry_unittest.cc
+++ b/gpu/config/gpu_control_list_entry_unittest.cc
@@ -398,6 +398,9 @@
   gpu_info.gl_version = "OpenGL ES 3.0 V@66.0 AU@ (CL@)";
   EXPECT_TRUE(entry->Contains(GpuControlList::kOsAndroid, "4.4.2", gpu_info));
 
+  gpu_info.gl_version = "OpenGL ES 3.0V@66.0 AU@ (CL@)";
+  EXPECT_TRUE(entry->Contains(GpuControlList::kOsAndroid, "4.4.2", gpu_info));
+
   gpu_info.gl_version = "OpenGL ES 3.1 V@66.0 AU@ (CL@)";
   EXPECT_FALSE(entry->Contains(GpuControlList::kOsAndroid, "4.4.2", gpu_info));
 
diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
index 437c5d9..95d828d 100644
--- a/gpu/config/software_rendering_list_json.cc
+++ b/gpu/config/software_rendering_list_json.cc
@@ -18,7 +18,7 @@
 {
   "name": "software rendering list",
   // Please update the version number whenever you change this file.
-  "version": "9.18",
+  "version": "9.19",
   "entries": [
     {
       "id": 1,
@@ -1054,15 +1054,6 @@
             "type": "android",
             "version": {
               "op": ">=",
-              "value": "4.4.99"
-            }
-          }
-        },
-        {
-          "os": {
-            "type": "android",
-            "version": {
-              "op": ">=",
               "value": "4.4"
             }
           },
diff --git a/gpu/gles2_conform_support/egl/BUILD.gn b/gpu/gles2_conform_support/egl/BUILD.gn
new file mode 100644
index 0000000..0216522
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/BUILD.gn
@@ -0,0 +1,36 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# GYP version: gpu/gles2_conform_support/gles_conform_support.gyp:egl_native
+source_set("egl") {
+  output_name = "egl_native"
+  sources = [
+    "config.cc",
+    "config.h",
+    "display.cc",
+    "display.h",
+    "egl.cc",
+    "surface.cc",
+    "surface.h",
+  ]
+
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+  defines = [
+    "EGLAPI=",
+    "EGLAPIENTRY=",
+  ]
+
+  deps = [
+    "//base",
+    "//gpu/command_buffer/client:gles2_c_lib",
+    "//gpu/command_buffer/client:gles2_implementation_no_check",
+    "//gpu/command_buffer/service",
+    "//gpu",
+    "//ui/base",
+    "//ui/gfx",
+    "//ui/gfx/geometry",
+    "//ui/gl",
+  ]
+}
diff --git a/gpu/gles2_conform_support/gles2_conform_support.gyp b/gpu/gles2_conform_support/gles2_conform_support.gyp
index 6bf8510..05aa9ac 100644
--- a/gpu/gles2_conform_support/gles2_conform_support.gyp
+++ b/gpu/gles2_conform_support/gles2_conform_support.gyp
@@ -30,6 +30,7 @@
   },
   'targets': [
     {
+      # GN version: //gpu/gles2_conform_support/egl
       'target_name': 'egl_native',
       'type': 'static_library',
       'dependencies': [
@@ -60,6 +61,7 @@
       'msvs_disabled_warnings': [ 4267, ],
     },
     {
+      # GN version: //gpu/gles2_conform_support/native
       'target_name': 'egl_main_native',
       'type': 'static_library',
       'dependencies': [
@@ -77,6 +79,7 @@
       ],
     },
     {
+      # GN version: //gpu/gles2_conform_support/native:windowless
       'target_name': 'egl_main_windowless',
       'type': 'static_library',
       'dependencies': [
diff --git a/gpu/gles2_conform_support/native/BUILD.gn b/gpu/gles2_conform_support/native/BUILD.gn
new file mode 100644
index 0000000..aeaa6d2
--- /dev/null
+++ b/gpu/gles2_conform_support/native/BUILD.gn
@@ -0,0 +1,62 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# GYP version: gpu/gles2_conform_support/gles2_conform_support.gyp:egl_main_native
+source_set("native") {
+  output_name = "egl_main_native"
+  sources = [
+    "egl_native.cc",
+    "main.cc",
+  ]
+  defines = [
+    "GLES2_CONFORM_SUPPORT_ONLY",
+    "GTF_GLES20",
+    "EGLAPI=",
+    "EGLAPIENTRY=",
+  ]
+  deps = [
+    "//base",
+    "//gpu/gles2_conform_support/egl",
+    "//ui/gl",
+  ]
+  if (is_linux) {
+    sources += [
+      "egl_native_aura.cc",
+      "egl_native_x11.cc",
+    ]
+  }
+  if (is_win) {
+    sources += [ "egl_native_win.cc" ]
+  }
+}
+
+# GYP version: gpu/gles2_conform_support/gles2_conform_support.gyp:egl_main_windowless
+source_set("windowless") {
+  output_name = "egl_main_windowless"
+  sources = [
+    "egl_native.cc",
+    "egl_native_windowless.cc",
+    "main.cc",
+  ]
+  defines = [
+    "GLES2_CONFORM_SUPPORT_ONLY",
+    "GTF_GLES20",
+    "EGLAPI=",
+    "EGLAPIENTRY=",
+  ]
+  deps = [
+    "//base",
+    "//gpu/gles2_conform_support/egl",
+    "//ui/gl",
+  ]
+  if (is_linux) {
+    sources += [
+      "egl_native_aura.cc",
+      "egl_native_x11.cc",
+    ]
+  }
+  if (is_win) {
+    sources += [ "egl_native_win.cc" ]
+  }
+}
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 2bb7465..0e31fb0 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -103,6 +103,7 @@
       'msvs_disabled_warnings': [4267, ],
     },
     {
+      # GN version: //gpu/command_buffer/client:gles2_c_lib_nocheck
       # Same as gles2_c_lib except with no parameter checking. Required for
       # OpenGL ES 2.0 conformance tests.
       'target_name': 'gles2_c_lib_nocheck',
@@ -220,6 +221,7 @@
         'command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc',
         'command_buffer/service/gles2_cmd_decoder_unittest_base.cc',
         'command_buffer/service/gles2_cmd_decoder_unittest_base.h',
+        'command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc',
         'command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc',
         'command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc',
         'command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc',
@@ -287,6 +289,7 @@
       'dependencies': [
         '../base/base.gyp:base',
         '../base/base.gyp:test_support_base',
+        '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
         '../testing/perf/perf_test.gyp:perf_test',
         '../ui/gfx/gfx.gyp:gfx_geometry',
diff --git a/gpu/gpu_unittests.isolate b/gpu/gpu_unittests.isolate
index a718aac..7ad1b79 100644
--- a/gpu/gpu_unittests.isolate
+++ b/gpu/gpu_unittests.isolate
@@ -3,15 +3,20 @@
 # found in the LICENSE file.
 {
   'conditions': [
-    ['OS=="linux" or OS=="mac" or OS=="win"', {
+    ['use_x11==0', {
       'variables': {
-        'files': [
+        'command': [
           '../testing/test_env.py',
           '<(PRODUCT_DIR)/gpu_unittests<(EXECUTABLE_SUFFIX)',
+          '--brave-new-test-launcher',
+          '--test-launcher-bot-mode',
+          '--asan=<(asan)',
+          '--msan=<(msan)',
+          '--tsan=<(tsan)',
         ],
       },
     }],
-    ['OS=="linux"', {
+    ['use_x11==1', {
       'variables': {
         'command': [
           '../testing/xvfb.py',
@@ -29,29 +34,11 @@
         ],
       },
     }],
-    ['OS=="mac"', {
+    ['OS=="linux" or OS=="mac" or OS=="win"', {
       'variables': {
-        'command': [
+        'files': [
           '../testing/test_env.py',
-          '<(PRODUCT_DIR)/gpu_unittests',
-          '--brave-new-test-launcher',
-          '--test-launcher-bot-mode',
-          '--asan=<(asan)',
-          '--msan=<(msan)',
-          '--tsan=<(tsan)',
-        ],
-      },
-    }],
-    ['OS=="win"', {
-      'variables': {
-        'command': [
-          '../testing/test_env.py',
-          '<(PRODUCT_DIR)/gpu_unittests.exe',
-          '--brave-new-test-launcher',
-          '--test-launcher-bot-mode',
-          '--asan=<(asan)',
-          '--msan=<(msan)',
-          '--tsan=<(tsan)',
+          '<(PRODUCT_DIR)/gpu_unittests<(EXECUTABLE_SUFFIX)',
         ],
       },
     }],
@@ -72,5 +59,6 @@
   ],
   'includes': [
     '../base/base.isolate',
+    '../third_party/angle/angle.isolate',
   ],
 }
diff --git a/gpu/perftests/texture_upload_perftest.cc b/gpu/perftests/texture_upload_perftest.cc
index 5f76746..e36fb1b 100644
--- a/gpu/perftests/texture_upload_perftest.cc
+++ b/gpu/perftests/texture_upload_perftest.cc
@@ -11,11 +11,14 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/stringprintf.h"
 #include "gpu/perftests/measurements.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d_f.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
+#include "ui/gl/gl_enums.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gpu_timing.h"
 #include "ui/gl/scoped_make_current.h"
@@ -31,11 +34,13 @@
 // clang-format off
 const char kVertexShader[] =
 SHADER(
+  uniform vec2 translation = vec2(0.0, 0.0);
   attribute vec2 a_position;
   attribute vec2 a_texCoord;
   varying vec2 v_texCoord;
   void main() {
-    gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);
+    gl_Position = vec4(
+        translation.x + a_position.x, translation.y + a_position.y, 0.0, 1.0);
     v_texCoord = a_texCoord;
   }
 );
@@ -77,20 +82,57 @@
 }
 
 void GenerateTextureData(const gfx::Size& size,
+                         int bytes_per_pixel,
                          const int seed,
                          std::vector<uint8>* const pixels) {
-  pixels->resize(size.GetArea() * 4);
-  for (int y = 0; y < size.height(); ++y) {
-    for (int x = 0; x < size.width(); ++x) {
-      const size_t offset = (y * size.width() + x) * 4;
-      pixels->at(offset) = (y + seed) % 64;
-      pixels->at(offset + 1) = (x + seed) % 128;
-      pixels->at(offset + 2) = (y + x + seed) % 256;
-      pixels->at(offset + 3) = 255;
+  int bytes = size.GetArea() * bytes_per_pixel;
+  pixels->resize(bytes);
+  for (int i = 0; i < bytes; ++i) {
+    int channel = i % bytes_per_pixel;
+    if (channel == 3) {  // Alpha channel.
+      pixels->at(i) = 255;
+    } else {
+      pixels->at(i) = (i + (seed << 2)) % (32 << channel);
     }
   }
 }
 
+// Compare a buffer containing pixels in a specified format to GL_RGBA buffer
+// where the former buffer have been uploaded as a texture and drawn on the
+// RGBA buffer.
+bool CompareBufferToRGBABuffer(GLenum format,
+                               const std::vector<uint8>& pixels,
+                               const std::vector<uint8>& pixels_rgba) {
+  for (size_t i = 0; i < pixels.size(); i += 4) {
+    switch (format) {
+      case GL_RED_EXT:  // (R_t, 0, 0, 1)
+        if (pixels_rgba[i] != pixels[i / 4] || pixels_rgba[i + 1] != 0 ||
+            pixels_rgba[i + 2] != 0 || pixels_rgba[i + 3] != 255) {
+          return false;
+        }
+        break;
+      case GL_LUMINANCE:  // (L_t, L_t, L_t, 1)
+        if (pixels_rgba[i] != pixels[i / 4] ||
+            pixels_rgba[i + 1] != pixels[i / 4] ||
+            pixels_rgba[i + 2] != pixels[i / 4] || pixels_rgba[i + 3] != 255) {
+          return false;
+        }
+        break;
+      case GL_RGBA:  // (R_t, G_t, B_t, A_t)
+        if (pixels_rgba[i] != pixels[i] ||
+            pixels_rgba[i + 1] != pixels[i + 1] ||
+            pixels_rgba[i + 2] != pixels[i + 2] ||
+            pixels_rgba[i + 3] != pixels[i + 3]) {
+          return false;
+        }
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+  return true;
+}
+
 // PerfTest to check costs of texture upload at different stages
 // on different platforms.
 class TextureUploadPerfTest : public testing::Test {
@@ -99,8 +141,9 @@
 
   // Overridden from testing::Test
   void SetUp() override {
+    static bool gl_initialized = gfx::GLSurface::InitializeOneOff();
+    DCHECK(gl_initialized);
     // Initialize an offscreen surface and a gl context.
-    gfx::GLSurface::InitializeOneOff();
     surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(4, 4));
     gl_context_ = gfx::GLContext::CreateGLContext(NULL,  // share_group
                                                   surface_.get(),
@@ -146,15 +189,28 @@
     glBindAttribLocation(program_object_, 1, "a_texCoord");
     glLinkProgram(program_object_);
 
+    translation_location_ =
+        glGetUniformLocation(program_object_, "translation");
+    DCHECK_NE(-1, translation_location_);
+
     GLint linked = -1;
     glGetProgramiv(program_object_, GL_LINK_STATUS, &linked);
     CHECK_NE(0, linked);
+    glUseProgram(program_object_);
+    glUniform1i(sampler_location_, 0);
 
     sampler_location_ = glGetUniformLocation(program_object_, "a_texture");
     CHECK_NE(-1, sampler_location_);
 
     glGenBuffersARB(1, &vertex_buffer_);
     CHECK_NE(0u, vertex_buffer_);
+    DCHECK_NE(0u, vertex_buffer_);
+    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
+    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4,
+                          reinterpret_cast<void*>(sizeof(GLfloat) * 2));
+    glEnableVertexAttribArray(0);
+    glEnableVertexAttribArray(1);
     CheckNoGlError();
   }
 
@@ -176,7 +232,6 @@
       -1.f, top,     0.f, 1.f,
       right, top,    1.f, 1.f};
     // clang-format on
-
     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
     CheckNoGlError();
   }
@@ -199,41 +254,39 @@
   }
 
  protected:
-  // Upload and draw on the offscren surface.
-  // Return a list of pair. Each pair describe a gl operation and the wall
-  // time elapsed in milliseconds.
-  std::vector<Measurement> UploadAndDraw(const gfx::Size& size,
-                                         const std::vector<uint8>& pixels,
-                                         const GLenum format,
-                                         const GLenum type) {
-    MeasurementTimers total_timers(gpu_timing_client_.get());
+  GLuint CreateGLTexture() {
     GLuint texture_id = 0;
-
-    MeasurementTimers tex_timers(gpu_timing_client_.get());
     glActiveTexture(GL_TEXTURE0);
     glGenTextures(1, &texture_id);
     glBindTexture(GL_TEXTURE_2D, texture_id);
+    return texture_id;
+  }
 
+  void UploadTexture(GLuint texture_id,
+                     const gfx::Size& size,
+                     const std::vector<uint8>& pixels,
+                     GLenum format) {
     glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0,
-                 format, type, &pixels[0]);
+                 format, GL_UNSIGNED_BYTE, &pixels[0]);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     CheckNoGlError();
+  }
+
+  // Upload and draw on the offscren surface.
+  // Return a list of pair. Each pair describe a gl operation and the wall
+  // time elapsed in milliseconds.
+  std::vector<Measurement> UploadAndDraw(const gfx::Size& size,
+                                         const std::vector<uint8>& pixels,
+                                         const GLenum format) {
+    GLuint texture_id = CreateGLTexture();
+    MeasurementTimers tex_timers(gpu_timing_client_.get());
+    UploadTexture(texture_id, size, pixels, format);
     tex_timers.Record();
 
     MeasurementTimers draw_timers(gpu_timing_client_.get());
-    glUseProgram(program_object_);
-    glUniform1i(sampler_location_, 0);
-
-    DCHECK_NE(0u, vertex_buffer_);
-    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
-    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
-    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4,
-                          reinterpret_cast<void*>(sizeof(GLfloat) * 2));
-    glEnableVertexAttribArray(0);
-    glEnableVertexAttribArray(1);
 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     draw_timers.Record();
@@ -242,26 +295,21 @@
     glFinish();
     CheckNoGlError();
     finish_timers.Record();
-    total_timers.Record();
 
     glDeleteTextures(1, &texture_id);
 
     std::vector<uint8> pixels_rendered(size.GetArea() * 4);
-    glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, type,
+    glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE,
                  &pixels_rendered[0]);
     CheckNoGlError();
-
-    // TODO(dcastagna): don't assume the format of the texture and do
-    // the appropriate format conversion.
-    EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
-    EXPECT_EQ(pixels, pixels_rendered);
+    EXPECT_TRUE(CompareBufferToRGBABuffer(format, pixels, pixels_rendered))
+        << "Format is: " << gfx::GLEnums::GetStringEnum(format);
 
     std::vector<Measurement> measurements;
     bool gpu_timer_errors =
         gpu_timing_client_->IsAvailable() &&
         gpu_timing_client_->CheckAndResetTimerErrors();
     if (!gpu_timer_errors) {
-      measurements.push_back(total_timers.GetAsMeasurement("total"));
       measurements.push_back(tex_timers.GetAsMeasurement("teximage2d"));
       measurements.push_back(draw_timers.GetAsMeasurement("drawarrays"));
       measurements.push_back(finish_timers.GetAsMeasurement("finish"));
@@ -269,14 +317,16 @@
     return measurements;
   }
 
-  void RunUploadAndDrawMultipleTimes(const gfx::Size& size) {
+  void RunUploadAndDrawMultipleTimes(const gfx::Size& size,
+                                     const GLenum format) {
     std::vector<uint8> pixels;
     base::SmallMap<std::map<std::string, Measurement>>
         aggregates;  // indexed by name
     int successful_runs = 0;
+    ASSERT_THAT(format, testing::AnyOf(GL_RGBA, GL_LUMINANCE, GL_RED_EXT));
     for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) {
-      GenerateTextureData(size, i + 1, &pixels);
-      auto run = UploadAndDraw(size, pixels, GL_RGBA, GL_UNSIGNED_BYTE);
+      GenerateTextureData(size, format == GL_RGBA ? 4 : 1, i + 1, &pixels);
+      auto run = UploadAndDraw(size, pixels, format);
       if (i < kUploadPerfWarmupRuns || !run.size()) {
         continue;
       }
@@ -287,13 +337,15 @@
         aggregate.Increment(measurement);
       }
     }
+    std::string suffix = base::StringPrintf(
+        "_%d_%s", size.width(), gfx::GLEnums::GetStringEnum(format).c_str());
     if (successful_runs) {
       for (const auto& entry : aggregates) {
         const auto m = entry.second.Divide(successful_runs);
-        m.PrintResult(base::StringPrintf("_%d", size.width()));
+        m.PrintResult(suffix);
       }
     }
-    perf_test::PrintResult("sample_runs", "", "",
+    perf_test::PrintResult("sample_runs", suffix, "",
                            static_cast<size_t>(successful_runs), "laps", true);
   }
 
@@ -308,6 +360,7 @@
   GLuint fragment_shader_ = 0;
   GLuint program_object_ = 0;
   GLint sampler_location_ = -1;
+  GLint translation_location_ = -1;
   GLuint vertex_buffer_ = 0;
 };
 
@@ -315,18 +368,95 @@
 // and prints out aggregated measurements for all the runs.
 TEST_F(TextureUploadPerfTest, glTexImage2d) {
   int sizes[] = {128, 256, 512, 1024};
+  std::vector<GLenum> formats;
+  formats.push_back(GL_RGBA);
+  // Used by default for ResourceProvider::yuv_resource_format_.
+  formats.push_back(GL_LUMINANCE);
+
+  ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
+  bool has_texture_rg = gl_context_->HasExtension("GL_EXT_texture_rg") ||
+                        gl_context_->HasExtension("GL_ARB_texture_rg");
+
+  if (has_texture_rg) {
+    // Used as ResourceProvider::yuv_resource_format_ if
+    // {ARB,EXT}_texture_rg is available.
+    formats.push_back(GL_RED_EXT);
+  }
   for (int side : sizes) {
     ASSERT_GE(fbo_size_.width(), side);
     ASSERT_GE(fbo_size_.height(), side);
-
     gfx::Size size(side, side);
-    ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
     GenerateVertexBuffer(size);
+    for (GLenum format : formats) {
+      RunUploadAndDrawMultipleTimes(size, format);
+    }
+  }
+}
 
-    DCHECK_NE(0u, framebuffer_object_);
-    glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_object_);
+// Perf test to check if the driver is doing texture renaming.
+// This test creates one GL texture_id and four different images. For
+// every image it uploads it using texture_id and it draws multiple
+// times. The cpu/wall time and the gpu time for all the uploads and
+// draws, but before glFinish, is computed and is printed out at the end as
+// "upload_and_draw". If the gpu time is >> than the cpu/wall time we expect the
+// driver to do texture renaming: this means that while the gpu is drawing using
+// texture_id it didn't block cpu side the texture upload using the same
+// texture_id.
+TEST_F(TextureUploadPerfTest, renaming) {
+  gfx::Size texture_size(fbo_size_.width() / 2, fbo_size_.height() / 2);
 
-    RunUploadAndDrawMultipleTimes(size);
+  std::vector<uint8> pixels[4];
+  for (int i = 0; i < 4; ++i) {
+    GenerateTextureData(texture_size, 4, i + 1, &pixels[i]);
+  }
+
+  ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
+  GenerateVertexBuffer(texture_size);
+
+  gfx::Vector2dF positions[] = {gfx::Vector2dF(0.f, 0.f),
+                                gfx::Vector2dF(1.f, 0.f),
+                                gfx::Vector2dF(0.f, 1.f),
+                                gfx::Vector2dF(1.f, 1.f)};
+  GLuint texture_id = CreateGLTexture();
+
+  MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get());
+
+  for (int i = 0; i < 4; ++i) {
+    UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA);
+    DCHECK_NE(-1, translation_location_);
+    glUniform2f(translation_location_, positions[i % 4].x(),
+                positions[i % 4].y());
+    // Draw the same quad multiple times to make sure that the time spent on the
+    // gpu is more than the cpu time.
+    for (int draw = 0; draw < 128; ++draw) {
+      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    }
+  }
+
+  upload_and_draw_timers.Record();
+  MeasurementTimers finish_timers(gpu_timing_client_.get());
+  glFinish();
+  CheckNoGlError();
+  finish_timers.Record();
+
+  glDeleteTextures(1, &texture_id);
+
+  for (int i = 0; i < 4; ++i) {
+    std::vector<uint8> pixels_rendered(texture_size.GetArea() * 4);
+    glReadPixels(texture_size.width() * positions[i].x(),
+                 texture_size.height() * positions[i].y(), texture_size.width(),
+                 texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+                 &pixels_rendered[0]);
+    CheckNoGlError();
+    ASSERT_EQ(pixels[i].size(), pixels_rendered.size());
+    EXPECT_EQ(pixels[i], pixels_rendered);
+  }
+
+  bool gpu_timer_errors = gpu_timing_client_->IsAvailable() &&
+                          gpu_timing_client_->CheckAndResetTimerErrors();
+  if (!gpu_timer_errors) {
+    upload_and_draw_timers.GetAsMeasurement("upload_and_draw").PrintResult("");
+    finish_timers.GetAsMeasurement("finish").PrintResult("");
   }
 }
 
diff --git a/gpu/tools/tools.gyp b/gpu/tools/tools.gyp
index 73ef754..4ea41b7 100644
--- a/gpu/tools/tools.gyp
+++ b/gpu/tools/tools.gyp
@@ -12,6 +12,7 @@
     ['OS == "linux" and target_arch != "arm" and use_x11==1', {
       'targets': [
         {
+          # GN: //gpu:compositor_model_bench
           'target_name': 'compositor_model_bench',
           'type': 'executable',
           'dependencies': [
diff --git a/mojo/tools/roll/build_v8.patch b/mojo/tools/roll/build_v8.patch
index 5f37307..7de0f0a 100644
--- a/mojo/tools/roll/build_v8.patch
+++ b/mojo/tools/roll/build_v8.patch
@@ -1,10 +1,10 @@
 diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni
-index e4bbf46..d42babd 100644
+index df6a4a3..05b673b 100644
 --- a/build/module_args/v8.gni
 +++ b/build/module_args/v8.gni
-@@ -6,5 +6,7 @@ if (is_android) {
-   import("//build/config/android/config.gni")
- }
+@@ -9,5 +9,7 @@ if (is_android) {
+ # TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456.
+ enable_correct_v8_arch = false
  
 -v8_use_external_startup_data =
 -    !((is_android && is_android_webview_build) || is_chromeos || is_win)
diff --git a/mojo/tools/roll/cc_strip_video.patch b/mojo/tools/roll/cc_strip_video.patch
index a992d5d..ebc7495 100644
--- a/mojo/tools/roll/cc_strip_video.patch
+++ b/mojo/tools/roll/cc_strip_video.patch
@@ -1,5 +1,5 @@
 diff --git a/cc/BUILD.gn b/cc/BUILD.gn
-index 9c4752d..e217b12 100644
+index 0411b45..4ee07db 100644
 --- a/cc/BUILD.gn
 +++ b/cc/BUILD.gn
 @@ -222,13 +222,6 @@ component("cc") {
@@ -16,7 +16,7 @@
      "output/begin_frame_args.cc",
      "output/begin_frame_args.h",
      "output/bsp_tree.cc",
-@@ -480,8 +473,6 @@ component("cc") {
+@@ -486,8 +479,6 @@ component("cc") {
      "resources/ui_resource_client.h",
      "resources/ui_resource_request.cc",
      "resources/ui_resource_request.h",
@@ -25,7 +25,7 @@
      "resources/zero_copy_tile_task_worker_pool.cc",
      "resources/zero_copy_tile_task_worker_pool.h",
      "scheduler/begin_frame_source.cc",
-@@ -623,8 +614,6 @@ source_set("test_support") {
+@@ -628,8 +619,6 @@ source_set("test_support") {
      "test/fake_tile_manager_client.h",
      "test/fake_ui_resource_layer_tree_host_impl.cc",
      "test/fake_ui_resource_layer_tree_host_impl.h",
@@ -34,7 +34,7 @@
      "test/geometry_test_utils.cc",
      "test/geometry_test_utils.h",
      "test/impl_side_painting_settings.h",
-@@ -782,7 +771,6 @@ test("cc_unittests") {
+@@ -787,7 +776,6 @@ test("cc_unittests") {
      "layers/tiled_layer_unittest.cc",
      "layers/ui_resource_layer_impl_unittest.cc",
      "layers/ui_resource_layer_unittest.cc",
@@ -42,7 +42,7 @@
      "output/begin_frame_args_unittest.cc",
      "output/delegating_renderer_unittest.cc",
      "output/filter_operations_unittest.cc",
-@@ -843,7 +831,6 @@ test("cc_unittests") {
+@@ -848,7 +836,6 @@ test("cc_unittests") {
      "trees/layer_tree_host_unittest_picture.cc",
      "trees/layer_tree_host_unittest_proxy.cc",
      "trees/layer_tree_host_unittest_scroll.cc",
@@ -242,11 +242,11 @@
 -
 -}  // namespace cc
 diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
-index 2016447..578faa9 100644
+index 613ea4b..3813e1d 100644
 --- a/cc/output/gl_renderer.cc
 +++ b/cc/output/gl_renderer.cc
-@@ -13,7 +13,6 @@
- #include "base/logging.h"
+@@ -18,7 +18,6 @@
+ #include "build/build_config.h"
  #include "base/trace_event/trace_event.h"
  #include "cc/base/math_util.h"
 -#include "cc/layers/video_layer_impl.h"
@@ -254,7 +254,7 @@
  #include "cc/output/compositor_frame_metadata.h"
  #include "cc/output/context_provider.h"
 diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
-index b30b0a5..81ad842 100644
+index 295fc84..ebda8d6 100644
 --- a/cc/output/renderer_pixeltest.cc
 +++ b/cc/output/renderer_pixeltest.cc
 @@ -12,7 +12,6 @@
@@ -265,86 +265,12 @@
  #include "third_party/skia/include/core/SkColorPriv.h"
  #include "third_party/skia/include/core/SkImageFilter.h"
  #include "third_party/skia/include/core/SkMatrix.h"
-@@ -388,453 +387,6 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) {
+@@ -902,243 +901,6 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) {
        FuzzyPixelOffByOneComparator(true)));
  }
-
+ 
 -class VideoGLRendererPixelTest : public GLRendererPixelTest {
 - protected:
--  void CreateTestYUVVideoDrawQuad_Striped(const SharedQuadState* shared_state,
--                                          media::VideoFrame::Format format,
--                                          bool is_transparent,
--                                          const gfx::RectF& tex_coord_rect,
--                                          RenderPass* render_pass) {
--    const gfx::Rect rect(this->device_viewport_size_);
--
--    scoped_refptr<media::VideoFrame> video_frame =
--        media::VideoFrame::CreateFrame(
--            format, rect.size(), rect, rect.size(), base::TimeDelta());
--
--    // YUV values representing a striped pattern, for validating texture
--    // coordinates for sampling.
--    uint8_t y_value = 0;
--    uint8_t u_value = 0;
--    uint8_t v_value = 0;
--    for (int i = 0; i < video_frame->rows(media::VideoFrame::kYPlane); ++i) {
--      uint8_t* y_row = video_frame->data(media::VideoFrame::kYPlane) +
--                       video_frame->stride(media::VideoFrame::kYPlane) * i;
--      for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kYPlane);
--           ++j) {
--        y_row[j] = (y_value += 1);
--      }
--    }
--    for (int i = 0; i < video_frame->rows(media::VideoFrame::kUPlane); ++i) {
--      uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) +
--                       video_frame->stride(media::VideoFrame::kUPlane) * i;
--      uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) +
--                       video_frame->stride(media::VideoFrame::kVPlane) * i;
--      for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane);
--           ++j) {
--        u_row[j] = (u_value += 3);
--        v_row[j] = (v_value += 5);
--      }
--    }
--    uint8 alpha_value = is_transparent ? 0 : 128;
--    CreateTestYUVVideoDrawQuad_FromVideoFrame(
--        shared_state, video_frame, alpha_value, tex_coord_rect, render_pass);
--  }
--
--  void CreateTestYUVVideoDrawQuad_Solid(const SharedQuadState* shared_state,
--                                        media::VideoFrame::Format format,
--                                        bool is_transparent,
--                                        const gfx::RectF& tex_coord_rect,
--                                        uint8 y,
--                                        uint8 u,
--                                        uint8 v,
--                                        RenderPass* render_pass) {
--    const gfx::Rect rect(this->device_viewport_size_);
--
--    scoped_refptr<media::VideoFrame> video_frame =
--        media::VideoFrame::CreateFrame(
--            format, rect.size(), rect, rect.size(), base::TimeDelta());
--
--    // YUV values of a solid, constant, color. Useful for testing that color
--    // space/color range are being handled properly.
--    memset(video_frame->data(media::VideoFrame::kYPlane),
--           y,
--           video_frame->stride(media::VideoFrame::kYPlane) *
--               video_frame->rows(media::VideoFrame::kYPlane));
--    memset(video_frame->data(media::VideoFrame::kUPlane),
--           u,
--           video_frame->stride(media::VideoFrame::kUPlane) *
--               video_frame->rows(media::VideoFrame::kUPlane));
--    memset(video_frame->data(media::VideoFrame::kVPlane),
--           v,
--           video_frame->stride(media::VideoFrame::kVPlane) *
--               video_frame->rows(media::VideoFrame::kVPlane));
--
--    uint8 alpha_value = is_transparent ? 0 : 128;
--    CreateTestYUVVideoDrawQuad_FromVideoFrame(
--        shared_state, video_frame, alpha_value, tex_coord_rect, render_pass);
--  }
--
 -  void CreateEdgeBleedPass(media::VideoFrame::Format format,
 -                           RenderPassList* pass_list) {
 -    gfx::Rect rect(200, 200);
@@ -373,139 +299,19 @@
 -    // green sub-rectangle that should be the only thing displayed in
 -    // the final image.  Bleeding will appear on all four sides of the video
 -    // if the tex coords are not clamped.
--    CreateTestYUVVideoDrawQuad_TwoColor(shared_state, format, false,
--                                        tex_coord_rect, background_size, 0, 0,
--                                        0, green_rect, 149, 43, 21, pass.get());
+-    CreateTestYUVVideoDrawQuad_TwoColor(
+-        shared_state, format, false, tex_coord_rect, background_size, 0, 0, 0,
+-        green_rect, 149, 43, 21, pass.get(), video_resource_updater_.get(),
+-        resource_provider_.get());
 -    pass_list->push_back(pass.Pass());
 -  }
 -
--  // Creates a video frame of size background_size filled with yuv_background,
--  // and then draws a foreground rectangle in a different color on top of
--  // that. The foreground rectangle must have coordinates that are divisible
--  // by 2 because YUV is a block format.
--  void CreateTestYUVVideoDrawQuad_TwoColor(const SharedQuadState* shared_state,
--                                           media::VideoFrame::Format format,
--                                           bool is_transparent,
--                                           const gfx::RectF& tex_coord_rect,
--                                           const gfx::Size& background_size,
--                                           uint8 y_background,
--                                           uint8 u_background,
--                                           uint8 v_background,
--                                           const gfx::Rect& foreground_rect,
--                                           uint8 y_foreground,
--                                           uint8 u_foreground,
--                                           uint8 v_foreground,
--                                           RenderPass* render_pass) {
--    const gfx::Rect rect(background_size);
--
--    scoped_refptr<media::VideoFrame> video_frame =
--        media::VideoFrame::CreateFrame(format, background_size, foreground_rect,
--                                       foreground_rect.size(),
--                                       base::TimeDelta());
--
--    int planes[] = {media::VideoFrame::kYPlane,
--                    media::VideoFrame::kUPlane,
--                    media::VideoFrame::kVPlane};
--    uint8 yuv_background[] = {y_background, u_background, v_background};
--    uint8 yuv_foreground[] = {y_foreground, u_foreground, v_foreground};
--    int sample_size[] = {1, 2, 2};
--
--    for (int i = 0; i < 3; ++i) {
--      memset(video_frame->data(planes[i]), yuv_background[i],
--             video_frame->stride(planes[i]) * video_frame->rows(planes[i]));
--    }
--
--    for (int i = 0; i < 3; ++i) {
--      // Since yuv encoding uses block encoding, widths have to be divisible
--      // by the sample size in order for this function to behave properly.
--      DCHECK_EQ(foreground_rect.x() % sample_size[i], 0);
--      DCHECK_EQ(foreground_rect.y() % sample_size[i], 0);
--      DCHECK_EQ(foreground_rect.width() % sample_size[i], 0);
--      DCHECK_EQ(foreground_rect.height() % sample_size[i], 0);
--
--      gfx::Rect sample_rect(foreground_rect.x() / sample_size[i],
--                            foreground_rect.y() / sample_size[i],
--                            foreground_rect.width() / sample_size[i],
--                            foreground_rect.height() / sample_size[i]);
--      for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) {
--        for (int x = sample_rect.x(); x < sample_rect.right(); ++x) {
--          size_t offset = y * video_frame->stride(planes[i]) + x;
--          video_frame->data(planes[i])[offset] = yuv_foreground[i];
--        }
--      }
--    }
--
--    uint8 alpha_value = 255;
--    CreateTestYUVVideoDrawQuad_FromVideoFrame(
--        shared_state, video_frame, alpha_value, tex_coord_rect, render_pass);
--  }
--
--  void CreateTestYUVVideoDrawQuad_FromVideoFrame(
--      const SharedQuadState* shared_state,
--      scoped_refptr<media::VideoFrame> video_frame,
--      uint8 alpha_value,
--      const gfx::RectF& tex_coord_rect,
--      RenderPass* render_pass) {
--    const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A);
--    const YUVVideoDrawQuad::ColorSpace color_space =
--        (video_frame->format() == media::VideoFrame::YV12J
--             ? YUVVideoDrawQuad::JPEG
--             : YUVVideoDrawQuad::REC_601);
--    const gfx::Rect rect(shared_state->content_bounds);
--    const gfx::Rect opaque_rect(0, 0, 0, 0);
--
--    if (with_alpha)
--      memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value,
--             video_frame->stride(media::VideoFrame::kAPlane) *
--                 video_frame->rows(media::VideoFrame::kAPlane));
--
--    VideoFrameExternalResources resources =
--        video_resource_updater_->CreateExternalResourcesFromVideoFrame(
--            video_frame);
--
--    EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
--    EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
--              resources.mailboxes.size());
--    EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
--              resources.release_callbacks.size());
--
--    ResourceProvider::ResourceId y_resource =
--        resource_provider_->CreateResourceFromTextureMailbox(
--            resources.mailboxes[media::VideoFrame::kYPlane],
--            SingleReleaseCallbackImpl::Create(
--                resources.release_callbacks[media::VideoFrame::kYPlane]));
--    ResourceProvider::ResourceId u_resource =
--        resource_provider_->CreateResourceFromTextureMailbox(
--            resources.mailboxes[media::VideoFrame::kUPlane],
--            SingleReleaseCallbackImpl::Create(
--                resources.release_callbacks[media::VideoFrame::kUPlane]));
--    ResourceProvider::ResourceId v_resource =
--        resource_provider_->CreateResourceFromTextureMailbox(
--            resources.mailboxes[media::VideoFrame::kVPlane],
--            SingleReleaseCallbackImpl::Create(
--                resources.release_callbacks[media::VideoFrame::kVPlane]));
--    ResourceProvider::ResourceId a_resource = 0;
--    if (with_alpha) {
--      a_resource = resource_provider_->CreateResourceFromTextureMailbox(
--          resources.mailboxes[media::VideoFrame::kAPlane],
--          SingleReleaseCallbackImpl::Create(
--              resources.release_callbacks[media::VideoFrame::kAPlane]));
--    }
--
--    YUVVideoDrawQuad* yuv_quad =
--        render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
--    yuv_quad->SetNew(shared_state, rect, opaque_rect, rect, tex_coord_rect,
--                     video_frame->coded_size(), y_resource, u_resource,
--                     v_resource, a_resource, color_space);
--  }
--
 -  void SetUp() override {
 -    GLRendererPixelTest::SetUp();
 -    video_resource_updater_.reset(new VideoResourceUpdater(
 -        output_surface_->context_provider(), resource_provider_.get()));
 -  }
 -
-- private:
 -  scoped_ptr<VideoResourceUpdater> video_resource_updater_;
 -};
 -
@@ -518,11 +324,10 @@
 -  SharedQuadState* shared_state =
 -      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 -
--  CreateTestYUVVideoDrawQuad_Striped(shared_state,
--                                     media::VideoFrame::YV12,
--                                     false,
--                                     gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
--                                     pass.get());
+-  CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12,
+-                                     false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
+-                                     pass.get(), video_resource_updater_.get(),
+-                                     rect, resource_provider_.get());
 -
 -  RenderPassList pass_list;
 -  pass_list.push_back(pass.Pass());
@@ -543,11 +348,10 @@
 -      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 -
 -  // Intentionally sets frame format to I420 for testing coverage.
--  CreateTestYUVVideoDrawQuad_Striped(shared_state,
--                                     media::VideoFrame::I420,
--                                     false,
--                                     gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f),
--                                     pass.get());
+-  CreateTestYUVVideoDrawQuad_Striped(
+-      shared_state, media::VideoFrame::I420, false,
+-      gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f), pass.get(),
+-      video_resource_updater_.get(), rect, resource_provider_.get());
 -
 -  RenderPassList pass_list;
 -  pass_list.push_back(pass.Pass());
@@ -568,14 +372,10 @@
 -      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 -
 -  // In MPEG color range YUV values of (15,128,128) should produce black.
--  CreateTestYUVVideoDrawQuad_Solid(shared_state,
--                                   media::VideoFrame::YV12,
--                                   false,
--                                   gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
--                                   15,
--                                   128,
--                                   128,
--                                   pass.get());
+-  CreateTestYUVVideoDrawQuad_Solid(
+-      shared_state, media::VideoFrame::YV12, false,
+-      gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
+-      video_resource_updater_.get(), rect, resource_provider_.get());
 -
 -  RenderPassList pass_list;
 -  pass_list.push_back(pass.Pass());
@@ -597,14 +397,10 @@
 -      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 -
 -  // YUV of (149,43,21) should be green (0,255,0) in RGB.
--  CreateTestYUVVideoDrawQuad_Solid(shared_state,
--                                   media::VideoFrame::YV12J,
--                                   false,
--                                   gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
--                                   149,
--                                   43,
--                                   21,
--                                   pass.get());
+-  CreateTestYUVVideoDrawQuad_Solid(
+-      shared_state, media::VideoFrame::YV12J, false,
+-      gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
+-      video_resource_updater_.get(), rect, resource_provider_.get());
 -
 -  RenderPassList pass_list;
 -  pass_list.push_back(pass.Pass());
@@ -642,14 +438,10 @@
 -      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 -
 -  // Dark grey in JPEG color range (in MPEG, this is black).
--  CreateTestYUVVideoDrawQuad_Solid(shared_state,
--                                   media::VideoFrame::YV12J,
--                                   false,
--                                   gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
--                                   15,
--                                   128,
--                                   128,
--                                   pass.get());
+-  CreateTestYUVVideoDrawQuad_Solid(
+-      shared_state, media::VideoFrame::YV12J, false,
+-      gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
+-      video_resource_updater_.get(), rect, resource_provider_.get());
 -
 -  RenderPassList pass_list;
 -  pass_list.push_back(pass.Pass());
@@ -669,11 +461,10 @@
 -  SharedQuadState* shared_state =
 -      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 -
--  CreateTestYUVVideoDrawQuad_Striped(shared_state,
--                                     media::VideoFrame::YV12A,
--                                     false,
--                                     gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
--                                     pass.get());
+-  CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A,
+-                                     false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
+-                                     pass.get(), video_resource_updater_.get(),
+-                                     rect, resource_provider_.get());
 -
 -  SolidColorDrawQuad* color_quad =
 -      pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -697,11 +488,10 @@
 -  SharedQuadState* shared_state =
 -      CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 -
--  CreateTestYUVVideoDrawQuad_Striped(shared_state,
--                                     media::VideoFrame::YV12A,
--                                     true,
--                                     gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
--                                     pass.get());
+-  CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A,
+-                                     true, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
+-                                     pass.get(), video_resource_updater_.get(),
+-                                     rect, resource_provider_.get());
 -
 -  SolidColorDrawQuad* color_quad =
 -      pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -718,7 +508,7 @@
 -
  TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
    gfx::Rect viewport_rect(this->device_viewport_size_);
-
+ 
 diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
 index 358929e..15bce98 100644
 --- a/cc/quads/yuv_video_draw_quad.h
@@ -729,22 +519,22 @@
  #include "cc/base/cc_export.h"
 -#include "cc/layers/video_layer_impl.h"
  #include "cc/quads/draw_quad.h"
-
+ 
  namespace cc {
 diff --git a/cc/resources/drawing_display_item.cc b/cc/resources/drawing_display_item.cc
 index 648f9de..6dffad9 100644
 --- a/cc/resources/drawing_display_item.cc
 +++ b/cc/resources/drawing_display_item.cc
 @@ -6,6 +6,7 @@
-
+ 
  #include <string>
-
+ 
 +#include "base/logging.h"
  #include "base/strings/stringprintf.h"
  #include "base/trace_event/trace_event_argument.h"
  #include "cc/debug/picture_debug_util.h"
 diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
-index 4b2bc75..7ffa683 100644
+index 4289a99..4e3230b 100644
 --- a/cc/trees/layer_tree_host_impl_unittest.cc
 +++ b/cc/trees/layer_tree_host_impl_unittest.cc
 @@ -27,7 +27,6 @@
@@ -776,7 +566,7 @@
  using ::testing::AtLeast;
  using ::testing::_;
 -using media::VideoFrame;
-
+ 
  namespace cc {
  namespace {
 @@ -96,7 +92,6 @@ class LayerTreeHostImplTest : public testing::Test,
@@ -785,12 +575,12 @@
          current_priority_cutoff_value_(0) {
 -    media::InitializeMediaLibraryForTesting();
    }
-
+ 
    LayerTreeSettings DefaultSettings() {
-@@ -5486,18 +5481,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
+@@ -5473,18 +5468,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
    root_layer->SetBounds(gfx::Size(10, 10));
    root_layer->SetHasRenderSurface(true);
-
+ 
 -  scoped_refptr<VideoFrame> softwareFrame =
 -      media::VideoFrame::CreateColorFrame(
 -          gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
@@ -806,10 +596,10 @@
    scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
        IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
    io_surface_layer->SetBounds(gfx::Size(10, 10));
-@@ -6578,16 +6561,6 @@ TEST_F(LayerTreeHostImplTest,
+@@ -6566,16 +6549,6 @@ TEST_F(LayerTreeHostImplTest,
    scoped_ptr<SolidColorLayerImpl> root_layer =
        SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
-
+ 
 -  // VideoLayerImpl will not be drawn.
 -  FakeVideoFrameProvider provider;
 -  scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
@@ -824,7 +614,7 @@
    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
    host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
 diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
-index c52132e..1be61a5 100644
+index 68a1f58..2ec6e66 100644
 --- a/cc/trees/layer_tree_host_unittest.cc
 +++ b/cc/trees/layer_tree_host_unittest.cc
 @@ -18,7 +18,6 @@
@@ -843,10 +633,10 @@
  #include "cc/test/geometry_test_utils.h"
  #include "cc/test/impl_side_painting_settings.h"
  #include "cc/test/layer_tree_test.h"
-@@ -4163,28 +4161,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest {
+@@ -4170,28 +4168,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest {
    int num_draws_;
  };
-
+ 
 -// VideoLayer must support being invalidated and then passing that along
 -// to the compositor thread, even though no resources are updated in
 -// response to that invalidation.
@@ -900,7 +690,7 @@
 -#include "media/base/media.h"
 -
 -using media::VideoFrame;
-
+ 
  namespace cc {
  namespace {
 @@ -66,7 +60,6 @@ class LayerTreeHostContextTest : public LayerTreeTest {
@@ -909,12 +699,12 @@
          async_output_surface_creation_(false) {
 -    media::InitializeMediaLibraryForTesting();
    }
-
+ 
    void LoseContext() {
 @@ -1055,41 +1048,6 @@ class LayerTreeHostContextTestDontUseLostResources
      layer_with_mask->SetMaskLayer(mask.get());
      root->AddChild(layer_with_mask);
-
+ 
 -    scoped_refptr<VideoLayer> video_color =
 -        VideoLayer::Create(&color_frame_provider_, media::VIDEO_ROTATION_0);
 -    video_color->SetBounds(gfx::Size(10, 10));
@@ -954,7 +744,7 @@
        // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
        scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
 @@ -1119,14 +1077,6 @@ class LayerTreeHostContextTestDontUseLostResources
-
+ 
    void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
      LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
 -
@@ -966,7 +756,7 @@
 -      scaled_hw_frame_provider_.set_frame(NULL);
 -    }
    }
-
+ 
    DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
 @@ -1175,14 +1125,6 @@ class LayerTreeHostContextTestDontUseLostResources
    scoped_refptr<DelegatedFrameResourceCollection>
@@ -981,5 +771,5 @@
 -  FakeVideoFrameProvider hw_frame_provider_;
 -  FakeVideoFrameProvider scaled_hw_frame_provider_;
  };
-
+ 
  SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
diff --git a/mojo/tools/roll/skia_build.patch b/mojo/tools/roll/skia_build.patch
index a252691..5340f2d 100644
--- a/mojo/tools/roll/skia_build.patch
+++ b/mojo/tools/roll/skia_build.patch
@@ -1,8 +1,8 @@
 diff --git a/skia/BUILD.gn b/skia/BUILD.gn
-index c793e0b..85ccce7 100644
+index 248bc1c..2357a7f 100644
 --- a/skia/BUILD.gn
 +++ b/skia/BUILD.gn
-@@ -12,18 +12,6 @@ if (cpu_arch == "arm") {
+@@ -12,18 +12,6 @@ if (current_cpu == "arm") {
  skia_support_gpu = !is_ios
  skia_support_pdf = !is_ios && (enable_basic_printing || enable_print_preview)
  
@@ -21,8 +21,8 @@
  # The list of Skia defines that are to be set for chromium.
  gypi_skia_defines =
      exec_script("//build/gypi_to_gn.py",
-@@ -133,8 +121,7 @@ config("skia_config") {
-     "//third_party/skia/src/core",
+@@ -130,8 +118,7 @@ config("skia_config") {
+     "//third_party/skia/include/utils",
    ]
  
 -  defines = gypi_blink_skia_defines.blink_skia_defines
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index ccb186a..3b340bd 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -168,6 +168,8 @@
     "bpf_dsl/syscall_set.cc",
     "bpf_dsl/syscall_set.h",
     "bpf_dsl/trap_registry.h",
+    "bpf_dsl/verifier.cc",
+    "bpf_dsl/verifier.h",
     "seccomp-bpf/die.cc",
     "seccomp-bpf/die.h",
     "seccomp-bpf/errorcode.cc",
@@ -178,8 +180,6 @@
     "seccomp-bpf/syscall.h",
     "seccomp-bpf/trap.cc",
     "seccomp-bpf/trap.h",
-    "seccomp-bpf/verifier.cc",
-    "seccomp-bpf/verifier.h",
   ]
   defines = [ "SANDBOX_IMPLEMENTATION" ]
 
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
index cffadc5..dba421f 100644
--- a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
+++ b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
@@ -12,55 +12,132 @@
 #include <sys/utsname.h>
 #include <unistd.h>
 
+#include <map>
+#include <utility>
+
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
-#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
+#include "sandbox/linux/bpf_dsl/policy_compiler.h"
+#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
+#include "sandbox/linux/bpf_dsl/trap_registry.h"
+#include "sandbox/linux/bpf_dsl/verifier.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
-#include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #define CASES SANDBOX_BPF_DSL_CASES
 
-// Helper macro to assert that invoking system call |sys| directly via
-// Syscall::Call with arguments |...| returns |res|.
-// Errors can be asserted by specifying a value like "-EINVAL".
-#define ASSERT_SYSCALL_RESULT(res, sys, ...) \
-  BPF_ASSERT_EQ(res, Stubs::sys(__VA_ARGS__))
-
 namespace sandbox {
 namespace bpf_dsl {
 namespace {
 
-// Type safe stubs for tested system calls.
-class Stubs {
+// Helper function to construct fake arch_seccomp_data objects.
+struct arch_seccomp_data FakeSyscall(int nr,
+                                     uint64_t p0 = 0,
+                                     uint64_t p1 = 0,
+                                     uint64_t p2 = 0,
+                                     uint64_t p3 = 0,
+                                     uint64_t p4 = 0,
+                                     uint64_t p5 = 0) {
+  // Made up program counter for syscall address.
+  const uint64_t kFakePC = 0x543210;
+
+  struct arch_seccomp_data data = {
+      nr,
+      SECCOMP_ARCH,
+      kFakePC,
+      {
+       p0, p1, p2, p3, p4, p5,
+      },
+  };
+
+  return data;
+}
+
+class FakeTrapRegistry : public TrapRegistry {
  public:
-  static int getpgid(pid_t pid) { return Syscall::Call(__NR_getpgid, pid); }
-  static int setuid(uid_t uid) { return Syscall::Call(__NR_setuid, uid); }
-  static int setgid(gid_t gid) { return Syscall::Call(__NR_setgid, gid); }
-  static int setpgid(pid_t pid, pid_t pgid) {
-    return Syscall::Call(__NR_setpgid, pid, pgid);
+  FakeTrapRegistry() : map_() {}
+  virtual ~FakeTrapRegistry() {}
+
+  uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override {
+    EXPECT_TRUE(safe);
+
+    const uint16_t next_id = map_.size() + 1;
+    return map_.insert(std::make_pair(Key(fnc, aux), next_id)).first->second;
   }
 
-  static int fcntl(int fd, int cmd, unsigned long arg = 0) {
-    return Syscall::Call(__NR_fcntl, fd, cmd, arg);
+  bool EnableUnsafeTraps() override {
+    ADD_FAILURE() << "Unimplemented";
+    return false;
   }
 
-  static int uname(struct utsname* buf) {
-    return Syscall::Call(__NR_uname, buf);
+ private:
+  using Key = std::pair<TrapFnc, const void*>;
+
+  std::map<Key, uint16_t> map_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeTrapRegistry);
+};
+
+intptr_t FakeTrapFuncOne(const arch_seccomp_data& data, void* aux) { return 1; }
+intptr_t FakeTrapFuncTwo(const arch_seccomp_data& data, void* aux) { return 2; }
+
+// Test that FakeTrapRegistry correctly assigns trap IDs to trap handlers.
+TEST(FakeTrapRegistry, TrapIDs) {
+  struct {
+    TrapRegistry::TrapFnc fnc;
+    const void* aux;
+  } funcs[] = {
+      {FakeTrapFuncOne, nullptr},
+      {FakeTrapFuncTwo, nullptr},
+      {FakeTrapFuncOne, funcs},
+      {FakeTrapFuncTwo, funcs},
+  };
+
+  FakeTrapRegistry traps;
+
+  // Add traps twice to test that IDs are reused correctly.
+  for (int i = 0; i < 2; ++i) {
+    for (size_t j = 0; j < arraysize(funcs); ++j) {
+      // Trap IDs start at 1.
+      EXPECT_EQ(j + 1, traps.Add(funcs[j].fnc, funcs[j].aux, true));
+    }
+  }
+}
+
+class PolicyEmulator {
+ public:
+  explicit PolicyEmulator(const Policy* policy) : program_(), traps_() {
+    program_ = *PolicyCompiler(policy, &traps_).Compile(true /* verify */);
+  }
+  ~PolicyEmulator() {}
+
+  uint32_t Emulate(const struct arch_seccomp_data& data) const {
+    const char* err = nullptr;
+    uint32_t res = Verifier::EvaluateBPF(program_, data, &err);
+    if (err) {
+      ADD_FAILURE() << err;
+      return 0;
+    }
+    return res;
   }
 
-  static int setresuid(uid_t ruid, uid_t euid, uid_t suid) {
-    return Syscall::Call(__NR_setresuid, ruid, euid, suid);
+  void ExpectAllow(const struct arch_seccomp_data& data) const {
+    EXPECT_EQ(SECCOMP_RET_ALLOW, Emulate(data));
   }
 
-#if !defined(ARCH_CPU_X86)
-  static int socketpair(int domain, int type, int protocol, int sv[2]) {
-    return Syscall::Call(__NR_socketpair, domain, type, protocol, sv);
+  void ExpectErrno(uint16_t err, const struct arch_seccomp_data& data) const {
+    EXPECT_EQ(SECCOMP_RET_ERRNO | err, Emulate(data));
   }
-#endif
+
+ private:
+  CodeGen::Program program_;
+  FakeTrapRegistry traps_;
+
+  DISALLOW_COPY_AND_ASSIGN(PolicyEmulator);
 };
 
 class BasicPolicy : public Policy {
@@ -83,12 +160,15 @@
   DISALLOW_COPY_AND_ASSIGN(BasicPolicy);
 };
 
-BPF_TEST_C(BPFDSL, Basic, BasicPolicy) {
-  ASSERT_SYSCALL_RESULT(-EPERM, getpgid, 0);
-  ASSERT_SYSCALL_RESULT(-EINVAL, getpgid, 1);
+TEST(BPFDSL, Basic) {
+  BasicPolicy policy;
+  PolicyEmulator emulator(&policy);
 
-  ASSERT_SYSCALL_RESULT(-ENOMEM, setuid, 42);
-  ASSERT_SYSCALL_RESULT(-ESRCH, setuid, 43);
+  emulator.ExpectErrno(EPERM, FakeSyscall(__NR_getpgid, 0));
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_getpgid, 1));
+
+  emulator.ExpectErrno(ENOMEM, FakeSyscall(__NR_setuid, 42));
+  emulator.ExpectErrno(ESRCH, FakeSyscall(__NR_setuid, 43));
 }
 
 /* On IA-32, socketpair() is implemented via socketcall(). :-( */
@@ -112,22 +192,30 @@
   DISALLOW_COPY_AND_ASSIGN(BooleanLogicPolicy);
 };
 
-BPF_TEST_C(BPFDSL, BooleanLogic, BooleanLogicPolicy) {
-  int sv[2];
+TEST(BPFDSL, BooleanLogic) {
+  BooleanLogicPolicy policy;
+  PolicyEmulator emulator(&policy);
+
+  const intptr_t kFakeSV = 0x12345;
 
   // Acceptable combinations that should return EPERM.
-  ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_STREAM, 0, sv);
-  ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_DGRAM, 0, sv);
+  emulator.ExpectErrno(
+      EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_STREAM, 0, kFakeSV));
+  emulator.ExpectErrno(
+      EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_DGRAM, 0, kFakeSV));
 
   // Combinations that are invalid for only one reason; should return EINVAL.
-  ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_INET, SOCK_STREAM, 0, sv);
-  ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_UNIX, SOCK_SEQPACKET, 0, sv);
-  ASSERT_SYSCALL_RESULT(
-      -EINVAL, socketpair, AF_UNIX, SOCK_STREAM, IPPROTO_TCP, sv);
+  emulator.ExpectErrno(
+      EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_STREAM, 0, kFakeSV));
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX,
+                                           SOCK_SEQPACKET, 0, kFakeSV));
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX,
+                                           SOCK_STREAM, IPPROTO_TCP, kFakeSV));
 
   // Completely unacceptable combination; should also return EINVAL.
-  ASSERT_SYSCALL_RESULT(
-      -EINVAL, socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP, sv);
+  emulator.ExpectErrno(
+      EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP,
+                          kFakeSV));
 }
 #endif  // !ARCH_CPU_X86
 
@@ -149,20 +237,23 @@
   DISALLOW_COPY_AND_ASSIGN(MoreBooleanLogicPolicy);
 };
 
-BPF_TEST_C(BPFDSL, MoreBooleanLogic, MoreBooleanLogicPolicy) {
+TEST(BPFDSL, MoreBooleanLogic) {
+  MoreBooleanLogicPolicy policy;
+  PolicyEmulator emulator(&policy);
+
   // Expect EPERM if any set to 0.
-  ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 0, 5, 5);
-  ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 0, 5);
-  ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 5, 0);
+  emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 0, 5, 5));
+  emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 0, 5));
+  emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 5, 0));
 
   // Expect EAGAIN if all set to 1.
-  ASSERT_SYSCALL_RESULT(-EAGAIN, setresuid, 1, 1, 1);
+  emulator.ExpectErrno(EAGAIN, FakeSyscall(__NR_setresuid, 1, 1, 1));
 
   // Expect EINVAL for anything else.
-  ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 5, 1, 1);
-  ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 5, 1);
-  ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 1, 5);
-  ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 3, 4, 5);
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 5, 1, 1));
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 5, 1));
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 1, 5));
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 3, 4, 5));
 }
 
 static const uintptr_t kDeadBeefAddr =
@@ -184,13 +275,17 @@
   DISALLOW_COPY_AND_ASSIGN(ArgSizePolicy);
 };
 
-BPF_TEST_C(BPFDSL, ArgSizeTest, ArgSizePolicy) {
-  struct utsname buf;
-  ASSERT_SYSCALL_RESULT(0, uname, &buf);
-  ASSERT_SYSCALL_RESULT(
-      -EPERM, uname, reinterpret_cast<struct utsname*>(kDeadBeefAddr));
+TEST(BPFDSL, ArgSizeTest) {
+  ArgSizePolicy policy;
+  PolicyEmulator emulator(&policy);
+
+  emulator.ExpectAllow(FakeSyscall(__NR_uname, 0));
+  emulator.ExpectErrno(EPERM, FakeSyscall(__NR_uname, kDeadBeefAddr));
 }
 
+#if 0
+// TODO(mdempsky): This is really an integration test.
+
 class TrappingPolicy : public Policy {
  public:
   TrappingPolicy() {}
@@ -220,6 +315,7 @@
   ASSERT_SYSCALL_RESULT(2, uname, NULL);
   ASSERT_SYSCALL_RESULT(3, uname, NULL);
 }
+#endif
 
 class MaskingPolicy : public Policy {
  public:
@@ -245,20 +341,23 @@
   DISALLOW_COPY_AND_ASSIGN(MaskingPolicy);
 };
 
-BPF_TEST_C(BPFDSL, MaskTest, MaskingPolicy) {
+TEST(BPFDSL, MaskTest) {
+  MaskingPolicy policy;
+  PolicyEmulator emulator(&policy);
+
   for (uid_t uid = 0; uid < 0x100; ++uid) {
     const int expect_errno = (uid & 0xf) == 0 ? EINVAL : EACCES;
-    ASSERT_SYSCALL_RESULT(-expect_errno, setuid, uid);
+    emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setuid, uid));
   }
 
   for (gid_t gid = 0; gid < 0x100; ++gid) {
     const int expect_errno = (gid & 0xf0) == 0xf0 ? EINVAL : EACCES;
-    ASSERT_SYSCALL_RESULT(-expect_errno, setgid, gid);
+    emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setgid, gid));
   }
 
   for (pid_t pid = 0; pid < 0x100; ++pid) {
     const int expect_errno = (pid & 0xa5) == 0xa0 ? EINVAL : EACCES;
-    ASSERT_SYSCALL_RESULT(-expect_errno, setpgid, pid, 0);
+    emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setpgid, pid, 0));
   }
 }
 
@@ -281,17 +380,20 @@
   DISALLOW_COPY_AND_ASSIGN(ElseIfPolicy);
 };
 
-BPF_TEST_C(BPFDSL, ElseIfTest, ElseIfPolicy) {
-  ASSERT_SYSCALL_RESULT(0, setuid, 0);
+TEST(BPFDSL, ElseIfTest) {
+  ElseIfPolicy policy;
+  PolicyEmulator emulator(&policy);
 
-  ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0001);
-  ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0002);
+  emulator.ExpectErrno(0, FakeSyscall(__NR_setuid, 0));
 
-  ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0011);
-  ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0022);
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0001));
+  emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0002));
 
-  ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0111);
-  ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0222);
+  emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0011));
+  emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0022));
+
+  emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0111));
+  emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0222));
 }
 
 class SwitchPolicy : public Policy {
@@ -315,19 +417,25 @@
   DISALLOW_COPY_AND_ASSIGN(SwitchPolicy);
 };
 
-BPF_TEST_C(BPFDSL, SwitchTest, SwitchPolicy) {
-  base::ScopedFD sock_fd(socket(AF_UNIX, SOCK_STREAM, 0));
-  BPF_ASSERT(sock_fd.is_valid());
+TEST(BPFDSL, SwitchTest) {
+  SwitchPolicy policy;
+  PolicyEmulator emulator(&policy);
 
-  ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFD);
-  ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFL);
+  const int kFakeSockFD = 42;
 
-  ASSERT_SYSCALL_RESULT(0, fcntl, sock_fd.get(), F_SETFD, O_CLOEXEC);
-  ASSERT_SYSCALL_RESULT(-EINVAL, fcntl, sock_fd.get(), F_SETFD, 0);
+  emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFD));
+  emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFL));
 
-  ASSERT_SYSCALL_RESULT(-EPERM, fcntl, sock_fd.get(), F_SETFL, O_RDONLY);
+  emulator.ExpectAllow(
+      FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, O_CLOEXEC));
+  emulator.ExpectErrno(EINVAL,
+                       FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, 0));
 
-  ASSERT_SYSCALL_RESULT(-EACCES, fcntl, sock_fd.get(), F_DUPFD, 0);
+  emulator.ExpectErrno(EPERM,
+                       FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFL, O_RDONLY));
+
+  emulator.ExpectErrno(EACCES,
+                       FakeSyscall(__NR_fcntl, kFakeSockFD, F_DUPFD, 0));
 }
 
 static intptr_t DummyTrap(const struct arch_seccomp_data& data, void* aux) {
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index 18ed7be..f508b30 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -15,12 +15,12 @@
 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
 #include "sandbox/linux/bpf_dsl/codegen.h"
+#include "sandbox/linux/bpf_dsl/dump_bpf.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
 #include "sandbox/linux/bpf_dsl/syscall_set.h"
-#include "sandbox/linux/seccomp-bpf/die.h"
+#include "sandbox/linux/bpf_dsl/verifier.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
-#include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
 
 namespace sandbox {
@@ -86,6 +86,7 @@
 PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry)
     : policy_(policy),
       registry_(registry),
+      escapepc_(0),
       conds_(),
       gen_(),
       has_unsafe_traps_(HasUnsafeTraps(policy_)) {
@@ -95,47 +96,46 @@
 PolicyCompiler::~PolicyCompiler() {
 }
 
-scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() {
-  if (!policy_->InvalidSyscall()->IsDeny()) {
-    SANDBOX_DIE("Policies should deny invalid system calls.");
-  }
+scoped_ptr<CodeGen::Program> PolicyCompiler::Compile(bool verify) {
+  CHECK(policy_->InvalidSyscall()->IsDeny())
+      << "Policies should deny invalid system calls";
 
   // If our BPF program has unsafe traps, enable support for them.
   if (has_unsafe_traps_) {
-    // As support for unsafe jumps essentially defeats all the security
-    // measures that the sandbox provides, we print a big warning message --
-    // and of course, we make sure to only ever enable this feature if it
-    // is actually requested by the sandbox policy.
-    if (Syscall::Call(-1) == -1 && errno == ENOSYS) {
-      SANDBOX_DIE(
-          "Support for UnsafeTrap() has not yet been ported to this "
-          "architecture");
-    }
+    CHECK_NE(0U, escapepc_) << "UnsafeTrap() requires a valid escape PC";
 
     for (int sysnum : kSyscallsRequiredForUnsafeTraps) {
-      if (!policy_->EvaluateSyscall(sysnum)->IsAllow()) {
-        SANDBOX_DIE(
-            "Policies that use UnsafeTrap() must unconditionally allow all "
-            "required system calls");
-      }
+      CHECK(policy_->EvaluateSyscall(sysnum)->IsAllow())
+          << "Policies that use UnsafeTrap() must unconditionally allow all "
+             "required system calls";
     }
 
-    if (!registry_->EnableUnsafeTraps()) {
-      // We should never be able to get here, as UnsafeTrap() should never
-      // actually return a valid ErrorCode object unless the user set the
-      // CHROME_SANDBOX_DEBUGGING environment variable; and therefore,
-      // "has_unsafe_traps" would always be false. But better double-check
-      // than enabling dangerous code.
-      SANDBOX_DIE("We'd rather die than enable unsafe traps");
-    }
+    CHECK(registry_->EnableUnsafeTraps())
+        << "We'd rather die than enable unsafe traps";
   }
 
   // Assemble the BPF filter program.
   scoped_ptr<CodeGen::Program> program(new CodeGen::Program());
   gen_.Compile(AssemblePolicy(), program.get());
+
+  // Make sure compilation resulted in a BPF program that executes
+  // correctly. Otherwise, there is an internal error in our BPF compiler.
+  // There is really nothing the caller can do until the bug is fixed.
+  if (verify) {
+    const char* err = nullptr;
+    if (!Verifier::VerifyBPF(this, *program, *policy_, &err)) {
+      DumpBPF::PrintProgram(*program);
+      LOG(FATAL) << err;
+    }
+  }
+
   return program.Pass();
 }
 
+void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) {
+  escapepc_ = escapepc;
+}
+
 CodeGen::Node PolicyCompiler::AssemblePolicy() {
   // A compiled policy consists of three logical parts:
   //   1. Check that the "arch" field matches the expected architecture.
@@ -162,12 +162,13 @@
     return rest;
   }
 
-  // Allow system calls, if they originate from our magic return address
-  // (which we can query by calling Syscall::Call(-1)).
-  uint64_t syscall_entry_point =
-      static_cast<uint64_t>(static_cast<uintptr_t>(Syscall::Call(-1)));
-  uint32_t low = static_cast<uint32_t>(syscall_entry_point);
-  uint32_t hi = static_cast<uint32_t>(syscall_entry_point >> 32);
+  // We already enabled unsafe traps in Compile, but enable them again to give
+  // the trap registry a second chance to complain before we add the backdoor.
+  CHECK(registry_->EnableUnsafeTraps());
+
+  // Allow system calls, if they originate from our magic return address.
+  const uint32_t lopc = static_cast<uint32_t>(escapepc_);
+  const uint32_t hipc = static_cast<uint32_t>(escapepc_ >> 32);
 
   // BPF cannot do native 64-bit comparisons, so we have to compare
   // both 32-bit halves of the instruction pointer. If they match what
@@ -179,10 +180,10 @@
   return gen_.MakeInstruction(
       BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_LSB_IDX,
       gen_.MakeInstruction(
-          BPF_JMP + BPF_JEQ + BPF_K, low,
+          BPF_JMP + BPF_JEQ + BPF_K, lopc,
           gen_.MakeInstruction(
               BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_MSB_IDX,
-              gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hi,
+              gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hipc,
                                    CompileResult(Allow()), rest)),
           rest));
 }
@@ -259,9 +260,9 @@
   // a binary search over the ranges.
   // As a sanity check, we need to have at least one distinct ranges for us
   // to be able to build a jump table.
-  if (stop - start <= 0) {
-    SANDBOX_DIE("Invalid set of system call ranges");
-  } else if (stop - start == 1) {
+  CHECK(start < stop) << "Invalid iterator range";
+  const auto n = stop - start;
+  if (n == 1) {
     // If we have narrowed things down to a single range object, we can
     // return from the BPF filter program.
     return start->node;
@@ -271,7 +272,7 @@
   // We compare our system call number against the lowest valid system call
   // number in this range object. If our number is lower, it is outside of
   // this range object. If it is greater or equal, it might be inside.
-  Ranges::const_iterator mid = start + (stop - start) / 2;
+  Ranges::const_iterator mid = start + n / 2;
 
   // Sub-divide the list of ranges and continue recursively.
   CodeGen::Node jf = AssembleJumpTable(start, mid);
@@ -291,31 +292,30 @@
     case ErrorCode::ET_TRAP:
       return gen_.MakeInstruction(BPF_RET + BPF_K, err.err());
     default:
-      SANDBOX_DIE("ErrorCode is not suitable for returning from a BPF program");
+      LOG(FATAL)
+          << "ErrorCode is not suitable for returning from a BPF program";
+      return CodeGen::kNullNode;
   }
 }
 
 CodeGen::Node PolicyCompiler::CondExpression(const ErrorCode& cond) {
   // Sanity check that |cond| makes sense.
-  if (cond.argno_ < 0 || cond.argno_ >= 6) {
-    SANDBOX_DIE("sandbox_bpf: invalid argument number");
+  CHECK(cond.argno_ >= 0 && cond.argno_ < 6) << "Invalid argument number "
+                                             << cond.argno_;
+  CHECK(cond.width_ == ErrorCode::TP_32BIT ||
+        cond.width_ == ErrorCode::TP_64BIT)
+      << "Invalid argument width " << cond.width_;
+  CHECK_NE(0U, cond.mask_) << "Zero mask is invalid";
+  CHECK_EQ(cond.value_, cond.value_ & cond.mask_)
+      << "Value contains masked out bits";
+  if (sizeof(void*) == 4) {
+    CHECK_EQ(ErrorCode::TP_32BIT, cond.width_)
+        << "Invalid width on 32-bit platform";
   }
-  if (cond.width_ != ErrorCode::TP_32BIT &&
-      cond.width_ != ErrorCode::TP_64BIT) {
-    SANDBOX_DIE("sandbox_bpf: invalid argument width");
+  if (cond.width_ == ErrorCode::TP_32BIT) {
+    CHECK_EQ(0U, cond.mask_ >> 32) << "Mask exceeds argument size";
+    CHECK_EQ(0U, cond.value_ >> 32) << "Value exceeds argument size";
   }
-  if (cond.mask_ == 0) {
-    SANDBOX_DIE("sandbox_bpf: zero mask is invalid");
-  }
-  if ((cond.value_ & cond.mask_) != cond.value_) {
-    SANDBOX_DIE("sandbox_bpf: value contains masked out bits");
-  }
-  if (cond.width_ == ErrorCode::TP_32BIT &&
-      ((cond.mask_ >> 32) != 0 || (cond.value_ >> 32) != 0)) {
-    SANDBOX_DIE("sandbox_bpf: test exceeds argument size");
-  }
-  // TODO(mdempsky): Reject TP_64BIT on 32-bit platforms. For now we allow it
-  // because some SandboxBPF unit tests exercise it.
 
   CodeGen::Node passed = RetExpression(*cond.passed_);
   CodeGen::Node failed = RetExpression(*cond.failed_);
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.h b/sandbox/linux/bpf_dsl/policy_compiler.h
index faf6be5..df38d4c 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.h
+++ b/sandbox/linux/bpf_dsl/policy_compiler.h
@@ -32,7 +32,11 @@
 
   // Compile registers any trap handlers needed by the policy and
   // compiles the policy to a BPF program, which it returns.
-  scoped_ptr<CodeGen::Program> Compile();
+  scoped_ptr<CodeGen::Program> Compile(bool verify);
+
+  // DangerousSetEscapePC sets the "escape PC" that is allowed to issue any
+  // system calls, regardless of policy.
+  void DangerousSetEscapePC(uint64_t escapepc);
 
   // Error returns an ErrorCode to indicate the system call should fail with
   // the specified error number.
@@ -88,7 +92,7 @@
   CodeGen::Node CheckArch(CodeGen::Node passed);
 
   // If |has_unsafe_traps_| is true, returns an instruction sequence
-  // that allows all system calls from Syscall::Call(), and otherwise
+  // that allows all system calls from |escapepc_|, and otherwise
   // passes control to |rest|. Otherwise, simply returns |rest|.
   CodeGen::Node MaybeAddEscapeHatch(CodeGen::Node rest);
 
@@ -140,6 +144,7 @@
 
   const Policy* policy_;
   TrapRegistry* registry_;
+  uint64_t escapepc_;
 
   Conds conds_;
   CodeGen gen_;
diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h
index b72357a..7fd0e67 100644
--- a/sandbox/linux/bpf_dsl/seccomp_macros.h
+++ b/sandbox/linux/bpf_dsl/seccomp_macros.h
@@ -21,6 +21,8 @@
 #endif
 #endif
 
+#include "sandbox/linux/system_headers/linux_seccomp.h"  // For AUDIT_ARCH_*
+
 // Impose some reasonable maximum BPF program size. Realistically, the
 // kernel probably has much lower limits. But by limiting to less than
 // 30 bits, we can ease requirements on some of our data types.
diff --git a/sandbox/linux/bpf_dsl/trap_registry.h b/sandbox/linux/bpf_dsl/trap_registry.h
index 94d4722..0a5d2f1 100644
--- a/sandbox/linux/bpf_dsl/trap_registry.h
+++ b/sandbox/linux/bpf_dsl/trap_registry.h
@@ -49,10 +49,19 @@
 
   // EnableUnsafeTraps tries to enable unsafe traps and returns
   // whether it was successful. This is a one-way operation.
+  //
+  // CAUTION: Enabling unsafe traps effectively defeats the security
+  // guarantees provided by the sandbox policy. TrapRegistry
+  // implementations should ensure unsafe traps are only enabled
+  // during testing.
   virtual bool EnableUnsafeTraps() = 0;
 
  protected:
   TrapRegistry() {}
+
+  // TrapRegistry's destructor is intentionally non-virtual so that
+  // implementations can omit their destructor.  Instead we protect against
+  // misuse by marking it protected.
   ~TrapRegistry() {}
 
   DISALLOW_COPY_AND_ASSIGN(TrapRegistry);
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/bpf_dsl/verifier.cc
similarity index 89%
rename from sandbox/linux/seccomp-bpf/verifier.cc
rename to sandbox/linux/bpf_dsl/verifier.cc
index e533b2d..adbc960 100644
--- a/sandbox/linux/seccomp-bpf/verifier.cc
+++ b/sandbox/linux/bpf_dsl/verifier.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "sandbox/linux/seccomp-bpf/verifier.h"
+#include "sandbox/linux/bpf_dsl/verifier.h"
 
 #include <string.h>
 
@@ -15,16 +15,15 @@
 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
 #include "sandbox/linux/bpf_dsl/syscall_set.h"
 #include "sandbox/linux/seccomp-bpf/errorcode.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
 
 namespace sandbox {
+namespace bpf_dsl {
 
 namespace {
 
 const uint64_t kLower32Bits = std::numeric_limits<uint32_t>::max();
 const uint64_t kUpper32Bits = static_cast<uint64_t>(kLower32Bits) << 32;
-const uint64_t kFull64Bits = std::numeric_limits<uint64_t>::max();
 
 struct State {
   State(const std::vector<struct sock_filter>& p,
@@ -54,8 +53,8 @@
       return compiler->Unexpected64bitArgument().err();
     }
     bool equal = (data.args[code.argno()] & code.mask()) == code.value();
-    return EvaluateErrorCode(
-        compiler, equal ? *code.passed() : *code.failed(), data);
+    return EvaluateErrorCode(compiler, equal ? *code.passed() : *code.failed(),
+                             data);
   } else {
     return SECCOMP_RET_INVALID;
   }
@@ -69,10 +68,12 @@
                      const char** err) {
   if (code.error_type() == ErrorCode::ET_SIMPLE ||
       code.error_type() == ErrorCode::ET_TRAP) {
-    uint32_t computed_ret = Verifier::EvaluateBPF(program, *data, err);
+    const uint32_t computed_ret = Verifier::EvaluateBPF(program, *data, err);
     if (*err) {
       return false;
-    } else if (computed_ret != EvaluateErrorCode(compiler, root_code, *data)) {
+    }
+    const uint32_t policy_ret = EvaluateErrorCode(compiler, root_code, *data);
+    if (computed_ret != policy_ret) {
       // For efficiency's sake, we'd much rather compare "computed_ret"
       // against "code.err()". This works most of the time, but it doesn't
       // always work for nested conditional expressions. The test values
@@ -97,8 +98,8 @@
 
     // Verify that we can check a value for simple equality.
     data->args[code.argno()] = code.value();
-    if (!VerifyErrorCode(
-            compiler, program, data, root_code, *code.passed(), err)) {
+    if (!VerifyErrorCode(compiler, program, data, root_code, *code.passed(),
+                         err)) {
       return false;
     }
 
@@ -110,15 +111,15 @@
     }
     if ((ignored_bits & kLower32Bits) != 0) {
       data->args[code.argno()] = code.value() | (ignored_bits & kLower32Bits);
-      if (!VerifyErrorCode(
-              compiler, program, data, root_code, *code.passed(), err)) {
+      if (!VerifyErrorCode(compiler, program, data, root_code, *code.passed(),
+                           err)) {
         return false;
       }
     }
     if ((ignored_bits & kUpper32Bits) != 0) {
       data->args[code.argno()] = code.value() | (ignored_bits & kUpper32Bits);
-      if (!VerifyErrorCode(
-              compiler, program, data, root_code, *code.passed(), err)) {
+      if (!VerifyErrorCode(compiler, program, data, root_code, *code.passed(),
+                           err)) {
         return false;
       }
     }
@@ -126,15 +127,15 @@
     // Verify that changing bits included in the mask is detected as inequality.
     if ((code.mask() & kLower32Bits) != 0) {
       data->args[code.argno()] = code.value() ^ (code.mask() & kLower32Bits);
-      if (!VerifyErrorCode(
-              compiler, program, data, root_code, *code.failed(), err)) {
+      if (!VerifyErrorCode(compiler, program, data, root_code, *code.failed(),
+                           err)) {
         return false;
       }
     }
     if ((code.mask() & kUpper32Bits) != 0) {
       data->args[code.argno()] = code.value() ^ (code.mask() & kUpper32Bits);
-      if (!VerifyErrorCode(
-              compiler, program, data, root_code, *code.failed(), err)) {
+      if (!VerifyErrorCode(compiler, program, data, root_code, *code.failed(),
+                           err)) {
         return false;
       }
     }
@@ -145,24 +146,16 @@
 
       // Arbitrary 64-bit values should be rejected.
       data->args[code.argno()] = 1ULL << 32;
-      if (!VerifyErrorCode(compiler,
-                           program,
-                           data,
-                           root_code,
-                           compiler->Unexpected64bitArgument(),
-                           err)) {
+      if (!VerifyErrorCode(compiler, program, data, root_code,
+                           compiler->Unexpected64bitArgument(), err)) {
         return false;
       }
 
       // Upper 32-bits set without the MSB of the lower 32-bits set should be
       // rejected too.
       data->args[code.argno()] = kUpper32Bits;
-      if (!VerifyErrorCode(compiler,
-                           program,
-                           data,
-                           root_code,
-                           compiler->Unexpected64bitArgument(),
-                           err)) {
+      if (!VerifyErrorCode(compiler, program, data, root_code,
+                           compiler->Unexpected64bitArgument(), err)) {
         return false;
       }
     }
@@ -182,8 +175,7 @@
   if (insn.k < sizeof(struct arch_seccomp_data) && (insn.k & 3) == 0) {
     // We only allow loading of properly aligned 32bit quantities.
     memcpy(&state->accumulator,
-           reinterpret_cast<const char*>(&state->data) + insn.k,
-           4);
+           reinterpret_cast<const char*>(&state->data) + insn.k, 4);
   } else {
     *err = "Invalid operand in BPF_LD instruction";
     return;
@@ -399,4 +391,5 @@
   return 0;
 }
 
+}  // namespace bpf_dsl
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/verifier.h b/sandbox/linux/bpf_dsl/verifier.h
similarity index 89%
rename from sandbox/linux/seccomp-bpf/verifier.h
rename to sandbox/linux/bpf_dsl/verifier.h
index 6bd747b..b0435d1 100644
--- a/sandbox/linux/seccomp-bpf/verifier.h
+++ b/sandbox/linux/bpf_dsl/verifier.h
@@ -2,25 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SANDBOX_LINUX_SECCOMP_BPF_VERIFIER_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_VERIFIER_H__
+#ifndef SANDBOX_LINUX_BPF_DSL_VERIFIER_H__
+#define SANDBOX_LINUX_BPF_DSL_VERIFIER_H__
 
 #include <stdint.h>
 
 #include <vector>
 
 #include "base/macros.h"
+#include "sandbox/sandbox_export.h"
 
 struct sock_filter;
 
 namespace sandbox {
 struct arch_seccomp_data;
+
 namespace bpf_dsl {
 class Policy;
 class PolicyCompiler;
-}
 
-class Verifier {
+class SANDBOX_EXPORT Verifier {
  public:
   // Evaluate the BPF program for all possible inputs and verify that it
   // computes the correct result. We use the "evaluators" to determine
@@ -50,6 +51,7 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(Verifier);
 };
 
+}  // namespace bpf_dsl
 }  // namespace sandbox
 
-#endif  // SANDBOX_LINUX_SECCOMP_BPF_VERIFIER_H__
+#endif  // SANDBOX_LINUX_BPF_DSL_VERIFIER_H__
diff --git a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
index 8e7e144..e884774 100644
--- a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
+++ b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
@@ -557,11 +557,11 @@
   Die::SuppressInfoMessages(true);
 
   unsetenv(kSandboxDebuggingEnv);
-  SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false);
+  SANDBOX_ASSERT(Trap::Registry()->EnableUnsafeTraps() == false);
   setenv(kSandboxDebuggingEnv, "", 1);
-  SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false);
+  SANDBOX_ASSERT(Trap::Registry()->EnableUnsafeTraps() == false);
   setenv(kSandboxDebuggingEnv, "t", 1);
-  SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == true);
+  SANDBOX_ASSERT(Trap::Registry()->EnableUnsafeTraps() == true);
 }
 
 intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) {
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index a623971..6111fd3 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -137,6 +137,8 @@
         'bpf_dsl/syscall_set.cc',
         'bpf_dsl/syscall_set.h',
         'bpf_dsl/trap_registry.h',
+        'bpf_dsl/verifier.cc',
+        'bpf_dsl/verifier.h',
         'seccomp-bpf/die.cc',
         'seccomp-bpf/die.h',
         'seccomp-bpf/errorcode.cc',
@@ -147,8 +149,6 @@
         'seccomp-bpf/syscall.h',
         'seccomp-bpf/trap.cc',
         'seccomp-bpf/trap.h',
-        'seccomp-bpf/verifier.cc',
-        'seccomp-bpf/verifier.h',
       ],
       'dependencies': [
         '../base/base.gyp:base',
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index b6553d7..c96642e 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -24,16 +24,13 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/third_party/valgrind/valgrind.h"
 #include "sandbox/linux/bpf_dsl/codegen.h"
-#include "sandbox/linux/bpf_dsl/dump_bpf.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
 #include "sandbox/linux/bpf_dsl/syscall_set.h"
 #include "sandbox/linux/seccomp-bpf/die.h"
-#include "sandbox/linux/seccomp-bpf/errorcode.h"
 #include "sandbox/linux/seccomp-bpf/syscall.h"
 #include "sandbox/linux/seccomp-bpf/trap.h"
-#include "sandbox/linux/seccomp-bpf/verifier.h"
 #include "sandbox/linux/services/proc_util.h"
 #include "sandbox/linux/services/syscall_wrappers.h"
 #include "sandbox/linux/services/thread_helpers.h"
@@ -79,6 +76,14 @@
   }
 }
 
+uint64_t EscapePC() {
+  intptr_t rv = Syscall::Call(-1);
+  if (rv == -1 && errno == ENOSYS) {
+    return 0;
+  }
+  return static_cast<uint64_t>(static_cast<uintptr_t>(rv));
+}
+
 }  // namespace
 
 SandboxBPF::SandboxBPF(bpf_dsl::Policy* policy)
@@ -184,25 +189,12 @@
   force_verification = true;
 #endif
   DCHECK(policy_);
+
   bpf_dsl::PolicyCompiler compiler(policy_.get(), Trap::Registry());
-  scoped_ptr<CodeGen::Program> program = compiler.Compile();
-
-  // Make sure compilation resulted in a BPF program that executes
-  // correctly. Otherwise, there is an internal error in our BPF compiler.
-  // There is really nothing the caller can do until the bug is fixed.
-  if (force_verification) {
-    // Verification is expensive. We only perform this step, if we are
-    // compiled in debug mode, or if the caller explicitly requested
-    // verification.
-
-    const char* err = NULL;
-    if (!Verifier::VerifyBPF(&compiler, *program, *policy_, &err)) {
-      bpf_dsl::DumpBPF::PrintProgram(*program);
-      SANDBOX_DIE(err);
-    }
+  if (Trap::SandboxDebuggingAllowedByUser()) {
+    compiler.DangerousSetEscapePC(EscapePC());
   }
-
-  return program.Pass();
+  return compiler.Compile(force_verification);
 }
 
 void SandboxBPF::InstallFilter(bool must_sync_threads) {
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index c87bb00..145e624 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -251,10 +251,6 @@
   }
 }
 
-uint16_t Trap::MakeTrap(TrapFnc fnc, const void* aux, bool safe) {
-  return Registry()->Add(fnc, aux, safe);
-}
-
 uint16_t Trap::Add(TrapFnc fnc, const void* aux, bool safe) {
   if (!safe && !SandboxDebuggingAllowedByUser()) {
     // Unless the user set the CHROME_SANDBOX_DEBUGGING environment variable,
@@ -353,15 +349,11 @@
   return id;
 }
 
-bool Trap::SandboxDebuggingAllowedByUser() const {
+bool Trap::SandboxDebuggingAllowedByUser() {
   const char* debug_flag = getenv(kSandboxDebuggingEnv);
   return debug_flag && *debug_flag;
 }
 
-bool Trap::EnableUnsafeTrapsInSigSysHandler() {
-  return Registry()->EnableUnsafeTraps();
-}
-
 bool Trap::EnableUnsafeTraps() {
   if (!has_unsafe_traps_) {
     // Unsafe traps are a one-way fuse. Once enabled, they can never be turned
diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h
index fea0052..4073bfe 100644
--- a/sandbox/linux/seccomp-bpf/trap.h
+++ b/sandbox/linux/seccomp-bpf/trap.h
@@ -34,23 +34,9 @@
   // creating it if necessary.
   static bpf_dsl::TrapRegistry* Registry();
 
-  // Registers a new trap handler and sets up the appropriate SIGSYS handler
-  // as needed.
-  // N.B.: This makes a permanent state change. Traps cannot be unregistered,
-  //   as that would break existing BPF filters that are still active.
-  // TODO(mdempsky): Deprecated; remove.
-  static uint16_t MakeTrap(TrapFnc fnc, const void* aux, bool safe);
-
-  // Enables support for unsafe traps in the SIGSYS signal handler. This is a
-  // one-way fuse. It works in conjunction with the BPF compiler emitting code
-  // that unconditionally allows system calls, if they have a magic return
-  // address (i.e. SandboxSyscall(-1)).
-  // Once unsafe traps are enabled, the sandbox is essentially compromised.
-  // But this is still a very useful feature for debugging purposes. Use with
-  // care. This feature is availably only if enabled by the user (see above).
-  // Returns "true", if unsafe traps were turned on.
-  // TODO(mdempsky): Deprecated; remove.
-  static bool EnableUnsafeTrapsInSigSysHandler();
+  // SandboxDebuggingAllowedByUser returns whether the
+  // "CHROME_SANDBOX_DEBUGGING" environment variable is set.
+  static bool SandboxDebuggingAllowedByUser();
 
  private:
   struct TrapKey {
@@ -67,9 +53,9 @@
   // automatically as needed.
   Trap();
 
-  // The destructor is unimplemented. Don't ever attempt to destruct this
-  // object. It'll break subsequent system calls that trigger a SIGSYS.
-  ~Trap();
+  // The destructor is unimplemented as destroying this object would
+  // break subsequent system calls that trigger a SIGSYS.
+  ~Trap() = delete;
 
   static void SigSysAction(int nr, siginfo_t* info, void* void_context);
 
@@ -77,8 +63,6 @@
   // dumps.
   void SigSys(int nr, siginfo_t* info, void* void_context)
       __attribute__((noinline));
-  bool SandboxDebuggingAllowedByUser() const;
-
   // We have a global singleton that handles all of our SIGSYS traps. This
   // variable must never be deallocated after it has been set up initially, as
   // there is no way to reset in-kernel BPF filters that generate SIGSYS
diff --git a/sdch/BUILD.gn b/sdch/BUILD.gn
new file mode 100644
index 0000000..3ceeeb4
--- /dev/null
+++ b/sdch/BUILD.gn
@@ -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.
+
+config("sdch_config") {
+  include_dirs = [ "open-vcdiff/src" ]
+}
+
+static_library("sdch") {
+  sources = [
+    "logging_forward.h",
+    "open-vcdiff/src/addrcache.cc",
+    "open-vcdiff/src/blockhash.cc",
+    "open-vcdiff/src/blockhash.h",
+    "open-vcdiff/src/checksum.h",
+    "open-vcdiff/src/codetable.cc",
+    "open-vcdiff/src/codetable.h",
+    "open-vcdiff/src/compile_assert.h",
+    "open-vcdiff/src/decodetable.cc",
+    "open-vcdiff/src/decodetable.h",
+    "open-vcdiff/src/encodetable.cc",
+    "open-vcdiff/src/encodetable.h",
+    "open-vcdiff/src/google/output_string.h",
+    "open-vcdiff/src/google/vcdecoder.h",
+    "open-vcdiff/src/google/vcencoder.h",
+    "open-vcdiff/src/headerparser.cc",
+    "open-vcdiff/src/headerparser.h",
+    "open-vcdiff/src/instruction_map.cc",
+    "open-vcdiff/src/instruction_map.h",
+    "open-vcdiff/src/jsonwriter.cc",
+    "open-vcdiff/src/jsonwriter.h",
+    "open-vcdiff/src/rolling_hash.h",
+    "open-vcdiff/src/testing.h",
+    "open-vcdiff/src/varint_bigendian.cc",
+    "open-vcdiff/src/varint_bigendian.h",
+    "open-vcdiff/src/vcdecoder.cc",
+    "open-vcdiff/src/vcdiff_defs.h",
+    "open-vcdiff/src/vcdiffengine.cc",
+    "open-vcdiff/src/vcdiffengine.h",
+    "open-vcdiff/src/vcencoder.cc",
+    "open-vcdiff/vsprojects/config.h",
+    "open-vcdiff/vsprojects/stdint.h",
+  ]
+
+  public_configs = [ ":sdch_config" ]
+
+  deps = [
+    "//base",
+    "//third_party/zlib",
+  ]
+
+  # gn orders flags on a target before flags from configs. The default config
+  # adds -Wall, and these flags have to be after -Wall -- so they need to come
+  # from a config and can't be on the target directly.
+  config("sdch_warnings") {
+    cflags = []
+    if (is_linux) {
+      # TODO(mostynb): remove this if open-vcdiff is ever updated for c++11:
+      cflags += [ "-Wno-deprecated-declarations" ]
+    }
+
+    if (is_clang) {
+      # sdch uses the pre-c++11 typedef-as-static_assert hack.
+      # https://code.google.com/p/open-vcdiff/issues/detail?id=44
+      cflags += [ "-Wno-unused-local-typedef" ]
+    }
+  }
+  configs += [ ":sdch_warnings" ]
+
+  if (is_linux || is_android) {
+    include_dirs = [ "linux" ]
+  } else if (is_ios) {
+    include_dirs = [ "ios" ]
+  } else if (is_mac) {
+    include_dirs = [ "mac" ]
+  } else if (is_win) {
+    include_dirs = [ "win" ]
+  }
+
+  # open-vcdiff's logging.h introduces static initializers. This was
+  # reported upstream years ago (
+  # https://code.google.com/p/open-vcdiff/issues/detail?id=33 ). Since
+  # upstream won't fix this, work around it on the chromium side:
+  # Inject a header that forwards to base/logging.h instead (which doesn't
+  # introduce static initializers, and which prevents open-vcdiff's
+  # logging.h from being used).
+  if (is_win) {
+    cflags = [
+      "/FI",
+      "sdch/logging_forward.h",
+    ]
+  } else {
+    logging_file = rebase_path("logging_forward.h", root_build_dir)
+    cflags = [
+      "-include",
+      logging_file,
+    ]
+  }
+}
diff --git a/sdch/OWNERS b/sdch/OWNERS
new file mode 100644
index 0000000..b68fa81
--- /dev/null
+++ b/sdch/OWNERS
@@ -0,0 +1,3 @@
+jar@chromium.org
+mark@chromium.org
+wtc@chromium.org
diff --git a/sdch/README.chromium b/sdch/README.chromium
new file mode 100644
index 0000000..93ae6a0
--- /dev/null
+++ b/sdch/README.chromium
@@ -0,0 +1,19 @@
+The linux directory contains a config.h generated from a run of configure on
+Ubuntu 10.04.1 LTS x86_64, with VCDIFF_USE_BLOCK_COMPARE_WORDS manually
+changed to match the $host_cpu test in configure.
+
+The mac directory contains a config.h generated from a run of configure on a
+Mac, with VCDIFF_USE_BLOCK_COMPARE_WORDS manually changed to match the
+$host_cpu test in configure.
+
+The ios directory contains a config.h generated from a run of configure
+--host=arm-apple-darwin10 on a Mac with the following environment variables:
+  CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -x c -arch armv6
+  CFLAGS=-mno-thumb -miphoneos-version-min=4.2
+  CPPFLAGS=-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk
+  CXX=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -x c++ -arch armv6
+  CXXFLAGS=-mno-thumb -miphoneos-version-min=4.2
+
+The win directory contains a config.h that forwards to one provided with
+open-vcdiff. We have this to avoid putting open-vcdiff's minimal stdint.h hack
+into our include path.
diff --git a/sdch/bsd/config.h b/sdch/bsd/config.h
new file mode 100644
index 0000000..44417b4
--- /dev/null
+++ b/sdch/bsd/config.h
@@ -0,0 +1,113 @@
+/* src/config.h.  Generated by SCons.  */
+/* src/config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define to 1 if you have the <ext/rope> header file. */
+/* #undef HAVE_EXT_ROPE */
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+/* #undef HAVE_FNMATCH_H */
+
+/* Define to 1 if you have the <getopt.h> header file. */
+/* #undef HAVE_GETOPT_H */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the `memalign' function. */
+/* #undef HAVE_MEMALIGN */
+
+/* Define to 1 if you have the <memory.h> header file. */
+/* #undef HAVE_MEMORY_H */
+
+/* Define to 1 if you have the `mprotect' function. */
+/* #undef HAVE_MPROTECT */
+
+/* Define to 1 if you have the `posix_memalign' function. */
+/* #undef HAVE_POSIX_MEMALIGN */
+
+/* Define to 1 if you have the `QueryPerformanceCounter' function. */
+/* #undef HAVE_QUERYPERFORMANCECOUNTER */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+/* #undef HAVE_STDLIB_H */
+
+/* Define to 1 if you have the <strings.h> header file. */
+/* #undef HAVE_STRINGS_H */
+
+/* Define to 1 if you have the <string.h> header file. */
+/* #undef HAVE_STRING_H */
+
+/* Define to 1 if you have the `strtoll' function. */
+/* #undef HAVE_STRTOLL */
+
+/* Define to 1 if you have the `strtoq' function. */
+/* #undef HAVE_STRTOQ */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+/* #undef HAVE_SYS_MMAN_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+/* #undef HAVE_SYS_STAT_H */
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+/* #undef HAVE_SYS_TYPES_H */
+
+/* Define to 1 if the system has the type `uint16_t'. */
+/* #undef HAVE_UINT16_T */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+/* #undef HAVE_U_INT16_T */
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* define if your compiler has __attribute__ */
+/* #undef HAVE___ATTRIBUTE__ */
+
+/* Define to 1 if the system has the type `__int16'. */
+/* #undef HAVE___INT16 */
+
+/* Name of package */
+/* #undef PACKAGE */
+
+/* Define to the address where bug reports for this package should be sent. */
+/* #undef PACKAGE_BUGREPORT */
+
+/* Define to the full name of this package. */
+/* #undef PACKAGE_NAME */
+
+/* Define to the full name and version of this package. */
+/* #undef PACKAGE_STRING */
+
+/* Define to the one symbol short name of this package. */
+/* #undef PACKAGE_TARNAME */
+
+/* Define to the version of this package. */
+/* #undef PACKAGE_VERSION */
+
+/* Define to 1 if you have the ANSI C header files. */
+/* #undef STDC_HEADERS */
+
+/* Use custom compare function instead of memcmp */
+/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */
+
+/* Version number of package */
+/* #undef VERSION */
diff --git a/sdch/ios/config.h b/sdch/ios/config.h
new file mode 100644
index 0000000..5dde8c9
--- /dev/null
+++ b/sdch/ios/config.h
@@ -0,0 +1,113 @@
+/* src/config.h.  Generated from config.h.in by configure.  */
+/* src/config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <ext/rope> header file. */
+/* #undef HAVE_EXT_ROPE */
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the `memalign' function. */
+/* #undef HAVE_MEMALIGN */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mprotect' function. */
+#define HAVE_MPROTECT 1
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#define HAVE_POSIX_MEMALIGN 1
+
+/* Define to 1 if you have the `QueryPerformanceCounter' function. */
+/* #undef HAVE_QUERYPERFORMANCECOUNTER */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `strtoq' function. */
+#define HAVE_STRTOQ 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#define HAVE_UINT16_T 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+#define HAVE_U_INT16_T 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define to 1 if the system has the type `__int16'. */
+/* #undef HAVE___INT16 */
+
+/* Name of package */
+#define PACKAGE "open-vcdiff"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "open-vcdiff"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "open-vcdiff 0.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "open-vcdiff"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.7"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Use custom compare function instead of memcmp */
+/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */
+
+/* Version number of package */
+#define VERSION "0.7"
diff --git a/sdch/linux/config.h b/sdch/linux/config.h
new file mode 100644
index 0000000..3232eae
--- /dev/null
+++ b/sdch/linux/config.h
@@ -0,0 +1,119 @@
+/* src/config.h.  Generated from config.h.in by configure.  */
+/* src/config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <ext/rope> header file. */
+/* #undef HAVE_EXT_ROPE */
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* Manual edit: This is defined in AndroidConfig.h. */
+#undef HAVE_MALLOC_H
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the `memalign' function. */
+#define HAVE_MEMALIGN 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mprotect' function. */
+#define HAVE_MPROTECT 1
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#define HAVE_POSIX_MEMALIGN 1
+
+/* Define to 1 if you have the `QueryPerformanceCounter' function. */
+/* #undef HAVE_QUERYPERFORMANCECOUNTER */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `strtoq' function. */
+#define HAVE_STRTOQ 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#define HAVE_UINT16_T 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+#define HAVE_U_INT16_T 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define to 1 if the system has the type `__int16'. */
+/* #undef HAVE___INT16 */
+
+/* Name of package */
+#define PACKAGE "open-vcdiff"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "open-vcdiff"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "open-vcdiff 0.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "open-vcdiff"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.7"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Use custom compare function instead of memcmp */
+#if defined(__i386__) || defined(__x86_64__)
+#define VCDIFF_USE_BLOCK_COMPARE_WORDS 1
+#else
+/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */
+#endif
+
+/* Version number of package */
+#define VERSION "0.7"
diff --git a/sdch/logging_forward.h b/sdch/logging_forward.h
new file mode 100644
index 0000000..fc0d327
--- /dev/null
+++ b/sdch/logging_forward.h
@@ -0,0 +1,22 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SDCH_LOGGING_FORWARD_H_
+#define SDCH_LOGGING_FORWARD_H_
+
+// Define open-vcdiff's logging.h header guard, so that it doesn't get used.
+#define OPEN_VCDIFF_LOGGING_H_
+
+#include "base/logging.h"
+
+// open-vcdiff's logging.h includes iostream, which adds static initializers
+// to several compilation units. To prevent this, provide this replacement
+// header which forwards open-vcdiffs logging macros to chromium's base logging
+// mechanism.
+#define VCD_WARNING LOG(WARNING)
+#define VCD_ERROR LOG(ERROR)
+#define VCD_DFATAL LOG(DFATAL)
+#define VCD_ENDL "\n"
+
+#endif  // SDCH_LOGGING_FORWARD_H_
diff --git a/sdch/mac/config.h b/sdch/mac/config.h
new file mode 100644
index 0000000..e9ee90e
--- /dev/null
+++ b/sdch/mac/config.h
@@ -0,0 +1,117 @@
+/* src/config.h.  Generated from config.h.in by configure.  */
+/* src/config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <ext/rope> header file. */
+/* #undef HAVE_EXT_ROPE */
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the `memalign' function. */
+/* #undef HAVE_MEMALIGN */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mprotect' function. */
+#define HAVE_MPROTECT 1
+
+/* Define to 1 if you have the `posix_memalign' function. */
+/* #undef HAVE_POSIX_MEMALIGN */
+
+/* Define to 1 if you have the `QueryPerformanceCounter' function. */
+/* #undef HAVE_QUERYPERFORMANCECOUNTER */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `strtoq' function. */
+#define HAVE_STRTOQ 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#define HAVE_UINT16_T 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+#define HAVE_U_INT16_T 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define to 1 if the system has the type `__int16'. */
+/* #undef HAVE___INT16 */
+
+/* Name of package */
+#define PACKAGE "open-vcdiff"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "open-vcdiff"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "open-vcdiff 0.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "open-vcdiff"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.7"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Use custom compare function instead of memcmp */
+#if defined(__i386__) || defined(__x86_64__)
+#define VCDIFF_USE_BLOCK_COMPARE_WORDS 1
+#else
+/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */
+#endif
+
+/* Version number of package */
+#define VERSION "0.7"
diff --git a/sdch/sdch.gyp b/sdch/sdch.gyp
new file mode 100644
index 0000000..e886288
--- /dev/null
+++ b/sdch/sdch.gyp
@@ -0,0 +1,109 @@
+# 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.
+
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'targets': [
+    {
+      'target_name': 'sdch',
+      'type': 'static_library',
+      'dependencies': [
+        '../base/base.gyp:base',
+        '../third_party/zlib/zlib.gyp:zlib',
+      ],
+      'sources': [
+        'logging_forward.h',
+        'open-vcdiff/src/addrcache.cc',
+        'open-vcdiff/src/blockhash.cc',
+        'open-vcdiff/src/blockhash.h',
+        'open-vcdiff/src/checksum.h',
+        'open-vcdiff/src/codetable.cc',
+        'open-vcdiff/src/codetable.h',
+        'open-vcdiff/src/compile_assert.h',
+        'open-vcdiff/src/decodetable.cc',
+        'open-vcdiff/src/decodetable.h',
+        'open-vcdiff/src/encodetable.cc',
+        'open-vcdiff/src/encodetable.h',
+        'open-vcdiff/src/google/output_string.h',
+        'open-vcdiff/src/google/vcdecoder.h',
+        'open-vcdiff/src/google/vcencoder.h',
+        'open-vcdiff/src/headerparser.cc',
+        'open-vcdiff/src/headerparser.h',
+        'open-vcdiff/src/instruction_map.cc',
+        'open-vcdiff/src/instruction_map.h',
+        'open-vcdiff/src/jsonwriter.h',
+        'open-vcdiff/src/jsonwriter.cc',
+        'open-vcdiff/src/rolling_hash.h',
+        'open-vcdiff/src/testing.h',
+        'open-vcdiff/src/varint_bigendian.cc',
+        'open-vcdiff/src/varint_bigendian.h',
+        'open-vcdiff/src/vcdecoder.cc',
+        'open-vcdiff/src/vcencoder.cc',
+        'open-vcdiff/src/vcdiff_defs.h',
+        'open-vcdiff/src/vcdiffengine.cc',
+        'open-vcdiff/src/vcdiffengine.h',
+        'open-vcdiff/vsprojects/config.h',
+        'open-vcdiff/vsprojects/stdint.h',
+      ],
+      'include_dirs': [
+        'open-vcdiff/src',
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          'open-vcdiff/src',
+        ],
+      },
+      'conditions': [
+        [ 'OS == "linux" or OS == "android"', { 'include_dirs': [ 'linux' ] } ],
+        [ 'os_bsd==1 or OS=="solaris"', { 'include_dirs': [ 'bsd' ] } ],
+        [ 'OS == "ios"', { 'include_dirs': [ 'ios' ] } ],
+        [ 'OS == "mac"', { 'include_dirs': [ 'mac' ] } ],
+        [ 'OS == "win"', { 'include_dirs': [ 'win' ] } ],
+      ],
+      # open-vcdiff's logging.h introduces static initializers. This was
+      # reported upstream years ago (
+      # https://code.google.com/p/open-vcdiff/issues/detail?id=33 ). Since
+      # upstream won't fix this, work around it on the chromium side:
+      # Inject a header that forwards to base/logging.h instead (which doesn't
+      # introduce static initializers, and which prevents open-vcdiff's
+      # logging.h from being used).
+      'variables': {
+        'clang_warning_flags': [
+          # sdch uses the pre-c++11 typedef-as-static_assert hack.
+          # https://code.google.com/p/open-vcdiff/issues/detail?id=44
+          '-Wno-unused-local-typedef',
+        ],
+        'logging_path': 'logging_forward.h',
+        'conditions': [
+          # gyp leaves unspecified what the cwd is when running the compiler,
+          # and gyp/linux doesn't have a built-in way for forcing an include.
+          # So hardcode the base directory. If this spreads, provide native
+          # support in gyp, like we have for gyp/mac and gyp/windows.
+          # path.
+          ['"<(GENERATOR)"=="ninja"', { 'logging_dir': '../..' },
+                                      { 'logging_dir': '.' }
+          ],
+        ],
+      },
+      # GCC_PREFIX_HEADER is relative to the current directory,
+      # ForcedIncludeFiles is relative to include_dirs, cflags relative to the
+      # build directory.
+      'xcode_settings': { 'GCC_PREFIX_HEADER': '<(logging_path)' },
+      'msvs_settings': {
+        'VCCLCompilerTool': {
+          'ForcedIncludeFiles': [
+            'sdch/<(logging_path)',
+          ]
+        }
+      },
+      'cflags': [
+        '-include', '<(logging_dir)/sdch/<(logging_path)',
+        # TODO(mostynb): remove this if open-vcdiff is ever updated for c++11:
+        '-Wno-deprecated-declarations',
+      ],
+    },
+  ],
+}
diff --git a/sdch/win/config.h b/sdch/win/config.h
new file mode 100644
index 0000000..b5fb37c
--- /dev/null
+++ b/sdch/win/config.h
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file and directory exist so that we can use the provided config.h
+// without putting vsprojects into our include path (which would also give us an
+// incorrect/incompatible stdint.h).
+
+#ifndef SDCH_WIN_CONFIG_H_
+#define SDCH_WIN_CONFIG_H_
+
+#include "../open-vcdiff/vsprojects/config.h"
+
+#endif  // SDCH_WIN_CONFIG_H_
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 472a8cf..2357a7f 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -116,9 +116,6 @@
     "//third_party/skia/include/pipe",
     "//third_party/skia/include/ports",
     "//third_party/skia/include/utils",
-
-    # need to move this to internal. see crbug.com/457691
-    "//third_party/skia/src/core",
   ]
 
   defines = gypi_skia_defines.skia_for_chromium_defines
@@ -126,7 +123,10 @@
   defines += []
 
   if (component_mode == "shared_library") {
-    defines += [ "SKIA_DLL" ]
+    defines += [
+      "SKIA_DLL",
+      "GR_GL_IGNORE_ES3_MSAA=0",
+    ]
   }
 
   if (skia_support_gpu) {
@@ -157,6 +157,7 @@
   # exported to dependents. It's not clear if this is on purpose, but this
   # matches the GYP build.
   include_dirs = [
+    "//third_party/skia/src/core",
     "//third_party/skia/src/image",
     "//third_party/skia/src/opts",
     "//third_party/skia/src/pdf",
@@ -231,7 +232,12 @@
       "//third_party/skia/src/utils/win",
     ]
 
-    defines += [ "SK_FONTHOST_USES_FONTMGR" ]
+    defines += [
+      # On windows, GDI handles are a scarse system-wide resource so we have to
+      # keep the glyph cache, which holds up to 4 GDI handles per entry, to a
+      # fairly small size. http://crbug.com/314387
+      "SK_DEFAULT_FONT_CACHE_COUNT_LIMIT=256",
+    ]
 
     cflags = [
       "/wd4244",  # conversion from 'type1( __int64)' to 'type2 (unsigned int)'
@@ -242,6 +248,7 @@
       "/wd4554",  # 'operator' : check operator precedence for possible error
       "/wd4748",  # compiler will disable optimizations if a function has inline
                   # assembly code contains flow control(jmp or jcc) statements.
+
       "/wd4800",  # forcing value to bool 'true/false'(assigning int to bool).
     ]
   }
@@ -486,14 +493,6 @@
     "//third_party/zlib",
   ]
 
-  if (is_win) {
-    configs -= [
-      # Some files define WIN32_LEAN_AND_MEAN and we want to avoid a duplicate
-      # definition warning.
-      "//build/config/win:lean_and_mean",
-    ]
-  }
-
   if (is_linux) {
     configs += [
       "//build/config/linux:fontconfig",
@@ -617,3 +616,28 @@
     "//ui/gfx/geometry",
   ]
 }
+
+if (is_linux && !is_chromeos) {
+  # TODO(GYP): Figure out which of these work and are needed on other platforms.
+  executable("image_operations_bench") {
+    sources = [
+      "ext/image_operations_bench.cc",
+    ]
+
+    deps = [
+      ":skia",
+      "//base",
+    ]
+  }
+
+  executable("filter_fuzz_stub") {
+    sources = [
+      "tools/filter_fuzz_stub/filter_fuzz_stub.cc",
+    ]
+
+    deps = [
+      ":skia",
+      "//base",
+    ]
+  }
+}
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index d9b6297..6369e34 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -261,10 +261,6 @@
 #   define SK_IGNORE_GPU_DITHER
 #endif
 
-#ifndef SK_SUPPORT_LEGACY_ADDOVAL
-#   define SK_SUPPORT_LEGACY_ADDOVAL
-#endif
-
 #ifndef    SK_LEGACY_STROKE_CURVES
 #   define SK_LEGACY_STROKE_CURVES
 #endif
diff --git a/skia/ext/SkDiscardableMemory_chrome.cc b/skia/ext/SkDiscardableMemory_chrome.cc
index 7103100..50e7f2e 100644
--- a/skia/ext/SkDiscardableMemory_chrome.cc
+++ b/skia/ext/SkDiscardableMemory_chrome.cc
@@ -7,17 +7,7 @@
 SkDiscardableMemoryChrome::~SkDiscardableMemoryChrome() {}
 
 bool SkDiscardableMemoryChrome::lock() {
-  const base::DiscardableMemoryLockStatus status = discardable_->Lock();
-  switch (status) {
-    case base::DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS:
-      return true;
-    case base::DISCARDABLE_MEMORY_LOCK_STATUS_PURGED:
-      discardable_->Unlock();
-      return false;
-    default:
-      discardable_.reset();
-      return false;
-  }
+  return discardable_->Lock();
 }
 
 void* SkDiscardableMemoryChrome::data() {
@@ -34,9 +24,6 @@
 }
 
 SkDiscardableMemory* SkDiscardableMemory::Create(size_t bytes) {
-  scoped_ptr<base::DiscardableMemory> discardable(
+  return new SkDiscardableMemoryChrome(
       base::DiscardableMemory::CreateLockedMemory(bytes));
-  if (!discardable)
-    return NULL;
-  return new SkDiscardableMemoryChrome(discardable.Pass());
 }
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc
index fe447c7..0ff1660 100644
--- a/skia/ext/analysis_canvas.cc
+++ b/skia/ext/analysis_canvas.cc
@@ -418,7 +418,7 @@
   SkXfermode::Mode xfermode = SkXfermode::kSrc_Mode;
   if (paint)
     SkXfermode::AsMode(paint->getXfermode(), &xfermode);
-  if (xfermode != SkXfermode::kSrc_Mode) {
+  if (xfermode != SkXfermode::kDst_Mode) {
     if (force_not_transparent_stack_level_ == kNoLayer) {
       force_not_transparent_stack_level_ = saved_stack_size_;
       SetForceNotTransparent(true);
diff --git a/skia/ext/analysis_canvas_unittest.cc b/skia/ext/analysis_canvas_unittest.cc
index 5bb18eb..8263075 100644
--- a/skia/ext/analysis_canvas_unittest.cc
+++ b/skia/ext/analysis_canvas_unittest.cc
@@ -222,6 +222,49 @@
   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
 }
 
+TEST(AnalysisCanvasTest, SaveLayerWithXfermode) {
+  skia::AnalysisCanvas canvas(255, 255);
+  SkRect bounds = SkRect::MakeWH(255, 255);
+  SkColor outputColor;
+
+  EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
+  EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
+  SkPaint paint;
+
+  // Note: nothing is draw to the the save layer, but solid color
+  // and transparency are handled conservatively in case the layer's
+  // SkPaint draws something. For example, there could be an
+  // SkPictureImageFilter. If someday analysis_canvas starts doing
+  // a deeper analysis of the SkPaint, this test may need to be
+  // redesigned.
+  TransparentFill(canvas);
+  EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
+  EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
+  paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+  canvas.saveLayer(&bounds, &paint);
+  canvas.restore();
+  EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
+
+  TransparentFill(canvas);
+  EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
+  EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
+  paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+  canvas.saveLayer(&bounds, &paint);
+  canvas.restore();
+  EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
+
+  // Layer with dst xfermode is a no-op, so this is the only case
+  // where solid color is unaffected by the layer.
+  TransparentFill(canvas);
+  EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
+  EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
+  paint.setXfermodeMode(SkXfermode::kDst_Mode);
+  canvas.saveLayer(&bounds, &paint);
+  canvas.restore();
+  EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
+  EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
+}
+
 TEST(AnalysisCanvasTest, SaveLayerRestore) {
   skia::AnalysisCanvas canvas(255, 255);
 
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc
index 0dd6949..dbe851a 100644
--- a/skia/ext/benchmarking_canvas.cc
+++ b/skia/ext/benchmarking_canvas.cc
@@ -8,8 +8,10 @@
 #include "skia/ext/benchmarking_canvas.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
+#include "third_party/skia/include/core/SkTLazy.h"
 #include "third_party/skia/include/core/SkPicture.h"
 #include "third_party/skia/include/core/SkRegion.h"
+#include "third_party/skia/include/core/SkString.h"
 #include "third_party/skia/include/core/SkTextBlob.h"
 #include "third_party/skia/include/core/SkXfermode.h"
 
@@ -406,6 +408,47 @@
   return val.Pass();
 }
 
+class OverdrawXfermode : public SkXfermode {
+public:
+  SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override {
+    // This table encodes the color progression of the overdraw visualization
+    static const SkPMColor gTable[] = {
+      SkPackARGB32(0x00, 0x00, 0x00, 0x00),
+      SkPackARGB32(0xFF, 128, 158, 255),
+      SkPackARGB32(0xFF, 170, 185, 212),
+      SkPackARGB32(0xFF, 213, 195, 170),
+      SkPackARGB32(0xFF, 255, 192, 127),
+      SkPackARGB32(0xFF, 255, 185, 85),
+      SkPackARGB32(0xFF, 255, 165, 42),
+      SkPackARGB32(0xFF, 255, 135, 0),
+      SkPackARGB32(0xFF, 255,  95, 0),
+      SkPackARGB32(0xFF, 255,  50, 0),
+      SkPackARGB32(0xFF, 255,  0, 0)
+    };
+
+    size_t idx;
+    if (SkColorGetR(dst) < 64) { // 0
+      idx = 0;
+    } else if (SkColorGetG(dst) < 25) { // 10
+      idx = 9;  // cap at 9 for upcoming increment
+    } else if ((SkColorGetB(dst) + 21) / 42 > 0) { // 1-6
+      idx = 7 - (SkColorGetB(dst) + 21) / 42;
+    } else { // 7-9
+      idx = 10 - (SkColorGetG(dst) + 22) / 45;
+    }
+
+    ++idx;
+    SkASSERT(idx < SK_ARRAY_COUNT(gTable));
+
+    return gTable[idx];
+  }
+
+  Factory getFactory() const override { return NULL; }
+#ifndef SK_IGNORE_TO_STRING
+  void toString(SkString* str) const override { str->set("OverdrawXfermode"); }
+#endif
+};
+
 } // namespace
 
 namespace skia {
@@ -416,7 +459,10 @@
          const SkPaint* paint = nullptr)
       : canvas_(canvas)
       , op_record_(new base::DictionaryValue())
-      , op_params_(new base::ListValue()) {
+      , op_params_(new base::ListValue())
+      // AutoOp objects are always scoped within draw call frames,
+      // so the paint is guaranteed to be valid for their lifetime.
+      , paint_(paint) {
 
     DCHECK(canvas);
     DCHECK(op_name);
@@ -427,6 +473,14 @@
     if (paint)
       this->addParam("paint", AsValue(*paint));
 
+    if (canvas->flags_ & kOverdrawVisualization_Flag) {
+      DCHECK(canvas->overdraw_xfermode_);
+
+      paint_ = paint ? filtered_paint_.set(*paint) : filtered_paint_.init();
+      filtered_paint_.get()->setXfermode(canvas->overdraw_xfermode_.get());
+      filtered_paint_.get()->setAntiAlias(false);
+    }
+
     start_ticks_ = base::TimeTicks::Now();
   }
 
@@ -444,11 +498,16 @@
     op_params_->Append(param.release());
   }
 
+  const SkPaint* paint() const { return paint_; }
+
 private:
   BenchmarkingCanvas* canvas_;
   base::DictionaryValue* op_record_;
   base::ListValue* op_params_;
   base::TimeTicks start_ticks_;
+
+  const SkPaint* paint_;
+  SkTLazy<SkPaint> filtered_paint_;
 };
 
 BenchmarkingCanvas::BenchmarkingCanvas(SkCanvas* canvas, unsigned flags)
@@ -456,6 +515,9 @@
                 canvas->imageInfo().height())
     , flags_(flags) {
   addCanvas(canvas);
+
+  if (flags & kOverdrawVisualization_Flag)
+    overdraw_xfermode_ = AdoptRef(new OverdrawXfermode);
 }
 
 BenchmarkingCanvas::~BenchmarkingCanvas() {
@@ -493,12 +555,10 @@
   AutoOp op(this, "SaveLayer", paint);
   if (rect)
     op.addParam("bounds", AsValue(*rect));
-  if (paint)
-    op.addParam("paint", AsValue(*paint));
   if (flags)
     op.addParam("flags", AsValue(flags));
 
-  return INHERITED::willSaveLayer(rect, paint, flags);
+  return INHERITED::willSaveLayer(rect, op.paint(), flags);
 }
 
 void BenchmarkingCanvas::willRestore() {
@@ -566,7 +626,7 @@
 void BenchmarkingCanvas::onDrawPaint(const SkPaint& paint) {
   AutoOp op(this, "DrawPaint", &paint);
 
-  INHERITED::onDrawPaint(paint);
+  INHERITED::onDrawPaint(*op.paint());
 }
 
 void BenchmarkingCanvas::onDrawPoints(PointMode mode, size_t count,
@@ -575,28 +635,28 @@
   op.addParam("mode", AsValue(mode));
   op.addParam("points", AsListValue(pts, count));
 
-  INHERITED::onDrawPoints(mode, count, pts, paint);
+  INHERITED::onDrawPoints(mode, count, pts, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
   AutoOp op(this, "DrawRect", &paint);
   op.addParam("rect", AsValue(rect));
 
-  INHERITED::onDrawRect(rect, paint);
+  INHERITED::onDrawRect(rect, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
   AutoOp op(this, "DrawOval", &paint);
   op.addParam("rect", AsValue(rect));
 
-  INHERITED::onDrawOval(rect, paint);
+  INHERITED::onDrawOval(rect, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
   AutoOp op(this, "DrawRRect", &paint);
   op.addParam("rrect", AsValue(rrect));
 
-  INHERITED::onDrawRRect(rrect, paint);
+  INHERITED::onDrawRRect(rrect, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
@@ -605,14 +665,14 @@
   op.addParam("outer", AsValue(outer));
   op.addParam("inner", AsValue(inner));
 
-  INHERITED::onDrawDRRect(outer, inner, paint);
+  INHERITED::onDrawDRRect(outer, inner, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
   AutoOp op(this, "DrawPath", &paint);
   op.addParam("path", AsValue(path));
 
-  INHERITED::onDrawPath(path, paint);
+  INHERITED::onDrawPath(path, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawPicture(const SkPicture* picture,
@@ -624,7 +684,7 @@
   if (matrix)
     op.addParam("matrix", AsValue(*matrix));
 
-  INHERITED::drawPicture(picture, matrix, paint);
+  INHERITED::onDrawPicture(picture, matrix, op.paint());
 }
 
 void BenchmarkingCanvas::onDrawBitmap(const SkBitmap& bitmap,
@@ -636,7 +696,7 @@
   op.addParam("left", AsValue(left));
   op.addParam("top", AsValue(top));
 
-  INHERITED::onDrawBitmap(bitmap, left, top, paint);
+  INHERITED::onDrawBitmap(bitmap, left, top, op.paint());
 }
 
 void BenchmarkingCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
@@ -650,7 +710,7 @@
     op.addParam("src", AsValue(*src));
   op.addParam("dst", AsValue(dst));
 
-  INHERITED::onDrawBitmapRect(bitmap, src, dst, paint, flags);
+  INHERITED::onDrawBitmapRect(bitmap, src, dst, op.paint(), flags);
 }
 
 void BenchmarkingCanvas::onDrawImage(const SkImage* image,
@@ -663,7 +723,7 @@
   op.addParam("left", AsValue(left));
   op.addParam("top", AsValue(top));
 
-  INHERITED::onDrawImage(image, left, top, paint);
+  INHERITED::onDrawImage(image, left, top, op.paint());
 }
 
 void BenchmarkingCanvas::onDrawImageRect(const SkImage* image, const SkRect* src,
@@ -675,7 +735,7 @@
     op.addParam("src", AsValue(*src));
   op.addParam("dst", AsValue(dst));
 
-  INHERITED::onDrawImageRect(image, src, dst, paint);
+  INHERITED::onDrawImageRect(image, src, dst, op.paint());
 }
 
 void BenchmarkingCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
@@ -687,7 +747,7 @@
   op.addParam("center", AsValue(SkRect::Make(center)));
   op.addParam("dst", AsValue(dst));
 
-  INHERITED::onDrawBitmapNine(bitmap, center, dst, paint);
+  INHERITED::onDrawBitmapNine(bitmap, center, dst, op.paint());
 }
 
 void BenchmarkingCanvas::onDrawSprite(const SkBitmap& bitmap, int left, int top,
@@ -697,7 +757,7 @@
   op.addParam("left", AsValue(SkIntToScalar(left)));
   op.addParam("top", AsValue(SkIntToScalar(top)));
 
-  INHERITED::onDrawSprite(bitmap, left, top, paint);
+  INHERITED::onDrawSprite(bitmap, left, top, op.paint());
 }
 
 void BenchmarkingCanvas::onDrawText(const void* text, size_t byteLength,
@@ -708,7 +768,7 @@
   op.addParam("x", AsValue(x));
   op.addParam("y", AsValue(y));
 
-  INHERITED::onDrawText(text, byteLength, x, y, paint);
+  INHERITED::onDrawText(text, byteLength, x, y, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawPosText(const void* text, size_t byteLength,
@@ -719,7 +779,7 @@
   op.addParam("count", AsValue(SkIntToScalar(count)));
   op.addParam("pos", AsListValue(pos, count));
 
-  INHERITED::onDrawPosText(text, byteLength, pos, paint);
+  INHERITED::onDrawPosText(text, byteLength, pos, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawPosTextH(const void* text, size_t byteLength,
@@ -732,7 +792,7 @@
   op.addParam("count", AsValue(SkIntToScalar(count)));
   op.addParam("pos", AsListValue(xpos, count));
 
-  INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, paint);
+  INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawTextOnPath(const void* text, size_t byteLength,
@@ -744,7 +804,7 @@
   if (matrix)
     op.addParam("matrix", AsValue(*matrix));
 
-  INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint);
+  INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, *op.paint());
 }
 
 void BenchmarkingCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
@@ -755,7 +815,7 @@
   op.addParam("x", AsValue(x));
   op.addParam("y", AsValue(y));
 
-  INHERITED::onDrawTextBlob(blob, x, y, paint);
+  INHERITED::onDrawTextBlob(blob, x, y, *op.paint());
 }
 
 } // namespace skia
diff --git a/skia/ext/benchmarking_canvas.h b/skia/ext/benchmarking_canvas.h
index 4f2e257..a33c42d 100644
--- a/skia/ext/benchmarking_canvas.h
+++ b/skia/ext/benchmarking_canvas.h
@@ -6,8 +6,11 @@
 #define SKIA_EXT_BENCHMARKING_CANVAS_H_
 
 #include "base/values.h"
+#include "skia/ext/refptr.h"
 #include "third_party/skia/include/utils/SkNWayCanvas.h"
 
+class SkXfermode;
+
 namespace skia {
 
 class SK_API BenchmarkingCanvas : public SkNWayCanvas {
@@ -16,8 +19,6 @@
   ~BenchmarkingCanvas() override;
 
   enum Flags {
-      // TODO(fmalita): add overdraw visualization support
-      // (http://crbug.com/461534)
       kOverdrawVisualization_Flag = 0x01,
   };
 
@@ -85,6 +86,7 @@
 
   base::ListValue op_records_;
   unsigned flags_;
+  RefPtr<SkXfermode> overdraw_xfermode_;
 };
 
 }
diff --git a/skia/skia_gn_files.gypi b/skia/skia_gn_files.gypi
index f066bc5..ae99261 100644
--- a/skia/skia_gn_files.gypi
+++ b/skia/skia_gn_files.gypi
@@ -42,12 +42,6 @@
     '<(skia_src_path)/sfnt/SkOTTable_name.h',
     '<(skia_src_path)/sfnt/SkOTUtils.cpp',
     '<(skia_src_path)/sfnt/SkOTUtils.h',
-    '<(skia_src_path)/utils/debugger/SkDebugCanvas.cpp',
-    '<(skia_src_path)/utils/debugger/SkDebugCanvas.h',
-    '<(skia_src_path)/utils/debugger/SkDrawCommand.cpp',
-    '<(skia_src_path)/utils/debugger/SkDrawCommand.h',
-    '<(skia_src_path)/utils/debugger/SkObjectParser.cpp',
-    '<(skia_src_path)/utils/debugger/SkObjectParser.h',
 
     #mac
     '<(skia_src_path)/utils/mac/SkStream_mac.cpp',
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi
index 04e428a..b138e4d 100644
--- a/skia/skia_library.gypi
+++ b/skia/skia_library.gypi
@@ -68,13 +68,6 @@
     '../third_party/skia/src/sfnt/SkOTUtils.cpp',
     '../third_party/skia/src/sfnt/SkOTUtils.h',
 
-    '../third_party/skia/src/utils/debugger/SkDebugCanvas.cpp',
-    '../third_party/skia/src/utils/debugger/SkDebugCanvas.h',
-    '../third_party/skia/src/utils/debugger/SkDrawCommand.cpp',
-    '../third_party/skia/src/utils/debugger/SkDrawCommand.h',
-    '../third_party/skia/src/utils/debugger/SkObjectParser.cpp',
-    '../third_party/skia/src/utils/debugger/SkObjectParser.h',
-
     '../third_party/skia/include/core/SkFontStyle.h',
 
     '../third_party/skia/include/images/SkMovie.h',
@@ -360,9 +353,6 @@
 
   'direct_dependent_settings': {
     'include_dirs': [
-      #temporary until we can hide SkFontHost
-      '../third_party/skia/src/core',
-
       '../third_party/skia/include/core',
       '../third_party/skia/include/effects',
       '../third_party/skia/include/pdf',
diff --git a/skia/skia_test_expectations.txt b/skia/skia_test_expectations.txt
index 5927d5c..4327f6e 100644
--- a/skia/skia_test_expectations.txt
+++ b/skia/skia_test_expectations.txt
@@ -48,7 +48,4 @@
 #
 # START OVERRIDES HERE
 
-# We fixed a blending bug.
-crbug.com/459579 virtual/gpu/fast/canvas/canvas-composite-transformclip.html [ ImageOnlyFailure ]
-
 # END OVERRIDES HERE (this line ensures that the file is newline-terminated)
diff --git a/sky/tests/TestExpectations b/sky/tests/TestExpectations
index 4b6c6c6..0e4f586 100644
--- a/sky/tests/TestExpectations
+++ b/sky/tests/TestExpectations
@@ -41,3 +41,8 @@
 crbug.com/2 modules/script-import.sky [ Skip ]
 crbug.com/2 parser/script.sky [ Skip ]
 crbug.com/2 services/iframe-service-provider.sky [ Skip ]
+
+# Started failing on DEPS roll.
+# https://codereview.chromium.org/1001833005/
+https://github.com/domokit/mojo/issues/64 framework/flights-app-pixels.sky [ Skip ]
+https://github.com/domokit/mojo/issues/64 lowlevel/layers.sky [ Skip ]
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 71e67ad..a839c45 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -338,7 +338,7 @@
       { "test": "content_unittests", "args": ["--site-per-process"] },
       { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] },
       { "test": "unit_tests", "args": ["--site-per-process"] },
-      { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*"] }
+      { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] }
     ]
   },
   "Site Isolation Win": {
@@ -346,7 +346,7 @@
       { "test": "content_unittests", "args": ["--site-per-process"] },
       { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] },
       { "test": "unit_tests", "args": ["--site-per-process"] },
-      { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*"] }
+      { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] }
     ]
   },
   "Browser Side Navigation Linux": {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 6e748c7..e9f616a 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -41,20 +41,10 @@
   },
   "Mac 10.8 Perf (1)": {
     "scripts": [
-      {
-	"name": "gpu_perftests",
-	"script": "gtest_perf_test.py",
-	"args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
-      }
     ]
   },
   "Mac 10.9 Perf (1)": {
     "scripts": [
-      {
-	"name": "gpu_perftests",
-	"script": "gtest_perf_test.py",
-	"args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"]
-      }
     ]
   }
 }
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json
index a469ddd..ed45362 100644
--- a/testing/buildbot/trybot_analyze_config.json
+++ b/testing/buildbot/trybot_analyze_config.json
@@ -11,6 +11,7 @@
       "build/linux/sysroot_ld_path.sh",
       "DEPS",
       "testing/buildbot/.*",
+      "testing/test_env.py",
       "tools/clang/blink_gc_plugin/CMakeLists.txt",
       "tools/whitespace.txt"
     ]
@@ -34,7 +35,6 @@
       "third_party/accessibility-audit/axs_testing.js",
       "third_party/hunspell_dictionaries/.*",
       "third_party/zlib/google/test/data/.*",
-      "tools/clang/scripts/plugin_flags.py",
       "tools/clang/scripts/update.py",
       "tools/clang/scripts/update.sh",
       "tools/metrics/histograms/histograms.xml",
diff --git a/testing/chromoting/chromoting_integration_tests.isolate b/testing/chromoting/chromoting_integration_tests.isolate
index 82bf5f1..8dcbe5d 100644
--- a/testing/chromoting/chromoting_integration_tests.isolate
+++ b/testing/chromoting/chromoting_integration_tests.isolate
@@ -68,6 +68,7 @@
         'files': [
           '<(PRODUCT_DIR)/chrome_elf.dll',
           '<(PRODUCT_DIR)/ffmpegsumo.dll',
+          '<(PRODUCT_DIR)/libglesv2.dll',
         ],
       },
     }],
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json
index a335f78..6ca3384 100644
--- a/testing/commit_queue/config.json
+++ b/testing/commit_queue/config.json
@@ -6,11 +6,12 @@
                 "launched": {
                     "tryserver.chromium.linux": {
                         "android_amp_rel_tests_recipe": ["defaulttests"],
+                        "android_n5_rel_tests_recipe": ["defaulttests"],
                         "cast_shell": ["defaulttests"],
                         "cast_shell_apk": ["defaulttests"],
-                        "linux_android_rel_ng": ["defaulttests"],
                         "linux_arm_compile": ["defaulttests"],
-                        "linux_chromium_asan_rel_ng": ["defaulttests"]
+                        "linux_chromium_asan_rel_ng": ["defaulttests"],
+                        "linux_chromium_chromeos_ozone_rel_ng": ["defaulttests"]
                     },
                     "tryserver.chromium.mac": {
                         "mac_chromium_gn_rel": ["defaulttests"]
@@ -59,6 +60,7 @@
               "android_chromium_gn_compile_rel": ["defaulttests"],
               "android_compile_rel": ["defaulttests"],
               "chromium_presubmit": ["defaulttests"],
+              "linux_android_rel_ng": ["defaulttests"],
               "linux_chromium_asan_rel": ["defaulttests"],
               "linux_chromium_chromeos_compile_dbg_ng": ["defaulttests"],
               "linux_chromium_chromeos_rel_ng": ["defaulttests"],
@@ -67,7 +69,6 @@
               "linux_chromium_gn_dbg": ["defaulttests"],
               "linux_chromium_gn_rel": ["defaulttests"],
               "linux_chromium_rel_ng": ["defaulttests"],
-              "android_rel_tests_recipe": ["defaulttests"],
               "android_arm64_dbg_recipe": ["defaulttests"],
               "android_clang_dbg_recipe": ["defaulttests"],
               "android_aosp": ["compile"],
diff --git a/testing/legion/examples/subprocess/subprocess_test.py b/testing/legion/examples/subprocess/subprocess_test.py
index 0377800..1a28ddd 100755
--- a/testing/legion/examples/subprocess/subprocess_test.py
+++ b/testing/legion/examples/subprocess/subprocess_test.py
@@ -32,7 +32,7 @@
 
     self.task = self.CreateNewTask(
         isolated_hash=args.task_hash,
-        dimensions={'os': 'Ubuntu-14.04', 'pool': 'Legion'},
+        dimensions={'os': 'Ubuntu-14.04', 'pool': 'Chromoting'},
         idle_timeout_secs=90, connection_timeout_secs=90,
         verbosity=logging.DEBUG)
     self.task.Create()
@@ -47,8 +47,10 @@
   def TestMultipleProcesses(self):
     start = time.time()
 
-    sleep20 = self.task.rpc.subprocess.Popen(['sleep', '20'])
-    sleep10 = self.task.rpc.subprocess.Popen(['sleep', '10'])
+    sleep20 = self.task.rpc.subprocess.Process(['sleep', '20'])
+    self.task.rpc.subprocess.Start(sleep20)
+    sleep10 = self.task.rpc.subprocess.Process(['sleep', '10'])
+    self.task.rpc.subprocess.Start(sleep10)
 
     self.task.rpc.subprocess.Wait(sleep10)
     elapsed = time.time() - start
@@ -63,16 +65,20 @@
 
   def TestTerminate(self):
     start = time.time()
-    proc = self.task.rpc.subprocess.Popen(['sleep', '20'])
-    self.task.rpc.subprocess.Terminate(proc)  # Implicitly deleted
+    proc = self.task.rpc.subprocess.Process(['sleep', '20'])
+    self.task.rpc.subprocess.Start(proc)
+    self.task.rpc.subprocess.Terminate(proc)
     try:
       self.task.rpc.subprocess.Wait(proc)
     except xmlrpclib.Fault:
       pass
+    finally:
+      self.task.rpc.subprocess.Delete(proc)
     assert time.time() - start < 20
 
   def TestLs(self):
-    proc = self.task.rpc.subprocess.Popen(['ls'])
+    proc = self.task.rpc.subprocess.Process(['ls'])
+    self.task.rpc.subprocess.Start(proc)
     self.task.rpc.subprocess.Wait(proc)
     assert self.task.rpc.subprocess.GetReturncode(proc) == 0
     assert 'task.isolate' in self.task.rpc.subprocess.ReadStdout(proc)
diff --git a/testing/legion/rpc_methods.py b/testing/legion/rpc_methods.py
index 7f17e23..1a59f28 100644
--- a/testing/legion/rpc_methods.py
+++ b/testing/legion/rpc_methods.py
@@ -41,6 +41,10 @@
     logging.info('Echoing %s', message)
     return 'echo %s' % str(message)
 
+  def AbsPath(self, path):
+    """Returns the absolute path."""
+    return os.path.abspath(path)
+
   def Quit(self):
     """Call _server.shutdown in another thread.
 
@@ -58,6 +62,10 @@
   This non-blocking subprocess allows the caller to continue operating while
   also able to interact with this subprocess based on a key returned to
   the caller at the time of creation.
+
+  Creation args are set via Set* methods called after calling Process but
+  before calling Start. This is due to a limitation of the XML-RPC
+  implementation not supporting keyword arguments.
   """
 
   _processes = {}
@@ -65,23 +73,38 @@
   _creation_lock = threading.Lock()
 
   def __init__(self, cmd):
-    self.proc = subprocess42.Popen(cmd, stdout=subprocess42.PIPE,
-                                   stderr=subprocess42.PIPE)
     self.stdout = ''
     self.stderr = ''
+    self.cmd = cmd
+    self.proc = None
+    self.cwd = None
+    self.verbose = False
+    self.detached = False
     self.data_lock = threading.Lock()
-    threading.Thread(target=self._run).start()
 
-  def _run(self):
+  def __str__(self):
+    return '%r, cwd=%r, verbose=%r, detached=%r' % (
+        self.cmd, self.cwd, self.verbose, self.detached)
+
+  def _reader(self):
     for pipe, data in self.proc.yield_any():
       with self.data_lock:
         if pipe == 'stdout':
           self.stdout += data
+          if self.verbose:
+            sys.stdout.write(data)
         else:
           self.stderr += data
+          if self.verbose:
+            sys.stderr.write(data)
 
   @classmethod
-  def Popen(cls, cmd):
+  def KillAll(cls):
+    for key in cls._processes:
+      cls.Kill(key)
+
+  @classmethod
+  def Process(cls, cmd):
     with cls._creation_lock:
       key = 'Process%d' % cls._process_next_id
       cls._process_next_id += 1
@@ -90,18 +113,50 @@
     cls._processes[key] = process
     return key
 
+  def _Start(self):
+    logging.info('Starting process %s', self)
+    self.proc = subprocess42.Popen(self.cmd, stdout=subprocess42.PIPE,
+                                   stderr=subprocess42.PIPE,
+                                   detached=self.detached, cwd=self.cwd)
+    threading.Thread(target=self._reader).start()
+
+  @classmethod
+  def Start(cls, key):
+    cls._processes[key]._Start()
+
+  @classmethod
+  def SetCwd(cls, key, cwd):
+    """Sets the process's cwd."""
+    logging.debug('Setting %s cwd to %s', key, cwd)
+    cls._processes[key].cwd = cwd
+
+  @classmethod
+  def SetDetached(cls, key):
+    """Creates a detached process."""
+    logging.debug('Setting %s to run detached', key)
+    cls._processes[key].detached = True
+
+  @classmethod
+  def SetVerbose(cls, key):
+    """Sets the stdout and stderr to be emitted locally."""
+    logging.debug('Setting %s to be verbose', key)
+    cls._processes[key].verbose = True
+
   @classmethod
   def Terminate(cls, key):
-    logging.debug('Terminating and deleting process %s', key)
-    return cls._processes.pop(key).proc.terminate()
+    logging.debug('Terminating process %s', key)
+    cls._processes[key].proc.terminate()
 
   @classmethod
   def Kill(cls, key):
-    logging.debug('Killing and deleting process %s', key)
-    return cls._processes.pop(key).proc.kill()
+    logging.debug('Killing process %s', key)
+    cls._processes[key].proc.kill()
 
   @classmethod
   def Delete(cls, key):
+    if cls.GetReturncode(key) is None:
+      logging.warning('Killing %s before deleting it', key)
+      cls.Kill(key)
     logging.debug('Deleting process %s', key)
     cls._processes.pop(key)
 
@@ -139,6 +194,14 @@
     return stderr
 
   @classmethod
+  def ReadOutput(cls, key):
+    """Returns the (stdout, stderr) since the last Read* call.
+
+    See ReadStdout for additional details.
+    """
+    return cls.ReadStdout(key), cls.ReadStderr(key)
+
+  @classmethod
   def Wait(cls, key):
     return cls._processes[key].proc.wait()
 
diff --git a/testing/legion/run_task.py b/testing/legion/run_task.py
index 6a55073..26c6e5c 100755
--- a/testing/legion/run_task.py
+++ b/testing/legion/run_task.py
@@ -34,12 +34,13 @@
   logging.info(
       'Registering with registration server at %s using OTP "%s"',
       args.controller, args.otp)
-  server = common_lib.ConnectToServer(args.controller).RegisterTask(
+  common_lib.ConnectToServer(args.controller).RegisterTask(
       args.otp, common_lib.MY_IP)
 
   server = rpc_server.RPCServer(args.controller, args.idle_timeout)
 
   server.serve_forever()
+  logging.info('Server shutdown complete')
   return 0
 
 
diff --git a/testing/scripts/gtest_perf_test.py b/testing/scripts/gtest_perf_test.py
index 5518cb1..6243a79 100755
--- a/testing/scripts/gtest_perf_test.py
+++ b/testing/scripts/gtest_perf_test.py
@@ -31,6 +31,7 @@
           '--builder-name', args.properties.get('buildername'),
           '--build-number', str(args.properties.get('buildnumber')),
           '--log-processor-output-file', tempfile_path,
+          '--test-type', test_suite,
     ]
 
     if 'android' == args.properties.get('target_platform'):
@@ -43,7 +44,7 @@
           '--verbose',
       ])
     else:
-      gtest_args.extend(['--xvfb', '--test-type', test_suite])
+      gtest_args.extend(['--xvfb'])
       gtest_args.extend(script_args)
 
     rc = common.run_runtest(args, gtest_args + filter_tests)
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi
index d44071e..d2fc5d4 100644
--- a/third_party/boringssl/boringssl.gypi
+++ b/third_party/boringssl/boringssl.gypi
@@ -7,6 +7,7 @@
 {
   'variables': {
     'boringssl_lib_sources': [
+      'err_data.c',
       'src/crypto/aes/aes.c',
       'src/crypto/aes/mode_wrappers.c',
       'src/crypto/asn1/a_bitstr.c',
diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c
new file mode 100644
index 0000000..65bc34f
--- /dev/null
+++ b/third_party/boringssl/err_data.c
@@ -0,0 +1,2570 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+ /* This file was generated by err_data_generate.go. */
+
+#include <openssl/base.h>
+#include <openssl/err.h>
+#include <openssl/type_check.h>
+
+
+OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 31, library_values_changed_31);
+OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 32, library_values_changed_32);
+OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num);
+
+const uint32_t kOpenSSLFunctionValues[] = {
+    0xc320540,
+    0xc32854b,
+    0xc330556,
+    0xc338563,
+    0xc34056d,
+    0xc348577,
+    0xc35057e,
+    0xc35858a,
+    0xc360591,
+    0xc3685a7,
+    0xc3705bc,
+    0xc3785cd,
+    0xc3805dd,
+    0xc3885f7,
+    0xc39060c,
+    0xc39861b,
+    0xc3a0634,
+    0xc3a8648,
+    0xc3b0654,
+    0xc3b865b,
+    0xc3c0663,
+    0xc3c8671,
+    0xc3d0679,
+    0xc3d8681,
+    0xc3e068c,
+    0x10321744,
+    0x1032975b,
+    0x10331774,
+    0x1033978a,
+    0x1034179a,
+    0x103497ad,
+    0x103517bb,
+    0x103597ca,
+    0x103617ea,
+    0x10369809,
+    0x10371826,
+    0x10379843,
+    0x10381858,
+    0x1038987a,
+    0x10391899,
+    0x103998b8,
+    0x103a18cf,
+    0x103a98e6,
+    0x103b18ef,
+    0x103b98fa,
+    0x103c1914,
+    0x103c991c,
+    0x103d1924,
+    0x103d992b,
+    0x103e193e,
+    0x103e9950,
+    0x103f1963,
+    0x103f996c,
+    0x143209cb,
+    0x143289d9,
+    0x143309e5,
+    0x143389f2,
+    0x1832100b,
+    0x18329023,
+    0x18331045,
+    0x18339057,
+    0x18341068,
+    0x18349081,
+    0x18351092,
+    0x183590a8,
+    0x183610b8,
+    0x183690cd,
+    0x183710e6,
+    0x183790f7,
+    0x1838110d,
+    0x1838911e,
+    0x18391130,
+    0x18399145,
+    0x183a1157,
+    0x183a9167,
+    0x183b117c,
+    0x183b9189,
+    0x183c119b,
+    0x183c91a9,
+    0x183d11bc,
+    0x183d91cc,
+    0x183e11e1,
+    0x183e91f2,
+    0x183f1205,
+    0x183f9214,
+    0x18401224,
+    0x18409231,
+    0x18411240,
+    0x18419251,
+    0x18421264,
+    0x18429276,
+    0x18431288,
+    0x18439299,
+    0x184412aa,
+    0x184492bb,
+    0x184512cc,
+    0x184592d9,
+    0x184612e7,
+    0x184692fa,
+    0x1847130e,
+    0x1847931b,
+    0x1848132a,
+    0x18489339,
+    0x1849134a,
+    0x18499357,
+    0x184a1365,
+    0x184a9376,
+    0x184b1387,
+    0x184b9395,
+    0x184c13a5,
+    0x184c93cb,
+    0x184d13da,
+    0x184d93ea,
+    0x184e13fa,
+    0x184e9409,
+    0x1c320699,
+    0x1c3286a5,
+    0x1c3306b0,
+    0x1c3386bc,
+    0x2032141d,
+    0x20329428,
+    0x20331430,
+    0x2033943c,
+    0x24321448,
+    0x24329456,
+    0x24331468,
+    0x24339477,
+    0x2434148a,
+    0x2434949d,
+    0x243514b4,
+    0x243594cc,
+    0x243614da,
+    0x243694f2,
+    0x243714fb,
+    0x2437950d,
+    0x24381521,
+    0x2438952e,
+    0x24391544,
+    0x2439955c,
+    0x243a1574,
+    0x243a957e,
+    0x243b1593,
+    0x243b95a1,
+    0x243c15b9,
+    0x243c95d0,
+    0x243d15db,
+    0x243d95e9,
+    0x28320a2b,
+    0x28328a3a,
+    0x28330a45,
+    0x28338a4a,
+    0x28340a55,
+    0x2c322850,
+    0x2c32a85c,
+    0x2c33286f,
+    0x2c33a880,
+    0x2c342899,
+    0x2c34a8c1,
+    0x2c3528d8,
+    0x2c35a8f5,
+    0x2c362912,
+    0x2c36a92f,
+    0x2c372948,
+    0x2c37a961,
+    0x2c382977,
+    0x2c38a985,
+    0x2c392997,
+    0x2c39a9b4,
+    0x2c3a29d1,
+    0x2c3aa9df,
+    0x2c3b29fd,
+    0x2c3baa1b,
+    0x2c3c2a36,
+    0x2c3caa4a,
+    0x2c3d2a5c,
+    0x2c3daa6c,
+    0x2c3e2a7a,
+    0x2c3eaa8a,
+    0x2c3f2a9a,
+    0x2c3faab5,
+    0x2c402ac6,
+    0x2c40aae1,
+    0x2c412af5,
+    0x2c41ab08,
+    0x2c422b27,
+    0x2c42ab3b,
+    0x2c432b4e,
+    0x2c43ab5d,
+    0x2c442b6c,
+    0x2c44ab83,
+    0x2c452b9e,
+    0x2c45abb6,
+    0x2c462bca,
+    0x2c46abdd,
+    0x2c472bee,
+    0x2c47abff,
+    0x2c482c10,
+    0x2c48ac21,
+    0x2c492c30,
+    0x2c49ac3d,
+    0x2c4a2c4a,
+    0x2c4aac57,
+    0x2c4b2c60,
+    0x2c4bac74,
+    0x2c4c2c83,
+    0x2c4cac91,
+    0x2c4d2cb3,
+    0x2c4dacc4,
+    0x2c4e2cd5,
+    0x2c4eaca0,
+    0x2c4f28b2,
+    0x30320000,
+    0x30328018,
+    0x3033002c,
+    0x30338042,
+    0x3034005b,
+    0x3034806c,
+    0x3035007f,
+    0x3035808f,
+    0x3036009d,
+    0x303680b3,
+    0x303700c3,
+    0x303780d8,
+    0x303800e6,
+    0x303880f7,
+    0x30390103,
+    0x3039810c,
+    0x303a011d,
+    0x303a812d,
+    0x303b013a,
+    0x303b8146,
+    0x303c0157,
+    0x303c8165,
+    0x303d0176,
+    0x303d8188,
+    0x303e0199,
+    0x303e81a8,
+    0x303f01b9,
+    0x303f81cd,
+    0x304001df,
+    0x304081ec,
+    0x30410202,
+    0x30418215,
+    0x30420225,
+    0x30428239,
+    0x3043024a,
+    0x3043825a,
+    0x30440265,
+    0x3044826d,
+    0x3045027d,
+    0x30458294,
+    0x304602a1,
+    0x304682b7,
+    0x304702c9,
+    0x304782d5,
+    0x304802e1,
+    0x304882ef,
+    0x30490308,
+    0x30498316,
+    0x304a032b,
+    0x304a8343,
+    0x304b034d,
+    0x304b8361,
+    0x304c0372,
+    0x304c8382,
+    0x304d038f,
+    0x304d83a0,
+    0x304e03b0,
+    0x304e83c2,
+    0x304f03d3,
+    0x304f83e2,
+    0x305003f6,
+    0x30508404,
+    0x30510413,
+    0x3051841c,
+    0x3432095d,
+    0x3432896d,
+    0x34330978,
+    0x34338985,
+    0x3832098e,
+    0x383289a1,
+    0x383309ab,
+    0x383389bd,
+    0x3c320a5c,
+    0x3c328a6a,
+    0x3c330a81,
+    0x3c338a95,
+    0x3c340ab0,
+    0x3c348ac1,
+    0x3c350acd,
+    0x3c358ae1,
+    0x3c360af3,
+    0x3c368b1c,
+    0x3c370b29,
+    0x3c378b36,
+    0x3c380b44,
+    0x3c388b51,
+    0x3c390b5e,
+    0x3c398b82,
+    0x3c3a0b92,
+    0x3c3a8baa,
+    0x3c3b0bbf,
+    0x3c3b8bd4,
+    0x3c3c0be1,
+    0x3c3c8bf4,
+    0x3c3d0c07,
+    0x3c3d8c2b,
+    0x3c3e0c53,
+    0x3c3e8c6c,
+    0x3c3f0c82,
+    0x3c3f8c8f,
+    0x3c400ca2,
+    0x3c408cb3,
+    0x3c410cc4,
+    0x3c418cdd,
+    0x3c420cf6,
+    0x3c428d0c,
+    0x3c430d29,
+    0x3c438d3f,
+    0x3c440d5b,
+    0x3c448d82,
+    0x3c450da0,
+    0x3c458dba,
+    0x3c460dd2,
+    0x3c468dea,
+    0x3c470e15,
+    0x3c478e40,
+    0x3c480e61,
+    0x3c488e8a,
+    0x3c490ea5,
+    0x3c498ec0,
+    0x3c4a0ecd,
+    0x3c4a8ee4,
+    0x3c4b0efb,
+    0x3c4b8f24,
+    0x3c4c0f34,
+    0x3c4c8f40,
+    0x3c4d0f58,
+    0x3c4d8f6b,
+    0x3c4e0f7c,
+    0x3c4e8f8d,
+    0x3c4f0f9d,
+    0x40321977,
+    0x40329991,
+    0x4033199d,
+    0x403399b5,
+    0x403419d3,
+    0x403499f2,
+    0x40351a09,
+    0x40359a25,
+    0x40361a41,
+    0x40369a5b,
+    0x40371a7a,
+    0x40379a99,
+    0x40381ab1,
+    0x40389ace,
+    0x40391af1,
+    0x40399b0e,
+    0x403a1b2c,
+    0x403a9b3c,
+    0x403b1b51,
+    0x403b9b6d,
+    0x403c1b87,
+    0x403c9b92,
+    0x403d1bb5,
+    0x403d9bd9,
+    0x403e1bef,
+    0x403e9bf9,
+    0x403f1c05,
+    0x403f9c16,
+    0x40401c2e,
+    0x40409c36,
+    0x40411c3f,
+    0x40419c48,
+    0x40421c58,
+    0x40429c6c,
+    0x40431c77,
+    0x40439c83,
+    0x40441c9e,
+    0x40449caa,
+    0x40451cb7,
+    0x40459cca,
+    0x40461ce2,
+    0x40469cfa,
+    0x40471d10,
+    0x40479d2b,
+    0x40481d46,
+    0x40489d5a,
+    0x40491d73,
+    0x40499d8c,
+    0x404a1da6,
+    0x404a9db0,
+    0x404b1dc0,
+    0x404b9de1,
+    0x404c1dfc,
+    0x404c9e0a,
+    0x404d1e17,
+    0x404d9e2b,
+    0x404e1e43,
+    0x404e9e51,
+    0x404f1e7b,
+    0x404f9e92,
+    0x40501ea4,
+    0x40509ed5,
+    0x40511f06,
+    0x40519f1b,
+    0x40521f2c,
+    0x40529f4c,
+    0x40531f67,
+    0x40539f77,
+    0x40541f83,
+    0x40549f96,
+    0x40551fac,
+    0x40559fca,
+    0x40561fd7,
+    0x40569fe1,
+    0x40571fef,
+    0x4057a00a,
+    0x40582025,
+    0x4058a044,
+    0x40592059,
+    0x4059a06e,
+    0x405a208b,
+    0x405aa09f,
+    0x405b20bb,
+    0x405ba0d1,
+    0x405c20ee,
+    0x405ca100,
+    0x405d2117,
+    0x405da128,
+    0x405e2144,
+    0x405ea158,
+    0x405f2168,
+    0x405fa184,
+    0x40602199,
+    0x4060a1af,
+    0x406121cc,
+    0x4061a1e5,
+    0x406221f8,
+    0x4062a201,
+    0x40632211,
+    0x4063a21d,
+    0x40642233,
+    0x4064a251,
+    0x40652266,
+    0x4065a283,
+    0x4066229a,
+    0x4066a2b8,
+    0x406722d5,
+    0x4067a2ec,
+    0x4068230a,
+    0x4068a321,
+    0x40692339,
+    0x4069a34a,
+    0x406a235d,
+    0x406aa370,
+    0x406b2384,
+    0x406ba3a8,
+    0x406c23c3,
+    0x406ca3e4,
+    0x406d2408,
+    0x406da423,
+    0x406e2444,
+    0x406ea459,
+    0x406f2472,
+    0x406fa47f,
+    0x4070248d,
+    0x4070a49a,
+    0x407124b7,
+    0x4071a4d7,
+    0x407224f2,
+    0x4072a50b,
+    0x40732522,
+    0x4073a53c,
+    0x40742560,
+    0x4074a576,
+    0x4075258a,
+    0x4075a59f,
+    0x407625b9,
+    0x4076a5cb,
+    0x407725e0,
+    0x4077a606,
+    0x40782623,
+    0x4078a646,
+    0x4079266c,
+    0x4079a689,
+    0x407a26ac,
+    0x407aa6c8,
+    0x407b26e4,
+    0x407ba6f6,
+    0x407c2703,
+    0x407ca710,
+    0x407d272d,
+    0x407da744,
+    0x407e2760,
+    0x407ea776,
+    0x407f278e,
+    0x407fa7a1,
+    0x408027b6,
+    0x4080a7cf,
+    0x408127ed,
+    0x4081a80d,
+    0x40822816,
+    0x4082a832,
+    0x4083283b,
+    0x40839e60,
+    0x40841eef,
+    0x40849ebf,
+    0x4432042a,
+    0x4432843c,
+    0x44330445,
+    0x4433844d,
+    0x4434045a,
+    0x4434846a,
+    0x44350485,
+    0x443584a5,
+    0x443604c1,
+    0x443684e2,
+    0x443704e9,
+    0x443784f7,
+    0x44380501,
+    0x4438850d,
+    0x44390517,
+    0x44398522,
+    0x443a052c,
+    0x443a8536,
+    0x4c3215f1,
+    0x4c329600,
+    0x4c33160f,
+    0x4c339628,
+    0x4c341643,
+    0x4c34965f,
+    0x4c351671,
+    0x4c35967f,
+    0x4c361694,
+    0x4c3696a5,
+    0x4c3716b3,
+    0x4c3796c1,
+    0x4c3816d3,
+    0x4c3896e3,
+    0x4c3916ed,
+    0x4c399705,
+    0x4c3a171d,
+    0x4c3a9730,
+    0x50322ce6,
+    0x5032acfb,
+    0x50332d0c,
+    0x5033ad1f,
+    0x50342d30,
+    0x5034ad43,
+    0x50352d52,
+    0x5035ad67,
+    0x50362d77,
+    0x5036ad86,
+    0x50372d97,
+    0x5037ada7,
+    0x50382db8,
+    0x5038adcb,
+    0x50392ddd,
+    0x5039adf3,
+    0x503a2e05,
+    0x503aae16,
+    0x503b2e27,
+    0x503bae38,
+    0x503c2e43,
+    0x503cae4f,
+    0x503d2e5a,
+    0x503dae65,
+    0x503e2e72,
+    0x503eae87,
+    0x503f2e95,
+    0x503faea9,
+    0x50402ebc,
+    0x5040aecd,
+    0x50412ee7,
+    0x5041aef6,
+    0x50422eff,
+    0x5042af0e,
+    0x50432f20,
+    0x5043af2c,
+    0x50442f34,
+    0x5044af47,
+    0x50452f58,
+    0x5045af6e,
+    0x50462f7a,
+    0x5046af8e,
+    0x50472f9c,
+    0x5047afb0,
+    0x50482fca,
+    0x5048afde,
+    0x50492ff4,
+    0x5049b00b,
+    0x504a301d,
+    0x504ab031,
+    0x504b3046,
+    0x504bb05d,
+    0x504c3071,
+    0x504cb07a,
+    0x504d3082,
+    0x504db091,
+    0x504e30a1,
+    0x68320fbe,
+    0x68328fcf,
+    0x68330fdf,
+    0x68338fed,
+    0x68340ffa,
+    0x6c320fad,
+    0x74320a06,
+    0x74328a18,
+    0x783206c9,
+    0x783286fc,
+    0x7833070e,
+    0x78338720,
+    0x78340734,
+    0x78348748,
+    0x78350766,
+    0x78358778,
+    0x7836078c,
+    0x783687a0,
+    0x783707b2,
+    0x783787c4,
+    0x783807d6,
+    0x783887ed,
+    0x78390804,
+    0x7839881b,
+    0x783a0837,
+    0x783a8853,
+    0x783b086f,
+    0x783b8885,
+    0x783c089b,
+    0x783c88b1,
+    0x783d08ce,
+    0x783d88dd,
+    0x783e08ec,
+    0x783e88fb,
+    0x783f0917,
+    0x783f8925,
+    0x78400933,
+    0x78408941,
+    0x7841094e,
+    0x784186db,
+    0x80321418,
+};
+
+const size_t kOpenSSLFunctionValuesLen = sizeof(kOpenSSLFunctionValues) / sizeof(kOpenSSLFunctionValues[0]);
+
+const char kOpenSSLFunctionStringData[] =
+    "ASN1_BIT_STRING_set_bit\0"
+    "ASN1_ENUMERATED_set\0"
+    "ASN1_ENUMERATED_to_BN\0"
+    "ASN1_GENERALIZEDTIME_adj\0"
+    "ASN1_INTEGER_set\0"
+    "ASN1_INTEGER_to_BN\0"
+    "ASN1_OBJECT_new\0"
+    "ASN1_PCTX_new\0"
+    "ASN1_STRING_TABLE_add\0"
+    "ASN1_STRING_set\0"
+    "ASN1_STRING_type_new\0"
+    "ASN1_TIME_adj\0"
+    "ASN1_UTCTIME_adj\0"
+    "ASN1_d2i_fp\0"
+    "ASN1_dup\0"
+    "ASN1_generate_v3\0"
+    "ASN1_get_object\0"
+    "ASN1_i2d_bio\0"
+    "ASN1_i2d_fp\0"
+    "ASN1_item_d2i_fp\0"
+    "ASN1_item_dup\0"
+    "ASN1_item_ex_d2i\0"
+    "ASN1_item_i2d_bio\0"
+    "ASN1_item_i2d_fp\0"
+    "ASN1_item_pack\0"
+    "ASN1_item_unpack\0"
+    "ASN1_mbstring_ncopy\0"
+    "ASN1_template_new\0"
+    "BIO_new_NDEF\0"
+    "BN_to_ASN1_ENUMERATED\0"
+    "BN_to_ASN1_INTEGER\0"
+    "a2d_ASN1_OBJECT\0"
+    "a2i_ASN1_ENUMERATED\0"
+    "a2i_ASN1_INTEGER\0"
+    "a2i_ASN1_STRING\0"
+    "append_exp\0"
+    "asn1_cb\0"
+    "asn1_check_tlen\0"
+    "asn1_collate_primitive\0"
+    "asn1_collect\0"
+    "asn1_d2i_ex_primitive\0"
+    "asn1_d2i_read_bio\0"
+    "asn1_do_adb\0"
+    "asn1_ex_c2i\0"
+    "asn1_find_end\0"
+    "asn1_item_ex_combine_new\0"
+    "asn1_str2type\0"
+    "asn1_template_ex_d2i\0"
+    "asn1_template_noexp_d2i\0"
+    "bitstr_cb\0"
+    "c2i_ASN1_BIT_STRING\0"
+    "c2i_ASN1_INTEGER\0"
+    "c2i_ASN1_OBJECT\0"
+    "collect_data\0"
+    "d2i_ASN1_BOOLEAN\0"
+    "d2i_ASN1_OBJECT\0"
+    "d2i_ASN1_UINTEGER\0"
+    "d2i_ASN1_UTCTIME\0"
+    "d2i_ASN1_bytes\0"
+    "d2i_ASN1_type_bytes\0"
+    "i2d_ASN1_TIME\0"
+    "i2d_PrivateKey\0"
+    "long_c2i\0"
+    "parse_tagging\0"
+    "BIO_callback_ctrl\0"
+    "BIO_ctrl\0"
+    "BIO_new\0"
+    "BIO_new_file\0"
+    "BIO_new_mem_buf\0"
+    "BIO_zero_copy_get_read_buf\0"
+    "BIO_zero_copy_get_read_buf_done\0"
+    "BIO_zero_copy_get_write_buf\0"
+    "BIO_zero_copy_get_write_buf_done\0"
+    "bio_io\0"
+    "bio_make_pair\0"
+    "bio_write\0"
+    "buffer_ctrl\0"
+    "conn_ctrl\0"
+    "conn_state\0"
+    "file_ctrl\0"
+    "file_read\0"
+    "mem_write\0"
+    "BN_CTX_get\0"
+    "BN_CTX_new\0"
+    "BN_CTX_start\0"
+    "BN_bn2dec\0"
+    "BN_bn2hex\0"
+    "BN_div\0"
+    "BN_div_recp\0"
+    "BN_exp\0"
+    "BN_generate_dsa_nonce\0"
+    "BN_generate_prime_ex\0"
+    "BN_mod_exp2_mont\0"
+    "BN_mod_exp_mont\0"
+    "BN_mod_exp_mont_consttime\0"
+    "BN_mod_exp_mont_word\0"
+    "BN_mod_inverse\0"
+    "BN_mod_inverse_no_branch\0"
+    "BN_mod_lshift_quick\0"
+    "BN_mod_sqrt\0"
+    "BN_new\0"
+    "BN_rand\0"
+    "BN_rand_range\0"
+    "BN_sqrt\0"
+    "BN_usub\0"
+    "bn_wexpand\0"
+    "mod_exp_recp\0"
+    "BUF_MEM_new\0"
+    "BUF_memdup\0"
+    "BUF_strndup\0"
+    "buf_mem_grow\0"
+    "EVP_AEAD_CTX_init\0"
+    "EVP_AEAD_CTX_init_with_direction\0"
+    "EVP_AEAD_CTX_open\0"
+    "EVP_AEAD_CTX_seal\0"
+    "EVP_CIPHER_CTX_copy\0"
+    "EVP_CIPHER_CTX_ctrl\0"
+    "EVP_CIPHER_CTX_set_key_length\0"
+    "EVP_CipherInit_ex\0"
+    "EVP_DecryptFinal_ex\0"
+    "EVP_EncryptFinal_ex\0"
+    "aead_aes_gcm_init\0"
+    "aead_aes_gcm_open\0"
+    "aead_aes_gcm_seal\0"
+    "aead_aes_key_wrap_init\0"
+    "aead_aes_key_wrap_open\0"
+    "aead_aes_key_wrap_seal\0"
+    "aead_chacha20_poly1305_init\0"
+    "aead_chacha20_poly1305_open\0"
+    "aead_chacha20_poly1305_seal\0"
+    "aead_rc4_md5_tls_init\0"
+    "aead_rc4_md5_tls_open\0"
+    "aead_rc4_md5_tls_seal\0"
+    "aead_ssl3_ensure_cipher_init\0"
+    "aead_ssl3_init\0"
+    "aead_ssl3_open\0"
+    "aead_ssl3_seal\0"
+    "aead_tls_ensure_cipher_init\0"
+    "aead_tls_init\0"
+    "aead_tls_open\0"
+    "aead_tls_seal\0"
+    "aes_init_key\0"
+    "aesni_init_key\0"
+    "CONF_parse_list\0"
+    "NCONF_load\0"
+    "def_load_bio\0"
+    "str_copy\0"
+    "CRYPTO_set_ex_data\0"
+    "get_class\0"
+    "get_func_pointers\0"
+    "get_new_index\0"
+    "DH_new_method\0"
+    "compute_key\0"
+    "generate_key\0"
+    "generate_parameters\0"
+    "EVP_DigestInit_ex\0"
+    "EVP_MD_CTX_copy_ex\0"
+    "DSA_new_method\0"
+    "dsa_sig_cb\0"
+    "sign\0"
+    "sign_setup\0"
+    "verify\0"
+    "EC_GROUP_copy\0"
+    "EC_GROUP_get_curve_GFp\0"
+    "EC_GROUP_get_degree\0"
+    "EC_GROUP_new_by_curve_name\0"
+    "EC_KEY_check_key\0"
+    "EC_KEY_copy\0"
+    "EC_KEY_generate_key\0"
+    "EC_KEY_new_method\0"
+    "EC_KEY_set_public_key_affine_coordinates\0"
+    "EC_POINT_add\0"
+    "EC_POINT_cmp\0"
+    "EC_POINT_copy\0"
+    "EC_POINT_dbl\0"
+    "EC_POINT_dup\0"
+    "EC_POINT_get_affine_coordinates_GFp\0"
+    "EC_POINT_invert\0"
+    "EC_POINT_is_at_infinity\0"
+    "EC_POINT_is_on_curve\0"
+    "EC_POINT_make_affine\0"
+    "EC_POINT_new\0"
+    "EC_POINT_oct2point\0"
+    "EC_POINT_point2oct\0"
+    "EC_POINT_set_affine_coordinates_GFp\0"
+    "EC_POINT_set_compressed_coordinates_GFp\0"
+    "EC_POINT_set_to_infinity\0"
+    "EC_POINTs_make_affine\0"
+    "compute_wNAF\0"
+    "d2i_ECPKParameters\0"
+    "d2i_ECParameters\0"
+    "d2i_ECPrivateKey\0"
+    "ec_GFp_mont_field_decode\0"
+    "ec_GFp_mont_field_encode\0"
+    "ec_GFp_mont_field_mul\0"
+    "ec_GFp_mont_field_set_to_one\0"
+    "ec_GFp_mont_field_sqr\0"
+    "ec_GFp_mont_group_set_curve\0"
+    "ec_GFp_simple_group_check_discriminant\0"
+    "ec_GFp_simple_group_set_curve\0"
+    "ec_GFp_simple_make_affine\0"
+    "ec_GFp_simple_oct2point\0"
+    "ec_GFp_simple_point2oct\0"
+    "ec_GFp_simple_point_get_affine_coordinates\0"
+    "ec_GFp_simple_point_set_affine_coordinates\0"
+    "ec_GFp_simple_points_make_affine\0"
+    "ec_GFp_simple_set_compressed_coordinates\0"
+    "ec_asn1_group2pkparameters\0"
+    "ec_asn1_pkparameters2group\0"
+    "ec_group_new\0"
+    "ec_group_new_curve_GFp\0"
+    "ec_group_new_from_data\0"
+    "ec_point_set_Jprojective_coordinates_GFp\0"
+    "ec_pre_comp_new\0"
+    "ec_wNAF_mul\0"
+    "ec_wNAF_precompute_mult\0"
+    "i2d_ECPKParameters\0"
+    "i2d_ECParameters\0"
+    "i2d_ECPrivateKey\0"
+    "i2o_ECPublicKey\0"
+    "o2i_ECPublicKey\0"
+    "ECDH_compute_key\0"
+    "ECDSA_do_sign_ex\0"
+    "ECDSA_do_verify\0"
+    "ECDSA_sign_ex\0"
+    "digest_to_bn\0"
+    "ecdsa_sign_setup\0"
+    "EVP_DigestSignAlgorithm\0"
+    "EVP_DigestVerifyInitFromAlgorithm\0"
+    "EVP_PKEY_CTX_ctrl\0"
+    "EVP_PKEY_CTX_dup\0"
+    "EVP_PKEY_copy_parameters\0"
+    "EVP_PKEY_decrypt\0"
+    "EVP_PKEY_decrypt_init\0"
+    "EVP_PKEY_derive\0"
+    "EVP_PKEY_derive_init\0"
+    "EVP_PKEY_derive_set_peer\0"
+    "EVP_PKEY_encrypt\0"
+    "EVP_PKEY_encrypt_init\0"
+    "EVP_PKEY_get1_DH\0"
+    "EVP_PKEY_get1_DSA\0"
+    "EVP_PKEY_get1_EC_KEY\0"
+    "EVP_PKEY_get1_RSA\0"
+    "EVP_PKEY_keygen\0"
+    "EVP_PKEY_keygen_init\0"
+    "EVP_PKEY_new\0"
+    "EVP_PKEY_set_type\0"
+    "EVP_PKEY_sign\0"
+    "EVP_PKEY_sign_init\0"
+    "EVP_PKEY_verify\0"
+    "EVP_PKEY_verify_init\0"
+    "check_padding_md\0"
+    "d2i_AutoPrivateKey\0"
+    "d2i_PrivateKey\0"
+    "do_EC_KEY_print\0"
+    "do_rsa_print\0"
+    "do_sigver_init\0"
+    "eckey_param2type\0"
+    "eckey_param_decode\0"
+    "eckey_priv_decode\0"
+    "eckey_priv_encode\0"
+    "eckey_pub_decode\0"
+    "eckey_pub_encode\0"
+    "eckey_type2param\0"
+    "evp_pkey_ctx_new\0"
+    "hmac_signctx\0"
+    "i2d_PublicKey\0"
+    "old_ec_priv_decode\0"
+    "old_rsa_priv_decode\0"
+    "pkey_ec_ctrl\0"
+    "pkey_ec_derive\0"
+    "pkey_ec_keygen\0"
+    "pkey_ec_paramgen\0"
+    "pkey_ec_sign\0"
+    "pkey_rsa_ctrl\0"
+    "pkey_rsa_decrypt\0"
+    "pkey_rsa_encrypt\0"
+    "pkey_rsa_sign\0"
+    "rsa_algor_to_md\0"
+    "rsa_digest_verify_init_from_algorithm\0"
+    "rsa_mgf1_to_md\0"
+    "rsa_priv_decode\0"
+    "rsa_priv_encode\0"
+    "rsa_pss_to_ctx\0"
+    "rsa_pub_decode\0"
+    "HKDF\0"
+    "OBJ_create\0"
+    "OBJ_dup\0"
+    "OBJ_nid2obj\0"
+    "OBJ_txt2obj\0"
+    "PEM_ASN1_read\0"
+    "PEM_ASN1_read_bio\0"
+    "PEM_ASN1_write\0"
+    "PEM_ASN1_write_bio\0"
+    "PEM_X509_INFO_read\0"
+    "PEM_X509_INFO_read_bio\0"
+    "PEM_X509_INFO_write_bio\0"
+    "PEM_do_header\0"
+    "PEM_get_EVP_CIPHER_INFO\0"
+    "PEM_read\0"
+    "PEM_read_DHparams\0"
+    "PEM_read_PrivateKey\0"
+    "PEM_read_bio\0"
+    "PEM_read_bio_DHparams\0"
+    "PEM_read_bio_Parameters\0"
+    "PEM_read_bio_PrivateKey\0"
+    "PEM_write\0"
+    "PEM_write_PrivateKey\0"
+    "PEM_write_bio\0"
+    "d2i_PKCS8PrivateKey_bio\0"
+    "d2i_PKCS8PrivateKey_fp\0"
+    "do_pk8pkey\0"
+    "do_pk8pkey_fp\0"
+    "load_iv\0"
+    "EVP_PKCS82PKEY\0"
+    "EVP_PKEY2PKCS8\0"
+    "PKCS12_get_key_and_certs\0"
+    "PKCS12_handle_content_info\0"
+    "PKCS12_handle_content_infos\0"
+    "PKCS5_pbe2_set_iv\0"
+    "PKCS5_pbe_set\0"
+    "PKCS5_pbe_set0_algor\0"
+    "PKCS5_pbkdf2_set\0"
+    "PKCS8_decrypt\0"
+    "PKCS8_encrypt\0"
+    "PKCS8_encrypt_pbe\0"
+    "pbe_cipher_init\0"
+    "pbe_crypt\0"
+    "pkcs12_item_decrypt_d2i\0"
+    "pkcs12_item_i2d_encrypt\0"
+    "pkcs12_key_gen_raw\0"
+    "pkcs12_pbe_keyivgen\0"
+    "BN_BLINDING_convert_ex\0"
+    "BN_BLINDING_create_param\0"
+    "BN_BLINDING_invert_ex\0"
+    "BN_BLINDING_new\0"
+    "BN_BLINDING_update\0"
+    "RSA_check_key\0"
+    "RSA_new_method\0"
+    "RSA_padding_add_PKCS1_OAEP_mgf1\0"
+    "RSA_padding_add_PKCS1_PSS_mgf1\0"
+    "RSA_padding_add_PKCS1_type_1\0"
+    "RSA_padding_add_PKCS1_type_2\0"
+    "RSA_padding_add_none\0"
+    "RSA_padding_check_PKCS1_OAEP_mgf1\0"
+    "RSA_padding_check_PKCS1_type_1\0"
+    "RSA_padding_check_PKCS1_type_2\0"
+    "RSA_padding_check_none\0"
+    "RSA_recover_crt_params\0"
+    "RSA_sign\0"
+    "RSA_verify\0"
+    "RSA_verify_PKCS1_PSS_mgf1\0"
+    "decrypt\0"
+    "encrypt\0"
+    "keygen\0"
+    "pkcs1_prefixed_msg\0"
+    "private_transform\0"
+    "rsa_setup_blinding\0"
+    "sign_raw\0"
+    "verify_raw\0"
+    "SSL_CTX_check_private_key\0"
+    "SSL_CTX_new\0"
+    "SSL_CTX_set_cipher_list\0"
+    "SSL_CTX_set_cipher_list_tls11\0"
+    "SSL_CTX_set_session_id_context\0"
+    "SSL_CTX_use_PrivateKey\0"
+    "SSL_CTX_use_PrivateKey_ASN1\0"
+    "SSL_CTX_use_PrivateKey_file\0"
+    "SSL_CTX_use_RSAPrivateKey\0"
+    "SSL_CTX_use_RSAPrivateKey_ASN1\0"
+    "SSL_CTX_use_RSAPrivateKey_file\0"
+    "SSL_CTX_use_certificate\0"
+    "SSL_CTX_use_certificate_ASN1\0"
+    "SSL_CTX_use_certificate_chain_file\0"
+    "SSL_CTX_use_certificate_file\0"
+    "SSL_CTX_use_psk_identity_hint\0"
+    "SSL_SESSION_new\0"
+    "SSL_SESSION_print_fp\0"
+    "SSL_SESSION_set1_id_context\0"
+    "SSL_SESSION_to_bytes_full\0"
+    "SSL_accept\0"
+    "SSL_add_dir_cert_subjects_to_stack\0"
+    "SSL_add_file_cert_subjects_to_stack\0"
+    "SSL_check_private_key\0"
+    "SSL_clear\0"
+    "SSL_connect\0"
+    "SSL_do_handshake\0"
+    "SSL_load_client_CA_file\0"
+    "SSL_new\0"
+    "SSL_peek\0"
+    "SSL_read\0"
+    "SSL_renegotiate\0"
+    "SSL_set_cipher_list\0"
+    "SSL_set_fd\0"
+    "SSL_set_rfd\0"
+    "SSL_set_session_id_context\0"
+    "SSL_set_wfd\0"
+    "SSL_shutdown\0"
+    "SSL_use_PrivateKey\0"
+    "SSL_use_PrivateKey_ASN1\0"
+    "SSL_use_PrivateKey_file\0"
+    "SSL_use_RSAPrivateKey\0"
+    "SSL_use_RSAPrivateKey_ASN1\0"
+    "SSL_use_RSAPrivateKey_file\0"
+    "SSL_use_certificate\0"
+    "SSL_use_certificate_ASN1\0"
+    "SSL_use_certificate_file\0"
+    "SSL_use_psk_identity_hint\0"
+    "SSL_write\0"
+    "d2i_SSL_SESSION\0"
+    "d2i_SSL_SESSION_get_octet_string\0"
+    "d2i_SSL_SESSION_get_string\0"
+    "do_ssl3_write\0"
+    "dtls1_accept\0"
+    "dtls1_buffer_record\0"
+    "dtls1_check_timeout_num\0"
+    "dtls1_connect\0"
+    "dtls1_do_write\0"
+    "dtls1_get_buffered_message\0"
+    "dtls1_get_hello_verify\0"
+    "dtls1_get_message\0"
+    "dtls1_get_message_fragment\0"
+    "dtls1_hm_fragment_new\0"
+    "dtls1_preprocess_fragment\0"
+    "dtls1_process_fragment\0"
+    "dtls1_process_record\0"
+    "dtls1_read_bytes\0"
+    "dtls1_send_hello_verify_request\0"
+    "dtls1_write_app_data_bytes\0"
+    "i2d_SSL_SESSION\0"
+    "ssl3_accept\0"
+    "ssl3_callback_ctrl\0"
+    "ssl3_cert_verify_hash\0"
+    "ssl3_check_cert_and_algorithm\0"
+    "ssl3_connect\0"
+    "ssl3_ctrl\0"
+    "ssl3_ctx_ctrl\0"
+    "ssl3_digest_cached_records\0"
+    "ssl3_do_change_cipher_spec\0"
+    "ssl3_expect_change_cipher_spec\0"
+    "ssl3_get_cert_status\0"
+    "ssl3_get_cert_verify\0"
+    "ssl3_get_certificate_request\0"
+    "ssl3_get_channel_id\0"
+    "ssl3_get_client_certificate\0"
+    "ssl3_get_client_hello\0"
+    "ssl3_get_client_key_exchange\0"
+    "ssl3_get_finished\0"
+    "ssl3_get_initial_bytes\0"
+    "ssl3_get_message\0"
+    "ssl3_get_new_session_ticket\0"
+    "ssl3_get_next_proto\0"
+    "ssl3_get_record\0"
+    "ssl3_get_server_certificate\0"
+    "ssl3_get_server_done\0"
+    "ssl3_get_server_hello\0"
+    "ssl3_get_server_key_exchange\0"
+    "ssl3_get_v2_client_hello\0"
+    "ssl3_handshake_mac\0"
+    "ssl3_prf\0"
+    "ssl3_read_bytes\0"
+    "ssl3_read_n\0"
+    "ssl3_send_cert_verify\0"
+    "ssl3_send_certificate_request\0"
+    "ssl3_send_channel_id\0"
+    "ssl3_send_client_certificate\0"
+    "ssl3_send_client_hello\0"
+    "ssl3_send_client_key_exchange\0"
+    "ssl3_send_server_certificate\0"
+    "ssl3_send_server_hello\0"
+    "ssl3_send_server_key_exchange\0"
+    "ssl3_setup_read_buffer\0"
+    "ssl3_setup_write_buffer\0"
+    "ssl3_write_bytes\0"
+    "ssl3_write_pending\0"
+    "ssl_add_cert_chain\0"
+    "ssl_add_cert_to_buf\0"
+    "ssl_add_clienthello_renegotiate_ext\0"
+    "ssl_add_clienthello_tlsext\0"
+    "ssl_add_clienthello_use_srtp_ext\0"
+    "ssl_add_serverhello_renegotiate_ext\0"
+    "ssl_add_serverhello_tlsext\0"
+    "ssl_add_serverhello_use_srtp_ext\0"
+    "ssl_build_cert_chain\0"
+    "ssl_bytes_to_cipher_list\0"
+    "ssl_cert_dup\0"
+    "ssl_cert_inst\0"
+    "ssl_cert_new\0"
+    "ssl_check_serverhello_tlsext\0"
+    "ssl_check_srvr_ecc_cert_and_alg\0"
+    "ssl_cipher_process_rulestr\0"
+    "ssl_cipher_strength_sort\0"
+    "ssl_create_cipher_list\0"
+    "ssl_ctx_log_master_secret\0"
+    "ssl_ctx_log_rsa_client_key_exchange\0"
+    "ssl_ctx_make_profiles\0"
+    "ssl_get_new_session\0"
+    "ssl_get_prev_session\0"
+    "ssl_get_server_cert_index\0"
+    "ssl_get_sign_pkey\0"
+    "ssl_init_wbio_buffer\0"
+    "ssl_parse_clienthello_renegotiate_ext\0"
+    "ssl_parse_clienthello_tlsext\0"
+    "ssl_parse_clienthello_use_srtp_ext\0"
+    "ssl_parse_serverhello_renegotiate_ext\0"
+    "ssl_parse_serverhello_tlsext\0"
+    "ssl_parse_serverhello_use_srtp_ext\0"
+    "ssl_scan_clienthello_tlsext\0"
+    "ssl_scan_serverhello_tlsext\0"
+    "ssl_sess_cert_new\0"
+    "ssl_set_cert\0"
+    "ssl_set_pkey\0"
+    "ssl_undefined_const_function\0"
+    "ssl_undefined_function\0"
+    "ssl_undefined_void_function\0"
+    "ssl_verify_cert_chain\0"
+    "tls12_check_peer_sigalg\0"
+    "tls1_aead_ctx_init\0"
+    "tls1_cert_verify_mac\0"
+    "tls1_change_cipher_state\0"
+    "tls1_change_cipher_state_aead\0"
+    "tls1_check_duplicate_extensions\0"
+    "tls1_enc\0"
+    "tls1_export_keying_material\0"
+    "tls1_prf\0"
+    "tls1_setup_key_block\0"
+    "ASN1_digest\0"
+    "ASN1_item_sign_ctx\0"
+    "ASN1_item_verify\0"
+    "NETSCAPE_SPKI_b64_decode\0"
+    "NETSCAPE_SPKI_b64_encode\0"
+    "PKCS7_get_CRLs\0"
+    "PKCS7_get_certificates\0"
+    "X509_ATTRIBUTE_create_by_NID\0"
+    "X509_ATTRIBUTE_create_by_OBJ\0"
+    "X509_ATTRIBUTE_create_by_txt\0"
+    "X509_ATTRIBUTE_get0_data\0"
+    "X509_ATTRIBUTE_set1_data\0"
+    "X509_CRL_add0_revoked\0"
+    "X509_CRL_diff\0"
+    "X509_CRL_print_fp\0"
+    "X509_EXTENSION_create_by_NID\0"
+    "X509_EXTENSION_create_by_OBJ\0"
+    "X509_INFO_new\0"
+    "X509_NAME_ENTRY_create_by_NID\0"
+    "X509_NAME_ENTRY_create_by_txt\0"
+    "X509_NAME_ENTRY_set_object\0"
+    "X509_NAME_add_entry\0"
+    "X509_NAME_oneline\0"
+    "X509_NAME_print\0"
+    "X509_PKEY_new\0"
+    "X509_PUBKEY_get\0"
+    "X509_PUBKEY_set\0"
+    "X509_REQ_check_private_key\0"
+    "X509_REQ_to_X509\0"
+    "X509_STORE_CTX_get1_issuer\0"
+    "X509_STORE_CTX_init\0"
+    "X509_STORE_CTX_new\0"
+    "X509_STORE_CTX_purpose_inherit\0"
+    "X509_STORE_add_cert\0"
+    "X509_STORE_add_crl\0"
+    "X509_TRUST_add\0"
+    "X509_TRUST_set\0"
+    "X509_check_private_key\0"
+    "X509_get_pubkey_parameters\0"
+    "X509_load_cert_crl_file\0"
+    "X509_load_cert_file\0"
+    "X509_load_crl_file\0"
+    "X509_print_ex_fp\0"
+    "X509_to_X509_REQ\0"
+    "X509_verify_cert\0"
+    "X509at_add1_attr\0"
+    "X509v3_add_ext\0"
+    "add_cert_dir\0"
+    "by_file_ctrl\0"
+    "check_policy\0"
+    "dir_ctrl\0"
+    "get_cert_by_subject\0"
+    "i2d_DSA_PUBKEY\0"
+    "i2d_EC_PUBKEY\0"
+    "i2d_RSA_PUBKEY\0"
+    "pkcs7_parse_header\0"
+    "x509_name_encode\0"
+    "x509_name_ex_d2i\0"
+    "x509_name_ex_new\0"
+    "SXNET_add_id_INTEGER\0"
+    "SXNET_add_id_asc\0"
+    "SXNET_add_id_ulong\0"
+    "SXNET_get_id_asc\0"
+    "SXNET_get_id_ulong\0"
+    "X509V3_EXT_add\0"
+    "X509V3_EXT_add_alias\0"
+    "X509V3_EXT_free\0"
+    "X509V3_EXT_i2d\0"
+    "X509V3_EXT_nconf\0"
+    "X509V3_add1_i2d\0"
+    "X509V3_add_value\0"
+    "X509V3_get_section\0"
+    "X509V3_get_string\0"
+    "X509V3_get_value_bool\0"
+    "X509V3_parse_list\0"
+    "X509_PURPOSE_add\0"
+    "X509_PURPOSE_set\0"
+    "a2i_GENERAL_NAME\0"
+    "copy_email\0"
+    "copy_issuer\0"
+    "do_dirname\0"
+    "do_ext_i2d\0"
+    "do_ext_nconf\0"
+    "gnames_from_sectname\0"
+    "hex_to_string\0"
+    "i2s_ASN1_ENUMERATED\0"
+    "i2s_ASN1_IA5STRING\0"
+    "i2s_ASN1_INTEGER\0"
+    "i2v_AUTHORITY_INFO_ACCESS\0"
+    "notice_section\0"
+    "nref_nos\0"
+    "policy_section\0"
+    "process_pci_value\0"
+    "r2i_certpol\0"
+    "r2i_pci\0"
+    "s2i_ASN1_IA5STRING\0"
+    "s2i_ASN1_INTEGER\0"
+    "s2i_ASN1_OCTET_STRING\0"
+    "s2i_skey_id\0"
+    "set_dist_point_name\0"
+    "string_to_hex\0"
+    "v2i_ASN1_BIT_STRING\0"
+    "v2i_AUTHORITY_INFO_ACCESS\0"
+    "v2i_AUTHORITY_KEYID\0"
+    "v2i_BASIC_CONSTRAINTS\0"
+    "v2i_EXTENDED_KEY_USAGE\0"
+    "v2i_GENERAL_NAMES\0"
+    "v2i_GENERAL_NAME_ex\0"
+    "v2i_NAME_CONSTRAINTS\0"
+    "v2i_POLICY_CONSTRAINTS\0"
+    "v2i_POLICY_MAPPINGS\0"
+    "v2i_crld\0"
+    "v2i_idp\0"
+    "v2i_issuer_alt\0"
+    "v2i_subject_alt\0"
+    "v3_generic_extension\0"
+    "";
+
+const uint32_t kOpenSSLReasonValues[] = {
+    0xc3207ba,
+    0xc3287c7,
+    0xc3307d6,
+    0xc3387e6,
+    0xc3407f5,
+    0xc34880e,
+    0xc35081a,
+    0xc358837,
+    0xc360849,
+    0xc368857,
+    0xc370867,
+    0xc378874,
+    0xc380884,
+    0xc38888f,
+    0xc3908a5,
+    0xc3988b4,
+    0xc3a08c8,
+    0x10321417,
+    0x10329423,
+    0x1033143c,
+    0x1033944f,
+    0x10340da9,
+    0x10349462,
+    0x10351477,
+    0x1035948a,
+    0x103614a3,
+    0x103694b8,
+    0x103714d6,
+    0x103794e5,
+    0x10381501,
+    0x1038951c,
+    0x1039152b,
+    0x10399547,
+    0x103a1562,
+    0x103a9579,
+    0x103b158a,
+    0x103b959e,
+    0x103c15bd,
+    0x103c95cc,
+    0x103d15e3,
+    0x103d95f6,
+    0x103e0b5f,
+    0x103e9609,
+    0x103f161c,
+    0x103f9636,
+    0x10401646,
+    0x1040965a,
+    0x10411670,
+    0x10419688,
+    0x1042169d,
+    0x104296b1,
+    0x104316c3,
+    0x104385d0,
+    0x104408b4,
+    0x104496d8,
+    0x104516ef,
+    0x10459704,
+    0x10461712,
+    0x14320b42,
+    0x14328b50,
+    0x14330b5f,
+    0x14338b71,
+    0x18320083,
+    0x18328dff,
+    0x18330e15,
+    0x18338094,
+    0x18340e2d,
+    0x18348e41,
+    0x18350e56,
+    0x18358e78,
+    0x18360e90,
+    0x18368ea5,
+    0x18370eb8,
+    0x18378ecc,
+    0x18380ef0,
+    0x18388efe,
+    0x18390f14,
+    0x18398f28,
+    0x183a0f38,
+    0x183a89cc,
+    0x183b0f48,
+    0x183b8f5d,
+    0x183c0f74,
+    0x183c8f88,
+    0x183d0f9c,
+    0x183d8fac,
+    0x183e0b8e,
+    0x183e8fb9,
+    0x183f0fcb,
+    0x183f8fd6,
+    0x18400fe6,
+    0x18408ff7,
+    0x18411008,
+    0x1841901a,
+    0x18421043,
+    0x1842905c,
+    0x1843106b,
+    0x1843907f,
+    0x184410a0,
+    0x184490b8,
+    0x184510d4,
+    0x184590ea,
+    0x18461105,
+    0x1846866b,
+    0x18471120,
+    0x1847913b,
+    0x20321162,
+    0x2432116e,
+    0x243288fa,
+    0x24331180,
+    0x2433918d,
+    0x2434119a,
+    0x243491ac,
+    0x243511bb,
+    0x243591d8,
+    0x243611e5,
+    0x243691f3,
+    0x24371201,
+    0x2437920f,
+    0x24381218,
+    0x24389225,
+    0x24391238,
+    0x28320b82,
+    0x28328b8e,
+    0x28330b5f,
+    0x28338ba1,
+    0x2c3229d2,
+    0x2c32a9e0,
+    0x2c3329f2,
+    0x2c33aa04,
+    0x2c342a18,
+    0x2c34aa2a,
+    0x2c352a45,
+    0x2c35aa57,
+    0x2c362a6a,
+    0x2c3682f3,
+    0x2c372a77,
+    0x2c37aa89,
+    0x2c382a9c,
+    0x2c38aaaa,
+    0x2c392aba,
+    0x2c39aacc,
+    0x2c3a2ae0,
+    0x2c3aaaf1,
+    0x2c3b12f8,
+    0x2c3bab02,
+    0x2c3c2b16,
+    0x2c3cab2c,
+    0x2c3d2b45,
+    0x2c3dab73,
+    0x2c3e2b81,
+    0x2c3eab99,
+    0x2c3f2bb1,
+    0x2c3fabbe,
+    0x2c402be1,
+    0x2c40ac00,
+    0x2c411162,
+    0x2c41ac11,
+    0x2c422c24,
+    0x2c4290d4,
+    0x2c432c35,
+    0x2c4386a2,
+    0x2c442b62,
+    0x30320000,
+    0x30328015,
+    0x3033001f,
+    0x30338038,
+    0x3034004a,
+    0x30348064,
+    0x3035006b,
+    0x30358083,
+    0x30360094,
+    0x303680a1,
+    0x303700b0,
+    0x303780bd,
+    0x303800d0,
+    0x303880eb,
+    0x30390100,
+    0x30398114,
+    0x303a0128,
+    0x303a8139,
+    0x303b0152,
+    0x303b816f,
+    0x303c017d,
+    0x303c8191,
+    0x303d01a1,
+    0x303d81ba,
+    0x303e01ca,
+    0x303e81dd,
+    0x303f01ec,
+    0x303f81f8,
+    0x3040020d,
+    0x3040821d,
+    0x30410234,
+    0x30418241,
+    0x30420254,
+    0x30428263,
+    0x30430278,
+    0x30438299,
+    0x304402ac,
+    0x304482bf,
+    0x304502d8,
+    0x304582f3,
+    0x30460310,
+    0x30468329,
+    0x30470337,
+    0x30478348,
+    0x30480357,
+    0x3048836f,
+    0x30490381,
+    0x30498395,
+    0x304a03b4,
+    0x304a83c7,
+    0x304b03d2,
+    0x304b83e1,
+    0x304c03f2,
+    0x304c83fe,
+    0x304d0414,
+    0x304d8422,
+    0x304e0438,
+    0x304e844a,
+    0x304f045c,
+    0x304f846f,
+    0x30500482,
+    0x30508493,
+    0x305104a3,
+    0x305184bb,
+    0x305204d0,
+    0x305284e8,
+    0x305304fc,
+    0x30538514,
+    0x3054052d,
+    0x30548546,
+    0x30550563,
+    0x3055856e,
+    0x30560586,
+    0x30568596,
+    0x305705a7,
+    0x305785ba,
+    0x305805d0,
+    0x305885d9,
+    0x305905ee,
+    0x30598601,
+    0x305a0610,
+    0x305a8630,
+    0x305b063f,
+    0x305b864b,
+    0x305c066b,
+    0x305c8687,
+    0x305d0698,
+    0x305d86a2,
+    0x34320abc,
+    0x34328ad0,
+    0x34330aed,
+    0x34338b00,
+    0x34340b0f,
+    0x34348b2c,
+    0x3c320083,
+    0x3c328bb7,
+    0x3c330bd0,
+    0x3c338beb,
+    0x3c340c08,
+    0x3c348c23,
+    0x3c350c3e,
+    0x3c358c53,
+    0x3c360c6c,
+    0x3c368c84,
+    0x3c370c95,
+    0x3c378ca3,
+    0x3c380cb0,
+    0x3c388cc4,
+    0x3c390b8e,
+    0x3c398cd8,
+    0x3c3a0cec,
+    0x3c3a8874,
+    0x3c3b0cfc,
+    0x3c3b8d17,
+    0x3c3c0d29,
+    0x3c3c8d3f,
+    0x3c3d0d49,
+    0x3c3d8d5d,
+    0x3c3e0d6b,
+    0x3c3e8d79,
+    0x40321729,
+    0x4032973f,
+    0x4033176d,
+    0x40339777,
+    0x4034178e,
+    0x403497ac,
+    0x403517bc,
+    0x403597ce,
+    0x403617db,
+    0x403697e7,
+    0x403717fc,
+    0x40379811,
+    0x40381823,
+    0x4038982e,
+    0x40391840,
+    0x40398da9,
+    0x403a1850,
+    0x403a9863,
+    0x403b1884,
+    0x403b9895,
+    0x403c18a5,
+    0x403c8064,
+    0x403d18b1,
+    0x403d98cd,
+    0x403e18e3,
+    0x403e98f2,
+    0x403f1905,
+    0x403f991f,
+    0x4040192d,
+    0x40409942,
+    0x40411956,
+    0x40419973,
+    0x4042198c,
+    0x404299a7,
+    0x404319c0,
+    0x404399d3,
+    0x404419e7,
+    0x404499ff,
+    0x40451a0f,
+    0x40459a1d,
+    0x40461a3b,
+    0x40468094,
+    0x40471a50,
+    0x40479a62,
+    0x40481a86,
+    0x40489aa6,
+    0x40491aba,
+    0x40499acf,
+    0x404a1ae8,
+    0x404a9b0b,
+    0x404b1b25,
+    0x404b9b43,
+    0x404c1b5e,
+    0x404c9b78,
+    0x404d1b8f,
+    0x404d9bb7,
+    0x404e1bce,
+    0x404e9bea,
+    0x404f1c06,
+    0x404f9c27,
+    0x40501c49,
+    0x40509c65,
+    0x40511c79,
+    0x40519c86,
+    0x40521c9d,
+    0x40529cad,
+    0x40531cbd,
+    0x40539cd1,
+    0x40541cec,
+    0x40549cfc,
+    0x40551d13,
+    0x40559d22,
+    0x40561d3d,
+    0x40569d55,
+    0x40571d71,
+    0x40579d8a,
+    0x40581d9d,
+    0x40589db2,
+    0x40591dd5,
+    0x40599de3,
+    0x405a1df0,
+    0x405a9e09,
+    0x405b1e21,
+    0x405b9e34,
+    0x405c1e49,
+    0x405c9e5b,
+    0x405d1e70,
+    0x405d9e80,
+    0x405e1e99,
+    0x405e9ead,
+    0x405f1ebd,
+    0x405f9ed5,
+    0x40601ee6,
+    0x40609ef9,
+    0x40611f0a,
+    0x40619f28,
+    0x40621f39,
+    0x40629f46,
+    0x40631f5d,
+    0x40639f7d,
+    0x40641f94,
+    0x40649fa1,
+    0x40651faf,
+    0x40659fd1,
+    0x40661ff9,
+    0x4066a00e,
+    0x40672025,
+    0x4067a036,
+    0x40682047,
+    0x4068a058,
+    0x4069206d,
+    0x4069a084,
+    0x406a2095,
+    0x406aa0ae,
+    0x406b20c9,
+    0x406ba0e0,
+    0x406c20f8,
+    0x406ca119,
+    0x406d212c,
+    0x406da14d,
+    0x406e2168,
+    0x406ea183,
+    0x406f21a4,
+    0x406fa1ca,
+    0x407021ea,
+    0x4070a206,
+    0x40712393,
+    0x4071a3b6,
+    0x407223cc,
+    0x4072a3eb,
+    0x40732403,
+    0x4073a423,
+    0x4074264d,
+    0x4074a672,
+    0x4075268d,
+    0x4075a6ac,
+    0x407626db,
+    0x4076a703,
+    0x4077271c,
+    0x4077a73b,
+    0x40782760,
+    0x4078a777,
+    0x4079278a,
+    0x4079a7a7,
+    0x407a0782,
+    0x407aa7b9,
+    0x407b27cc,
+    0x407ba7e5,
+    0x407c27fd,
+    0x407c905c,
+    0x407d2811,
+    0x407da82b,
+    0x407e283c,
+    0x407ea850,
+    0x407f285e,
+    0x407fa879,
+    0x40801225,
+    0x4080a89e,
+    0x408128c0,
+    0x4081a8db,
+    0x408228f0,
+    0x4082a908,
+    0x40832920,
+    0x4083a937,
+    0x4084294d,
+    0x4084a959,
+    0x4085296c,
+    0x4085a981,
+    0x40862993,
+    0x4086a9a8,
+    0x408729b1,
+    0x40879ba5,
+    0x41f422be,
+    0x41f92350,
+    0x41fe2243,
+    0x41fea474,
+    0x41ff2565,
+    0x420322d7,
+    0x420822f9,
+    0x4208a335,
+    0x42092227,
+    0x4209a36f,
+    0x420a227e,
+    0x420aa25e,
+    0x420b229e,
+    0x420ba317,
+    0x420c2581,
+    0x420ca441,
+    0x420d245b,
+    0x420da492,
+    0x421224ac,
+    0x42172548,
+    0x4217a4ee,
+    0x421c2510,
+    0x421f24cb,
+    0x42212598,
+    0x4226252b,
+    0x422b2631,
+    0x422ba5fa,
+    0x422c2619,
+    0x422ca5d4,
+    0x422d25b3,
+    0x443206ad,
+    0x443286bc,
+    0x443306c8,
+    0x443386d6,
+    0x443406e9,
+    0x443486fa,
+    0x44350701,
+    0x4435870b,
+    0x4436071e,
+    0x44368734,
+    0x44370746,
+    0x44378753,
+    0x44380762,
+    0x4438876a,
+    0x44390782,
+    0x44398790,
+    0x443a07a3,
+    0x4c32124f,
+    0x4c32925f,
+    0x4c331272,
+    0x4c339292,
+    0x4c340094,
+    0x4c3480b0,
+    0x4c35129e,
+    0x4c3592ac,
+    0x4c3612c8,
+    0x4c3692db,
+    0x4c3712ea,
+    0x4c3792f8,
+    0x4c38130d,
+    0x4c389319,
+    0x4c391339,
+    0x4c399363,
+    0x4c3a137c,
+    0x4c3a9395,
+    0x4c3b05d0,
+    0x4c3b93ae,
+    0x4c3c13c0,
+    0x4c3c93cf,
+    0x4c3d105c,
+    0x4c3d93e8,
+    0x4c3e13f5,
+    0x50322c47,
+    0x5032ac56,
+    0x50332c61,
+    0x5033ac71,
+    0x50342c8a,
+    0x5034aca4,
+    0x50352cb2,
+    0x5035acc8,
+    0x50362cda,
+    0x5036acf0,
+    0x50372d09,
+    0x5037ad1c,
+    0x50382d34,
+    0x5038ad45,
+    0x50392d5a,
+    0x5039ad6e,
+    0x503a2d8e,
+    0x503aada4,
+    0x503b2dbc,
+    0x503badce,
+    0x503c2dea,
+    0x503cae01,
+    0x503d2e1a,
+    0x503dae30,
+    0x503e2e3d,
+    0x503eae53,
+    0x503f2e65,
+    0x503f8348,
+    0x50402e78,
+    0x5040ae88,
+    0x50412ea2,
+    0x5041aeb1,
+    0x50422ecb,
+    0x5042aee8,
+    0x50432ef8,
+    0x5043af08,
+    0x50442f17,
+    0x50448414,
+    0x50452f2b,
+    0x5045af49,
+    0x50462f5c,
+    0x5046af72,
+    0x50472f84,
+    0x5047af99,
+    0x50482fbf,
+    0x5048afcd,
+    0x50492fe0,
+    0x5049aff5,
+    0x504a300b,
+    0x504ab01b,
+    0x504b303b,
+    0x504bb04e,
+    0x504c3071,
+    0x504cb09f,
+    0x504d30b1,
+    0x504db0ce,
+    0x504e30e9,
+    0x504eb105,
+    0x504f3117,
+    0x504fb12e,
+    0x5050313d,
+    0x50508687,
+    0x50513150,
+    0x58320de7,
+    0x68320da9,
+    0x68328b8e,
+    0x68330ba1,
+    0x68338db7,
+    0x68340dc7,
+    0x6c320d85,
+    0x6c328b71,
+    0x6c330d90,
+    0x74320980,
+    0x783208e5,
+    0x783288fa,
+    0x78330906,
+    0x78338083,
+    0x78340915,
+    0x7834892a,
+    0x78350949,
+    0x7835896b,
+    0x78360980,
+    0x78368996,
+    0x783709a6,
+    0x783789b9,
+    0x783809cc,
+    0x783889de,
+    0x783909eb,
+    0x78398a0a,
+    0x783a0a1f,
+    0x783a8a2d,
+    0x783b0a37,
+    0x783b8a4b,
+    0x783c0a62,
+    0x783c8a77,
+    0x783d0a8e,
+    0x783d8aa3,
+    0x783e09f9,
+    0x80321151,
+};
+
+const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]);
+
+const char kOpenSSLReasonStringData[] =
+    "ASN1_LENGTH_MISMATCH\0"
+    "AUX_ERROR\0"
+    "BAD_GET_ASN1_OBJECT_CALL\0"
+    "BAD_OBJECT_HEADER\0"
+    "BMPSTRING_IS_WRONG_LENGTH\0"
+    "BN_LIB\0"
+    "BOOLEAN_IS_WRONG_LENGTH\0"
+    "BUFFER_TOO_SMALL\0"
+    "DECODE_ERROR\0"
+    "DEPTH_EXCEEDED\0"
+    "ENCODE_ERROR\0"
+    "ERROR_GETTING_TIME\0"
+    "EXPECTING_AN_ASN1_SEQUENCE\0"
+    "EXPECTING_AN_INTEGER\0"
+    "EXPECTING_AN_OBJECT\0"
+    "EXPECTING_A_BOOLEAN\0"
+    "EXPECTING_A_TIME\0"
+    "EXPLICIT_LENGTH_MISMATCH\0"
+    "EXPLICIT_TAG_NOT_CONSTRUCTED\0"
+    "FIELD_MISSING\0"
+    "FIRST_NUM_TOO_LARGE\0"
+    "HEADER_TOO_LONG\0"
+    "ILLEGAL_BITSTRING_FORMAT\0"
+    "ILLEGAL_BOOLEAN\0"
+    "ILLEGAL_CHARACTERS\0"
+    "ILLEGAL_FORMAT\0"
+    "ILLEGAL_HEX\0"
+    "ILLEGAL_IMPLICIT_TAG\0"
+    "ILLEGAL_INTEGER\0"
+    "ILLEGAL_NESTED_TAGGING\0"
+    "ILLEGAL_NULL\0"
+    "ILLEGAL_NULL_VALUE\0"
+    "ILLEGAL_OBJECT\0"
+    "ILLEGAL_OPTIONAL_ANY\0"
+    "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\0"
+    "ILLEGAL_TAGGED_ANY\0"
+    "ILLEGAL_TIME_VALUE\0"
+    "INTEGER_NOT_ASCII_FORMAT\0"
+    "INTEGER_TOO_LARGE_FOR_LONG\0"
+    "INVALID_BIT_STRING_BITS_LEFT\0"
+    "INVALID_BMPSTRING_LENGTH\0"
+    "INVALID_DIGIT\0"
+    "INVALID_MODIFIER\0"
+    "INVALID_NUMBER\0"
+    "INVALID_OBJECT_ENCODING\0"
+    "INVALID_SEPARATOR\0"
+    "INVALID_TIME_FORMAT\0"
+    "INVALID_UNIVERSALSTRING_LENGTH\0"
+    "INVALID_UTF8STRING\0"
+    "LIST_ERROR\0"
+    "MALLOC_FAILURE\0"
+    "MISSING_ASN1_EOS\0"
+    "MISSING_EOC\0"
+    "MISSING_SECOND_NUMBER\0"
+    "MISSING_VALUE\0"
+    "MSTRING_NOT_UNIVERSAL\0"
+    "MSTRING_WRONG_TAG\0"
+    "NESTED_ASN1_ERROR\0"
+    "NESTED_ASN1_STRING\0"
+    "NON_HEX_CHARACTERS\0"
+    "NOT_ASCII_FORMAT\0"
+    "NOT_ENOUGH_DATA\0"
+    "NO_MATCHING_CHOICE_TYPE\0"
+    "NULL_IS_WRONG_LENGTH\0"
+    "OBJECT_NOT_ASCII_FORMAT\0"
+    "ODD_NUMBER_OF_CHARS\0"
+    "SECOND_NUMBER_TOO_LARGE\0"
+    "SEQUENCE_LENGTH_MISMATCH\0"
+    "SEQUENCE_NOT_CONSTRUCTED\0"
+    "SEQUENCE_OR_SET_NEEDS_CONFIG\0"
+    "SHORT_LINE\0"
+    "STREAMING_NOT_SUPPORTED\0"
+    "STRING_TOO_LONG\0"
+    "STRING_TOO_SHORT\0"
+    "TAG_VALUE_TOO_HIGH\0"
+    "TIME_NOT_ASCII_FORMAT\0"
+    "TOO_LONG\0"
+    "TYPE_NOT_CONSTRUCTED\0"
+    "TYPE_NOT_PRIMITIVE\0"
+    "UNEXPECTED_EOC\0"
+    "UNIVERSALSTRING_IS_WRONG_LENGTH\0"
+    "UNKNOWN_FORMAT\0"
+    "UNKNOWN_TAG\0"
+    "UNSUPPORTED_ANY_DEFINED_BY_TYPE\0"
+    "UNSUPPORTED_PUBLIC_KEY_TYPE\0"
+    "UNSUPPORTED_TYPE\0"
+    "WRONG_TAG\0"
+    "WRONG_TYPE\0"
+    "BAD_FOPEN_MODE\0"
+    "BROKEN_PIPE\0"
+    "CONNECT_ERROR\0"
+    "ERROR_SETTING_NBIO\0"
+    "INVALID_ARGUMENT\0"
+    "IN_USE\0"
+    "KEEPALIVE\0"
+    "NBIO_CONNECT_ERROR\0"
+    "NO_HOSTNAME_SPECIFIED\0"
+    "NO_PORT_SPECIFIED\0"
+    "NO_SUCH_FILE\0"
+    "NULL_PARAMETER\0"
+    "SYS_LIB\0"
+    "UNABLE_TO_CREATE_SOCKET\0"
+    "UNINITIALIZED\0"
+    "UNSUPPORTED_METHOD\0"
+    "WRITE_TO_READ_ONLY_BIO\0"
+    "ARG2_LT_ARG3\0"
+    "BAD_RECIPROCAL\0"
+    "BIGNUM_TOO_LONG\0"
+    "BITS_TOO_SMALL\0"
+    "CALLED_WITH_EVEN_MODULUS\0"
+    "DIV_BY_ZERO\0"
+    "EXPAND_ON_STATIC_BIGNUM_DATA\0"
+    "INPUT_NOT_REDUCED\0"
+    "INVALID_RANGE\0"
+    "NEGATIVE_NUMBER\0"
+    "NOT_A_SQUARE\0"
+    "NOT_INITIALIZED\0"
+    "NO_INVERSE\0"
+    "PRIVATE_KEY_TOO_LARGE\0"
+    "P_IS_NOT_PRIME\0"
+    "TOO_MANY_ITERATIONS\0"
+    "TOO_MANY_TEMPORARY_VARIABLES\0"
+    "AES_KEY_SETUP_FAILED\0"
+    "BAD_DECRYPT\0"
+    "BAD_KEY_LENGTH\0"
+    "CTRL_NOT_IMPLEMENTED\0"
+    "CTRL_OPERATION_NOT_IMPLEMENTED\0"
+    "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\0"
+    "INITIALIZATION_ERROR\0"
+    "INPUT_NOT_INITIALIZED\0"
+    "INVALID_AD_SIZE\0"
+    "INVALID_KEY_LENGTH\0"
+    "INVALID_NONCE_SIZE\0"
+    "INVALID_OPERATION\0"
+    "IV_TOO_LARGE\0"
+    "NO_CIPHER_SET\0"
+    "NO_DIRECTION_SET\0"
+    "OUTPUT_ALIASES_INPUT\0"
+    "TAG_TOO_LARGE\0"
+    "TOO_LARGE\0"
+    "UNSUPPORTED_AD_SIZE\0"
+    "UNSUPPORTED_INPUT_SIZE\0"
+    "UNSUPPORTED_KEY_SIZE\0"
+    "UNSUPPORTED_NONCE_SIZE\0"
+    "UNSUPPORTED_TAG_SIZE\0"
+    "WRONG_FINAL_BLOCK_LENGTH\0"
+    "LIST_CANNOT_BE_NULL\0"
+    "MISSING_CLOSE_SQUARE_BRACKET\0"
+    "MISSING_EQUAL_SIGN\0"
+    "NO_CLOSE_BRACE\0"
+    "UNABLE_TO_CREATE_NEW_SECTION\0"
+    "VARIABLE_HAS_NO_VALUE\0"
+    "BAD_GENERATOR\0"
+    "INVALID_PUBKEY\0"
+    "MODULUS_TOO_LARGE\0"
+    "NO_PRIVATE_VALUE\0"
+    "BAD_Q_VALUE\0"
+    "MISSING_PARAMETERS\0"
+    "NEED_NEW_SETUP_VALUES\0"
+    "COORDINATES_OUT_OF_RANGE\0"
+    "D2I_ECPKPARAMETERS_FAILURE\0"
+    "EC_GROUP_NEW_BY_NAME_FAILURE\0"
+    "GROUP2PKPARAMETERS_FAILURE\0"
+    "I2D_ECPKPARAMETERS_FAILURE\0"
+    "INCOMPATIBLE_OBJECTS\0"
+    "INVALID_COMPRESSED_POINT\0"
+    "INVALID_COMPRESSION_BIT\0"
+    "INVALID_ENCODING\0"
+    "INVALID_FIELD\0"
+    "INVALID_FORM\0"
+    "INVALID_GROUP_ORDER\0"
+    "INVALID_PRIVATE_KEY\0"
+    "MISSING_PRIVATE_KEY\0"
+    "NON_NAMED_CURVE\0"
+    "PKPARAMETERS2GROUP_FAILURE\0"
+    "POINT_AT_INFINITY\0"
+    "POINT_IS_NOT_ON_CURVE\0"
+    "SLOT_FULL\0"
+    "UNDEFINED_GENERATOR\0"
+    "UNKNOWN_GROUP\0"
+    "UNKNOWN_ORDER\0"
+    "WRONG_ORDER\0"
+    "KDF_FAILED\0"
+    "POINT_ARITHMETIC_FAILURE\0"
+    "BAD_SIGNATURE\0"
+    "NOT_IMPLEMENTED\0"
+    "RANDOM_NUMBER_GENERATION_FAILED\0"
+    "OPERATION_NOT_SUPPORTED\0"
+    "COMMAND_NOT_SUPPORTED\0"
+    "CONTEXT_NOT_INITIALISED\0"
+    "DIFFERENT_KEY_TYPES\0"
+    "DIFFERENT_PARAMETERS\0"
+    "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\0"
+    "EXPECTING_AN_EC_KEY_KEY\0"
+    "EXPECTING_AN_RSA_KEY\0"
+    "EXPECTING_A_DH_KEY\0"
+    "EXPECTING_A_DSA_KEY\0"
+    "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0"
+    "INVALID_CURVE\0"
+    "INVALID_DIGEST_LENGTH\0"
+    "INVALID_DIGEST_TYPE\0"
+    "INVALID_KEYBITS\0"
+    "INVALID_MGF1_MD\0"
+    "INVALID_PADDING_MODE\0"
+    "INVALID_PSS_PARAMETERS\0"
+    "INVALID_PSS_SALTLEN\0"
+    "INVALID_SALT_LENGTH\0"
+    "INVALID_TRAILER\0"
+    "KEYS_NOT_SET\0"
+    "NO_DEFAULT_DIGEST\0"
+    "NO_KEY_SET\0"
+    "NO_MDC2_SUPPORT\0"
+    "NO_NID_FOR_CURVE\0"
+    "NO_OPERATION_SET\0"
+    "NO_PARAMETERS_SET\0"
+    "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0"
+    "OPERATON_NOT_INITIALIZED\0"
+    "UNKNOWN_DIGEST\0"
+    "UNKNOWN_MASK_DIGEST\0"
+    "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0"
+    "UNKNOWN_PUBLIC_KEY_TYPE\0"
+    "UNKNOWN_SIGNATURE_ALGORITHM\0"
+    "UNSUPPORTED_ALGORITHM\0"
+    "UNSUPPORTED_MASK_ALGORITHM\0"
+    "UNSUPPORTED_MASK_PARAMETER\0"
+    "UNSUPPORTED_SIGNATURE_TYPE\0"
+    "WRONG_PUBLIC_KEY_TYPE\0"
+    "OUTPUT_TOO_LARGE\0"
+    "UNKNOWN_NID\0"
+    "BAD_BASE64_DECODE\0"
+    "BAD_END_LINE\0"
+    "BAD_IV_CHARS\0"
+    "BAD_PASSWORD_READ\0"
+    "CIPHER_IS_NULL\0"
+    "ERROR_CONVERTING_PRIVATE_KEY\0"
+    "NOT_DEK_INFO\0"
+    "NOT_ENCRYPTED\0"
+    "NOT_PROC_TYPE\0"
+    "NO_START_LINE\0"
+    "READ_KEY\0"
+    "SHORT_HEADER\0"
+    "UNSUPPORTED_CIPHER\0"
+    "UNSUPPORTED_ENCRYPTION\0"
+    "BAD_PKCS12_DATA\0"
+    "BAD_PKCS12_VERSION\0"
+    "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0"
+    "CRYPT_ERROR\0"
+    "ENCRYPT_ERROR\0"
+    "ERROR_SETTING_CIPHER_PARAMS\0"
+    "INCORRECT_PASSWORD\0"
+    "KEYGEN_FAILURE\0"
+    "KEY_GEN_ERROR\0"
+    "METHOD_NOT_SUPPORTED\0"
+    "MISSING_MAC\0"
+    "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\0"
+    "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\0"
+    "PKCS12_TOO_DEEPLY_NESTED\0"
+    "PRIVATE_KEY_DECODE_ERROR\0"
+    "PRIVATE_KEY_ENCODE_ERROR\0"
+    "UNKNOWN_ALGORITHM\0"
+    "UNKNOWN_CIPHER\0"
+    "UNKNOWN_CIPHER_ALGORITHM\0"
+    "UNKNOWN_HASH\0"
+    "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\0"
+    "BAD_E_VALUE\0"
+    "BAD_FIXED_HEADER_DECRYPT\0"
+    "BAD_PAD_BYTE_COUNT\0"
+    "BAD_RSA_PARAMETERS\0"
+    "BLOCK_TYPE_IS_NOT_01\0"
+    "BN_NOT_INITIALIZED\0"
+    "CRT_PARAMS_ALREADY_GIVEN\0"
+    "CRT_VALUES_INCORRECT\0"
+    "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\0"
+    "DATA_TOO_LARGE\0"
+    "DATA_TOO_LARGE_FOR_KEY_SIZE\0"
+    "DATA_TOO_LARGE_FOR_MODULUS\0"
+    "DATA_TOO_SMALL\0"
+    "DATA_TOO_SMALL_FOR_KEY_SIZE\0"
+    "DIGEST_TOO_BIG_FOR_RSA_KEY\0"
+    "D_E_NOT_CONGRUENT_TO_1\0"
+    "EMPTY_PUBLIC_KEY\0"
+    "FIRST_OCTET_INVALID\0"
+    "INCONSISTENT_SET_OF_CRT_VALUES\0"
+    "INTERNAL_ERROR\0"
+    "INVALID_MESSAGE_LENGTH\0"
+    "KEY_SIZE_TOO_SMALL\0"
+    "LAST_OCTET_INVALID\0"
+    "NO_PUBLIC_EXPONENT\0"
+    "NULL_BEFORE_BLOCK_MISSING\0"
+    "N_NOT_EQUAL_P_Q\0"
+    "OAEP_DECODING_ERROR\0"
+    "ONLY_ONE_OF_P_Q_GIVEN\0"
+    "OUTPUT_BUFFER_TOO_SMALL\0"
+    "PADDING_CHECK_FAILED\0"
+    "PKCS_DECODING_ERROR\0"
+    "SLEN_CHECK_FAILED\0"
+    "SLEN_RECOVERY_FAILED\0"
+    "UNKNOWN_ALGORITHM_TYPE\0"
+    "UNKNOWN_PADDING_TYPE\0"
+    "VALUE_MISSING\0"
+    "WRONG_SIGNATURE_LENGTH\0"
+    "APP_DATA_IN_HANDSHAKE\0"
+    "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\0"
+    "BAD_ALERT\0"
+    "BAD_CHANGE_CIPHER_SPEC\0"
+    "BAD_DATA_RETURNED_BY_CALLBACK\0"
+    "BAD_DH_P_LENGTH\0"
+    "BAD_DIGEST_LENGTH\0"
+    "BAD_ECC_CERT\0"
+    "BAD_ECPOINT\0"
+    "BAD_HANDSHAKE_LENGTH\0"
+    "BAD_HANDSHAKE_RECORD\0"
+    "BAD_HELLO_REQUEST\0"
+    "BAD_LENGTH\0"
+    "BAD_PACKET_LENGTH\0"
+    "BAD_RSA_ENCRYPT\0"
+    "BAD_SRTP_MKI_VALUE\0"
+    "BAD_SRTP_PROTECTION_PROFILE_LIST\0"
+    "BAD_SSL_FILETYPE\0"
+    "BAD_WRITE_RETRY\0"
+    "BIO_NOT_SET\0"
+    "CANNOT_SERIALIZE_PUBLIC_KEY\0"
+    "CA_DN_LENGTH_MISMATCH\0"
+    "CA_DN_TOO_LONG\0"
+    "CCS_RECEIVED_EARLY\0"
+    "CERTIFICATE_VERIFY_FAILED\0"
+    "CERT_CB_ERROR\0"
+    "CERT_LENGTH_MISMATCH\0"
+    "CHANNEL_ID_NOT_P256\0"
+    "CHANNEL_ID_SIGNATURE_INVALID\0"
+    "CIPHER_CODE_WRONG_LENGTH\0"
+    "CIPHER_OR_HASH_UNAVAILABLE\0"
+    "CLIENTHELLO_PARSE_FAILED\0"
+    "CLIENTHELLO_TLSEXT\0"
+    "CONNECTION_REJECTED\0"
+    "CONNECTION_TYPE_NOT_SET\0"
+    "COOKIE_MISMATCH\0"
+    "D2I_ECDSA_SIG\0"
+    "DATA_BETWEEN_CCS_AND_FINISHED\0"
+    "DATA_LENGTH_TOO_LONG\0"
+    "DECRYPTION_FAILED\0"
+    "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\0"
+    "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\0"
+    "DIGEST_CHECK_FAILED\0"
+    "DTLS_MESSAGE_TOO_BIG\0"
+    "ECC_CERT_NOT_FOR_SIGNING\0"
+    "EMPTY_SRTP_PROTECTION_PROFILE_LIST\0"
+    "ENCRYPTED_LENGTH_TOO_LONG\0"
+    "ERROR_IN_RECEIVED_CIPHER_LIST\0"
+    "EVP_DIGESTSIGNFINAL_FAILED\0"
+    "EVP_DIGESTSIGNINIT_FAILED\0"
+    "EXCESSIVE_MESSAGE_SIZE\0"
+    "EXTRA_DATA_IN_MESSAGE\0"
+    "FRAGMENT_MISMATCH\0"
+    "GOT_A_FIN_BEFORE_A_CCS\0"
+    "GOT_CHANNEL_ID_BEFORE_A_CCS\0"
+    "GOT_NEXT_PROTO_BEFORE_A_CCS\0"
+    "GOT_NEXT_PROTO_WITHOUT_EXTENSION\0"
+    "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\0"
+    "HANDSHAKE_RECORD_BEFORE_CCS\0"
+    "HTTPS_PROXY_REQUEST\0"
+    "HTTP_REQUEST\0"
+    "INAPPROPRIATE_FALLBACK\0"
+    "INVALID_COMMAND\0"
+    "INVALID_MESSAGE\0"
+    "INVALID_SSL_SESSION\0"
+    "INVALID_TICKET_KEYS_LENGTH\0"
+    "LENGTH_MISMATCH\0"
+    "LIBRARY_HAS_NO_CIPHERS\0"
+    "MISSING_DH_KEY\0"
+    "MISSING_ECDSA_SIGNING_CERT\0"
+    "MISSING_RSA_CERTIFICATE\0"
+    "MISSING_RSA_ENCRYPTING_CERT\0"
+    "MISSING_RSA_SIGNING_CERT\0"
+    "MISSING_TMP_DH_KEY\0"
+    "MISSING_TMP_ECDH_KEY\0"
+    "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\0"
+    "MTU_TOO_SMALL\0"
+    "NESTED_GROUP\0"
+    "NO_CERTIFICATES_RETURNED\0"
+    "NO_CERTIFICATE_ASSIGNED\0"
+    "NO_CERTIFICATE_SET\0"
+    "NO_CIPHERS_AVAILABLE\0"
+    "NO_CIPHERS_PASSED\0"
+    "NO_CIPHERS_SPECIFIED\0"
+    "NO_CIPHER_MATCH\0"
+    "NO_COMPRESSION_SPECIFIED\0"
+    "NO_METHOD_SPECIFIED\0"
+    "NO_P256_SUPPORT\0"
+    "NO_PRIVATE_KEY_ASSIGNED\0"
+    "NO_RENEGOTIATION\0"
+    "NO_REQUIRED_DIGEST\0"
+    "NO_SHARED_CIPHER\0"
+    "NO_SHARED_SIGATURE_ALGORITHMS\0"
+    "NO_SRTP_PROFILES\0"
+    "NULL_SSL_CTX\0"
+    "NULL_SSL_METHOD_PASSED\0"
+    "OLD_SESSION_CIPHER_NOT_RETURNED\0"
+    "PACKET_LENGTH_TOO_LONG\0"
+    "PARSE_TLSEXT\0"
+    "PATH_TOO_LONG\0"
+    "PEER_DID_NOT_RETURN_A_CERTIFICATE\0"
+    "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0"
+    "PROTOCOL_IS_SHUTDOWN\0"
+    "PSK_IDENTITY_NOT_FOUND\0"
+    "PSK_NO_CLIENT_CB\0"
+    "PSK_NO_SERVER_CB\0"
+    "READ_BIO_NOT_SET\0"
+    "READ_TIMEOUT_EXPIRED\0"
+    "RECORD_LENGTH_MISMATCH\0"
+    "RECORD_TOO_LARGE\0"
+    "RENEGOTIATE_EXT_TOO_LONG\0"
+    "RENEGOTIATION_ENCODING_ERR\0"
+    "RENEGOTIATION_MISMATCH\0"
+    "REQUIRED_CIPHER_MISSING\0"
+    "SCSV_RECEIVED_WHEN_RENEGOTIATING\0"
+    "SERVERHELLO_TLSEXT\0"
+    "SESSION_ID_CONTEXT_UNINITIALIZED\0"
+    "SESSION_MAY_NOT_BE_CREATED\0"
+    "SIGNATURE_ALGORITHMS_ERROR\0"
+    "SRTP_COULD_NOT_ALLOCATE_PROFILES\0"
+    "SRTP_PROTECTION_PROFILE_LIST_TOO_LONG\0"
+    "SRTP_UNKNOWN_PROTECTION_PROFILE\0"
+    "SSL3_EXT_INVALID_SERVERNAME\0"
+    "SSL3_EXT_INVALID_SERVERNAME_TYPE\0"
+    "SSLV3_ALERT_BAD_CERTIFICATE\0"
+    "SSLV3_ALERT_BAD_RECORD_MAC\0"
+    "SSLV3_ALERT_CERTIFICATE_EXPIRED\0"
+    "SSLV3_ALERT_CERTIFICATE_REVOKED\0"
+    "SSLV3_ALERT_CERTIFICATE_UNKNOWN\0"
+    "SSLV3_ALERT_CLOSE_NOTIFY\0"
+    "SSLV3_ALERT_DECOMPRESSION_FAILURE\0"
+    "SSLV3_ALERT_HANDSHAKE_FAILURE\0"
+    "SSLV3_ALERT_ILLEGAL_PARAMETER\0"
+    "SSLV3_ALERT_NO_CERTIFICATE\0"
+    "SSLV3_ALERT_UNEXPECTED_MESSAGE\0"
+    "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\0"
+    "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\0"
+    "SSL_HANDSHAKE_FAILURE\0"
+    "SSL_SESSION_ID_CALLBACK_FAILED\0"
+    "SSL_SESSION_ID_CONFLICT\0"
+    "SSL_SESSION_ID_CONTEXT_TOO_LONG\0"
+    "SSL_SESSION_ID_HAS_BAD_LENGTH\0"
+    "TLSV1_ALERT_ACCESS_DENIED\0"
+    "TLSV1_ALERT_DECODE_ERROR\0"
+    "TLSV1_ALERT_DECRYPTION_FAILED\0"
+    "TLSV1_ALERT_DECRYPT_ERROR\0"
+    "TLSV1_ALERT_EXPORT_RESTRICTION\0"
+    "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\0"
+    "TLSV1_ALERT_INSUFFICIENT_SECURITY\0"
+    "TLSV1_ALERT_INTERNAL_ERROR\0"
+    "TLSV1_ALERT_NO_RENEGOTIATION\0"
+    "TLSV1_ALERT_PROTOCOL_VERSION\0"
+    "TLSV1_ALERT_RECORD_OVERFLOW\0"
+    "TLSV1_ALERT_UNKNOWN_CA\0"
+    "TLSV1_ALERT_USER_CANCELLED\0"
+    "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0"
+    "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0"
+    "TLSV1_CERTIFICATE_UNOBTAINABLE\0"
+    "TLSV1_UNRECOGNIZED_NAME\0"
+    "TLSV1_UNSUPPORTED_EXTENSION\0"
+    "TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER\0"
+    "TLS_ILLEGAL_EXPORTER_LABEL\0"
+    "TLS_INVALID_ECPOINTFORMAT_LIST\0"
+    "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0"
+    "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\0"
+    "TOO_MANY_EMPTY_FRAGMENTS\0"
+    "UNABLE_TO_FIND_ECDH_PARAMETERS\0"
+    "UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS\0"
+    "UNEXPECTED_GROUP_CLOSE\0"
+    "UNEXPECTED_MESSAGE\0"
+    "UNEXPECTED_OPERATOR_IN_GROUP\0"
+    "UNEXPECTED_RECORD\0"
+    "UNKNOWN_ALERT_TYPE\0"
+    "UNKNOWN_CERTIFICATE_TYPE\0"
+    "UNKNOWN_CIPHER_RETURNED\0"
+    "UNKNOWN_CIPHER_TYPE\0"
+    "UNKNOWN_KEY_EXCHANGE_TYPE\0"
+    "UNKNOWN_PROTOCOL\0"
+    "UNKNOWN_SSL_VERSION\0"
+    "UNKNOWN_STATE\0"
+    "UNPROCESSED_HANDSHAKE_DATA\0"
+    "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\0"
+    "UNSUPPORTED_COMPRESSION_ALGORITHM\0"
+    "UNSUPPORTED_ELLIPTIC_CURVE\0"
+    "UNSUPPORTED_PROTOCOL\0"
+    "UNSUPPORTED_SSL_VERSION\0"
+    "USE_SRTP_NOT_NEGOTIATED\0"
+    "WRONG_CERTIFICATE_TYPE\0"
+    "WRONG_CIPHER_RETURNED\0"
+    "WRONG_CURVE\0"
+    "WRONG_MESSAGE_TYPE\0"
+    "WRONG_SIGNATURE_TYPE\0"
+    "WRONG_SSL_VERSION\0"
+    "WRONG_VERSION_NUMBER\0"
+    "X509_LIB\0"
+    "X509_VERIFICATION_SETUP_PROBLEMS\0"
+    "AKID_MISMATCH\0"
+    "BAD_PKCS7_VERSION\0"
+    "BAD_X509_FILETYPE\0"
+    "BASE64_DECODE_ERROR\0"
+    "CANT_CHECK_DH_KEY\0"
+    "CERT_ALREADY_IN_HASH_TABLE\0"
+    "CRL_ALREADY_DELTA\0"
+    "CRL_VERIFY_FAILURE\0"
+    "IDP_MISMATCH\0"
+    "INVALID_DIRECTORY\0"
+    "INVALID_FIELD_NAME\0"
+    "INVALID_TRUST\0"
+    "ISSUER_MISMATCH\0"
+    "KEY_TYPE_MISMATCH\0"
+    "KEY_VALUES_MISMATCH\0"
+    "LOADING_CERT_DIR\0"
+    "LOADING_DEFAULTS\0"
+    "NEWER_CRL_NOT_NEWER\0"
+    "NOT_PKCS7_SIGNED_DATA\0"
+    "NO_CERTIFICATES_INCLUDED\0"
+    "NO_CERT_SET_FOR_US_TO_VERIFY\0"
+    "NO_CRLS_INCLUDED\0"
+    "NO_CRL_NUMBER\0"
+    "PUBLIC_KEY_DECODE_ERROR\0"
+    "PUBLIC_KEY_ENCODE_ERROR\0"
+    "SHOULD_RETRY\0"
+    "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN\0"
+    "UNABLE_TO_GET_CERTS_PUBLIC_KEY\0"
+    "UNKNOWN_KEY_TYPE\0"
+    "UNKNOWN_PURPOSE_ID\0"
+    "UNKNOWN_TRUST_ID\0"
+    "WRONG_LOOKUP_TYPE\0"
+    "BAD_IP_ADDRESS\0"
+    "BAD_OBJECT\0"
+    "BN_DEC2BN_ERROR\0"
+    "BN_TO_ASN1_INTEGER_ERROR\0"
+    "CANNOT_FIND_FREE_FUNCTION\0"
+    "DIRNAME_ERROR\0"
+    "DISTPOINT_ALREADY_SET\0"
+    "DUPLICATE_ZONE_ID\0"
+    "ERROR_CONVERTING_ZONE\0"
+    "ERROR_CREATING_EXTENSION\0"
+    "ERROR_IN_EXTENSION\0"
+    "EXPECTED_A_SECTION_NAME\0"
+    "EXTENSION_EXISTS\0"
+    "EXTENSION_NAME_ERROR\0"
+    "EXTENSION_NOT_FOUND\0"
+    "EXTENSION_SETTING_NOT_SUPPORTED\0"
+    "EXTENSION_VALUE_ERROR\0"
+    "ILLEGAL_EMPTY_EXTENSION\0"
+    "ILLEGAL_HEX_DIGIT\0"
+    "INCORRECT_POLICY_SYNTAX_TAG\0"
+    "INVALID_BOOLEAN_STRING\0"
+    "INVALID_EXTENSION_STRING\0"
+    "INVALID_MULTIPLE_RDNS\0"
+    "INVALID_NAME\0"
+    "INVALID_NULL_ARGUMENT\0"
+    "INVALID_NULL_NAME\0"
+    "INVALID_NULL_VALUE\0"
+    "INVALID_NUMBERS\0"
+    "INVALID_OBJECT_IDENTIFIER\0"
+    "INVALID_OPTION\0"
+    "INVALID_POLICY_IDENTIFIER\0"
+    "INVALID_PROXY_POLICY_SETTING\0"
+    "INVALID_PURPOSE\0"
+    "INVALID_SECTION\0"
+    "INVALID_SYNTAX\0"
+    "ISSUER_DECODE_ERROR\0"
+    "NEED_ORGANIZATION_AND_NUMBERS\0"
+    "NO_CONFIG_DATABASE\0"
+    "NO_ISSUER_CERTIFICATE\0"
+    "NO_ISSUER_DETAILS\0"
+    "NO_POLICY_IDENTIFIER\0"
+    "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\0"
+    "NO_PUBLIC_KEY\0"
+    "NO_SUBJECT_DETAILS\0"
+    "ODD_NUMBER_OF_DIGITS\0"
+    "OPERATION_NOT_DEFINED\0"
+    "OTHERNAME_ERROR\0"
+    "POLICY_LANGUAGE_ALREADY_DEFINED\0"
+    "POLICY_PATH_LENGTH\0"
+    "POLICY_PATH_LENGTH_ALREADY_DEFINED\0"
+    "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\0"
+    "SECTION_NOT_FOUND\0"
+    "UNABLE_TO_GET_ISSUER_DETAILS\0"
+    "UNABLE_TO_GET_ISSUER_KEYID\0"
+    "UNKNOWN_BIT_STRING_ARGUMENT\0"
+    "UNKNOWN_EXTENSION\0"
+    "UNKNOWN_EXTENSION_NAME\0"
+    "UNKNOWN_OPTION\0"
+    "UNSUPPORTED_OPTION\0"
+    "USER_TOO_LONG\0"
+    "";
+
diff --git a/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S
index b01ad7f..5f4b057 100644
--- a/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S
@@ -1294,7 +1294,8 @@
 .globl	asm_AES_cbc_encrypt
 .hidden asm_AES_cbc_encrypt
 .type	asm_AES_cbc_encrypt,@function
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 .hidden	asm_AES_cbc_encrypt
 asm_AES_cbc_encrypt:
 	cmpq	$0,%rdx
diff --git a/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S
index 9ab973d..ecefbe5 100644
--- a/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S
@@ -1,6 +1,7 @@
 #if defined(__x86_64__)
 .text	
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 .globl	aesni_encrypt
 .hidden aesni_encrypt
 .type	aesni_encrypt,@function
diff --git a/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S
index 2960e95..8cfa4df 100644
--- a/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S
@@ -1,8 +1,10 @@
 #if defined(__x86_64__)
 .text	
 
-
-
+.extern	asm_AES_encrypt
+.hidden asm_AES_encrypt
+.extern	asm_AES_decrypt
+.hidden asm_AES_decrypt
 
 .type	_bsaes_encrypt8,@function
 .align	64
@@ -1063,7 +1065,8 @@
 
 	.byte	0xf3,0xc3
 .size	_bsaes_key_convert,.-_bsaes_key_convert
-
+.extern	asm_AES_cbc_encrypt
+.hidden asm_AES_cbc_encrypt
 .globl	bsaes_cbc_encrypt
 .hidden bsaes_cbc_encrypt
 .type	bsaes_cbc_encrypt,@function
diff --git a/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S
index fe0eed5..dd3d310 100644
--- a/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S
@@ -1,7 +1,8 @@
 #if defined(__x86_64__)
 .text	
 
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 
 .globl	rsaz_512_sqr
 .hidden rsaz_512_sqr
diff --git a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S
index ebe7678..4d401c6 100644
--- a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S
+++ b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S
@@ -1,7 +1,8 @@
 #if defined(__x86_64__)
 .text	
 
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 
 .globl	bn_mul_mont
 .hidden bn_mul_mont
@@ -610,7 +611,8 @@
 .Lmul4x_epilogue:
 	.byte	0xf3,0xc3
 .size	bn_mul4x_mont,.-bn_mul4x_mont
-
+.extern	bn_sqr8x_internal
+.hidden bn_sqr8x_internal
 
 .type	bn_sqr8x_mont,@function
 .align	32
diff --git a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S
index 357bc11..02edc69 100644
--- a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S
+++ b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S
@@ -1,7 +1,8 @@
 #if defined(__x86_64__)
 .text	
 
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 
 .globl	bn_mul_mont_gather5
 .hidden bn_mul_mont_gather5
diff --git a/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S
index bd1b17f..1db7d69 100644
--- a/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S
@@ -1,6 +1,7 @@
 #if defined(__x86_64__)
 .text	
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 
 .globl	gcm_gmult_4bit
 .hidden gcm_gmult_4bit
diff --git a/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S
index d546154..c4d1002 100644
--- a/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S
@@ -1,6 +1,7 @@
 #if defined(__x86_64__)
 .text	
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 
 .globl	asm_RC4
 .hidden asm_RC4
diff --git a/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S
index ea2f403..7668c2b 100644
--- a/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S
@@ -1,6 +1,7 @@
 #if defined(__x86_64__)
 .text	
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 
 .globl	sha1_block_data_order
 .hidden sha1_block_data_order
diff --git a/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S
index 4649baf..f526de5 100644
--- a/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S
@@ -1,7 +1,8 @@
 #if defined(__x86_64__)
 .text	
 
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 .globl	sha256_block_data_order
 .hidden sha256_block_data_order
 .type	sha256_block_data_order,@function
diff --git a/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S
index 89fd5bf..ca3a3a1 100644
--- a/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S
@@ -1,7 +1,8 @@
 #if defined(__x86_64__)
 .text	
 
-
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 .globl	sha512_block_data_order
 .hidden sha512_block_data_order
 .type	sha512_block_data_order,@function
diff --git a/third_party/boringssl/update_gypi_and_asm.py b/third_party/boringssl/update_gypi_and_asm.py
index db11e64..1835695 100644
--- a/third_party/boringssl/update_gypi_and_asm.py
+++ b/third_party/boringssl/update_gypi_and_asm.py
@@ -193,6 +193,13 @@
   crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTests)
   ssl_c_files = FindCFiles(os.path.join('src', 'ssl'), NoTests)
 
+  # Generate err_data.c
+  with open('err_data.c', 'w+') as err_data:
+    subprocess.check_call(['go', 'run', 'err_data_generate.go'],
+                          cwd=os.path.join('src', 'crypto', 'err'),
+                          stdout=err_data)
+  crypto_c_files.append('err_data.c')
+
   with open('boringssl.gypi', 'w+') as gypi:
     gypi.write(FILE_HEADER + '{\n  \'variables\': {\n')
 
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium
index 368d604..fc027b0 100644
--- a/third_party/qcms/README.chromium
+++ b/third_party/qcms/README.chromium
@@ -55,5 +55,7 @@
    - https://code.google.com/p/chromium/issues/detail?id=443863
  - Add bgra (z,y,x) sampled transform lookup table api
    - https://code.google.com/p/chromium/issues/detail?id=443863
+ - Apply upstream fix reject invalid sizes from
+   - https://bugzilla.mozilla.org/show_bug.cgi?id=1132468
 To regenerate google.patch:
   git diff b8456f38 src > google.patch
diff --git a/third_party/qcms/google.patch b/third_party/qcms/google.patch
index ce60f9f..dea54fc 100644
--- a/third_party/qcms/google.patch
+++ b/third_party/qcms/google.patch
@@ -1,5 +1,5 @@
 diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c
-index 36b7011..aca19d3 100644
+index 36b7011..6cec34a 100644
 --- a/third_party/qcms/src/iccread.c
 +++ b/third_party/qcms/src/iccread.c
 @@ -266,7 +266,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
@@ -42,12 +42,13 @@
  
  static struct tag *find_tag(struct tag_index index, uint32_t tag_id)
  {
-@@ -344,6 +354,47 @@ static struct tag *find_tag(struct tag_index index, uint32_t tag_id)
+@@ -344,6 +354,152 @@ static struct tag *find_tag(struct tag_index index, uint32_t tag_id)
  	return tag;
  }
  
 +#define DESC_TYPE 0x64657363 // 'desc'
 +#define MLUC_TYPE 0x6d6c7563 // 'mluc'
++#define MMOD_TYPE 0x6D6D6F64 // 'mmod'
 +
 +static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id)
 +{
@@ -57,23 +58,31 @@
 +		uint32_t offset = tag->offset;
 +		uint32_t type = read_u32(src, offset);
 +		uint32_t length = read_u32(src, offset+8);
-+		uint32_t i, description;
++		uint32_t i, description_offset;
++		bool mluc = false;
 +		if (length && type == MLUC_TYPE) {
 +			length = read_u32(src, offset+20);
 +			if (!length || (length & 1) || (read_u32(src, offset+12) != 12))
 +				goto invalid_desc_tag;
-+			description = offset + read_u32(src, offset+24);
++			description_offset = offset + read_u32(src, offset+24);
 +			if (!src->valid)
 +				goto invalid_desc_tag;
++			mluc = true;
 +		} else if (length && type == DESC_TYPE) {
-+			description = offset + 12;
++			description_offset = offset + 12;
 +		} else {
 +			goto invalid_desc_tag;
 +		}
 +		if (length >= limit)
 +			length = limit - 1;
-+		for (i = 0; i < length; ++i)
-+			profile->description[i] = read_u8(src, description+i);
++		for (i = 0; i < length; ++i) {
++			uint8_t value = read_u8(src, description_offset + i);
++			if (!src->valid)
++				goto invalid_desc_tag;
++			if (mluc && !value)
++				value = '.';
++			profile->description[i] = value;
++		}
 +		profile->description[length] = 0;
 +	} else {
 +		goto invalid_desc_tag;
@@ -87,10 +96,106 @@
 +	return false;
 +}
 +
++#if defined(__APPLE__)
++
++// Use the dscm tag to change profile description "Display" to its more specific en-localized monitor name, if any.
++
++#define TAG_dscm  0x6473636D // 'dscm'
++
++static bool read_tag_dscmType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id)
++{
++	if (strcmp(profile->description, "Display") != 0)
++		return true;
++
++	struct tag *tag = find_tag(index, tag_id);
++	if (tag) {
++		uint32_t offset = tag->offset;
++		uint32_t type = read_u32(src, offset);
++		uint32_t records = read_u32(src, offset+8);
++
++		if (!src->valid || !records || type != MLUC_TYPE)
++			goto invalid_dscm_tag;
++		if (read_u32(src, offset+12) != 12) // MLUC record size: bytes
++			goto invalid_dscm_tag;
++
++		for (uint32_t i = 0; i < records; ++i) {
++			const uint32_t limit = sizeof profile->description;
++			const uint16_t isoen = 0x656E; // ISO-3166-1 language 'en'
++
++			uint16_t language = read_u16(src, offset + 16 + (i * 12) + 0);
++			uint32_t length = read_u32(src, offset + 16 + (i * 12) + 4);
++			uint32_t description_offset = read_u32(src, offset + 16 + (i * 12) + 8);
++
++			if (!src->valid || !length || (length & 1))
++				goto invalid_dscm_tag;
++			if (language != isoen)
++				continue;
++
++			// Use a prefix to identify the display description source
++			strcpy(profile->description, "dscm:");
++			length += 5;
++
++			if (length >= limit)
++				length = limit - 1;
++			for (uint32_t j = 5; j < length; ++j) {
++				uint8_t value = read_u8(src, offset + description_offset + j - 5);
++				if (!src->valid)
++					goto invalid_dscm_tag;
++				profile->description[j] = value ? value : '.';
++			}
++			profile->description[length] = 0;
++			break;
++		}
++	}
++
++	if (src->valid)
++		return true;
++
++invalid_dscm_tag:
++	invalid_source(src, "invalid dscm tag");
++	return false;
++}
++
++// Use the mmod tag to change profile description "Display" to its specific mmod maker model data, if any.
++
++#define TAG_mmod  0x6D6D6F64 // 'mmod'
++
++static bool read_tag_mmodType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id)
++{
++	if (strcmp(profile->description, "Display") != 0)
++		return true;
++
++	struct tag *tag = find_tag(index, tag_id);
++	if (tag) {
++		const uint8_t length = 4 * 4; // Four 4-byte fields: 'mmod', 0, maker, model.
++
++		uint32_t offset = tag->offset;
++		if (tag->size < 40 || read_u32(src, offset) != MMOD_TYPE)
++			goto invalid_mmod_tag;
++
++		for (uint8_t i = 0; i < length; ++i) {
++			uint8_t value = read_u8(src, offset + i);
++			if (!src->valid)
++				goto invalid_mmod_tag;
++			profile->description[i] = value ? value : '.';
++		}
++		profile->description[length] = 0;
++	}
++
++	if (src->valid)
++		return true;
++
++invalid_mmod_tag:
++	invalid_source(src, "invalid mmod tag");
++	return false;
++}
++
++#endif // __APPLE__
++
  #define XYZ_TYPE		0x58595a20 // 'XYZ '
  #define CURVE_TYPE		0x63757276 // 'curv'
  #define PARAMETRIC_CURVE_TYPE	0x70617261 // 'para'
-@@ -402,7 +453,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_inde
+@@ -402,7 +558,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_inde
  // present that are not part of the tag_index.
  static struct curveType *read_curveType(struct mem_source *src, uint32_t offset, uint32_t *len)
  {
@@ -99,7 +204,7 @@
  	struct curveType *curve = NULL;
  	uint32_t type = read_u32(src, offset);
  	uint32_t count;
-@@ -484,19 +535,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu
+@@ -484,19 +640,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu
  	uint32_t channel_offset = 0;
  	int i;
  	for (i = 0; i < num_channels; i++) {
@@ -125,7 +230,7 @@
  }
  
  static void mAB_release(struct lutmABType *lut)
-@@ -657,7 +712,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index
+@@ -657,7 +817,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index
  	uint16_t num_input_table_entries;
  	uint16_t num_output_table_entries;
  	uint8_t in_chan, grid_points, out_chan;
@@ -134,7 +239,7 @@
  	uint32_t clut_size;
  	size_t entry_size;
  	struct lutType *lut;
-@@ -979,6 +1034,9 @@ qcms_profile* qcms_profile_sRGB(void)
+@@ -979,6 +1139,9 @@ qcms_profile* qcms_profile_sRGB(void)
  		return NO_MEM_PROFILE;
  
  	profile = qcms_profile_create_rgb_with_table(D65, Rec709Primaries, table, 1024);
@@ -144,7 +249,7 @@
  	free(table);
  	return profile;
  }
-@@ -997,6 +1055,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
+@@ -997,6 +1160,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
  	source.size = size;
  	source.valid = true;
  
@@ -154,17 +259,23 @@
  	length = read_u32(src, 0);
  	if (length <= size) {
  		// shrink the area that we can read if appropriate
-@@ -1028,6 +1089,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
+@@ -1028,6 +1194,15 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
  	if (!src->valid || !index.tags)
  		goto invalid_tag_table;
  
 +	if (!read_tag_descType(profile, src, index, TAG_desc))
 +		goto invalid_tag_table;
++#if defined(__APPLE__)
++	if (!read_tag_dscmType(profile, src, index, TAG_dscm))
++		goto invalid_tag_table;
++	if (!read_tag_mmodType(profile, src, index, TAG_mmod))
++		goto invalid_tag_table;
++#endif // __APPLE__
 +
  	if (find_tag(index, TAG_CHAD)) {
  		profile->chromaticAdaption = read_tag_s15Fixed16ArrayType(src, index, TAG_CHAD);
  	} else {
-@@ -1098,6 +1162,16 @@ invalid_profile:
+@@ -1098,6 +1273,16 @@ invalid_profile:
  	return INVALID_PROFILE;
  }
  
@@ -182,7 +293,7 @@
  {
  	return profile->rendering_intent;
 diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h
-index 7d83623..c69a772 100644
+index 7d83623..e9c0b09 100644
 --- a/third_party/qcms/src/qcms.h
 +++ b/third_party/qcms/src/qcms.h
 @@ -40,6 +40,12 @@ sale, use or other dealings in this Software without written
@@ -221,11 +332,19 @@
  void qcms_profile_precache_output_transform(qcms_profile *profile);
  
  qcms_transform* qcms_transform_create(
-@@ -146,6 +161,7 @@ qcms_transform* qcms_transform_create(
- void qcms_transform_release(qcms_transform *);
+@@ -143,9 +158,14 @@ qcms_transform* qcms_transform_create(
+ 		qcms_profile* out, qcms_data_type out_type,
+ 		qcms_intent intent);
+ 
+-void qcms_transform_release(qcms_transform *);
++qcms_bool qcms_transform_create_LUT_zyx_bgra(
++		qcms_profile *in, qcms_profile* out, qcms_intent intent,
++		int samples, unsigned char* lut);
  
  void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length);
 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type);
++
++void qcms_transform_release(qcms_transform *);
  
  void qcms_enable_iccv4();
  
@@ -565,7 +684,7 @@
 +    dest[b_out] = otdata_b[output[2]];
  }
 diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
-index 9a6562b..08db142 100644
+index 9a6562b..f669a6b 100644
 --- a/third_party/qcms/src/transform.c
 +++ b/third_party/qcms/src/transform.c
 @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_point,
@@ -981,8 +1100,53 @@
  
  	/* don't precache if we do not have the TRC curves */
  	if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC)
-@@ -1078,7 +1153,8 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms
- 	//XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed
+@@ -1043,28 +1118,31 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms
+ 	float* src = NULL;
+ 	float* dest = NULL;
+ 	float* lut = NULL;
++	float inverse;
+ 
+ 	src = malloc(lutSize*sizeof(float));
+ 	dest = malloc(lutSize*sizeof(float));
+ 
+ 	if (src && dest) {
+-		/* Prepare a list of points we want to sample */
++		/* Prepare a list of points we want to sample: x, y, z order */
+ 		l = 0;
++		inverse = 1 / (float)(samples-1);
+ 		for (x = 0; x < samples; x++) {
+ 			for (y = 0; y < samples; y++) {
+ 				for (z = 0; z < samples; z++) {
+-					src[l++] = x / (float)(samples-1);
+-					src[l++] = y / (float)(samples-1);
+-					src[l++] = z / (float)(samples-1);
++					src[l++] = x * inverse; // r
++					src[l++] = y * inverse; // g
++					src[l++] = z * inverse; // b
+ 				}
+ 			}
+ 		}
+ 
+ 		lut = qcms_chain_transform(in, out, src, dest, lutSize);
++
+ 		if (lut) {
+-			transform->r_clut = &lut[0];
+-			transform->g_clut = &lut[1];
+-			transform->b_clut = &lut[2];
++			transform->r_clut = &lut[0]; // r
++			transform->g_clut = &lut[1]; // g
++			transform->b_clut = &lut[2]; // b
+ 			transform->grid_size = samples;
+ 			if (in_type == QCMS_DATA_RGBA_8) {
+ 				transform->transform_fn = qcms_transform_data_tetra_clut_rgba;
+@@ -1074,11 +1152,12 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms
+ 		}
+ 	}
+ 
+-
+-	//XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed
++	// XXX: qcms_modular_transform_data may return the lut in either the src or the
++	// dest buffer. If so, it must not be free-ed.
  	if (src && lut != src) {
  		free(src);
 -	} else if (dest && lut != src) {
@@ -991,7 +1155,79 @@
  		free(dest);
  	}
  
-@@ -1157,14 +1233,14 @@ qcms_transform* qcms_transform_create(
+@@ -1088,6 +1167,71 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms
+ 	return transform;
+ }
+ 
++/* Create a transform LUT using the given number of sample points. The transform LUT data is stored
++   in the output (cube) in bgra format in zyx sample order. */
++qcms_bool qcms_transform_create_LUT_zyx_bgra(qcms_profile *in, qcms_profile *out, qcms_intent intent,
++                                             int samples, unsigned char* cube)
++{
++	uint16_t z,y,x;
++	uint32_t l,index;
++	uint32_t lutSize = 3 * samples * samples * samples;
++
++	float* src = NULL;
++	float* dest = NULL;
++	float* lut = NULL;
++	float inverse;
++
++	src = malloc(lutSize*sizeof(float));
++	dest = malloc(lutSize*sizeof(float));
++
++	if (src && dest) {
++		/* Prepare a list of points we want to sample: z, y, x order */
++		l = 0;
++		inverse = 1 / (float)(samples-1);
++		for (z = 0; z < samples; z++) {
++			for (y = 0; y < samples; y++) {
++				for (x = 0; x < samples; x++) {
++					src[l++] = x * inverse; // r
++					src[l++] = y * inverse; // g
++					src[l++] = z * inverse; // b
++				}
++			}
++		}
++
++		lut = qcms_chain_transform(in, out, src, dest, lutSize);
++
++		if (lut) {
++			index = l = 0;
++			for (z = 0; z < samples; z++) {
++				for (y = 0; y < samples; y++) {
++					for (x = 0; x < samples; x++) {
++						cube[index++] = (int)floorf(lut[l + 2] * 255.0f + 0.5f); // b
++						cube[index++] = (int)floorf(lut[l + 1] * 255.0f + 0.5f); // g
++						cube[index++] = (int)floorf(lut[l + 0] * 255.0f + 0.5f); // r
++						cube[index++] = 255;                                     // a
++						l += 3;
++					}
++				}
++			}
++		}
++	}
++
++	// XXX: qcms_modular_transform_data may return the lut data in either the src or
++	// dest buffer so free src, dest, and lut with care.
++
++	if (src && lut != src)
++		free(src);
++	if (dest && lut != dest)
++		free(dest);
++
++	if (lut) {
++		free(lut);
++		return true;
++	}
++
++	return false;
++}
++
+ #define NO_MEM_TRANSFORM NULL
+ 
+ qcms_transform* qcms_transform_create(
+@@ -1157,14 +1301,14 @@ qcms_transform* qcms_transform_create(
                  	return NULL;
              	}
  		if (precache) {
@@ -1008,7 +1244,7 @@
                      /* Microsoft Compiler for x64 doesn't support MMX.
                       * SSE code uses MMX so that we disable on x64 */
  		    } else
-@@ -1256,13 +1332,34 @@ qcms_transform* qcms_transform_create(
+@@ -1256,13 +1400,34 @@ qcms_transform* qcms_transform_create(
  	return transform;
  }
  
diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c
index 6cec34a..208ebee 100644
--- a/third_party/qcms/src/iccread.c
+++ b/third_party/qcms/src/iccread.c
@@ -700,7 +700,7 @@
 	// We require 3in/out channels since we only support RGB->XYZ (or RGB->LAB)
 	// XXX: If we remove this restriction make sure that the number of channels
 	//      is less or equal to the maximum number of mAB curves in qcmsint.h
-	//      also check for clut_size overflow.
+	//      also check for clut_size overflow. Also make sure it's != 0
 	if (num_in_channels != 3 || num_out_channels != 3)
 		return NULL;
 
@@ -730,6 +730,9 @@
 		// clut_size can not overflow since lg(256^num_in_channels) = 24 bits.
 		for (i = 0; i < num_in_channels; i++) {
 			clut_size *= read_u8(src, clut_offset + i);
+			if (clut_size == 0) {
+				invalid_source(src, "bad clut_size");
+			}
 		}
 	} else {
 		clut_size = 0;
@@ -750,6 +753,9 @@
 
 	for (i = 0; i < num_in_channels; i++) {
 		lut->num_grid_points[i] = read_u8(src, clut_offset + i);
+		if (lut->num_grid_points[i] == 0) {
+			invalid_source(src, "bad grid_points");
+		}
 	}
 
 	// Reverse the processing of transformation elements for mBA type.
@@ -832,6 +838,10 @@
 	} else if (type == LUT16_TYPE) {
 		num_input_table_entries  = read_u16(src, offset + 48);
 		num_output_table_entries = read_u16(src, offset + 50);
+		if (num_input_table_entries == 0 || num_output_table_entries == 0) {
+			invalid_source(src, "Bad channel count");
+			return NULL;
+		}
 		entry_size = 2;
 	} else {
 		assert(0); // the caller checks that this doesn't happen
@@ -845,15 +855,18 @@
 
 	clut_size = pow(grid_points, in_chan);
 	if (clut_size > MAX_CLUT_SIZE) {
+		invalid_source(src, "CLUT too large");
 		return NULL;
 	}
 
 	if (in_chan != 3 || out_chan != 3) {
+		invalid_source(src, "CLUT only supports RGB");
 		return NULL;
 	}
 
 	lut = malloc(sizeof(struct lutType) + (num_input_table_entries * in_chan + clut_size*out_chan + num_output_table_entries * out_chan)*sizeof(float));
 	if (!lut) {
+		invalid_source(src, "CLUT too large");
 		return NULL;
 	}
 
@@ -864,9 +877,9 @@
 
 	lut->num_input_table_entries  = num_input_table_entries;
 	lut->num_output_table_entries = num_output_table_entries;
-	lut->num_input_channels   = read_u8(src, offset + 8);
-	lut->num_output_channels  = read_u8(src, offset + 9);
-	lut->num_clut_grid_points = read_u8(src, offset + 10);
+	lut->num_input_channels   = in_chan;
+	lut->num_output_channels  = out_chan;
+	lut->num_clut_grid_points = grid_points;
 	lut->e00 = read_s15Fixed16Number(src, offset+12);
 	lut->e01 = read_s15Fixed16Number(src, offset+16);
 	lut->e02 = read_s15Fixed16Number(src, offset+20);
diff --git a/third_party/yasm/yasm.gyp b/third_party/yasm/yasm.gyp
index 0c21b83..6a5e692 100644
--- a/third_party/yasm/yasm.gyp
+++ b/third_party/yasm/yasm.gyp
@@ -56,6 +56,10 @@
     'version_file': 'version.mac',  # Generated by genversion.
     'genmodule_source': 'genmodule_outfile.c',
   },
+  'target_defaults': {
+    # Silence warnings in libc++ builds (C code doesn't need this flag).
+    'ldflags!': [ '-stdlib=libc++', ],
+  },
   'targets': [
     {
       'target_name': 'yasm',
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
index fe868c0..770e255 100644
--- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
+++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -296,8 +296,9 @@
             emitWarning(it->getInnerLocStart(),
                         "Complex constructor has an inlined body.");
           }
-        } else if (it->isInlined() && (!it->isCopyOrMoveConstructor() ||
-                                       it->isExplicitlyDefaulted())) {
+        } else if (it->isInlined() && !it->isInlineSpecified() &&
+                   !it->isDeleted() && (!it->isCopyOrMoveConstructor() ||
+                                        it->isExplicitlyDefaulted())) {
           // isInlined() is a more reliable check than hasInlineBody(), but
           // unfortunately, it results in warnings for implicit copy/move
           // constructors in the previously mentioned situation. To preserve
@@ -318,7 +319,8 @@
                   "Complex class/struct needs an explicit out-of-line "
                   "destructor.");
     } else if (CXXDestructorDecl* dtor = record->getDestructor()) {
-      if (dtor->isInlined()) {
+      if (dtor->isInlined() && !dtor->isInlineSpecified() &&
+          !dtor->isDeleted()) {
         emitWarning(dtor->getInnerLocStart(),
                     "Complex destructor has an inline body.");
       }
diff --git a/tools/clang/plugins/tests/inline_ctor.h b/tools/clang/plugins/tests/inline_ctor.h
index d053b2f..9c6c286 100644
--- a/tools/clang/plugins/tests/inline_ctor.h
+++ b/tools/clang/plugins/tests/inline_ctor.h
@@ -18,4 +18,36 @@
   std::vector<std::string> two_;
 };
 
+class DeletedMembersInHeaderAreOKThough {
+ public:
+  DeletedMembersInHeaderAreOKThough() = delete;
+  ~DeletedMembersInHeaderAreOKThough() = delete;
+  DeletedMembersInHeaderAreOKThough(const DeletedMembersInHeaderAreOKThough&) =
+      delete;
+
+ private:
+  std::vector<int> one_;
+  std::vector<std::string> two_;
+};
+
+class ExplicitlyInlinedIsAlsoOK {
+  ExplicitlyInlinedIsAlsoOK();
+  ~ExplicitlyInlinedIsAlsoOK();
+  ExplicitlyInlinedIsAlsoOK(const ExplicitlyInlinedIsAlsoOK&);
+
+ private:
+  std::vector<int> one_;
+  std::vector<std::string> two_;
+};
+
+inline ExplicitlyInlinedIsAlsoOK::ExplicitlyInlinedIsAlsoOK() {
+}
+
+inline ExplicitlyInlinedIsAlsoOK::~ExplicitlyInlinedIsAlsoOK() {
+}
+
+inline ExplicitlyInlinedIsAlsoOK::ExplicitlyInlinedIsAlsoOK(
+    const ExplicitlyInlinedIsAlsoOK&) {
+}
+
 #endif  // INLINE_CTOR_H_
diff --git a/tools/clang/scripts/plugin_flags.py b/tools/clang/scripts/plugin_flags.py
deleted file mode 100755
index 3f61d6b..0000000
--- a/tools/clang/scripts/plugin_flags.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script returns the flags that should be used when GYP_DEFINES contains
-# clang_use_chrome_plugins. The flags are stored in a script so that they can
-# be changed on the bots without requiring a master restart.
-
-import os
-import sys
-
-# Path constants. (All of these should be absolute paths.)
-THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
-CLANG_LIB_PATH = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build',
-                              'Release+Asserts', 'lib')
-
-if sys.platform == 'darwin':
-  LIBSUFFIX = 'dylib'
-else:
-  LIBSUFFIX = 'so'
-
-LIB_PATH = os.path.join(
-    CLANG_LIB_PATH,
-    'libFindBadConstructs.' + LIBSUFFIX)
-
-print ('-Xclang -load -Xclang %s'
-       ' -Xclang -add-plugin -Xclang find-bad-constructs') % LIB_PATH
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index cb0878d..2cc6958 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -24,7 +24,7 @@
 # in bringup. Use a pinned revision to make it slightly more stable.
 if (re.search(r'\b(asan)=1', os.environ.get('GYP_DEFINES', '')) and
     not 'LLVM_FORCE_HEAD_REVISION' in os.environ):
-  LLVM_WIN_REVISION = '229860'
+  LLVM_WIN_REVISION = '231949'
 
 # Path constants. (All of these should be absolute paths.)
 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index ae90743..c842a58 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -8,7 +8,7 @@
 # Do NOT CHANGE this if you don't know what you're doing -- see
 # https://code.google.com/p/chromium/wiki/UpdatingClang
 # Reverting problematic clang rolls is safe, though.
-CLANG_REVISION=231191
+CLANG_REVISION=231690
 
 # This is incremented when pushing a new build of Clang at the same revision.
 CLANG_SUB_REVISION=1
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index d2b3ede..a64ae83 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -245,6 +245,9 @@
   "chrome/browser/devtools/device/webrtc/resources.grd": {
     "includes": [30800],
   },
+  "chrome/browser/resources/settings/settings_resources.grd": {
+    "structures": [30900],
+  },
 
   # These files don't need to reserve resource ids, but are listed here so that
   # translation scripts know of their existence.
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py
index bfe6698..bdd6dc7 100755
--- a/tools/idl_parser/idl_parser.py
+++ b/tools/idl_parser/idl_parser.py
@@ -264,6 +264,11 @@
       p[2].AddChildren(p[1])
       p[0] = ListFromConcat(p[2], p[3])
 
+  # [9.1] Error recovery for InterfaceMembers
+  def p_InterfaceMembersError(self, p):
+    """InterfaceMembers : error"""
+    p[0] = self.BuildError(p, 'InterfaceMembers')
+
   # [10] Removed unsupported: Serializer
   def p_InterfaceMember(self, p):
     """InterfaceMember : Const
diff --git a/tools/idl_parser/test_parser/interface_web.idl b/tools/idl_parser/test_parser/interface_web.idl
index 9e69e9f..b1f3278 100644
--- a/tools/idl_parser/test_parser/interface_web.idl
+++ b/tools/idl_parser/test_parser/interface_web.idl
@@ -72,6 +72,23 @@
 };
 
 /* TREE
+ *Interface(MyIFaceContainsUnresolvedConflictDiff)
+ *  Operation(foo)
+ *    Arguments()
+ *    Type()
+ *      PrimitiveType(DOMString)
+ *  Error(Unexpected "<" after ";".)
+ */
+interface MyIFaceContainsUnresolvedConflictDiff {
+    DOMString foo();
+<<<<<< ours
+    DOMString bar();
+    iterable<long>;
+======
+>>>>>> theirs
+};
+
+/* TREE
  *Interface(MyIFaceBig)
  *  Const(setString)
  *    PrimitiveType(DOMString)
diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py
index 0107406..898edf4 100755
--- a/tools/valgrind/asan/asan_symbolize.py
+++ b/tools/valgrind/asan/asan_symbolize.py
@@ -246,6 +246,9 @@
 
   disable_buffering()
   set_symbolizer_path()
+  # Disallow fallback to addr2line/atos if llvm-symbolizer is not present. Those
+  # are slow and we don't want to use them ever.
+  asan_symbolize.allow_system_symbolizer = False
   asan_symbolize.demangle = True
   asan_symbolize.fix_filename_patterns = args.strip_path_prefix
   # Most source paths for Chromium binaries start with
diff --git a/tools/valgrind/asan/third_party/README.chromium b/tools/valgrind/asan/third_party/README.chromium
index 5c363ea..63a1761 100644
--- a/tools/valgrind/asan/third_party/README.chromium
+++ b/tools/valgrind/asan/third_party/README.chromium
@@ -1,6 +1,6 @@
 Name: asan_symbolize.py
 License: University of Illinois Open Source License.
-Version: r227327
+Version: r231492
 URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py?view=co&content-type=text%2Fplain
 Security Critical: no
 
diff --git a/tools/valgrind/asan/third_party/asan_symbolize.py b/tools/valgrind/asan/third_party/asan_symbolize.py
index 59fceaa..b9d3ad3 100755
--- a/tools/valgrind/asan/third_party/asan_symbolize.py
+++ b/tools/valgrind/asan/third_party/asan_symbolize.py
@@ -23,6 +23,7 @@
 binary_name_filter = None
 fix_filename_patterns = None
 logfile = sys.stdin
+allow_system_symbolizer = True
 
 # FIXME: merge the code that calls fix_filename().
 def fix_filename(file_name):
@@ -392,6 +393,8 @@
           [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
     result = symbolizers[binary].symbolize(addr, binary, offset)
     if result is None:
+      if not allow_system_symbolizer:
+        raise Exception('Failed to launch or use llvm-symbolizer.')
       # Initialize system symbolizer only if other symbolizers failed.
       symbolizers[binary].append_symbolizer(
           SystemSymbolizerFactory(self.system, addr, binary))
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index eae85e5..dfe57e2 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1821,6 +1821,10 @@
 KERNEL32.dll!WriteFile
 mojo_system_impl.dll!mojo::system::`anonymous namespace'::RawChannelWin::WriteNoLock
 
+UNINITIALIZED READ
+name=bug_399842
+skia.dll!S32A_Opaque_BlitRow32_SSE4
+
 HANDLE LEAK
 name=bug_403544
 system call NtCreateSemaphore
@@ -1886,9 +1890,10 @@
 *!ash::test::ShelfViewTest_OverflowBubbleSize_Test::TestBody
 *!testing::internal::HandleExceptionsInMethodIfSupported<>
 
-UNINITIALIZED READ
-name=bug_399842
-skia.dll!S32A_Opaque_BlitRow32_SSE4
+UNADDRESSABLE ACCESS
+name=bug_442969
+*!testing::internal::CmpHelperNE<>
+*!extensions::WebrtcAudioPrivateTest_GetAndSetWithMediaStream_Test::RunTestOnMainThread
 
 UNINITIALIZED READ
 name=bug_455417
diff --git a/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt
index 636878e..64ab6ab 100644
--- a/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt
+++ b/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt
@@ -5,5 +5,4 @@
 # http://crbug.com/383384
 SystemGestureEventFilterTest.TwoFingerDragDelayed
 # http://crbug.com/421888
-SystemTrayTest.*TouchFeedback*
-TrayDetailsViewTest.*TouchFeedback*
+WebNotificationTrayTest.*TouchFeedback*
diff --git a/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt
deleted file mode 100644
index f1382da..0000000
--- a/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# crbug.com/455536
-ChromeWatcherCommandLineTest.BasicTest
diff --git a/tools/valgrind/memcheck/suppressions_mac.txt b/tools/valgrind/memcheck/suppressions_mac.txt
index f0e9d32..c9ed9bf 100644
--- a/tools/valgrind/memcheck/suppressions_mac.txt
+++ b/tools/valgrind/memcheck/suppressions_mac.txt
@@ -271,3 +271,12 @@
    fun:_ZN4base3mac30PathForFrameworkBundleResourceEPK10__CFString
    fun:_ZN3gin13IsolateHolder14LoadV8SnapshotEv
 }
+{
+   bug_464850
+   Memcheck:Uninitialized
+   fun:_ZN2v88internal9ExitFrame23GetStateForFramePointerEPhPNS0_10StackFrame5StateE
+   fun:_ZN2v88internal18StackFrameIterator5ResetEPNS0_14ThreadLocalTopE
+   fun:_ZN2v88internal18StackFrameIteratorC2EPNS0_7IsolateE
+   fun:_ZN2v88internal18StackFrameIteratorC1EPNS0_7IsolateE
+   fun:_ZN2v88internal7Isolate11FindHandlerEv
+}
diff --git a/ui/events/platform/platform_event_source.cc b/ui/events/platform/platform_event_source.cc
index 9607ab7..bf957f0 100644
--- a/ui/events/platform/platform_event_source.cc
+++ b/ui/events/platform/platform_event_source.cc
@@ -51,6 +51,9 @@
       new ScopedEventDispatcher(&overridden_dispatcher_, dispatcher));
 }
 
+void PlatformEventSource::StopCurrentEventStream() {
+}
+
 void PlatformEventSource::AddPlatformEventObserver(
     PlatformEventObserver* observer) {
   CHECK(observer);
@@ -73,7 +76,7 @@
 
   if ((action & POST_DISPATCH_PERFORM_DEFAULT) &&
       dispatchers_.might_have_observers()) {
-    ObserverList<PlatformEventDispatcher>::Iterator iter(dispatchers_);
+    ObserverList<PlatformEventDispatcher>::Iterator iter(&dispatchers_);
     while (PlatformEventDispatcher* dispatcher = iter.GetNext()) {
       if (dispatcher->CanDispatchEvent(platform_event))
         action = dispatcher->DispatchEvent(platform_event);
@@ -97,9 +100,6 @@
   return action;
 }
 
-void PlatformEventSource::StopCurrentEventStream() {
-}
-
 void PlatformEventSource::OnDispatcherListChanged() {
 }
 
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 07de9ac..f683761 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -62,6 +62,8 @@
     "frame_time.h",
     "gpu_memory_buffer.cc",
     "gpu_memory_buffer.h",
+    "hud_font.cc",
+    "hud_font.h",
     "native_widget_types.h",
     "sequential_id_generator.cc",
     "sequential_id_generator.h",
diff --git a/ui/gfx/geometry/quad_f.h b/ui/gfx/geometry/quad_f.h
index ada5c54..d795064 100644
--- a/ui/gfx/geometry/quad_f.h
+++ b/ui/gfx/geometry/quad_f.h
@@ -10,6 +10,7 @@
 #include <iosfwd>
 #include <string>
 
+#include "base/logging.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/gfx_export.h"
@@ -67,6 +68,18 @@
     return RectF(rl, rt, rr - rl, rb - rt);
   }
 
+  // Realigns the corners in the quad by rotating them n corners to the right.
+  void Realign(size_t times) {
+    DCHECK_LE(times, 4u);
+    for (size_t i = 0; i < times; ++i) {
+      PointF temp = p1_;
+      p1_ = p2_;
+      p2_ = p3_;
+      p3_ = p4_;
+      p4_ = temp;
+    }
+  }
+
   // Add a vector to the quad, offseting each point in the quad by the vector.
   void operator+=(const Vector2dF& rhs);
   // Subtract a vector from the quad, offseting each point in the quad by the
diff --git a/ui/gfx/hud_font.cc b/ui/gfx/hud_font.cc
new file mode 100644
index 0000000..8151778
--- /dev/null
+++ b/ui/gfx/hud_font.cc
@@ -0,0 +1,25 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/hud_font.h"
+
+#include "base/lazy_instance.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+
+namespace gfx {
+
+namespace {
+base::LazyInstance<skia::RefPtr<SkTypeface>> g_hud_typeface;
+}  // namespace
+
+void SetHudTypeface(skia::RefPtr<SkTypeface> typeface) {
+  g_hud_typeface.Get() = typeface;
+}
+
+skia::RefPtr<SkTypeface> GetHudTypeface() {
+  // nullptr is fine; caller will create its own in that case.
+  return g_hud_typeface.Get();
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/hud_font.h b/ui/gfx/hud_font.h
new file mode 100644
index 0000000..f72a050
--- /dev/null
+++ b/ui/gfx/hud_font.h
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_HUD_FONT_H_
+#define UI_GFX_HUD_FONT_H_
+
+#include "skia/ext/refptr.h"
+#include "ui/gfx/gfx_export.h"
+
+class SkTypeface;
+
+namespace gfx {
+
+GFX_EXPORT void SetHudTypeface(skia::RefPtr<SkTypeface> typeface);
+GFX_EXPORT skia::RefPtr<SkTypeface> GetHudTypeface();
+
+}  // namespace gfx
+
+#endif  // UI_GFX_HUD_FONT_H_
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc
index ac98f49..15df1ea 100644
--- a/ui/gfx/skia_util.cc
+++ b/ui/gfx/skia_util.cc
@@ -11,8 +11,9 @@
 #include "third_party/skia/include/effects/SkBlurMaskFilter.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/rect_f.h"
+#include "ui/gfx/geometry/quad_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/transform.h"
 
 namespace gfx {
@@ -45,6 +46,15 @@
                SkScalarToFloat(rect.height()));
 }
 
+SkSize SizeFToSkSize(const SizeF& size) {
+  return SkSize::Make(SkFloatToScalar(size.width()),
+                      SkFloatToScalar(size.height()));
+}
+
+SizeF SkSizeToSizeF(const SkSize& size) {
+  return SizeF(SkScalarToFloat(size.width()), SkScalarToFloat(size.height()));
+}
+
 void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
                                   SkMatrix* flattened) {
   // Convert from 4x4 to 3x3 by dropping the third row and column.
@@ -99,7 +109,7 @@
     const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[i]);
 
     // Pack the components here.
-    int alpha = SkGetPackedA32(pixel_in);
+    SkAlpha alpha = SkGetPackedA32(pixel_in);
     if (alpha != 0 && alpha != 255) {
       SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in);
       rgba[i + 0] = SkColorGetR(unmultiplied);
@@ -115,4 +125,11 @@
   }
 }
 
+void QuadFToSkPoints(const gfx::QuadF& quad, SkPoint points[4]) {
+  points[0] = SkPoint::Make(quad.p1().x(), quad.p1().y());
+  points[1] = SkPoint::Make(quad.p2().x(), quad.p2().y());
+  points[2] = SkPoint::Make(quad.p3().x(), quad.p3().y());
+  points[3] = SkPoint::Make(quad.p4().x(), quad.p4().y());
+}
+
 }  // namespace gfx
diff --git a/ui/gfx/skia_util.h b/ui/gfx/skia_util.h
index 3e611ea..44c9a09 100644
--- a/ui/gfx/skia_util.h
+++ b/ui/gfx/skia_util.h
@@ -12,6 +12,8 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/gfx/geometry/quad_f.h"
+#include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gfx_export.h"
 
 class SkBitmap;
@@ -31,10 +33,33 @@
 GFX_EXPORT Rect SkIRectToRect(const SkIRect& rect);
 GFX_EXPORT SkRect RectFToSkRect(const RectF& rect);
 GFX_EXPORT RectF SkRectToRectF(const SkRect& rect);
+GFX_EXPORT SkSize SizeFToSkSize(const SizeF& size);
+GFX_EXPORT SizeF SkSizeToSizeF(const SkSize& size);
+
+GFX_EXPORT void QuadFToSkPoints(const gfx::QuadF& quad, SkPoint points[4]);
 
 GFX_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
                                              SkMatrix* flattened);
 
+// Creates a bitmap shader for the image rep with the image rep's scale factor.
+// Sets the created shader's local matrix such that it displays the image rep at
+// the correct scale factor.
+// The shader's local matrix should not be changed after the shader is created.
+// TODO(pkotwicz): Allow shader's local matrix to be changed after the shader
+// is created.
+//
+GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShader(
+    const gfx::ImageSkiaRep& image_rep,
+    SkShader::TileMode tile_mode,
+    const SkMatrix& local_matrix);
+
+// Creates a bitmap shader for the image rep with the passed in scale factor.
+GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShaderForScale(
+    const gfx::ImageSkiaRep& image_rep,
+    SkShader::TileMode tile_mode,
+    const SkMatrix& local_matrix,
+    SkScalar scale);
+
 // Creates a vertical gradient shader. The caller owns the shader.
 // Example usage to avoid leaks:
 GFX_EXPORT skia::RefPtr<SkShader> CreateGradientShader(int start_point,
@@ -42,6 +67,12 @@
                                                        SkColor start_color,
                                                        SkColor end_color);
 
+// Creates a draw looper to generate |shadows|. The caller owns the draw looper.
+// NULL is returned if |shadows| is empty since no draw looper is needed in
+// this case.
+GFX_EXPORT skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
+    const std::vector<ShadowValue>& shadows);
+
 // Returns true if the two bitmaps contain the same pixels.
 GFX_EXPORT bool BitmapsAreEqual(const SkBitmap& bitmap1,
                                 const SkBitmap& bitmap2);
diff --git a/ui/gfx/x/x11_types.h b/ui/gfx/x/x11_types.h
index 945776d..82ce838 100644
--- a/ui/gfx/x/x11_types.h
+++ b/ui/gfx/x/x11_types.h
@@ -6,6 +6,7 @@
 #define UI_GFX_X_X11_UTIL_H_
 
 #include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
 #include "ui/gfx/gfx_export.h"
 
 typedef unsigned long XAtom;
@@ -14,8 +15,20 @@
 typedef struct _XGC *GC;
 typedef struct _XDisplay XDisplay;
 
+extern "C" {
+int XFree(void*);
+}
+
 namespace gfx {
 
+template <class T, class R, R (*F)(T*)>
+struct XObjectDeleter {
+  inline void operator()(void* ptr) const { F(static_cast<T*>(ptr)); }
+};
+
+template <class T, class D = XObjectDeleter<void, int, XFree>>
+using XScopedPtr = scoped_ptr<T, D>;
+
 // TODO(oshima|evan): This assume there is one display and doesn't work
 // undef multiple displays/monitor environment. Remove this and change the
 // chrome codebase to get the display from window.
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 12a44cc..88b4c36 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -183,6 +183,8 @@
   }
   if (is_win) {
     sources += [
+      "angle_platform_impl.cc",
+      "angle_platform_impl.h",
       "gl_bindings_autogen_wgl.cc",
       "gl_bindings_autogen_wgl.h",
       "gl_context_wgl.cc",
@@ -195,6 +197,8 @@
       "gl_wgl_api_implementation.h",
     ]
 
+    deps += [ "//third_party/angle:libGLESv2" ]
+
     libs = [ "dwmapi.lib" ]
     ldflags = [ "/DELAYLOAD:dwmapi.dll" ]
   }
diff --git a/ui/gl/DEPS b/ui/gl/DEPS
index 862c555..e582c0d 100644
--- a/ui/gl/DEPS
+++ b/ui/gl/DEPS
@@ -12,5 +12,9 @@
 # get access to desktop OpenGL.
   "gl_surface_osmesa.cc": [
     "+third_party/mesa/src/include/GL/osmesa.h",
-  ]
+  ],
+# Allow us to include ANGLE's base platform implementation.
+  "angle_platform_impl.h": [
+    "+third_party/angle/include/platform/Platform.h",
+  ],
 }
diff --git a/ui/gl/angle_platform_impl.cc b/ui/gl/angle_platform_impl.cc
new file mode 100644
index 0000000..2ce12b8
--- /dev/null
+++ b/ui/gl/angle_platform_impl.cc
@@ -0,0 +1,50 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/angle_platform_impl.h"
+
+#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
+
+namespace gfx {
+
+ANGLEPlatformImpl::ANGLEPlatformImpl() {
+}
+
+ANGLEPlatformImpl::~ANGLEPlatformImpl() {
+}
+
+void ANGLEPlatformImpl::histogramCustomCounts(const char* name,
+                                              int sample,
+                                              int min,
+                                              int max,
+                                              int bucket_count) {
+  // Copied from histogram macro, but without the static variable caching
+  // the histogram because name is dynamic.
+  base::HistogramBase* counter = base::Histogram::FactoryGet(
+      name, min, max, bucket_count,
+      base::HistogramBase::kUmaTargetedHistogramFlag);
+  DCHECK_EQ(name, counter->histogram_name());
+  counter->Add(sample);
+}
+
+void ANGLEPlatformImpl::histogramEnumeration(const char* name,
+                                             int sample,
+                                             int boundary_value) {
+  // Copied from histogram macro, but without the static variable caching
+  // the histogram because name is dynamic.
+  base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
+      name, 1, boundary_value, boundary_value + 1,
+      base::HistogramBase::kUmaTargetedHistogramFlag);
+  DCHECK_EQ(name, counter->histogram_name());
+  counter->Add(sample);
+}
+
+void ANGLEPlatformImpl::histogramSparse(const char* name, int sample) {
+  // For sparse histograms, we can use the macro, as it does not incorporate a
+  // static.
+  UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample);
+}
+
+}  // namespace gfx
diff --git a/ui/gl/angle_platform_impl.h b/ui/gl/angle_platform_impl.h
new file mode 100644
index 0000000..2d12f60
--- /dev/null
+++ b/ui/gl/angle_platform_impl.h
@@ -0,0 +1,39 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_ANGLE_PLATFORM_IMPL_H_
+#define UI_GL_ANGLE_PLATFORM_IMPL_H_
+
+// Implements the ANGLE platform interface, for functionality like
+// histograms and trace profiling.
+
+#include "base/macros.h"
+#include "third_party/angle/include/platform/Platform.h"
+
+namespace gfx {
+
+// Derives the base ANGLE platform and provides implementations
+class ANGLEPlatformImpl : public angle::Platform {
+ public:
+  ANGLEPlatformImpl();
+  ~ANGLEPlatformImpl() override;
+
+  // angle::Platform:
+  void histogramCustomCounts(const char* name,
+                             int sample,
+                             int min,
+                             int max,
+                             int bucket_count) override;
+  void histogramEnumeration(const char* name,
+                            int sample,
+                            int boundary_value) override;
+  void histogramSparse(const char* name, int sample) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ANGLEPlatformImpl);
+};
+
+}  // namespace gfx
+
+#endif  // UI_GL_ANGLE_PLATFORM_IMPL_H_
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp
index 0538107..d62950a 100644
--- a/ui/gl/gl.gyp
+++ b/ui/gl/gl.gyp
@@ -186,6 +186,8 @@
         }],
         ['OS=="win"', {
           'sources': [
+            'angle_platform_impl.cc',
+            'angle_platform_impl.h',
             'gl_bindings_autogen_wgl.cc',
             'gl_bindings_autogen_wgl.h',
             'gl_context_wgl.cc',
@@ -197,6 +199,11 @@
             'gl_wgl_api_implementation.cc',
             'gl_wgl_api_implementation.h',
           ],
+          'dependencies': [
+            # TODO(jmadill): Use ANGLE on other platforms.
+            '<(angle_path)/src/angle.gyp:libEGL',
+            '<(angle_path)/src/angle.gyp:libGLESv2',
+          ],
           'msvs_settings': {
             'VCLinkerTool': {
               'DelayLoadDLLs': [
diff --git a/ui/gl/gl_image_glx.cc b/ui/gl/gl_image_glx.cc
index 84c4d0c..dea6cd6 100644
--- a/ui/gl/gl_image_glx.cc
+++ b/ui/gl/gl_image_glx.cc
@@ -16,13 +16,6 @@
 
 namespace {
 
-// scoped_ptr functor for XFree(). Use as follows:
-//   scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...);
-// where "XVisualInfo" is any X type that is freed with XFree.
-struct ScopedPtrXFree {
-  void operator()(void* x) const { ::XFree(x); }
-};
-
 bool ValidFormat(unsigned internalformat) {
   switch (internalformat) {
     case GL_RGB:
@@ -141,11 +134,9 @@
       BindToTextureFormat(internalformat_), GL_TRUE,
       0};
   int num_elements = 0;
-  scoped_ptr<GLXFBConfig, ScopedPtrXFree> config(
-      glXChooseFBConfig(gfx::GetXDisplay(),
-                        DefaultScreen(gfx::GetXDisplay()),
-                        config_attribs,
-                        &num_elements));
+  gfx::XScopedPtr<GLXFBConfig> config(
+      glXChooseFBConfig(gfx::GetXDisplay(), DefaultScreen(gfx::GetXDisplay()),
+                        config_attribs, &num_elements));
   if (!config.get()) {
     DVLOG(0) << "glXChooseFBConfig failed.";
     return false;
diff --git a/ui/gl/gl_implementation_win.cc b/ui/gl/gl_implementation_win.cc
index 477f5a5..618250d 100644
--- a/ui/gl/gl_implementation_win.cc
+++ b/ui/gl/gl_implementation_win.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/native_library.h"
 #include "base/path_service.h"
@@ -16,6 +17,8 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/trace_event/trace_event.h"
 #include "base/win/windows_version.h"
+// TODO(jmadill): Apply to all platforms eventually
+#include "ui/gl/angle_platform_impl.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context_stub_with_extensions.h"
 #include "ui/gl/gl_egl_api_implementation.h"
@@ -97,6 +100,10 @@
     GetCategoryEnabledFlagFunc get_category_enabled_flag,
     AddTraceEventFunc add_trace_event_func);
 
+// TODO(jmadill): Apply to all platforms eventually
+base::LazyInstance<ANGLEPlatformImpl> g_angle_platform_impl =
+    LAZY_INSTANCE_INITIALIZER;
+
 }  // namespace
 
 void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
@@ -111,6 +118,10 @@
   // later switch to another GL implementation.
   DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
 
+  // Init ANGLE platform here, before we call GetPlatformDisplay().
+  // TODO(jmadill): Apply to all platforms eventually
+  angle::Platform::initialize(&g_angle_platform_impl.Get());
+
   // Allow the main thread or another to initialize these bindings
   // after instituting restrictions on I/O. Going forward they will
   // likely be used in the browser process on most platforms. The
@@ -348,6 +359,9 @@
 }
 
 void ClearGLBindings() {
+  // TODO(jmadill): Apply to all platforms eventually
+  angle::Platform::shutdown();
+
   ClearGLBindingsEGL();
   ClearGLBindingsGL();
   ClearGLBindingsOSMESA();
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc
index 5a3eafd..d66078c 100644
--- a/ui/gl/gl_surface_glx.cc
+++ b/ui/gl/gl_surface_glx.cc
@@ -33,15 +33,6 @@
 
 namespace {
 
-// scoped_ptr functor for XFree(). Use as follows:
-//   scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...);
-// where "XVisualInfo" is any X type that is freed with XFree.
-struct ScopedPtrXFree {
-  void operator()(void* x) const {
-    ::XFree(x);
-  }
-};
-
 Display* g_display = NULL;
 const char* g_glx_extensions = NULL;
 bool g_glx_context_create = false;
@@ -180,9 +171,8 @@
     visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
 
     int visual_info_count = 0;
-    scoped_ptr<XVisualInfo, ScopedPtrXFree> visual_info_list(
-        XGetVisualInfo(display_, VisualIDMask,
-                       &visual_info_template, &visual_info_count));
+    gfx::XScopedPtr<XVisualInfo> visual_info_list(XGetVisualInfo(
+        display_, VisualIDMask, &visual_info_template, &visual_info_count));
 
     DCHECK(visual_info_list.get());
     if (visual_info_count == 0) {
@@ -553,10 +543,8 @@
     int visual_id = XVisualIDFromVisual(attributes.visual);
 
     int num_elements = 0;
-    scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs(
-        glXGetFBConfigs(g_display,
-                        DefaultScreen(g_display),
-                        &num_elements));
+    gfx::XScopedPtr<GLXFBConfig> configs(
+        glXGetFBConfigs(g_display, DefaultScreen(g_display), &num_elements));
     if (!configs.get()) {
       LOG(ERROR) << "glXGetFBConfigs failed.";
       return NULL;
@@ -628,11 +616,8 @@
   };
 
   int num_elements = 0;
-  scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs(
-      glXChooseFBConfig(g_display,
-                        DefaultScreen(g_display),
-                        config_attributes,
-                        &num_elements));
+  gfx::XScopedPtr<GLXFBConfig> configs(glXChooseFBConfig(
+      g_display, DefaultScreen(g_display), config_attributes, &num_elements));
   if (!configs.get()) {
     LOG(ERROR) << "glXChooseFBConfig failed.";
     return false;
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc
index 47ea8d6..800be17 100644
--- a/ui/gl/gl_surface_ozone.cc
+++ b/ui/gl/gl_surface_ozone.cc
@@ -5,8 +5,12 @@
 #include "ui/gl/gl_surface.h"
 
 #include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/worker_pool.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_image.h"
@@ -25,6 +29,11 @@
 
 namespace {
 
+void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
+  eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+                       EGL_FOREVER_KHR);
+}
+
 // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow
 class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
  public:
@@ -111,7 +120,9 @@
         ozone_surface_(ozone_surface.Pass()),
         widget_(widget),
         has_implicit_external_sync_(
-            HasEGLExtension("EGL_ARM_implicit_external_sync")) {}
+            HasEGLExtension("EGL_ARM_implicit_external_sync")),
+        last_swap_buffers_result_(true),
+        weak_factory_(this) {}
 
   bool Initialize() override {
     if (!SurfacelessEGL::Initialize())
@@ -128,8 +139,21 @@
     return SurfacelessEGL::Resize(size);
   }
   bool SwapBuffers() override {
-    if (!Flush())
-      return false;
+    glFlush();
+    // TODO: the following should be replaced by a per surface flush as it gets
+    // implemented in GL drivers.
+    if (has_implicit_external_sync_) {
+      EGLSyncKHR fence = InsertFence();
+      if (!fence)
+        return false;
+
+      EGLDisplay display = GetDisplay();
+      WaitForFence(display, fence);
+      eglDestroySyncKHR(display, fence);
+    } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
+      glFinish();
+    }
+
     return ozone_surface_->OnSwapBuffers();
   }
   bool ScheduleOverlayPlane(int z_order,
@@ -149,8 +173,33 @@
     return true;
   }
   bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
-    if (!Flush())
-      return false;
+    glFlush();
+    // TODO: the following should be replaced by a per surface flush as it gets
+    // implemented in GL drivers.
+    if (has_implicit_external_sync_) {
+      // If last swap failed, don't try to schedule new ones.
+      if (!last_swap_buffers_result_) {
+        last_swap_buffers_result_ = true;
+        return false;
+      }
+
+      EGLSyncKHR fence = InsertFence();
+      if (!fence)
+        return false;
+
+      base::Closure fence_wait_task =
+          base::Bind(&WaitForFence, GetDisplay(), fence);
+
+      base::Closure fence_retired_callback =
+          base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
+                     weak_factory_.GetWeakPtr(), fence, callback);
+
+      base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
+                                         fence_retired_callback, false);
+      return true;
+    } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
+      glFinish();
+    }
     return ozone_surface_->OnSwapBuffersAsync(callback);
   }
   bool PostSubBufferAsync(int x,
@@ -166,30 +215,16 @@
     Destroy();  // EGL surface must be destroyed before SurfaceOzone
   }
 
-  bool Flush() {
-    glFlush();
-    // TODO: crbug.com/462360 the following should be replaced by a per surface
-    // flush as it gets implemented in GL drivers.
-    if (has_implicit_external_sync_) {
-      const EGLint attrib_list[] = {
-          EGL_SYNC_CONDITION_KHR,
-          EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
-          EGL_NONE};
-      EGLSyncKHR fence =
-          eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
-      if (fence) {
-        // TODO(dbehr): piman@ suggests we could improve here by moving
-        // following wait to right before drmModePageFlip crbug.com/456417.
-        eglClientWaitSyncKHR(GetDisplay(), fence,
-                             EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
-        eglDestroySyncKHR(GetDisplay(), fence);
-      } else {
-        return false;
-      }
-    } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) {
-      glFinish();
-    }
-    return true;
+  EGLSyncKHR InsertFence() {
+    const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
+                                  EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
+                                  EGL_NONE};
+    return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
+  }
+
+  void FenceRetired(EGLSyncKHR fence, const SwapCompletionCallback& callback) {
+    eglDestroySyncKHR(GetDisplay(), fence);
+    last_swap_buffers_result_ = ozone_surface_->OnSwapBuffersAsync(callback);
   }
 
   // The native surface. Deleting this is allowed to free the EGLNativeWindow.
@@ -197,6 +232,10 @@
   AcceleratedWidget widget_;
   scoped_ptr<VSyncProvider> vsync_provider_;
   bool has_implicit_external_sync_;
+  bool last_swap_buffers_result_;
+
+  base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
 };
 
diff --git a/ui/gl/gpu_timing.cc b/ui/gl/gpu_timing.cc
index a3b697f..a744164 100644
--- a/ui/gl/gpu_timing.cc
+++ b/ui/gl/gpu_timing.cc
@@ -20,6 +20,8 @@
     timer_type_ = kTimerTypeDisjoint;
   } else if (context->HasExtension("GL_ARB_timer_query")) {
     timer_type_ = kTimerTypeARB;
+  } else if (context->HasExtension("GL_EXT_timer_query")) {
+    timer_type_ = kTimerTypeEXT;
   }
 }
 
@@ -46,14 +48,35 @@
 }
 
 void GPUTimer::Start() {
-  // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
-  glQueryCounter(queries_[0], GL_TIMESTAMP);
+  switch (gpu_timing_client_->gpu_timing_->timer_type_) {
+    case GPUTiming::kTimerTypeARB:
+    case GPUTiming::kTimerTypeDisjoint:
+      // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
+      glQueryCounter(queries_[0], GL_TIMESTAMP);
+      break;
+    case GPUTiming::kTimerTypeEXT:
+      glBeginQuery(GL_TIME_ELAPSED_EXT, queries_[0]);
+      break;
+    default:
+      NOTREACHED();
+  }
 }
 
 void GPUTimer::End() {
   end_requested_ = true;
-  offset_ = gpu_timing_client_->CalculateTimerOffset();
-  glQueryCounter(queries_[1], GL_TIMESTAMP);
+  DCHECK(gpu_timing_client_->gpu_timing_);
+  switch (gpu_timing_client_->gpu_timing_->timer_type_) {
+    case GPUTiming::kTimerTypeARB:
+    case GPUTiming::kTimerTypeDisjoint:
+      offset_ = gpu_timing_client_->CalculateTimerOffset();
+      glQueryCounter(queries_[1], GL_TIMESTAMP);
+      break;
+    case GPUTiming::kTimerTypeEXT:
+      glEndQuery(GL_TIME_ELAPSED_EXT);
+      break;
+    default:
+      NOTREACHED();
+  }
 }
 
 bool GPUTimer::IsAvailable() {
@@ -61,13 +84,17 @@
     return false;
   }
   GLint done = 0;
-  glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
+  glGetQueryObjectivARB(queries_[1] ? queries_[1] : queries_[0],
+                        GL_QUERY_RESULT_AVAILABLE, &done);
   return done != 0;
 }
 
 void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) {
   DCHECK(start && end);
   DCHECK(IsAvailable());
+  DCHECK(gpu_timing_client_->gpu_timing_);
+  DCHECK(gpu_timing_client_->gpu_timing_->timer_type_ !=
+         GPUTiming::kTimerTypeEXT);
   GLuint64 begin_stamp = 0;
   GLuint64 end_stamp = 0;
   // TODO(dsinclair): It's possible for the timer to wrap during the start/end.
@@ -81,17 +108,44 @@
 }
 
 int64 GPUTimer::GetDeltaElapsed() {
-  int64 start = 0;
-  int64 end = 0;
-  GetStartEndTimestamps(&start, &end);
-  return end - start;
+  DCHECK(gpu_timing_client_->gpu_timing_);
+  switch (gpu_timing_client_->gpu_timing_->timer_type_) {
+    case GPUTiming::kTimerTypeARB:
+    case GPUTiming::kTimerTypeDisjoint: {
+      int64 start = 0;
+      int64 end = 0;
+      GetStartEndTimestamps(&start, &end);
+      return end - start;
+    } break;
+    case GPUTiming::kTimerTypeEXT: {
+      GLuint64 delta = 0;
+      glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &delta);
+      return static_cast<int64>(delta / base::Time::kNanosecondsPerMicrosecond);
+    } break;
+    default:
+      NOTREACHED();
+  }
+  return 0;
 }
 
 GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client)
     : gpu_timing_client_(gpu_timing_client) {
   DCHECK(gpu_timing_client_);
   memset(queries_, 0, sizeof(queries_));
-  glGenQueriesARB(2, queries_);
+  int queries = 0;
+  DCHECK(gpu_timing_client_->gpu_timing_);
+  switch (gpu_timing_client_->gpu_timing_->timer_type_) {
+    case GPUTiming::kTimerTypeARB:
+    case GPUTiming::kTimerTypeDisjoint:
+      queries = 2;
+      break;
+    case GPUTiming::kTimerTypeEXT:
+      queries = 1;
+      break;
+    default:
+      NOTREACHED();
+  }
+  glGenQueriesARB(queries, queries_);
 }
 
 GPUTimingClient::GPUTimingClient(GPUTiming* gpu_timing)
@@ -110,12 +164,19 @@
   return timer_type_ != GPUTiming::kTimerTypeInvalid;
 }
 
+bool GPUTimingClient::IsTimerOffsetAvailable() {
+  return timer_type_ == GPUTiming::kTimerTypeARB ||
+         timer_type_ == GPUTiming::kTimerTypeDisjoint;
+}
+
 const char* GPUTimingClient::GetTimerTypeName() const {
   switch (timer_type_) {
     case GPUTiming::kTimerTypeDisjoint:
       return "GL_EXT_disjoint_timer_query";
     case GPUTiming::kTimerTypeARB:
       return "GL_ARB_timer_query";
+    case GPUTiming::kTimerTypeEXT:
+      return "GL_EXT_timer_query";
     default:
       return "Unknown";
   }
@@ -133,6 +194,7 @@
 }
 
 int64 GPUTimingClient::CalculateTimerOffset() {
+  DCHECK(IsTimerOffsetAvailable());
   if (!offset_valid_) {
     GLint64 gl_now = 0;
     glGetInteger64v(GL_TIMESTAMP, &gl_now);
diff --git a/ui/gl/gpu_timing.h b/ui/gl/gpu_timing.h
index 1c8f8cf..a749ef1 100644
--- a/ui/gl/gpu_timing.h
+++ b/ui/gl/gpu_timing.h
@@ -2,16 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_
-#define GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_
+#ifndef UI_GL_GPU_TIMING_H_
+#define UI_GL_GPU_TIMING_H_
 
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "ui/gl/gl_export.h"
 
 // The gpu_timing classes handles the abstraction of GL GPU Timing extensions
-// into a common set of functions. Currently the different timer extensions
-// that are supported are ARB_timer_query and EXT_disjoint_timer_query.
+// into a common set of functions. Currently the different timer extensions that
+// are supported are EXT_timer_query, ARB_timer_query and
+// EXT_disjoint_timer_query.
 //
 // Explanation of Classes:
 //   GPUTiming - GPU Timing is a private class which is only owned by the
@@ -28,11 +29,11 @@
 //     obtain various GPU times they would access CreateGPUTimingClient() from
 //     their GLContext and use the returned object for their timing calls.
 //     Each virtual context as well as any other classes which need GPU times
-//     will hold one of these. When they want to time a GPU trace they will
-//     create GPUTimer objects.
-//   GPUTimer - Once a user decides to trace something, the user creates a new
+//     will hold one of these. When they want to time a set of GL commands they
+//     will create GPUTimer objects.
+//   GPUTimer - Once a user decides to time something, the user creates a new
 //     GPUTimer object from a GPUTimingClient and issue Start() and Stop() calls
-//     around various GL Calls. Once IsAvailable() returns true, the GPU times
+//     around various GL calls. Once IsAvailable() returns true, the GPU times
 //     will be available through the various time stamp related functions.
 //     The constructor and destructor of this object handles the actual
 //     creation and deletion of the GL Queries within GL.
@@ -47,6 +48,7 @@
   enum TimerType {
     kTimerTypeInvalid = -1,
 
+    kTimerTypeEXT,      // EXT_timer_query
     kTimerTypeARB,      // ARB_timer_query
     kTimerTypeDisjoint  // EXT_disjoint_timer_query
   };
@@ -57,6 +59,7 @@
  private:
   friend struct base::DefaultDeleter<GPUTiming>;
   friend class GLContextReal;
+  friend class GPUTimer;
   explicit GPUTiming(GLContextReal* context);
   ~GPUTiming();
 
@@ -102,6 +105,8 @@
 
   scoped_ptr<GPUTimer> CreateGPUTimer();
   bool IsAvailable();
+  bool IsTimerOffsetAvailable();
+
   const char* GetTimerTypeName() const;
 
   // CheckAndResetTimerErrors has to be called before reading timestamps
@@ -136,4 +141,4 @@
 
 }  // namespace gfx
 
-#endif  // GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_
+#endif  // UI_GL_GPU_TIMING_H_
diff --git a/url/url.gyp b/url/url.gyp
index 0ffc51a..4114801 100644
--- a/url/url.gyp
+++ b/url/url.gyp
@@ -33,28 +33,6 @@
       'defines': [
         'URL_IMPLEMENTATION',
       ],
-      'conditions': [
-        ['use_icu_alternatives_on_android==1', {
-          'sources!': [
-            'url_canon_icu.cc',
-            'url_canon_icu.h',
-          ],
-          'dependencies!': [
-            '../third_party/icu/icu.gyp:icui18n',
-            '../third_party/icu/icu.gyp:icuuc',
-          ],
-        }],
-        ['use_icu_alternatives_on_android==1 and OS=="android"', {
-          'dependencies': [
-            'url_java',
-            'url_jni_headers',
-          ],
-          'sources': [
-            'url_canon_icu_alternatives_android.cc',
-            'url_canon_icu_alternatives_android.h',
-          ],
-        }],
-      ],
       # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
       'msvs_disabled_warnings': [4267, ],
     },
@@ -84,23 +62,13 @@
             ],
           }
         ],
-        ['use_icu_alternatives_on_android==1',
-          {
-            'sources!': [
-              'url_canon_icu_unittest.cc',
-            ],
-            'dependencies!': [
-              '../third_party/icu/icu.gyp:icuuc',
-            ],
-          }
-        ],
       ],
       # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
       'msvs_disabled_warnings': [4267, ],
     },
   ],
   'conditions': [
-    ['use_icu_alternatives_on_android==1 and OS=="android"', {
+    ['OS=="android"', {
       'targets': [
         {
           'target_name': 'url_jni_headers',
@@ -124,6 +92,35 @@
           ],
           'includes': [ '../build/java.gypi' ],
         },
+        {
+          # Same as url_lib but using ICU alternatives on Android.
+          'target_name': 'url_lib_use_icu_alternatives_on_android',
+          'type': '<(component)',
+          'dependencies': [
+            '../base/base.gyp:base',
+            '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+            'url_java',
+            'url_jni_headers',
+          ],
+          'sources': [
+            '<@(gurl_sources)',
+            'url_canon_icu_alternatives_android.cc',
+            'url_canon_icu_alternatives_android.h',
+          ],
+          'sources!': [
+            'url_canon_icu.cc',
+            'url_canon_icu.h',
+          ],
+          'direct_dependent_settings': {
+            'include_dirs': [
+              '..',
+            ],
+          },
+          'defines': [
+            'URL_IMPLEMENTATION',
+            'USE_ICU_ALTERNATIVES_ON_ANDROID=1',
+          ],
+        },
       ],
     }],
   ],