diff --git a/DEPS b/DEPS
index 837694af..93479a6 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '228237cf81b29d4f3b67aa8bd8172442726b4d1f',
+  'v8_revision': '4e01f2a8efd8cbf3ee2142f0fbeaa221e0c6dc9c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '02759102cf998c9e937b3b65b64ed6b4c3b104bc',
+  'pdfium_revision': '8a463c5a1a2252b5fdbff3b5ab07d50273bbc391',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -257,7 +257,7 @@
     Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + 'ef811c6bd4de74e13e7035ca882cc77f85793fef',
 
   'src/third_party/ced/src':
-    Var('chromium_git') + '/external/github.com/google/compact_enc_det.git' + '@' + '9012c0ab648025dd0f8df14294bf5d6d73793ac9',
+    Var('chromium_git') + '/external/github.com/google/compact_enc_det.git' + '@' + 'e57cdc44bd541d10669312a6fdc59fc4bf52d2b9',
 
   'src/third_party/swiftshader':
     Var('swiftshader_git') + '/SwiftShader.git' + '@' +  Var('swiftshader_revision'),
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index e6e63399..c0bd34e 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -135,7 +135,6 @@
     "common/session/session_state_delegate.h",
     "common/session/session_state_observer.cc",
     "common/session/session_state_observer.h",
-    "common/session/session_types.h",
     "common/shelf/app_list_button.cc",
     "common/shelf/app_list_button.h",
     "common/shelf/app_list_shelf_item_delegate.cc",
@@ -886,6 +885,7 @@
     "//ui/base/ime",
     "//ui/compositor",
     "//ui/display",
+    "//ui/display/manager",
     "//ui/display/types",
     "//ui/events",
     "//ui/events:events_base",
@@ -1022,6 +1022,7 @@
     ":ash",
   ]
   deps = [
+    "//ash/public/cpp",
     "//base",
     "//base/third_party/dynamic_annotations",
     "//content/public/browser",
diff --git a/ash/common/media_delegate.h b/ash/common/media_delegate.h
index 1cc6cfc..018add7 100644
--- a/ash/common/media_delegate.h
+++ b/ash/common/media_delegate.h
@@ -5,7 +5,7 @@
 #ifndef ASH_COMMON_MEDIA_DELEGATE_H_
 #define ASH_COMMON_MEDIA_DELEGATE_H_
 
-#include "ash/common/session/session_types.h"
+#include "ash/public/cpp/session_types.h"
 
 namespace ash {
 
diff --git a/ash/common/session/session_state_delegate.h b/ash/common/session/session_state_delegate.h
index ebd91989..d0d2461e 100644
--- a/ash/common/session/session_state_delegate.h
+++ b/ash/common/session/session_state_delegate.h
@@ -6,7 +6,7 @@
 #define ASH_COMMON_SESSION_SESSION_STATE_DELEGATE_H_
 
 #include "ash/ash_export.h"
-#include "ash/common/session/session_types.h"
+#include "ash/public/cpp/session_types.h"
 #include "components/session_manager/session_manager_types.h"
 
 class AccountId;
diff --git a/ash/common/shelf/shelf_button.cc b/ash/common/shelf/shelf_button.cc
index 0ad1d8c..d80e8bf8 100644
--- a/ash/common/shelf/shelf_button.cc
+++ b/ash/common/shelf/shelf_button.cc
@@ -442,6 +442,7 @@
       gfx::Rect(button_bounds.x() + x_offset, button_bounds.y() + y_offset,
                 icon_width, icon_height);
   icon_view_bounds.Inset(insets_shadows);
+  icon_view_bounds.AdjustToFit(gfx::Rect(size()));
   icon_view_->SetBoundsRect(icon_view_bounds);
 
   // Icon size has been incorrect when running
diff --git a/ash/common/system/user/tray_user.h b/ash/common/system/user/tray_user.h
index 2739b3f..2b3573d7 100644
--- a/ash/common/system/user/tray_user.h
+++ b/ash/common/system/user/tray_user.h
@@ -6,9 +6,9 @@
 #define ASH_COMMON_SYSTEM_USER_TRAY_USER_H_
 
 #include "ash/ash_export.h"
-#include "ash/common/session/session_types.h"
 #include "ash/common/system/tray/system_tray_item.h"
 #include "ash/common/system/user/user_observer.h"
+#include "ash/public/cpp/session_types.h"
 #include "base/macros.h"
 
 namespace gfx {
diff --git a/ash/common/system/user/user_view.h b/ash/common/system/user/user_view.h
index 6d0e845..0443649 100644
--- a/ash/common/system/user/user_view.h
+++ b/ash/common/system/user/user_view.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
-#include "ash/common/session/session_types.h"
 #include "ash/common/system/tray/tray_constants.h"
 #include "ash/common/system/user/tray_user.h"
+#include "ash/public/cpp/session_types.h"
 #include "base/macros.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/focus/focus_manager.h"
diff --git a/ash/common/test/BUILD.gn b/ash/common/test/BUILD.gn
index 038998a..9152cd1 100644
--- a/ash/common/test/BUILD.gn
+++ b/ash/common/test/BUILD.gn
@@ -43,7 +43,7 @@
     # TODO: this is for ui/wm/public/window_types.h, which is in aura.
     # http://crbug.com/654078.
     "//ui/aura",
-    "//ui/display",
+    "//ui/display/manager",
     "//ui/gfx/geometry",
     "//ui/views",
     "//ui/wm",
diff --git a/ash/common/test/ash_test.h b/ash/common/test/ash_test.h
index bb665db3..570178d 100644
--- a/ash/common/test/ash_test.h
+++ b/ash/common/test/ash_test.h
@@ -11,7 +11,7 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/public/window_types.h"
diff --git a/ash/common/test/ash_test_impl.h b/ash/common/test/ash_test_impl.h
index ab477c9..c59260b 100644
--- a/ash/common/test/ash_test_impl.h
+++ b/ash/common/test/ash_test_impl.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <string>
 
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/public/window_types.h"
 
diff --git a/ash/content/shell_content_state.h b/ash/content/shell_content_state.h
index 661c425..3269a582 100644
--- a/ash/content/shell_content_state.h
+++ b/ash/content/shell_content_state.h
@@ -5,8 +5,8 @@
 #ifndef ASH_CONTENT_SHELL_CONTENT_STATE_H_
 #define ASH_CONTENT_SHELL_CONTENT_STATE_H_
 
-#include "ash/common/session/session_types.h"
 #include "ash/content/ash_with_content_export.h"
+#include "ash/public/cpp/session_types.h"
 #include "base/macros.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/ash/display/display_animator_chromeos.h b/ash/display/display_animator_chromeos.h
index 3270abb..097aa80 100644
--- a/ash/display/display_animator_chromeos.h
+++ b/ash/display/display_animator_chromeos.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace aura {
 class Window;
diff --git a/ash/display/display_change_observer_chromeos.cc b/ash/display/display_change_observer_chromeos.cc
index 352bd72..1f8ed17 100644
--- a/ash/display/display_change_observer_chromeos.cc
+++ b/ash/display/display_change_observer_chromeos.cc
@@ -20,9 +20,9 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/user_activity/user_activity_detector.h"
 #include "ui/compositor/dip_util.h"
-#include "ui/display/chromeos/touchscreen_util.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/manager/chromeos/touchscreen_util.h"
 #include "ui/display/manager/display_layout_store.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/display_manager_utilities.h"
diff --git a/ash/display/display_change_observer_chromeos.h b/ash/display/display_change_observer_chromeos.h
index aeb43fe..2e44778 100644
--- a/ash/display/display_change_observer_chromeos.h
+++ b/ash/display/display_change_observer_chromeos.h
@@ -12,7 +12,7 @@
 #include "ash/ash_export.h"
 #include "ash/common/shell_observer.h"
 #include "base/macros.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/events/devices/input_device_event_observer.h"
 
diff --git a/ash/display/display_change_observer_chromeos_unittest.cc b/ash/display/display_change_observer_chromeos_unittest.cc
index 30d22e9..be868773 100644
--- a/ash/display/display_change_observer_chromeos_unittest.cc
+++ b/ash/display/display_change_observer_chromeos_unittest.cc
@@ -6,8 +6,8 @@
 
 #include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/display_configurator.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/display/types/display_mode.h"
 
diff --git a/ash/display/display_color_manager_chromeos.h b/ash/display/display_color_manager_chromeos.h
index f31dd74b..4939b8a 100644
--- a/ash/display/display_color_manager_chromeos.h
+++ b/ash/display/display_color_manager_chromeos.h
@@ -16,7 +16,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/types/display_constants.h"
 
 namespace base {
diff --git a/ash/display/display_color_manager_chromeos_unittest.cc b/ash/display/display_color_manager_chromeos_unittest.cc
index 157fd85b..d4546979 100644
--- a/ash/display/display_color_manager_chromeos_unittest.cc
+++ b/ash/display/display_color_manager_chromeos_unittest.cc
@@ -16,9 +16,9 @@
 #include "components/quirks/quirks_manager.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/test/action_logger_util.h"
-#include "ui/display/chromeos/test/test_native_display_delegate.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/test_native_display_delegate.h"
 
 namespace ash {
 
diff --git a/ash/display/display_configuration_controller.cc b/ash/display/display_configuration_controller.cc
index 5184530..1e7bc4c 100644
--- a/ash/display/display_configuration_controller.cc
+++ b/ash/display/display_configuration_controller.cc
@@ -8,7 +8,7 @@
 #include "ash/display/display_util.h"
 #include "ash/rotator/screen_rotation_animator.h"
 #include "base/time/time.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/ash/display/display_error_observer_chromeos.h b/ash/display/display_error_observer_chromeos.h
index d62b02cb..e421b6f 100644
--- a/ash/display/display_error_observer_chromeos.h
+++ b/ash/display/display_error_observer_chromeos.h
@@ -9,7 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace ash {
 
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc
index 40448ffb..f51e2e3 100644
--- a/ash/display/display_manager_unittest.cc
+++ b/ash/display/display_manager_unittest.cc
@@ -29,9 +29,9 @@
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/display/display.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/display_observer.h"
 #include "ui/display/display_switches.h"
-#include "ui/display/manager/display_layout_builder.h"
 #include "ui/display/manager/display_layout_store.h"
 #include "ui/display/manager/display_manager_utilities.h"
 #include "ui/display/manager/managed_display_info.h"
diff --git a/ash/display/extended_mouse_warp_controller.cc b/ash/display/extended_mouse_warp_controller.cc
index a9cbe5c..c83bf07 100644
--- a/ash/display/extended_mouse_warp_controller.cc
+++ b/ash/display/extended_mouse_warp_controller.cc
@@ -13,7 +13,7 @@
 #include "ash/shell.h"
 #include "base/memory/ptr_util.h"
 #include "ui/aura/window.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/display_manager_utilities.h"
 #include "ui/display/screen.h"
diff --git a/ash/display/extended_mouse_warp_controller_unittest.cc b/ash/display/extended_mouse_warp_controller_unittest.cc
index 6f07e50..61214ac 100644
--- a/ash/display/extended_mouse_warp_controller_unittest.cc
+++ b/ash/display/extended_mouse_warp_controller_unittest.cc
@@ -8,8 +8,8 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/ash/display/json_converter.cc b/ash/display/json_converter.cc
index 424cf11..943eeb44 100644
--- a/ash/display/json_converter.cc
+++ b/ash/display/json_converter.cc
@@ -11,7 +11,7 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 
 namespace ash {
 
diff --git a/ash/display/json_converter_unittest.cc b/ash/display/json_converter_unittest.cc
index deac772..e254c99 100644
--- a/ash/display/json_converter_unittest.cc
+++ b/ash/display/json_converter_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/json/json_reader.h"
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 
 namespace ash {
 
diff --git a/ash/display/mirror_window_controller.cc b/ash/display/mirror_window_controller.cc
index 0b9d4343..8d48cfd9 100644
--- a/ash/display/mirror_window_controller.cc
+++ b/ash/display/mirror_window_controller.cc
@@ -32,7 +32,7 @@
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/layout.h"
 #include "ui/compositor/reflector.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/display/screen.h"
diff --git a/ash/display/mouse_cursor_event_filter_unittest.cc b/ash/display/mouse_cursor_event_filter_unittest.cc
index 194e02cb52..be81f86 100644
--- a/ash/display/mouse_cursor_event_filter_unittest.cc
+++ b/ash/display/mouse_cursor_event_filter_unittest.cc
@@ -8,7 +8,7 @@
 #include "ash/test/ash_test_base.h"
 #include "ash/test/cursor_manager_test_api.h"
 #include "ui/aura/env.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/test/event_generator.h"
diff --git a/ash/display/projecting_observer_chromeos.h b/ash/display/projecting_observer_chromeos.h
index 7d839b0..86f2177 100644
--- a/ash/display/projecting_observer_chromeos.h
+++ b/ash/display/projecting_observer_chromeos.h
@@ -8,7 +8,7 @@
 #include "ash/ash_export.h"
 #include "ash/common/shell_observer.h"
 #include "base/macros.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace chromeos {
 class PowerManagerClient;
diff --git a/ash/display/root_window_transformers_unittest.cc b/ash/display/root_window_transformers_unittest.cc
index 45cc69b5..eb850a3c 100644
--- a/ash/display/root_window_transformers_unittest.cc
+++ b/ash/display/root_window_transformers_unittest.cc
@@ -20,7 +20,7 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tracker.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/display/screen.h"
diff --git a/ash/display/screen_position_controller_unittest.cc b/ash/display/screen_position_controller_unittest.cc
index bf7a12d..96605ab 100644
--- a/ash/display/screen_position_controller_unittest.cc
+++ b/ash/display/screen_position_controller_unittest.cc
@@ -16,7 +16,7 @@
 #include "ui/aura/window_tracker.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/layout.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/events/test/event_generator.h"
diff --git a/ash/display/unified_mouse_warp_controller.cc b/ash/display/unified_mouse_warp_controller.cc
index f918405..68006a0 100644
--- a/ash/display/unified_mouse_warp_controller.cc
+++ b/ash/display/unified_mouse_warp_controller.cc
@@ -15,7 +15,7 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/layout.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/display_manager_utilities.h"
 #include "ui/display/screen.h"
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc
index 3ee9f48..2182595 100644
--- a/ash/display/window_tree_host_manager.cc
+++ b/ash/display/window_tree_host_manager.cc
@@ -42,7 +42,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/compositor/compositor.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_layout_store.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
diff --git a/ash/display/window_tree_host_manager_unittest.cc b/ash/display/window_tree_host_manager_unittest.cc
index 4e73937..3148c23 100644
--- a/ash/display/window_tree_host_manager_unittest.cc
+++ b/ash/display/window_tree_host_manager_unittest.cc
@@ -30,9 +30,9 @@
 #include "ui/aura/window_tracker.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/display/display.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/display_observer.h"
-#include "ui/display/manager/display_layout.h"
-#include "ui/display/manager/display_layout_builder.h"
 #include "ui/display/manager/display_layout_store.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/managed_display_info.h"
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc
index 9ac28ff..1f5c709 100644
--- a/ash/extended_desktop_unittest.cc
+++ b/ash/extended_desktop_unittest.cc
@@ -21,7 +21,7 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/events/event_handler.h"
diff --git a/ash/mus/BUILD.gn b/ash/mus/BUILD.gn
index f7970bb..bf6c408 100644
--- a/ash/mus/BUILD.gn
+++ b/ash/mus/BUILD.gn
@@ -88,6 +88,7 @@
     "//content/public/common:service_names",
     "//ui/app_list/presenter",
     "//ui/app_list/presenter:mojom",
+    "//ui/display/manager",
     "//ui/keyboard",
     "//ui/keyboard:mojom",
     "//ui/message_center",
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 9f3bf56..521d9fbb 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -5,6 +5,7 @@
 # C++ headers and sources that can be used outside ash.
 source_set("cpp") {
   sources = [
+    "session_types.h",
     "shelf_types.h",
     "shell_window_ids.cc",
     "shell_window_ids.h",
diff --git a/ash/common/session/session_types.h b/ash/public/cpp/session_types.h
similarity index 83%
rename from ash/common/session/session_types.h
rename to ash/public/cpp/session_types.h
index 6c7b079..c5c59f0 100644
--- a/ash/common/session/session_types.h
+++ b/ash/public/cpp/session_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 ASH_COMMON_SESSION_SESSION_TYPES_H_
-#define ASH_COMMON_SESSION_SESSION_TYPES_H_
+#ifndef ASH_PUBLIC_CPP_SESSION_TYPES_H_
+#define ASH_PUBLIC_CPP_SESSION_TYPES_H_
 
 namespace ash {
 
@@ -25,4 +25,4 @@
 
 }  // namespace ash
 
-#endif  // ASH_COMMON_SESSION_SESSION_TYPES_H_
+#endif  // ASH_PUBLIC_CPP_SESSION_TYPES_H_
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 52419e74..4ef2f84 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -39,7 +39,7 @@
 #include "ui/compositor/layer_animator.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/ash/shell.cc b/ash/shell.cc
index 626c56fb..fff241c2 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -135,10 +135,10 @@
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "ui/chromeos/user_activity_power_manager_notifier.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 #if defined(USE_X11)
-#include "ui/display/chromeos/x11/native_display_delegate_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_delegate_x11.h"
 #endif
 
 #if defined(USE_OZONE)
diff --git a/ash/sticky_keys/sticky_keys_overlay_unittest.cc b/ash/sticky_keys/sticky_keys_overlay_unittest.cc
index 714cc57b..5a5c538 100644
--- a/ash/sticky_keys/sticky_keys_overlay_unittest.cc
+++ b/ash/sticky_keys/sticky_keys_overlay_unittest.cc
@@ -8,7 +8,7 @@
 #include "ash/shell.h"
 #include "ash/sticky_keys/sticky_keys_controller.h"
 #include "ash/test/ash_test_base.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/event.h"
diff --git a/ash/system/chromeos/power/power_event_observer.cc b/ash/system/chromeos/power/power_event_observer.cc
index 897b1e2..b0834056 100644
--- a/ash/system/chromeos/power/power_event_observer.cc
+++ b/ash/system/chromeos/power/power_event_observer.cc
@@ -14,7 +14,7 @@
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/user_activity/user_activity_detector.h"
 #include "ui/compositor/compositor.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace ash {
 
diff --git a/ash/test/ash_test_impl_aura.cc b/ash/test/ash_test_impl_aura.cc
index 096050be..7768396a 100644
--- a/ash/test/ash_test_impl_aura.cc
+++ b/ash/test/ash_test_impl_aura.cc
@@ -11,7 +11,7 @@
 #include "ash/test/ash_test_base.h"
 #include "base/memory/ptr_util.h"
 #include "ui/aura/test/test_window_delegate.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/ash/touch/touch_observer_hud.h b/ash/touch/touch_observer_hud.h
index 4b1fc79..97e5766f1 100644
--- a/ash/touch/touch_observer_hud.h
+++ b/ash/touch/touch_observer_hud.h
@@ -15,7 +15,7 @@
 #include "ui/views/widget/widget_observer.h"
 
 #if defined(OS_CHROMEOS)
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #endif  // defined(OS_CHROMEOS)
 
 namespace views {
diff --git a/ash/touch/touch_transformer_controller.cc b/ash/touch/touch_transformer_controller.cc
index 0e94c13..020561f 100644
--- a/ash/touch/touch_transformer_controller.cc
+++ b/ash/touch/touch_transformer_controller.cc
@@ -9,8 +9,8 @@
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/display/chromeos/display_configurator.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/display/types/display_snapshot.h"
diff --git a/ash/wm/dock/docked_window_layout_manager_unittest.cc b/ash/wm/dock/docked_window_layout_manager_unittest.cc
index 344c1c3..47c947d4 100644
--- a/ash/wm/dock/docked_window_layout_manager_unittest.cc
+++ b/ash/wm/dock/docked_window_layout_manager_unittest.cc
@@ -25,7 +25,7 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/hit_test.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc
index d9584b4..215d8a3 100644
--- a/ash/wm/drag_window_resizer_unittest.cc
+++ b/ash/wm/drag_window_resizer_unittest.cc
@@ -25,8 +25,8 @@
 #include "ui/base/ui_base_types.h"
 #include "ui/compositor/layer_delegate.h"
 #include "ui/compositor/layer_tree_owner.h"
-#include "ui/display/manager/display_layout.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/views/widget/widget.h"
diff --git a/ash/wm/immersive_fullscreen_controller_unittest.cc b/ash/wm/immersive_fullscreen_controller_unittest.cc
index 1de5101..1c00bab3 100644
--- a/ash/wm/immersive_fullscreen_controller_unittest.cc
+++ b/ash/wm/immersive_fullscreen_controller_unittest.cc
@@ -20,7 +20,7 @@
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/event_utils.h"
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc
index 5842f17..c4f40ee 100644
--- a/ash/wm/lock_state_controller.cc
+++ b/ash/wm/lock_state_controller.cc
@@ -488,11 +488,14 @@
       base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs);
 #if defined(OS_CHROMEOS)
   // Increase lock timeout for slower hardware, see http://crbug.com/350628
-  const std::string board = base::SysInfo::GetLsbReleaseBoard();
-  if (board == "x86-mario" ||
+  // The devices with boards "x86-mario", "daisy", "x86-alex" and "x86-zgb" have
+  // slower hardware. For "x86-alex" and "x86-zgb" there are some modifications
+  // like "x86-alex-he". Also there's "daisy", "daisy_spring" and "daisy_skate",
+  // but they are all different devices and only "daisy" has slower hardware.
+  const std::string board = base::SysInfo::GetStrippedReleaseBoard();
+  if (board == "x86-mario" || board == "daisy" ||
       base::StartsWith(board, "x86-alex", base::CompareCase::SENSITIVE) ||
-      base::StartsWith(board, "x86-zgb", base::CompareCase::SENSITIVE) ||
-      base::StartsWith(board, "daisy", base::CompareCase::SENSITIVE)) {
+      base::StartsWith(board, "x86-zgb", base::CompareCase::SENSITIVE)) {
     timeout *= 2;
   }
 #endif
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index b37dc11e..9f471ba 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -24,8 +24,8 @@
 #include "base/time/time.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
-#include "ui/display/chromeos/display_configurator.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/geometry/size.h"
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 4611111..39dab4f 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -55,7 +55,7 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/hit_test.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/event_utils.h"
diff --git a/ash/wm/power_button_controller.h b/ash/wm/power_button_controller.h
index ce57883..77fe505 100644
--- a/ash/wm/power_button_controller.h
+++ b/ash/wm/power_button_controller.h
@@ -14,7 +14,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/power_manager_client.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #endif
 
 namespace ash {
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 9ce6407..969b562 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -36,7 +36,7 @@
 #include "base/run_loop.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/base/ui_base_types.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/ash/wm/workspace/workspace_window_resizer_unittest.cc b/ash/wm/workspace/workspace_window_resizer_unittest.cc
index 16face78..1bf44f6 100644
--- a/ash/wm/workspace/workspace_window_resizer_unittest.cc
+++ b/ash/wm/workspace/workspace_window_resizer_unittest.cc
@@ -26,7 +26,7 @@
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/hit_test.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/base/sys_info.h b/base/sys_info.h
index b107477..e35feff7 100644
--- a/base/sys_info.h
+++ b/base/sys_info.h
@@ -107,9 +107,19 @@
   static bool GetLsbReleaseValue(const std::string& key, std::string* value);
 
   // Convenience function for GetLsbReleaseValue("CHROMEOS_RELEASE_BOARD",...).
-  // Returns "unknown" if CHROMEOS_RELEASE_BOARD is not set.
+  // Returns "unknown" if CHROMEOS_RELEASE_BOARD is not set. Otherwise returns
+  // the full name of the board. WARNING: the returned value often differs in
+  // developer built system compared to devices that use the official version.
+  // E.g. for developer built version, the function could return 'glimmer' while
+  // for officially used versions it would be like 'glimmer-signed-mp-v4keys'.
+  // Use GetStrippedReleaseBoard() function if you need only the short name of
+  // the board (would be 'glimmer' in the case described above).
   static std::string GetLsbReleaseBoard();
 
+  // Convenience function for GetLsbReleaseBoard() removing trailing "-signed-*"
+  // if present. Returns "unknown" if CHROMEOS_RELEASE_BOARD is not set.
+  static std::string GetStrippedReleaseBoard();
+
   // Returns the creation time of /etc/lsb-release. (Used to get the date and
   // time of the Chrome OS build).
   static Time GetLsbReleaseTime();
diff --git a/base/sys_info_chromeos.cc b/base/sys_info_chromeos.cc
index e4d671f7..29f8384 100644
--- a/base/sys_info_chromeos.cc
+++ b/base/sys_info_chromeos.cc
@@ -200,6 +200,16 @@
 }
 
 // static
+std::string SysInfo::GetStrippedReleaseBoard() {
+  std::string board = GetLsbReleaseBoard();
+  const size_t index = board.find("-signed-");
+  if (index != std::string::npos)
+    board.resize(index);
+
+  return base::ToLowerASCII(board);
+}
+
+// static
 Time SysInfo::GetLsbReleaseTime() {
   return GetChromeOSVersionInfo().lsb_release_time();
 }
diff --git a/base/sys_info_unittest.cc b/base/sys_info_unittest.cc
index 0231df63..c3b8507 100644
--- a/base/sys_info_unittest.cc
+++ b/base/sys_info_unittest.cc
@@ -156,4 +156,14 @@
   EXPECT_TRUE(base::SysInfo::IsRunningOnChromeOS());
 }
 
+TEST_F(SysInfoTest, GetStrippedReleaseBoard) {
+  const char* kLsbRelease1 = "CHROMEOS_RELEASE_BOARD=Glimmer\n";
+  base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease1, base::Time());
+  EXPECT_EQ("glimmer", base::SysInfo::GetStrippedReleaseBoard());
+
+  const char* kLsbRelease2 = "CHROMEOS_RELEASE_BOARD=glimmer-signed-mp-v4keys";
+  base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease2, base::Time());
+  EXPECT_EQ("glimmer", base::SysInfo::GetStrippedReleaseBoard());
+}
+
 #endif  // OS_CHROMEOS
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index e1873bc..6591eeb 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -832,12 +832,8 @@
     worker_thread_->Start();
   }
 
-  if (command_line->HasSwitch(switches::kTestLauncherFilterFile) &&
-      command_line->HasSwitch(kGTestFilterFlag)) {
-    LOG(ERROR) << "Only one of --test-launcher-filter-file and --gtest_filter "
-               << "at a time is allowed.";
-    return false;
-  }
+  std::vector<std::string> positive_file_filter;
+  std::vector<std::string> positive_gtest_filter;
 
   if (command_line->HasSwitch(switches::kTestLauncherFilterFile)) {
     base::FilePath filter_file_path = base::MakeAbsoluteFilePath(
@@ -859,26 +855,27 @@
       if (filter_line[0] == '-')
         negative_test_filter_.push_back(filter_line.substr(1));
       else
-        positive_test_filter_.push_back(filter_line);
+        positive_file_filter.push_back(filter_line);
     }
+  }
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions.
+  std::string filter = command_line->GetSwitchValueASCII(kGTestFilterFlag);
+  size_t dash_pos = filter.find('-');
+  if (dash_pos == std::string::npos) {
+    positive_gtest_filter =
+        SplitString(filter, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
   } else {
-    // Split --gtest_filter at '-', if there is one, to separate into
-    // positive filter and negative filter portions.
-    std::string filter = command_line->GetSwitchValueASCII(kGTestFilterFlag);
-    size_t dash_pos = filter.find('-');
-    if (dash_pos == std::string::npos) {
-      positive_test_filter_ = SplitString(
-          filter, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-    } else {
-      // Everything up to the dash.
-      positive_test_filter_ = SplitString(
-          filter.substr(0, dash_pos), ":", base::TRIM_WHITESPACE,
-          base::SPLIT_WANT_ALL);
+    // Everything up to the dash.
+    positive_gtest_filter =
+        SplitString(filter.substr(0, dash_pos), ":", base::TRIM_WHITESPACE,
+                    base::SPLIT_WANT_ALL);
 
-      // Everything after the dash.
-      negative_test_filter_ = SplitString(
-          filter.substr(dash_pos + 1), ":", base::TRIM_WHITESPACE,
-          base::SPLIT_WANT_ALL);
+    // Everything after the dash.
+    for (std::string pattern :
+         SplitString(filter.substr(dash_pos + 1), ":", base::TRIM_WHITESPACE,
+                     base::SPLIT_WANT_ALL)) {
+      negative_test_filter_.push_back(pattern);
     }
   }
 
@@ -887,6 +884,8 @@
     return false;
   }
 
+  CombinePositiveTestFilters(positive_gtest_filter, positive_file_filter);
+
   if (!results_tracker_.Init(*command_line)) {
     LOG(ERROR) << "Failed to initialize test results tracker.";
     return 1;
@@ -957,11 +956,44 @@
   return true;
 }
 
+void TestLauncher::CombinePositiveTestFilters(
+    std::vector<std::string> filter_a,
+    std::vector<std::string> filter_b) {
+  has_at_least_one_positive_filter_ = !filter_a.empty() || !filter_b.empty();
+  if (!has_at_least_one_positive_filter_) {
+    return;
+  } else {
+    // If two positive filters are present, only run tests that match a pattern
+    // in both filters.
+    if (!filter_a.empty() && !filter_b.empty()) {
+      for (size_t i = 0; i < tests_.size(); i++) {
+        std::string test_name =
+            FormatFullTestName(tests_[i].test_case_name, tests_[i].test_name);
+        bool found_a = false;
+        bool found_b = false;
+        for (size_t k = 0; k < filter_a.size(); ++k) {
+          found_a = found_a || MatchPattern(test_name, filter_a[k]);
+        }
+        for (size_t k = 0; k < filter_b.size(); ++k) {
+          found_b = found_b || MatchPattern(test_name, filter_b[k]);
+        }
+        if (found_a && found_b) {
+          positive_test_filter_.push_back(test_name);
+        }
+      }
+    } else if (!filter_a.empty()) {
+      positive_test_filter_ = filter_a;
+    } else {
+      positive_test_filter_ = filter_b;
+    }
+  }
+}
+
 void TestLauncher::RunTests() {
   std::vector<std::string> test_names;
   for (size_t i = 0; i < tests_.size(); i++) {
-    std::string test_name = FormatFullTestName(
-        tests_[i].test_case_name, tests_[i].test_name);
+    std::string test_name =
+        FormatFullTestName(tests_[i].test_case_name, tests_[i].test_name);
 
     results_tracker_.AddTest(test_name, tests_[i].file, tests_[i].line);
 
@@ -974,23 +1006,23 @@
         continue;
     }
 
-    if (!launcher_delegate_->ShouldRunTest(
-        tests_[i].test_case_name, tests_[i].test_name)) {
+    if (!launcher_delegate_->ShouldRunTest(tests_[i].test_case_name,
+                                           tests_[i].test_name)) {
       continue;
     }
 
     // Count tests in the binary, before we apply filter and sharding.
     test_found_count_++;
 
-    std::string test_name_no_disabled = TestNameWithoutDisabledPrefix(
-        test_name);
+    std::string test_name_no_disabled =
+        TestNameWithoutDisabledPrefix(test_name);
 
     // Skip the test that doesn't match the filter (if given).
-    if (!positive_test_filter_.empty()) {
+    if (has_at_least_one_positive_filter_) {
       bool found = false;
-      for (size_t k = 0; k < positive_test_filter_.size(); ++k) {
-        if (MatchPattern(test_name, positive_test_filter_[k]) ||
-            MatchPattern(test_name_no_disabled, positive_test_filter_[k])) {
+      for (auto filter : positive_test_filter_) {
+        if (MatchPattern(test_name, filter) ||
+            MatchPattern(test_name_no_disabled, filter)) {
           found = true;
           break;
         }
@@ -1001,9 +1033,9 @@
     }
     if (!negative_test_filter_.empty()) {
       bool excluded = false;
-      for (size_t k = 0; k < negative_test_filter_.size(); ++k) {
-        if (MatchPattern(test_name, negative_test_filter_[k]) ||
-            MatchPattern(test_name_no_disabled, negative_test_filter_[k])) {
+      for (auto filter : negative_test_filter_) {
+        if (MatchPattern(test_name, filter) ||
+            MatchPattern(test_name_no_disabled, filter)) {
           excluded = true;
           break;
         }
diff --git a/base/test/launcher/test_launcher.h b/base/test/launcher/test_launcher.h
index 218d8b6..a2fd8b2 100644
--- a/base/test/launcher/test_launcher.h
+++ b/base/test/launcher/test_launcher.h
@@ -142,6 +142,9 @@
   // Runs all tests in current iteration. Uses callbacks to communicate success.
   void RunTests();
 
+  void CombinePositiveTestFilters(std::vector<std::string> filter_a,
+                                  std::vector<std::string> filter_b);
+
   void RunTestIteration();
 
   // Saves test results summary as JSON if requested from command line.
@@ -181,6 +184,7 @@
   int cycles_;  // Number of remaining test itreations, or -1 for infinite.
 
   // Test filters (empty means no filter).
+  bool has_at_least_one_positive_filter_;
   std::vector<std::string> positive_test_filter_;
   std::vector<std::string> negative_test_filter_;
 
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
index 21bff69..c8ba4ed 100644
--- a/base/trace_event/memory_infra_background_whitelist.cc
+++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -34,6 +34,7 @@
     "Sql",
     "V8Isolate",
     "WinHeap",
+    "SyncDirectory",
     nullptr  // End of list marker.
 };
 
@@ -91,6 +92,8 @@
     "v8/isolate_0x?/zapped_for_debug",
     "winheap",
     "winheap/allocated_objects",
+    "sync/0x?/kernel",
+    "sync/0x?/store",
     nullptr  // End of list marker.
 };
 
diff --git a/cc/ipc/quads.mojom b/cc/ipc/quads.mojom
index a7444ad..82f2542 100644
--- a/cc/ipc/quads.mojom
+++ b/cc/ipc/quads.mojom
@@ -63,6 +63,7 @@
 
 struct TextureQuadState {
   uint32 resource_id;
+  gfx.mojom.Size resource_size_in_pixels;
   bool premultiplied_alpha;
   gfx.mojom.PointF uv_top_left;
   gfx.mojom.PointF uv_bottom_right;
diff --git a/cc/ipc/quads_struct_traits.cc b/cc/ipc/quads_struct_traits.cc
index 7e567f5..6d649d5 100644
--- a/cc/ipc/quads_struct_traits.cc
+++ b/cc/ipc/quads_struct_traits.cc
@@ -113,8 +113,15 @@
     cc::mojom::TextureQuadStateDataView data,
     cc::DrawQuad* out) {
   cc::TextureDrawQuad* quad = static_cast<cc::TextureDrawQuad*>(out);
+
   quad->resources.ids[cc::TextureDrawQuad::kResourceIdIndex] =
       data.resource_id();
+  if (!data.ReadResourceSizeInPixels(
+          &quad->overlay_resources
+               .size_in_pixels[cc::TextureDrawQuad::kResourceIdIndex])) {
+    return false;
+  }
+
   quad->resources.count = 1;
   quad->premultiplied_alpha = data.premultiplied_alpha();
   if (!data.ReadUvTopLeft(&quad->uv_top_left) ||
diff --git a/cc/ipc/quads_struct_traits.h b/cc/ipc/quads_struct_traits.h
index 06fd68c..dc6aed9 100644
--- a/cc/ipc/quads_struct_traits.h
+++ b/cc/ipc/quads_struct_traits.h
@@ -247,6 +247,11 @@
     return quad->resource_id();
   }
 
+  static const gfx::Size& resource_size_in_pixels(const cc::DrawQuad& input) {
+    const cc::TextureDrawQuad* quad = cc::TextureDrawQuad::MaterialCast(&input);
+    return quad->resource_size_in_pixels();
+  }
+
   static bool premultiplied_alpha(const cc::DrawQuad& input) {
     const cc::TextureDrawQuad* quad = cc::TextureDrawQuad::MaterialCast(&input);
     return quad->premultiplied_alpha;
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc
index 62a8ca8..a952b11 100644
--- a/cc/ipc/struct_traits_unittest.cc
+++ b/cc/ipc/struct_traits_unittest.cc
@@ -472,9 +472,12 @@
   const bool y_flipped = true;
   const bool nearest_neighbor = true;
   const bool secure_output_only = true;
+  const bool needs_blending = true;
+  const gfx::Size resource_size_in_pixels5(1234, 5678);
   TextureDrawQuad* texture_draw_quad =
       render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
-  texture_draw_quad->SetNew(sqs, rect5, rect5, rect5, resource_id5,
+  texture_draw_quad->SetAll(sqs, rect5, rect5, rect5, needs_blending,
+                            resource_id5, resource_size_in_pixels5,
                             premultiplied_alpha, uv_top_left, uv_bottom_right,
                             background_color, vertex_opacity, y_flipped,
                             nearest_neighbor, secure_output_only);
@@ -539,7 +542,10 @@
   EXPECT_EQ(rect5, out_texture_draw_quad->rect);
   EXPECT_EQ(rect5, out_texture_draw_quad->opaque_rect);
   EXPECT_EQ(rect5, out_texture_draw_quad->visible_rect);
+  EXPECT_EQ(needs_blending, out_texture_draw_quad->needs_blending);
   EXPECT_EQ(resource_id5, out_texture_draw_quad->resource_id());
+  EXPECT_EQ(resource_size_in_pixels5,
+            out_texture_draw_quad->resource_size_in_pixels());
   EXPECT_EQ(premultiplied_alpha, out_texture_draw_quad->premultiplied_alpha);
   EXPECT_EQ(uv_top_left, out_texture_draw_quad->uv_top_left);
   EXPECT_EQ(uv_bottom_right, out_texture_draw_quad->uv_bottom_right);
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index b1bc688..5d86b38 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -35,6 +35,7 @@
     : owning_layer_(owning_layer),
       layer_tree_impl_(owning_layer->layer_tree_impl()),
       stable_effect_id_(owning_layer->id()),
+      effect_tree_index_(EffectTree::kInvalidNodeId),
       surface_property_changed_(false),
       ancestor_property_changed_(false),
       contributes_to_drawn_surface_(false),
@@ -159,8 +160,10 @@
 }
 
 int RenderSurfaceImpl::EffectTreeIndex() const {
-  return layer_tree_impl_->property_trees()
-      ->effect_id_to_index_map[stable_effect_id_];
+  DCHECK_EQ(effect_tree_index_,
+            layer_tree_impl_->property_trees()
+                ->effect_id_to_index_map[stable_effect_id_]);
+  return effect_tree_index_;
 }
 
 const EffectNode* RenderSurfaceImpl::OwningEffectNode() const {
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h
index 8cd9523f..4265ea0 100644
--- a/cc/layers/render_surface_impl.h
+++ b/cc/layers/render_surface_impl.h
@@ -152,6 +152,8 @@
 
   int TransformTreeIndex() const;
   int ClipTreeIndex() const;
+
+  void set_effect_tree_index(int index) { effect_tree_index_ = index; }
   int EffectTreeIndex() const;
 
  private:
@@ -164,6 +166,7 @@
 
   LayerTreeImpl* layer_tree_impl_;
   int stable_effect_id_;
+  int effect_tree_index_;
 
   // Container for properties that render surfaces need to compute before they
   // can be drawn.
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index ac9dd0f..7d9024fc 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -39,16 +39,23 @@
 
   FakeImplTaskRunnerProvider task_runner_provider;
   TestTaskGraphRunner task_graph_runner;
+  std::unique_ptr<CompositorFrameSink> compositor_frame_sink =
+      FakeCompositorFrameSink::Create3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
   std::unique_ptr<LayerImpl> owning_layer =
       LayerImpl::Create(host_impl.active_tree(), 1);
-  owning_layer->SetHasRenderSurface(true);
-  ASSERT_TRUE(owning_layer->render_surface());
-  RenderSurfaceImpl* render_surface = owning_layer->render_surface();
+  owning_layer->test_properties()->force_render_surface = true;
   gfx::Rect test_rect(3, 4, 5, 6);
   host_impl.active_tree()->ResetAllChangeTracking();
   host_impl.active_tree()->SetRootLayerForTesting(std::move(owning_layer));
-  host_impl.active_tree()->BuildPropertyTreesForTesting();
+  host_impl.SetVisible(true);
+  host_impl.InitializeRenderer(compositor_frame_sink.get());
+  host_impl.active_tree()->BuildLayerListAndPropertyTreesForTesting();
+  host_impl.active_tree()->UpdateDrawProperties(false /* update_lcd_text */);
+
+  RenderSurfaceImpl* render_surface =
+      host_impl.active_tree()->root_layer_for_testing()->render_surface();
+  ASSERT_TRUE(render_surface);
 
   // Currently, the content_rect, clip_rect, and
   // owning_layer->layerPropertyChanged() are the only sources of change.
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 9828651..f7877c1 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -1071,8 +1071,11 @@
                                 can_render_to_separate_surface, layer);
     EffectNode* node =
         property_trees->effect_tree.Node(layer->effect_tree_index());
-    if (node->owner_id == layer->id())
+    if (node->owner_id == layer->id()) {
       node->render_surface = layer->render_surface();
+      if (node->render_surface)
+        node->render_surface->set_effect_tree_index(node->id);
+    }
 #if DCHECK_IS_ON()
     if (can_render_to_separate_surface)
       ValidateRenderSurfaceForLayer(layer);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
index f87b9849..e897886 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
@@ -252,7 +252,6 @@
 
                     @Override
                     public View acquireView() {
-                        assert false : "Shold not reach here";
                         return null;
                     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
index 982d804..8f72a6e2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
@@ -184,6 +184,7 @@
         mContextControl.destroy();
         mSearchTermControl.destroy();
         mCaptionControl.destroy();
+        mQuickActionControl.destroy();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
index bef75b3d..76effa53 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
@@ -8,6 +8,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
+import org.chromium.content_public.browser.WebContents;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -51,6 +52,12 @@
             @Override
             public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
                 notifyChanged();
+
+                Tab oldTab = getTabById(lastId);
+                if (tab.getId() != lastId) {
+                    WebContents oldWebContents = (oldTab == null) ? null : oldTab.getWebContents();
+                    nativeOnActiveTabChanged(oldWebContents, tab.getWebContents());
+                }
             }
 
             @Override
@@ -231,4 +238,6 @@
             listener.onNewTabCreated(tab);
         }
     }
+
+    static native void nativeOnActiveTabChanged(WebContents oldContents, WebContents newContents);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
index 9daf04d..f32f1b6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -13,6 +13,7 @@
 
 import android.annotation.SuppressLint;
 import android.app.Activity;
+import android.graphics.Point;
 import android.graphics.SurfaceTexture;
 import android.graphics.SurfaceTexture.OnFrameAvailableListener;
 import android.opengl.GLES11Ext;
@@ -28,7 +29,9 @@
 import com.google.vr.ndk.base.GvrLayout;
 
 import org.chromium.base.CommandLine;
+import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeVersionInfo;
@@ -40,6 +43,8 @@
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.ViewAndroidDelegate;
 import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.display.DisplayAndroid;
+import org.chromium.ui.display.VirtualDisplayAndroid;
 
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
@@ -51,9 +56,26 @@
 public class VrShellImpl extends GvrLayout implements GLSurfaceView.Renderer, VrShell {
     private static final String TAG = "VrShellImpl";
 
-    private Activity mActivity;
+    // TODO(mthiesse): These values work well for Pixel/Pixel XL in VR, but we need to come up with
+    // a way to compute good values for any screen size/scaling ratio.
+
+    // Increasing DPR any more than this doesn't appear to increase text quality.
+    private static final float DEFAULT_DPR = 1.2f;
+    // For WebVR we just create a DPR 1.0 display that matches the physical display size.
+    private static final float WEBVR_DPR = 1.0f;
+    // Fairly arbitrary values that put a good amount of content on the screen without making the
+    // text too small to read.
+    private static final float DEFAULT_CONTENT_WIDTH = 1024f;
+    private static final float DEFAULT_CONTENT_HEIGHT = 576f;
+    // Temporary values that will be changed when the UI loads and figures out how what size it
+    // needs to be.
+    private static final float DEFAULT_UI_WIDTH = 1920f;
+    private static final float DEFAULT_UI_HEIGHT = 1080f;
 
     private final GLSurfaceView mGlSurfaceView;
+    private final Activity mActivity;
+    private final VirtualDisplayAndroid mContentVirtualDisplay;
+    private final VirtualDisplayAndroid mUiVirtualDisplay;
 
     private long mNativeVrShell = 0;
 
@@ -62,7 +84,8 @@
     private FrameListener mContentFrameListener;
     private FrameListener mUiFrameListener;
 
-    private FrameLayout mContentViewCoreContainer;
+    private FrameLayout mContentCVCContainer;
+    private FrameLayout mUiCVCContainer;
 
     // The tab that holds the main ContentViewCore.
     private Tab mTab;
@@ -83,18 +106,30 @@
     private ContentViewCore mUiCVC;
     private VrWindowAndroid mUiVrWindowAndroid;
 
+    private boolean mSurfacesInitialized;
+    private int mContentSurfaceWidth = -1;
+    private int mContentSurfaceHeight = -1;
+    private int mUiSurfaceWidth = -1;
+    private int mUiSurfaceHeight = -1;
+
     public VrShellImpl(Activity activity) {
         super(activity);
         mActivity = activity;
-        mContentViewCoreContainer = new FrameLayout(getContext()) {
+        mContentCVCContainer = new FrameLayout(getContext()) {
             @Override
             public boolean dispatchTouchEvent(MotionEvent event) {
                 return true;
             }
         };
-        addView(mContentViewCoreContainer, 0, new FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.MATCH_PARENT,
-                FrameLayout.LayoutParams.MATCH_PARENT));
+        mUiCVCContainer = new FrameLayout(getContext()) {
+            @Override
+            public boolean dispatchTouchEvent(MotionEvent event) {
+                return true;
+            }
+        };
+        addView(mContentCVCContainer, 0, new FrameLayout.LayoutParams(0, 0));
+        addView(mUiCVCContainer, 0, new FrameLayout.LayoutParams(0, 0));
+
         mGlSurfaceView = new GLSurfaceView(getContext());
         mGlSurfaceView.setEGLContextClientVersion(2);
         mGlSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0);
@@ -105,6 +140,11 @@
         if (setAsyncReprojectionEnabled(true)) {
             AndroidCompat.setSustainedPerformanceMode(mActivity, true);
         }
+        DisplayAndroid primaryDisplay = DisplayAndroid.getNonMultiDisplay(activity);
+        mContentVirtualDisplay = VirtualDisplayAndroid.createVirtualDisplay();
+        mContentVirtualDisplay.setTo(primaryDisplay);
+        mUiVirtualDisplay = VirtualDisplayAndroid.createVirtualDisplay();
+        mUiVirtualDisplay.setTo(primaryDisplay);
     }
 
     @Override
@@ -112,18 +152,37 @@
         assert currentTab.getContentViewCore() != null;
         mTab = currentTab;
         mContentCVC = mTab.getContentViewCore();
-        mContentVrWindowAndroid = new VrWindowAndroid(mActivity);
+        mContentVrWindowAndroid = new VrWindowAndroid(mActivity, mContentVirtualDisplay);
 
-        mUiVrWindowAndroid = new VrWindowAndroid(mActivity);
+        mUiVrWindowAndroid = new VrWindowAndroid(mActivity, mUiVirtualDisplay);
         mUiContents = WebContentsFactory.createWebContents(true, false);
         mUiCVC = new ContentViewCore(mActivity, ChromeVersionInfo.getProductVersion());
         ContentView uiContentView = ContentView.createContentView(mActivity, mUiCVC);
         mUiCVC.initialize(ViewAndroidDelegate.createBasicDelegate(uiContentView),
                 uiContentView, mUiContents, mUiVrWindowAndroid);
 
+        // Set the UI and content sizes before we initialize VR Shell and load the UI.
+        setUiCssSize(DEFAULT_UI_WIDTH, DEFAULT_UI_HEIGHT, DEFAULT_DPR);
+        float dpr;
+        if (forWebVR) {
+            DisplayAndroid primaryDisplay = DisplayAndroid.getNonMultiDisplay(mActivity);
+            dpr = WEBVR_DPR;
+            setContentCssSize(primaryDisplay.getPhysicalDisplayWidth(),
+                    primaryDisplay.getPhysicalDisplayHeight(), dpr);
+        } else {
+            dpr = DEFAULT_DPR;
+            setContentCssSize(DEFAULT_CONTENT_WIDTH, DEFAULT_CONTENT_HEIGHT, dpr);
+        }
+
         mNativeVrShell = nativeInit(mContentCVC.getWebContents(),
                 mContentVrWindowAndroid.getNativePointer(), mUiContents,
                 mUiVrWindowAndroid.getNativePointer(), forWebVR);
+
+        // Set the initial Content and UI bounds, as they won't have been propagated yet.
+        nativeContentBoundsChanged(mNativeVrShell, mContentSurfaceWidth, mContentSurfaceHeight,
+                dpr);
+        nativeUIBoundsChanged(mNativeVrShell, mUiSurfaceWidth, mUiSurfaceHeight, DEFAULT_DPR);
+
         mGlSurfaceView.setOnTouchListener(new View.OnTouchListener() {
             @Override
             @SuppressLint("ClickableViewAccessibility")
@@ -139,7 +198,7 @@
 
         uiContentView.setVisibility(View.VISIBLE);
         mUiCVC.onShow();
-        mContentViewCoreContainer.addView(uiContentView, new FrameLayout.LayoutParams(
+        mUiCVCContainer.addView(uiContentView, new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.MATCH_PARENT,
                 FrameLayout.LayoutParams.MATCH_PARENT));
         mUiCVC.setBottomControlsHeight(0);
@@ -164,7 +223,7 @@
         mOriginalLayoutParams = mTabParent.getLayoutParams();
         mTabParentParent.removeView(mTabParent);
 
-        mContentViewCoreContainer.addView(mTabParent, new FrameLayout.LayoutParams(
+        mContentCVCContainer.addView(mTabParent, new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
     }
 
@@ -173,13 +232,72 @@
 
         // If the tab's view has changed, the necessary view reparenting has already been done.
         if (mTab.getView() == mTabParent) {
-            mContentViewCoreContainer.removeView(mTabParent);
+            mContentCVCContainer.removeView(mTabParent);
             mTabParentParent.addView(mTabParent, mOriginalTabParentIndex, mOriginalLayoutParams);
             mTabParent.requestFocus();
         }
         mTabParent = null;
     }
 
+    private final Runnable mUpdateContentBufferSize = new Runnable() {
+        @Override
+        public void run() {
+            if (mSurfacesInitialized) {
+                mContentFrameListener.mSurfaceTexture.setDefaultBufferSize(
+                        mContentSurfaceWidth, mContentSurfaceHeight);
+            }
+        }
+    };
+
+    private final Runnable mUpdateUiBufferSize = new Runnable() {
+        @Override
+        public void run() {
+            if (mSurfacesInitialized) {
+                mUiFrameListener.mSurfaceTexture.setDefaultBufferSize(
+                        mUiSurfaceWidth, mUiSurfaceHeight);
+            }
+        }
+    };
+
+    @CalledByNative
+    public void setUiCssSize(float width, float height, float dpr) {
+        ThreadUtils.assertOnUiThread();
+        if (dpr != DEFAULT_DPR) {
+            Log.w(TAG, "Changing UI DPR causes the UI to flicker and should generally not be "
+                    + "done.");
+        }
+        mUiSurfaceWidth = (int) Math.ceil(width * dpr);
+        mUiSurfaceHeight = (int) Math.ceil(height * dpr);
+
+        Point size = new Point(mUiSurfaceWidth, mUiSurfaceHeight);
+        mUiVirtualDisplay.update(size, size, dpr, null, null, null);
+
+        mGlSurfaceView.post(mUpdateUiBufferSize);
+        mUiCVCContainer.setLayoutParams(new FrameLayout.LayoutParams(
+                mUiSurfaceWidth, mUiSurfaceHeight));
+        mUiCVC.onPhysicalBackingSizeChanged(mUiSurfaceWidth, mUiSurfaceHeight);
+        if (mNativeVrShell == 0) return;
+        nativeUIBoundsChanged(mNativeVrShell, mUiSurfaceWidth, mUiSurfaceHeight, dpr);
+    }
+
+    @CalledByNative
+    public void setContentCssSize(float width, float height, float dpr) {
+        ThreadUtils.assertOnUiThread();
+        mContentSurfaceWidth = (int) Math.ceil(width * dpr);
+        mContentSurfaceHeight = (int) Math.ceil(height * dpr);
+
+        Point size = new Point(mContentSurfaceWidth, mContentSurfaceHeight);
+        mContentVirtualDisplay.update(size, size, dpr, null, null, null);
+
+        mGlSurfaceView.post(mUpdateContentBufferSize);
+        mContentCVCContainer.setLayoutParams(new FrameLayout.LayoutParams(
+                mContentSurfaceWidth, mContentSurfaceHeight));
+        mContentCVC.onPhysicalBackingSizeChanged(mContentSurfaceWidth, mContentSurfaceHeight);
+        if (mNativeVrShell == 0) return;
+        nativeContentBoundsChanged(mNativeVrShell, mContentSurfaceWidth, mContentSurfaceHeight,
+                dpr);
+    }
+
     private static class FrameListener implements OnFrameAvailableListener {
         final SurfaceTexture mSurfaceTexture;
         final GLSurfaceView mGlSurfaceView;
@@ -210,26 +328,28 @@
 
     @Override
     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-        final int width = mContentCVC.getContainerView().getWidth();
-        final int height = mContentCVC.getContainerView().getHeight();
         mContentTextureHandle = createExternalTextureHandle();
         mUiTextureHandle = createExternalTextureHandle();
 
         mContentFrameListener = new FrameListener(mContentTextureHandle, mGlSurfaceView);
         mUiFrameListener = new FrameListener(mUiTextureHandle, mGlSurfaceView);
 
-        mContentFrameListener.mSurfaceTexture.setDefaultBufferSize(width, height);
-        mUiFrameListener.mSurfaceTexture.setDefaultBufferSize(width, height);
+        if (mContentSurfaceWidth != -1) {
+            mContentFrameListener.mSurfaceTexture.setDefaultBufferSize(
+                    mContentSurfaceWidth, mContentSurfaceHeight);
+        }
+        if (mUiSurfaceWidth != -1) {
+            mUiFrameListener.mSurfaceTexture.setDefaultBufferSize(
+                    mUiSurfaceWidth, mUiSurfaceHeight);
+        }
+        mSurfacesInitialized = true;
 
         ThreadUtils.postOnUiThread(new Runnable() {
             @Override
             public void run() {
-                nativeContentSurfaceChanged(mNativeVrShell, width, height,
-                        new Surface(mContentFrameListener.mSurfaceTexture));
-                mContentCVC.onPhysicalBackingSizeChanged(width, height);
-                nativeUiSurfaceChanged(mNativeVrShell, width, height,
+                nativeSurfacesChanged(mNativeVrShell,
+                        new Surface(mContentFrameListener.mSurfaceTexture),
                         new Surface(mUiFrameListener.mSurfaceTexture));
-                mUiCVC.onPhysicalBackingSizeChanged(width, height);
             }
         });
 
@@ -312,6 +432,8 @@
         }
         restoreContentWindow();
         mUiContents.destroy();
+        mContentVirtualDisplay.destroy();
+        mUiVirtualDisplay.destroy();
     }
 
     @Override
@@ -372,10 +494,11 @@
     private native void nativeOnTriggerEvent(long nativeVrShell);
     private native void nativeOnPause(long nativeVrShell);
     private native void nativeOnResume(long nativeVrShell);
-    private native void nativeContentSurfaceChanged(
-            long nativeVrShell, int width, int height, Surface surface);
-    private native void nativeUiSurfaceChanged(
-            long nativeVrShell, int width, int height, Surface surface);
+    private native void nativeSurfacesChanged(
+            long nativeVrShell, Surface contentSurface, Surface uiSurface);
+    private native void nativeContentBoundsChanged(long nativeVrShell, int width, int height,
+            float dpr);
+    private native void nativeUIBoundsChanged(long nativeVrShell, int width, int height, float dpr);
     private native void nativeUpdateCompositorLayers(long nativeVrShell);
     private native void nativeSetWebVrMode(long nativeVrShell, boolean enabled);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java
index 303d24d..3eb8b884 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java
@@ -17,6 +17,7 @@
 import org.chromium.base.Callback;
 import org.chromium.ui.base.AndroidPermissionDelegate;
 import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.display.DisplayAndroid;
 
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
@@ -25,12 +26,11 @@
  * The class provides the WindowAndroid's implementation which requires Activity Instance. It is
  * only intended to be used when in VR.
  */
-public class VrWindowAndroid
-        extends WindowAndroid
+public class VrWindowAndroid extends WindowAndroid
         implements ApplicationStatus.ActivityStateListener {
 
-    public VrWindowAndroid(Context context) {
-        super(context);
+    public VrWindowAndroid(Context context, DisplayAndroid display) {
+        super(context, display);
         Activity activity = activityFromContext(context);
         if (activity == null) {
             throw new IllegalArgumentException("Context is not and does not wrap an Activity");
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index f0bebec..4779a4b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4013,6 +4013,7 @@
       "../android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java",
       "../android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java",
       "../android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
+      "../android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java",
       "../android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java",
       "../android/java/src/org/chromium/chrome/browser/util/AccessibilityUtil.java",
       "../android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java",
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 25bf14f..106415a7 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -158,6 +158,7 @@
 #include "chrome/browser/ui/android/ssl_client_certificate_request.h"
 #include "chrome/browser/ui/android/tab_model/single_tab_model.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_jni_bridge.h"
+#include "chrome/browser/ui/android/tab_model/tab_model_selector_base.h"
 #include "chrome/browser/ui/android/toolbar/toolbar_model_android.h"
 #include "chrome/browser/ui/android/usb_chooser_dialog_android.h"
 #include "components/dom_distiller/content/browser/android/content_jni_registrar.h"
@@ -387,6 +388,7 @@
     {"TabContentManager", RegisterTabContentManager},
     {"TabListSceneLayer", RegisterTabListSceneLayer},
     {"TabModelJniBridge", TabModelJniBridge::Register},
+    {"TabModelSelectorBase", RegisterTabModelSelectorBase},
     {"TabState", RegisterTabState},
     {"TabStripSceneLayer", RegisterTabStripSceneLayer},
     {"TabWebContentsDelegateAndroid", RegisterTabWebContentsDelegateAndroid},
@@ -408,8 +410,7 @@
     {"DisplaySynchronizer",
      DisplaySynchronizer::RegisterDisplaySynchronizerNatives},
     {"GvrApi", GvrApi::RegisterGvrApiNatives},
-    {"NativeCallbacks",
-     NativeCallbacks::RegisterNativeCallbacksNatives},
+    {"NativeCallbacks", NativeCallbacks::RegisterNativeCallbacksNatives},
 #endif
     {"WarmupManager", RegisterWarmupManager},
     {"WebApkInstaller", WebApkInstaller::Register},
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
index f170cd0..3002395 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -558,18 +558,16 @@
       base::FeatureList::IsEnabled(
           chrome::android::kContextualSearchSingleActions)) {
     // Any Contextual Cards integration.
-    // For testing purposes check if there was a Contextual Cards backend
-    // failure and flag that in the log.
+    // For testing purposes check if there was a diagnostic from Contextual
+    // Cards and output that into the log.
     // TODO(donnd): remove after full Contextual Cards integration.
-    bool contextual_cards_backend_responded = true;
-    dict->GetBoolean("coca_responded", &contextual_cards_backend_responded);
-    if (!contextual_cards_backend_responded) {
-      DVLOG(0) << "";
-      DVLOG(0) << "!!! CONTEXTUAL SEARCH WARNING !!!";
-      DVLOG(0)
-          << "The Contextual Cards backend did not respond to this "
-             "request!!! The backend server may not be configured or is down.";
-      DVLOG(0) << "";
+    std::string contextual_cards_diagnostic;
+    dict->GetString("diagnostic", &contextual_cards_diagnostic);
+    if (contextual_cards_diagnostic.empty()) {
+      DVLOG(0) << "No diagnostic data in the response.";
+    } else {
+      DVLOG(0) << "The Contextual Cards backend response: ";
+      DVLOG(0) << contextual_cards_diagnostic;
     }
   }
 }
diff --git a/chrome/browser/android/vr_shell/vr_compositor.cc b/chrome/browser/android/vr_shell/vr_compositor.cc
index ad52fd2..6681e8d34 100644
--- a/chrome/browser/android/vr_shell/vr_compositor.cc
+++ b/chrome/browser/android/vr_shell/vr_compositor.cc
@@ -10,6 +10,8 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/android/window_android.h"
 
+using base::android::JavaParamRef;
+
 namespace vr_shell {
 
 VrCompositor::VrCompositor(ui::WindowAndroid* window, bool transparent)
@@ -35,6 +37,7 @@
 void VrCompositor::SetLayer(content::WebContents* web_contents) {
   assert(layer_ == nullptr);
   ui::ViewAndroid* view_android = web_contents->GetNativeView();
+
   // When we pass the layer for the ContentViewCore to the compositor it may be
   // removing it from its previous parent, so we remember that and restore it to
   // its previous parent on teardown.
@@ -53,13 +56,13 @@
   compositor_->SetSurface(nullptr);
 }
 
-void VrCompositor::SurfaceChanged(
-    int width,
-    int height,
-    const base::android::JavaParamRef<jobject>& surface) {
+void VrCompositor::SetWindowBounds(int width, int height) {
+  compositor_->SetWindowBounds(gfx::Size(width, height));
+}
+
+void VrCompositor::SurfaceChanged(const JavaParamRef<jobject>& surface) {
   DCHECK(surface);
   compositor_->SetSurface(surface);
-  compositor_->SetWindowBounds(gfx::Size(width, height));
 }
 
 }  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/vr_compositor.h b/chrome/browser/android/vr_shell/vr_compositor.h
index 218f877b..ddd8387 100644
--- a/chrome/browser/android/vr_shell/vr_compositor.h
+++ b/chrome/browser/android/vr_shell/vr_compositor.h
@@ -34,9 +34,8 @@
   ~VrCompositor() override;
 
   void SurfaceDestroyed();
-  void SurfaceChanged(int width,
-                      int height,
-                      const base::android::JavaParamRef<jobject>& surface);
+  void SetWindowBounds(int width, int height);
+  void SurfaceChanged(const base::android::JavaParamRef<jobject>& surface);
   void SetLayer(content::WebContents* web_contents);
 
   // CompositorClient implementation:
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc
index e43afb0..0c576f35 100644
--- a/chrome/browser/android/vr_shell/vr_shell.cc
+++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -141,7 +141,6 @@
 
   return mouse_event;
 }
-
 }  // namespace
 
 namespace vr_shell {
@@ -214,7 +213,7 @@
     const base::android::JavaParamRef<jobject>& delegate) {
   base::AutoLock lock(gvr_init_lock_);
   delegate_ = VrShellDelegate::GetNativeDelegate(env, delegate);
-  if (gvr_api_) {
+  if (swap_chain_.get()) {
     main_thread_task_runner_->PostTask(
         FROM_HERE, base::Bind(&device::GvrDeviceProvider::OnGvrDelegateReady,
                               delegate_->GetDeviceProvider(),
@@ -232,8 +231,6 @@
 void VrShell::GvrInit(JNIEnv* env,
                       const JavaParamRef<jobject>& obj,
                       jlong native_gvr_api) {
-  base::AutoLock lock(gvr_init_lock_);
-
   // set the initial webvr state
   metrics_helper_->SetVRActive(true);
 
@@ -269,6 +266,7 @@
                            const JavaParamRef<jobject>& obj,
                            jint content_texture_handle,
                            jint ui_texture_handle) {
+  base::AutoLock lock(gvr_init_lock_);
   CHECK(gl::GetGLImplementation() != gl::kGLImplementationNone ||
         gl::init::InitializeGLOneOff());
 
@@ -344,6 +342,13 @@
   buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE,
                                            webvr_right_viewport_.get());
   webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer);
+
+  if (delegate_) {
+    main_thread_task_runner_->PostTask(
+        FROM_HERE, base::Bind(&device::GvrDeviceProvider::OnGvrDelegateReady,
+                              delegate_->GetDeviceProvider(),
+                              weak_ptr_factory_.GetWeakPtr()));
+  }
 }
 
 void VrShell::UpdateController(const gvr::Vec3f& forward_vector) {
@@ -462,7 +467,7 @@
       closest_element_distance = distance_to_plane;
       Rectf pixel_rect;
       if (plane->content_quad) {
-        pixel_rect = {0, 0, content_tex_width_, content_tex_height_};
+        pixel_rect = {0, 0, content_tex_css_width_, content_tex_css_height_};
       } else {
         pixel_rect = {plane->copy_rect.x, plane->copy_rect.y,
                       plane->copy_rect.width, plane->copy_rect.height};
@@ -707,7 +712,7 @@
   // This is a stopgap while we're using the WebVR compositor rendering path.
   // TODO(klausw,crbug.com/655722): Remove this method and member once we're
   // using a separate WebVR render surface.
-  return content_tex_pixels_for_webvr_;
+  return content_tex_physical_size_;
 }
 
 
@@ -753,12 +758,12 @@
       copy_rect = {0, 0, 1, 1};
       texture_handle = content_texture_id_;
     } else {
-      copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_width_;
-      copy_rect.y = static_cast<float>(rect->copy_rect.y) / ui_tex_height_;
+      copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_css_width_;
+      copy_rect.y = static_cast<float>(rect->copy_rect.y) / ui_tex_css_height_;
       copy_rect.width = static_cast<float>(rect->copy_rect.width) /
-          ui_tex_width_;
+          ui_tex_css_width_;
       copy_rect.height = static_cast<float>(rect->copy_rect.height) /
-          ui_tex_height_;
+          ui_tex_css_height_;
       texture_handle = ui_texture_id_;
     }
     gvr::Mat4f transform = MatrixMul(render_matrix, rect->transform.to_world);
@@ -929,46 +934,32 @@
   return gvr_api_.get();
 }
 
-void VrShell::ContentSurfaceChanged(JNIEnv* env,
-                                    const JavaParamRef<jobject>& object,
-                                    jint width,
-                                    jint height,
-                                    const JavaParamRef<jobject>& surface) {
-  TRACE_EVENT0("gpu", "VrShell::ContentSurfaceChanged");
-  // If we have a delegate, must trigger "ready" callback one time only.
-  // Do so the first time we got a nonzero size. (This assumes it doesn't
-  // change, but once we get resize ability we'll no longer need this hack.)
-  // TODO(klausw,crbug.com/655722): remove when we have surface support.
-  bool delegate_not_ready = delegate_ && !content_tex_pixels_for_webvr_.width;
-
-  content_compositor_->SurfaceChanged((int)width, (int)height, surface);
-  content_tex_pixels_for_webvr_.width = width;
-  content_tex_pixels_for_webvr_.height = height;
-  float scale_factor = display::Screen::GetScreen()
-      ->GetPrimaryDisplay().device_scale_factor();
-  content_tex_width_ = width / scale_factor;
-  content_tex_height_ = height / scale_factor;
-
-  // TODO(klausw,crbug.com/655722): move this back to GvrInit once we have
-  // our own WebVR surface.
-  if (delegate_ && delegate_not_ready) {
-    main_thread_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&device::GvrDeviceProvider::OnGvrDelegateReady,
-                              delegate_->GetDeviceProvider(),
-                              weak_ptr_factory_.GetWeakPtr()));
-  }
+void VrShell::SurfacesChanged(JNIEnv* env,
+                              const JavaParamRef<jobject>& object,
+                              const JavaParamRef<jobject>& content_surface,
+                              const JavaParamRef<jobject>& ui_surface) {
+  content_compositor_->SurfaceChanged(content_surface);
+  ui_compositor_->SurfaceChanged(ui_surface);
 }
 
-void VrShell::UiSurfaceChanged(JNIEnv* env,
-                               const JavaParamRef<jobject>& object,
-                               jint width,
-                               jint height,
-                               const JavaParamRef<jobject>& surface) {
-  ui_compositor_->SurfaceChanged((int)width, (int)height, surface);
-  float scale_factor = display::Screen::GetScreen()
-      ->GetPrimaryDisplay().device_scale_factor();
-  ui_tex_width_ = width / scale_factor;
-  ui_tex_height_ = height / scale_factor;
+void VrShell::ContentBoundsChanged(JNIEnv* env,
+                                   const JavaParamRef<jobject>& object,
+                                   jint width, jint height, jfloat dpr) {
+  TRACE_EVENT0("gpu", "VrShell::ContentBoundsChanged");
+  content_tex_physical_size_.width = width;
+  content_tex_physical_size_.height = height;
+  // TODO(mthiesse): Synchronize with GL thread, and update tex css size in
+  // response to MainFrameWasResized, not here.
+  content_tex_css_width_ = width / dpr;
+  content_tex_css_height_ = height / dpr;
+
+  content_compositor_->SetWindowBounds(width, height);
+}
+
+void VrShell::UIBoundsChanged(JNIEnv* env,
+                              const JavaParamRef<jobject>& object,
+                              jint width, jint height, jfloat dpr) {
+  ui_compositor_->SetWindowBounds(width, height);
 }
 
 UiScene* VrShell::GetScene() {
@@ -1035,6 +1026,25 @@
   new_host->GetWidget()->GetView()->SetBackgroundColor(SK_ColorTRANSPARENT);
 }
 
+void VrShell::MainFrameWasResized(bool width_changed) {
+  display::Display display = display::Screen::GetScreen()
+      ->GetDisplayNearestWindow(ui_contents_->GetNativeView());
+  // TODO(mthiesse): Synchronize with GL thread.
+  ui_tex_css_width_ = display.size().width();
+  ui_tex_css_height_ = display.size().height();
+}
+
+void VrShell::SetContentCssSize(float width, float height, float dpr) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_VrShellImpl_setContentCssSize(env, j_vr_shell_.obj(), width, height,
+                                     dpr);
+}
+
+void VrShell::SetUiCssSize(float width, float height, float dpr) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_VrShellImpl_setUiCssSize(env, j_vr_shell_.obj(), width, height, dpr);
+}
+
 // ----------------------------------------------------------------------------
 // Native JNI methods
 // ----------------------------------------------------------------------------
diff --git a/chrome/browser/android/vr_shell/vr_shell.h b/chrome/browser/android/vr_shell/vr_shell.h
index 7c194114..1da2386 100644
--- a/chrome/browser/android/vr_shell/vr_shell.h
+++ b/chrome/browser/android/vr_shell/vr_shell.h
@@ -103,18 +103,21 @@
   void SetWebVRRenderSurfaceSize(int width, int height) override;
   gvr::Sizei GetWebVRCompositorSurfaceSize() override;
 
-  void ContentSurfaceChanged(
+  void SurfacesChanged(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& object,
-      jint width,
-      jint height,
-      const base::android::JavaParamRef<jobject>& surface);
-  void UiSurfaceChanged(
+      const base::android::JavaParamRef<jobject>& content_surface,
+      const base::android::JavaParamRef<jobject>& ui_surface);
+
+  void ContentBoundsChanged(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& object,
-      jint width,
-      jint height,
-      const base::android::JavaParamRef<jobject>& surface);
+      jint width, jint height, jfloat dpr);
+
+  void UIBoundsChanged(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& object,
+      jint width, jint height, jfloat dpr);
 
   // Called from non-render thread to queue a callback onto the render thread.
   // The render thread checks for callbacks and processes them between frames.
@@ -123,6 +126,9 @@
   // Perform a UI action triggered by the javascript API.
   void DoUiAction(const UiAction action);
 
+  void SetContentCssSize(float width, float height, float dpr);
+  void SetUiCssSize(float width, float height, float dpr);
+
  private:
   ~VrShell() override;
   void LoadUIContent();
@@ -145,6 +151,7 @@
   // content::WebContentsObserver implementation.
   void RenderViewHostChanged(content::RenderViewHost* old_host,
                              content::RenderViewHost* new_host) override;
+  void MainFrameWasResized(bool width_changed) override;
 
   // samplerExternalOES texture data for UI content image.
   jint ui_texture_id_ = 0;
@@ -191,11 +198,11 @@
   gvr::Vec3f target_point_;
   const ContentRectangle* target_element_ = nullptr;
   VrInputManager* current_input_target_ = nullptr;
-  int ui_tex_width_ = 0;
-  int ui_tex_height_ = 0;
-  int content_tex_width_ = 0;
-  int content_tex_height_ = 0;
-  gvr::Sizei content_tex_pixels_for_webvr_ = {0, 0};
+  int ui_tex_css_width_ = 0;
+  int ui_tex_css_height_ = 0;
+  int content_tex_css_width_ = 0;
+  int content_tex_css_height_ = 0;
+  gvr::Sizei content_tex_physical_size_ = {0, 0};
 
   // The pose ring buffer size must be a power of two to avoid glitches when
   // the pose index wraps around. It should be large enough to handle the
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 3b02122..a9aaea8 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -1212,8 +1212,6 @@
 
   // Task Scheduler initialization needs to be here for the following reasons:
   //   * After |SetupFieldTrials()|: Initialization uses variations.
-  //   * Before |SetupMetrics()|: |SetupMetrics()| uses the blocking pool. The
-  //         Task Scheduler must do any necessary redirection before then.
   //   * Near the end of |PreCreateThreads()|: The TaskScheduler needs to be
   //         created before any other threads are (by contract) but it creates
   //         threads itself so instantiating it earlier is also incorrect.
@@ -1221,8 +1219,6 @@
   // shutdown call may also need to be moved.
   task_scheduler_util::InitializeDefaultBrowserTaskScheduler();
 
-  SetupMetrics();
-
   // ChromeOS needs ResourceBundle::InitSharedInstance to be called before this.
   // This also instantiates the IOThread which requests the metrics service and
   // must be after |SetupMetrics()|.
@@ -1418,6 +1414,10 @@
   SCOPED_UMA_HISTOGRAM_LONG_TIMER("Startup.PreMainMessageLoopRunImplLongTime");
   const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
 
+  // This must occur at PreMainMessageLoopRun because |SetupMetrics()| uses the
+  // blocking pool, which is disabled until the CreateThreads phase of startup.
+  SetupMetrics();
+
 #if defined(OS_WIN)
   // Windows parental controls calls can be slow, so we do an early init here
   // that calculates this value off of the UI thread.
diff --git a/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.cc b/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.cc
index e6c0a0d..4b10e5e5 100644
--- a/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.cc
+++ b/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.h"
 
 #include "ash/shell.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/dbus/chrome_display_power_service_provider_delegate.cc b/chrome/browser/chromeos/dbus/chrome_display_power_service_provider_delegate.cc
index ed2cefc..cb8cd26 100644
--- a/chrome/browser/chromeos/dbus/chrome_display_power_service_provider_delegate.cc
+++ b/chrome/browser/chromeos/dbus/chrome_display_power_service_provider_delegate.cc
@@ -8,7 +8,7 @@
 #include "ash/shell.h"
 #include "base/memory/ptr_util.h"
 #include "ui/base/user_activity/user_activity_detector.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/display/display_preferences.h b/chrome/browser/chromeos/display/display_preferences.h
index 7580677..56d3d7f 100644
--- a/chrome/browser/chromeos/display/display_preferences.h
+++ b/chrome/browser/chromeos/display/display_preferences.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 
 #include "third_party/cros_system_api/dbus/service_constants.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 
 class PrefRegistrySimple;
 
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index 553c0b6..deb7814 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -31,8 +31,8 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/prefs/testing_pref_service.h"
-#include "ui/display/chromeos/display_configurator.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout_builder.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/manager/display_layout_store.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/display_manager_utilities.h"
diff --git a/chrome/browser/chromeos/display/output_protection_delegate.h b/chrome/browser/chromeos/display/output_protection_delegate.h
index a2cd5624..57b259a0 100644
--- a/chrome/browser/chromeos/display/output_protection_delegate.h
+++ b/chrome/browser/chromeos/display/output_protection_delegate.h
@@ -10,7 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc b/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc
index 219272d..204d364 100644
--- a/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc
+++ b/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc
@@ -33,7 +33,7 @@
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 
 namespace em = enterprise_management;
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index e649b3c..c647868 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -912,6 +912,7 @@
     "//ui/accessibility:ax_gen",
     "//ui/base",
     "//ui/base/ime",
+    "//ui/display/manager",
     "//ui/gfx",
     "//ui/gfx/geometry",
     "//ui/native_theme",
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index dc188c2..aea0486 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -232,7 +232,8 @@
 }
 
 // This test times out regularly on win_rel trybots. See http://crbug.com/122178
-#if defined(OS_WIN)
+// Also on Linux/ChromiumOS debug builds. https://crbug.com/670415
+#if defined(OS_WIN) || !defined(NDEBUG)
 #define MAYBE_WebRequestBlocking DISABLED_WebRequestBlocking
 #else
 #define MAYBE_WebRequestBlocking WebRequestBlocking
diff --git a/chrome/browser/extensions/display_info_provider_chromeos.cc b/chrome/browser/extensions/display_info_provider_chromeos.cc
index 0b5fee8..584f3f19 100644
--- a/chrome/browser/extensions/display_info_provider_chromeos.cc
+++ b/chrome/browser/extensions/display_info_provider_chromeos.cc
@@ -14,8 +14,8 @@
 #include "chrome/browser/chromeos/display/overscan_calibrator.h"
 #include "extensions/common/api/system_display.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
index fd87399..ab53176 100644
--- a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
+++ b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
@@ -17,8 +17,8 @@
 #include "base/strings/stringprintf.h"
 #include "extensions/common/api/system_display.h"
 #include "ui/display/display.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/display_switches.h"
-#include "ui/display/manager/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/display/types/display_constants.h"
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 958a4958..5d3f902 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -947,12 +947,6 @@
   if (command_line.HasSwitch(switches::kDisableHttp2))
     params->enable_http2 = false;
 
-  if (command_line.HasSwitch(switches::kDisableQuicPortSelection)) {
-    params->enable_quic_port_selection = false;
-  } else if (command_line.HasSwitch(switches::kEnableQuicPortSelection)) {
-    params->enable_quic_port_selection = true;
-  }
-
   if (params->enable_quic) {
     if (command_line.HasSwitch(switches::kQuicConnectionOptions)) {
       params->quic_connection_options =
diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc
index da1bd497..ea95288 100644
--- a/chrome/browser/io_thread_unittest.cc
+++ b/chrome/browser/io_thread_unittest.cc
@@ -30,7 +30,8 @@
 #include "net/http/http_auth_scheme.h"
 #include "net/http/http_network_session.h"
 #include "net/quic/chromium/quic_stream_factory.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_tag.h"
+#include "net/quic/core/quic_versions.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/permissions/permission_prompt_android.cc b/chrome/browser/permissions/permission_prompt_android.cc
index e1be908b..ba0b531d 100644
--- a/chrome/browser/permissions/permission_prompt_android.cc
+++ b/chrome/browser/permissions/permission_prompt_android.cc
@@ -20,9 +20,11 @@
 }
 
 PermissionPromptAndroid::~PermissionPromptAndroid() {
-  GroupedPermissionInfoBarDelegate* infobar_delegate =
-      static_cast<GroupedPermissionInfoBarDelegate*>(infobar_->delegate());
-  infobar_delegate->PermissionPromptDestroyed();
+  if (infobar_) {
+    GroupedPermissionInfoBarDelegate* infobar_delegate =
+        static_cast<GroupedPermissionInfoBarDelegate*>(infobar_->delegate());
+    infobar_delegate->PermissionPromptDestroyed();
+  }
 }
 
 void PermissionPromptAndroid::SetDelegate(Delegate* delegate) {
diff --git a/chrome/browser/resources/net_internals/quic_view.html b/chrome/browser/resources/net_internals/quic_view.html
index 8c098f5..9d1f1e0 100644
--- a/chrome/browser/resources/net_internals/quic_view.html
+++ b/chrome/browser/resources/net_internals/quic_view.html
@@ -3,7 +3,6 @@
     <li>QUIC Enabled: <span jscontent="!!quic_enabled"></span></li>
     <li>Origins To Force QUIC On: <span jscontent="origins_to_force_quic_on"></span></li>
     <li>Connection options: <span jscontent="connection_options"></span></li>
-    <li>Consistent Port Selection Enabled: <span jscontent="!!enable_quic_port_selection"></span></li>
     <li>Load Server Info Timeout Multiplier: <span jscontent="$this.load_server_info_timeout_srtt_multiplier"></span></li>
     <li>Enable Connection Racing: <span jscontent="!!enable_connection_racing"></span></li>
     <li>Disable Disk Cache: <span jscontent="!!disable_disk_cache"></span></li>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index e76d37a..69e1aef6 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -148,10 +148,13 @@
         </paper-checkbox>
       </div>
 
-      <div class="settings-box two-line single-column" actionable
+      <div class="settings-box two-line" actionable
           on-tap="onManageSyncedDataTap_">
-        <div>$i18n{manageSyncedDataTitle}</div>
-        <div class="secondary">$i18n{manageSyncedDataDescription}</div>
+        <div class="start">
+          $i18n{manageSyncedDataTitle}
+          <div class="secondary">$i18n{manageSyncedDataDescription}</div>
+        </div>
+        <button class="icon-external" is="paper-icon-button-light"></button>
       </div>
 
       <div class="settings-box two-line single-column">
diff --git a/chrome/browser/resources/settings/settings_vars_css.html b/chrome/browser/resources/settings/settings_vars_css.html
index 39e7a63..587a1fc 100644
--- a/chrome/browser/resources/settings/settings_vars_css.html
+++ b/chrome/browser/resources/settings/settings_vars_css.html
@@ -89,7 +89,9 @@
     --paper-item: {
       font-size: inherit;
     };
+    --paper-radio-button-ink-size: 40px;
     --paper-radio-button-label-color: inherit;
+    --paper-radio-button-size: 16px;
     --paper-radio-group-item-padding: 0;
 
     --paper-toggle-button-checked-bar: var(--settings-toggle-bar-size);
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.css b/chrome/browser/resources/vr_shell/vr_shell_ui.css
index b0ad92bb..d48fa334 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.css
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.css
@@ -7,13 +7,11 @@
 }
 
 #ui {
-  --scaleFactor: 4;
   left: 0;
+  max-width: 1920px;
   position: absolute;
   top: 0;
-  transform: scale(0.25, 0.25);
   transform-origin: left top;
-  width: 400%;
 }
 
 /* This class manages the position of elements on the texture page.
@@ -30,12 +28,6 @@
   justify-content: center;
 }
 
-/* Permanent security warning for WebVR. */
-#webvr-not-secure-permanent {
-  height: 128px;
-  width: 512px;
-}
-
 #webvr-not-secure-permanent .webvr-not-secure-icon {
   display: inline-block;
   margin: 20px 0;
@@ -48,11 +40,9 @@
   vertical-align: middle;
 }
 
-/* This is a single-line (nowrap) short message. The width has some elasticity
- * for translations, and the underlying string had a request to translators
- * to keep it short. The maximum is based on the fixed-size container DIV,
- * excess will be clipped. There's space for about twice the length of the
- * English "Not secure" message. */
+/* This is a single-line (nowrap) short message. The width is elastic for
+ * translations, and the underlying string had a request to translators
+ * to keep it short. */
 #webvr-not-secure-permanent .webvr-box {
   background-color: white;
   border-radius: 6px;
@@ -61,22 +51,13 @@
   color: #444;
   font-size: 26px;
   height: 78px;
-  max-width: 472px;
   min-width: 226px;
   overflow: hidden;
   padding: 0 20px;
   white-space: nowrap;
 }
 
-/* Transient security warning for WebVR. */
-#webvr-not-secure-transient {
-  height: 256px;
-  width: 512px;
-}
-
-/* This uses fixed width but the height has some elasticity for translations.
- * The maximum is based on the fixed-size container DIV, excess will be
- * clipped. */
+/* This uses fixed width but the height is elastic for translations. */
 #webvr-not-secure-transient > div {
   background-color: rgba(26, 26, 26, 0.8);
   border-radius: 6px;
@@ -87,7 +68,6 @@
   font-size: 26px;
   justify-content: center;
   line-height: 1.4;
-  max-height: 210px;
   min-height: 160px;
   overflow: hidden;
   padding: 20px;
@@ -143,6 +123,9 @@
   --tranX: 0;
   --tranY: -0.65;
   --tranZ: -1.2;
+  height: 164px;
+  overflow: hidden;
+  width: 512px;
 }
 
 #omni {
@@ -156,6 +139,7 @@
   margin-bottom: 60px;
   margin-top: 0;
   opacity: 1;
+  overflow: hidden;
   transition: opacity 500ms ease, margin-top 500ms ease;
   white-space: nowrap;
   width: 512px;
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chrome/browser/resources/vr_shell/vr_shell_ui.js
index 68e9d93..3964a82 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.js
@@ -10,9 +10,11 @@
 
   let uiRootElement = document.querySelector('#ui');
   let uiStyle = window.getComputedStyle(uiRootElement);
-  let scaleFactor = uiStyle.getPropertyValue('--scaleFactor');
   /** @const */ var ANIM_DURATION = 150;
 
+  // This value should match the one in VrShellImpl.java
+  /** @const */ var UI_DPR = 1.2;
+
   function getStyleFloat(style, property) {
     let value = parseFloat(style.getPropertyValue(property));
     return isNaN(value) ? 0 : value;
@@ -70,8 +72,7 @@
       let pixelHeight = Math.ceil(rect.bottom) - pixelY;
 
       let element = new api.UiElement(pixelX, pixelY, pixelWidth, pixelHeight);
-      element.setSize(scaleFactor * pixelWidth / 1000,
-          scaleFactor * pixelHeight / 1000);
+      element.setSize(pixelWidth / 1000, pixelHeight / 1000);
 
       // Pull additional custom properties from CSS.
       let style = window.getComputedStyle(domElement);
@@ -414,6 +415,9 @@
       this.controls.setEnabled(mode == api.Mode.STANDARD && !menuMode);
       this.omnibox.setEnabled(mode == api.Mode.STANDARD && !menuMode);
       this.secureOriginWarnings.setEnabled(mode == api.Mode.WEB_VR);
+
+      api.setUiCssSize(uiRootElement.clientWidth, uiRootElement.clientHeight,
+          UI_DPR);
     }
 
     setSecureOrigin(secure) {
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
index 8e2fca1..8f64ed4b 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
@@ -101,6 +101,13 @@
   }
 
   /**
+   * Sets the CSS size for this page.
+   */
+  function setUiCssSize(width, height, dpr) {
+    chrome.send('setUiCssSize', [width, height, dpr]);
+  }
+
+  /**
    * Represents updates to UI element properties. Any properties set on this
    * object are relayed to an underlying native element via scene command.
    * Properties that are not set on this object are left unchanged.
@@ -306,5 +313,6 @@
     Animation: Animation,
     doAction: doAction,
     domLoaded: domLoaded,
+    setUiCssSize: setUiCssSize,
   };
 })();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d6f6705..d39573a 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -596,6 +596,7 @@
     "//ui/compositor",
     "//ui/content_accelerators",
     "//ui/display",
+    "//ui/display/manager",
     "//ui/events",
     "//ui/events:gesture_detection",
     "//ui/gfx",
@@ -2227,6 +2228,8 @@
         "android/tab_model/tab_model_jni_bridge.h",
         "android/tab_model/tab_model_list.cc",
         "android/tab_model/tab_model_list.h",
+        "android/tab_model/tab_model_selector_base.cc",
+        "android/tab_model/tab_model_selector_base.h",
         "android/toolbar/toolbar_model_android.cc",
         "android/toolbar/toolbar_model_android.h",
         "android/usb_chooser_dialog_android.cc",
diff --git a/chrome/browser/ui/android/tab_model/tab_model_selector_base.cc b/chrome/browser/ui/android/tab_model/tab_model_selector_base.cc
new file mode 100644
index 0000000..753eb43e
--- /dev/null
+++ b/chrome/browser/ui/android/tab_model/tab_model_selector_base.cc
@@ -0,0 +1,46 @@
+// Copyright 2016 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 "chrome/browser/ui/android/tab_model/tab_model_selector_base.h"
+
+#include "base/android/jni_android.h"
+#include "chrome/browser/android/tab_android.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/TabModelSelectorBase_jni.h"
+
+using base::android::JavaParamRef;
+
+static void OnActiveTabChanged(
+    JNIEnv* env,
+    const JavaParamRef<jclass>& clazz,
+    const JavaParamRef<jobject>& java_old_web_contents,
+    const JavaParamRef<jobject>& java_new_web_contents) {
+  // Check if PermissionRequestManager is reused on Android to manage infobars.
+  // This is currently behind a switch flag.
+  if (!PermissionRequestManager::IsEnabled())
+    return;
+
+  // Visible permission infobars will get hidden and shown when switching tabs
+  // by the infobar infrastructure, but we do this explicitly to create/destroy
+  // PermissionPromptAndroid for old and new tabs. This also keeps the codepath
+  // consistent across different platforms.
+  content::WebContents* old_contents =
+      content::WebContents::FromJavaWebContents(java_old_web_contents);
+  content::WebContents* new_contents =
+      content::WebContents::FromJavaWebContents(java_new_web_contents);
+  DCHECK(new_contents);
+  if (old_contents)
+    PermissionRequestManager::FromWebContents(old_contents)->HideBubble();
+
+  if (new_contents) {
+    PermissionRequestManager::FromWebContents(new_contents)
+        ->DisplayPendingRequests();
+  }
+}
+
+// Register native methods
+bool RegisterTabModelSelectorBase(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
diff --git a/chrome/browser/ui/android/tab_model/tab_model_selector_base.h b/chrome/browser/ui/android/tab_model/tab_model_selector_base.h
new file mode 100644
index 0000000..40c679e2
--- /dev/null
+++ b/chrome/browser/ui/android/tab_model/tab_model_selector_base.h
@@ -0,0 +1,12 @@
+// Copyright 2016 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 CHROME_BROWSER_UI_ANDROID_TAB_MODEL_TAB_MODEL_SELECTOR_BASE_H_
+#define CHROME_BROWSER_UI_ANDROID_TAB_MODEL_TAB_MODEL_SELECTOR_BASE_H_
+
+#include <jni.h>
+
+bool RegisterTabModelSelectorBase(JNIEnv* env);
+
+#endif  // CHROME_BROWSER_UI_ANDROID_TAB_MODEL_TAB_MODEL_SELECTOR_BASE_H_
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index bed581f4..bcdcaf6f 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -327,7 +327,7 @@
 
 int AutofillPopupControllerImpl::GetElidedLabelWidthForRow(size_t row) {
   return gfx::GetStringWidth(GetElidedLabelAt(row),
-                             layout_model_.GetLabelFontList());
+                             layout_model_.GetLabelFontListForRow(row));
 }
 #endif
 
@@ -510,8 +510,8 @@
     int available_width) {
   int value_width = gfx::GetStringWidth(
       suggestions_[row].value, layout_model_.GetValueFontListForRow(row));
-  int label_width = gfx::GetStringWidth(suggestions_[row].label,
-                                        layout_model_.GetLabelFontList());
+  int label_width = gfx::GetStringWidth(
+      suggestions_[row].label, layout_model_.GetLabelFontListForRow(row));
   int total_text_length = value_width + label_width;
 
   // The line can have no strings if it represents a UI element, such as
@@ -526,9 +526,9 @@
       value_size, gfx::ELIDE_TAIL);
 
   int label_size = available_width * label_width / total_text_length;
-  elided_labels_[row] =
-      gfx::ElideText(suggestions_[row].label, layout_model_.GetLabelFontList(),
-                     label_size, gfx::ELIDE_TAIL);
+  elided_labels_[row] = gfx::ElideText(
+      suggestions_[row].label, layout_model_.GetLabelFontListForRow(row),
+      label_size, gfx::ELIDE_TAIL);
 }
 #endif
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
index ce2f055..a6ef040 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -445,7 +445,8 @@
               0)) +
       gfx::GetStringWidth(
           suggestions[0].label,
-          autofill_popup_controller_->layout_model().GetLabelFontList()) -
+          autofill_popup_controller_->layout_model().GetLabelFontListForRow(
+              0)) -
       25;
 
   autofill_popup_controller_->ElideValueAndLabelForRow(0, popup_max_width);
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
index b689fec..5364cb61 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
@@ -118,16 +118,19 @@
 int AutofillPopupLayoutModel::RowWidthWithoutText(int row,
                                                   bool with_label) const {
   std::vector<autofill::Suggestion> suggestions = delegate_->GetSuggestions();
+  bool is_warning_message = (suggestions[row].frontend_id ==
+                             POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE);
 
   int row_size = kEndPadding;
 
   if (with_label)
-    row_size += kNamePadding;
+    row_size += is_warning_message ? kHttpWarningNamePadding : kNamePadding;
 
   // Add the Autofill icon size, if required.
   const base::string16& icon = suggestions[row].icon;
   if (!icon.empty()) {
-    row_size += GetIconImage(row).width() + kIconPadding;
+    row_size += GetIconImage(row).width() +
+                (is_warning_message ? kHttpWarningIconPadding : kIconPadding);
   }
 
   // Add the padding at the end.
@@ -183,7 +186,13 @@
   return normal_font_list_;
 }
 
-const gfx::FontList& AutofillPopupLayoutModel::GetLabelFontList() const {
+const gfx::FontList& AutofillPopupLayoutModel::GetLabelFontListForRow(
+    size_t index) const {
+  std::vector<autofill::Suggestion> suggestions = delegate_->GetSuggestions();
+  if (suggestions[index].frontend_id ==
+      POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE)
+    return normal_font_list_;
+
   return smaller_font_list_;
 }
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.h b/chrome/browser/ui/autofill/autofill_popup_layout_model.h
index 560d5bc..b3a2c73 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model.h
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.h
@@ -32,9 +32,17 @@
   // in pixels.
   static const int kNamePadding = 15;
 
-  // The amount of padding between icons in pixels.
+  // The minimum amount of padding between the Autofill http warning message
+  // name and subtext, in pixels.
+  static const int kHttpWarningNamePadding = 8;
+
+  // The amount of padding around icons in pixels.
   static const int kIconPadding = 5;
 
+  // The amount of horizontal padding around icons in pixels for HTTP warning
+  // message.
+  static const int kHttpWarningIconPadding = 8;
+
   // The amount of padding at the end of the popup in pixels.
   static const int kEndPadding = 8;
 
@@ -62,7 +70,7 @@
   // The same font can vary based on the type of data it is showing at the row
   // |index|.
   const gfx::FontList& GetValueFontListForRow(size_t index) const;
-  const gfx::FontList& GetLabelFontList() const;
+  const gfx::FontList& GetLabelFontListForRow(size_t index) const;
 
   // Returns the value font color of the row item according to its |index|.
   SkColor GetValueFontColorForRow(size_t index) const;
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc
index 22c7188..47b408a7 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/autofill/autofill_popup_view_delegate.h"
 #include "chrome/browser/ui/autofill/popup_constants.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/autofill/core/browser/popup_item_ids.h"
 #include "components/autofill/core/browser/suggestion.h"
 #include "components/grit/components_scaled_resources.h"
 #include "content/public/browser/web_contents.h"
@@ -20,6 +21,7 @@
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace autofill {
@@ -50,6 +52,10 @@
     suggestions.push_back(Suggestion("", "x", "", 0));
     suggestions.push_back(Suggestion("", "", "americanExpressCC", 0));
     suggestions.push_back(Suggestion("", "x", "genericCC", 0));
+    // Http warning message.
+    suggestions.push_back(
+        Suggestion("x", "x", "httpWarning",
+                   POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE));
     return suggestions;
   }
 #if !defined(OS_ANDROID)
@@ -102,6 +108,10 @@
                     .GetImageNamed(IDR_AUTOFILL_CC_GENERIC)
                     .Width(),
             layout_model()->RowWidthWithoutText(3, /* with_label= */ true));
+  EXPECT_EQ(base_size + AutofillPopupLayoutModel::kHttpWarningNamePadding +
+                AutofillPopupLayoutModel::kHttpWarningIconPadding +
+                layout_model()->GetIconImage(4).width(),
+            layout_model()->RowWidthWithoutText(4, /* with_label= */ true));
 }
 #endif
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
index a4fb090..c21981d1 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
@@ -59,6 +59,7 @@
                     bounds:(NSRect)bounds;
 - (CGFloat)drawSubtext:(NSString*)subtext
                    atX:(CGFloat)x
+                 index:(size_t)index
             rightAlign:(BOOL)rightAlign
                 bounds:(NSRect)bounds
            textYOffset:(CGFloat)textYOffset;
@@ -184,6 +185,7 @@
   x = [self drawIconAtIndex:index atX:x rightAlign:!isRTL bounds:bounds];
   [self drawSubtext:subtext
                 atX:x
+              index:index
          rightAlign:!isRTL
              bounds:bounds
         textYOffset:textYOffset];
@@ -242,12 +244,13 @@
 
 - (CGFloat)drawSubtext:(NSString*)subtext
                    atX:(CGFloat)x
+                 index:(size_t)index
             rightAlign:(BOOL)rightAlign
                 bounds:(NSRect)bounds
            textYOffset:(CGFloat)textYOffset {
   NSDictionary* subtextAttributes = [NSDictionary
       dictionaryWithObjectsAndKeys:controller_->layout_model()
-                                       .GetLabelFontList()
+                                       .GetLabelFontListForRow(index)
                                        .GetPrimaryFont()
                                        .GetNativeFont(),
                                    NSFontAttributeName, [self subtextColor],
diff --git a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
index 988e555d..c6f5b449 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
@@ -1367,11 +1367,13 @@
     [window accessibilitySetOverrideValue:
         l10n_util::GetNSString(IDS_PROFILES_NEW_AVATAR_MENU_ACCESSIBLE_NAME)
                              forAttribute:NSAccessibilityHelpAttribute];
-
+    BOOL shouldUseLeadingEdgeForBubble =
+        cocoa_l10n_util::ShouldDoExperimentalRTLLayout() &&
+        !cocoa_l10n_util::ShouldFlipWindowControlsInRTL();
     [[self bubble]
-        setAlignment:cocoa_l10n_util::ShouldFlipWindowControlsInRTL()
-                         ? info_bubble::kAlignTrailingEdgeToAnchorEdge
-                         : info_bubble::kAlignLeadingEdgeToAnchorEdge];
+        setAlignment:shouldUseLeadingEdgeForBubble
+                         ? info_bubble::kAlignLeadingEdgeToAnchorEdge
+                         : info_bubble::kAlignTrailingEdgeToAnchorEdge];
     [[self bubble] setArrowLocation:info_bubble::kNoArrow];
     [[self bubble] setBackgroundColor:GetDialogBackgroundColor()];
     [self initMenuContentsWithView:viewMode_];
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
index 25cc671..0f9a51b 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -388,7 +388,8 @@
       // nondeterministic, we can't just assume the main bar will have the
       // extension and look it up.
       size_t main_index = main_model->FindNewPositionFromLastKnownGood(item);
-      bool visible = main_index < main_model->visible_icon_count();
+      bool visible =
+          is_new_extension || main_index < main_model->visible_icon_count();
       // We may need to adjust the visible count if the incognito bar isn't
       // showing all icons and this one is visible, or if it is showing all
       // icons and this is hidden.
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
index ae08f5555..c39f29d 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
@@ -1456,6 +1456,50 @@
   EXPECT_EQ(browser_action_c()->id(), GetActionIdAtIndex(2u));
 }
 
+TEST_F(ToolbarActionsModelUnitTest, AddComponentActionInIncognito) {
+  Init();
+  // Add three extension actions: A, B, C.
+  ASSERT_TRUE(AddBrowserActionExtensions());
+  EXPECT_EQ(3u, num_toolbar_items());
+
+  // Enable extension C in incognito.
+  extensions::ExtensionPrefs* extension_prefs =
+      extensions::ExtensionPrefs::Get(profile());
+  extension_prefs->SetIsIncognitoEnabled(browser_action_c()->id(), true);
+  extensions::util::SetIsIncognitoEnabled(browser_action_c()->id(), profile(),
+                                          true);
+
+  // Get an incognito toolbar.
+  ToolbarActionsModel* incognito_model =
+      extensions::extension_action_test_util::CreateToolbarModelForProfile(
+          profile()->GetOffTheRecordProfile());
+
+  // The incognito toolbar should only have extension C.
+  EXPECT_EQ(1u, incognito_model->toolbar_items().size());
+
+  // Add a component action to the incognito toolbar. It shouldn't appear on the
+  // non-incognito toolbar.
+  incognito_model->AddComponentAction(component_action_id());
+  EXPECT_EQ(2u, incognito_model->toolbar_items().size());
+  EXPECT_EQ(2u, incognito_model->visible_icon_count());
+  EXPECT_EQ(component_action_id(), GetActionIdAtIndex(1u, incognito_model));
+  EXPECT_EQ(3u, num_toolbar_items());
+  incognito_model->RemoveComponentAction(component_action_id());
+
+  // Set visible count to 2 so that C is overflowed on the non-incognito
+  // toolbar. Its state is A, B, [C]. C stays visible on the incognito toolbar.
+  toolbar_model()->SetVisibleIconCount(2);
+  EXPECT_EQ(1u, incognito_model->toolbar_items().size());
+  EXPECT_EQ(1u, incognito_model->visible_icon_count());
+
+  // Add a component action to the incognito toolbar. It shouldn't appear in the
+  // overflow menu.
+  incognito_model->AddComponentAction(component_action_id());
+  EXPECT_EQ(2u, incognito_model->toolbar_items().size());
+  EXPECT_EQ(2u, incognito_model->visible_icon_count());
+  EXPECT_EQ(component_action_id(), GetActionIdAtIndex(1u, incognito_model));
+}
+
 TEST_F(ToolbarActionsModelUnitTest,
        TestUninstallVisibleExtensionDoesntBringOutOther) {
   Init();
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
index 44cb516..0f05966c 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
@@ -67,26 +67,45 @@
   SchedulePaintInRect(controller_->layout_model().GetRowBounds(row));
 }
 
+/**
+* Autofill entries in ltr.
+*
+* ............................................................................
+* . ICON | HTTP WARNING MESSAGE VALUE                                | LABEL .
+* ............................................................................
+* . OTHER AUTOFILL ENTRY VALUE |                                LABEL | ICON .
+* ............................................................................
+*
+* Autofill entries in rtl.
+*
+* ............................................................................
+* . LABEL |                                HTTP WARNING MESSAGE VALUE | ICON .
+* ............................................................................
+* . ICON | LABEL                                | OTHER AUTOFILL ENTRY VALUE .
+* ............................................................................
+*
+* Anyone who wants to modify the code below, remember to make sure that HTTP
+* warning entry displays right. To trigger the warning message entry, enable
+* #mark-non-secure-as flag as "display form warning", go to goo.gl/CEIjc6 with
+* stored autofill info and check for credit card or password forms.
+*/
 void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
                                                int index,
                                                const gfx::Rect& entry_rect) {
   canvas->FillRect(entry_rect, controller_->GetBackgroundColorForRow(index));
 
+  const bool is_http_warning =
+      (controller_->GetSuggestionAt(index).frontend_id ==
+       POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE);
   const bool is_rtl = controller_->IsRTL();
   const int text_align =
       is_rtl ? gfx::Canvas::TEXT_ALIGN_RIGHT : gfx::Canvas::TEXT_ALIGN_LEFT;
   gfx::Rect value_rect = entry_rect;
   value_rect.Inset(AutofillPopupLayoutModel::kEndPadding, 0);
-  canvas->DrawStringRectWithFlags(
-      controller_->GetElidedValueAt(index),
-      controller_->layout_model().GetValueFontListForRow(index),
-      controller_->layout_model().GetValueFontColorForRow(index), value_rect,
-      text_align);
 
-  // Use this to figure out where all the other Autofill items should be placed.
-  int x_align_left =
-      is_rtl ? AutofillPopupLayoutModel::kEndPadding
-             : entry_rect.right() - AutofillPopupLayoutModel::kEndPadding;
+  // If the icon is on the right of the rect, no matter in RTL or LTR mode.
+  bool icon_on_the_right = is_http_warning == is_rtl;
+  int x_align_left = icon_on_the_right ? value_rect.right() : value_rect.x();
 
   // Draw the Autofill icon, if one exists
   int row_height = controller_->layout_model().GetRowBounds(index).height();
@@ -95,27 +114,68 @@
         controller_->layout_model().GetIconImage(index);
     int icon_y = entry_rect.y() + (row_height - image.height()) / 2;
 
-    x_align_left += is_rtl ? 0 : -image.width();
+    int icon_x_align_left =
+        icon_on_the_right ? x_align_left - image.width() : x_align_left;
 
-    canvas->DrawImageInt(image, x_align_left, icon_y);
+    canvas->DrawImageInt(image, icon_x_align_left, icon_y);
 
-    x_align_left += is_rtl
-                        ? image.width() + AutofillPopupLayoutModel::kIconPadding
-                        : -AutofillPopupLayoutModel::kIconPadding;
+    // An icon was drawn; adjust the |x_align_left| value for the next element.
+    if (is_http_warning) {
+      x_align_left =
+          icon_x_align_left +
+          (is_rtl ? -AutofillPopupLayoutModel::kHttpWarningIconPadding
+                  : image.width() +
+                        AutofillPopupLayoutModel::kHttpWarningIconPadding);
+    } else {
+      x_align_left =
+          icon_x_align_left +
+          (is_rtl ? image.width() + AutofillPopupLayoutModel::kIconPadding
+                  : -AutofillPopupLayoutModel::kIconPadding);
+    }
   }
 
-  // Draw the label text.
-  const int label_width =
-      gfx::GetStringWidth(controller_->GetElidedLabelAt(index),
-                          controller_->layout_model().GetLabelFontList());
-  if (!is_rtl)
-    x_align_left -= label_width;
+  // Draw the value text
+  const int value_width = gfx::GetStringWidth(
+      controller_->GetElidedValueAt(index),
+      controller_->layout_model().GetValueFontListForRow(index));
+  int value_x_align_left = x_align_left;
+
+  if (is_http_warning) {
+    value_x_align_left += is_rtl ? -value_width : 0;
+  } else {
+    value_x_align_left =
+        is_rtl ? value_rect.right() - value_width : value_rect.x();
+  }
 
   canvas->DrawStringRectWithFlags(
-      controller_->GetElidedLabelAt(index),
-      controller_->layout_model().GetLabelFontList(), kLabelTextColor,
-      gfx::Rect(x_align_left, entry_rect.y(), label_width, entry_rect.height()),
+      controller_->GetElidedValueAt(index),
+      controller_->layout_model().GetValueFontListForRow(index),
+      controller_->layout_model().GetValueFontColorForRow(index),
+      gfx::Rect(value_x_align_left, value_rect.y(), value_width,
+                value_rect.height()),
       text_align);
+
+  // Draw the label text, if one exists.
+  if (!controller_->GetSuggestionAt(index).label.empty()) {
+    const int label_width = gfx::GetStringWidth(
+        controller_->GetElidedLabelAt(index),
+        controller_->layout_model().GetLabelFontListForRow(index));
+    int label_x_align_left = x_align_left;
+
+    if (is_http_warning) {
+      label_x_align_left =
+          is_rtl ? value_rect.x() : value_rect.right() - label_width;
+    } else {
+      label_x_align_left += is_rtl ? 0 : -label_width;
+    }
+
+    canvas->DrawStringRectWithFlags(
+        controller_->GetElidedLabelAt(index),
+        controller_->layout_model().GetLabelFontListForRow(index),
+        kLabelTextColor, gfx::Rect(label_x_align_left, entry_rect.y(),
+                                   label_width, entry_rect.height()),
+        text_align);
+  }
 }
 
 AutofillPopupView* AutofillPopupView::Create(
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
index 83735dd..67a4f61 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -30,8 +30,8 @@
 #include "content/public/browser/web_ui.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/types/display_constants.h"
diff --git a/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.cc b/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.cc
index 7eb33f1..02ec685 100644
--- a/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.cc
+++ b/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.cc
@@ -35,6 +35,9 @@
   web_ui()->RegisterMessageCallback(
       "doAction", base::Bind(&VrShellUIMessageHandler::HandleDoAction,
                              base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setUiCssSize", base::Bind(&VrShellUIMessageHandler::HandleSetUiCssSize,
+                                 base::Unretained(this)));
 }
 
 void VrShellUIMessageHandler::HandleDomLoaded(const base::ListValue* args) {
@@ -72,6 +75,17 @@
   }
 }
 
+void VrShellUIMessageHandler::HandleSetUiCssSize(const base::ListValue* args) {
+  CHECK(args->GetSize() == 3);
+  double width, height, dpr;
+  CHECK(args->GetDouble(0, &width));
+  CHECK(args->GetDouble(1, &height));
+  CHECK(args->GetDouble(2, &dpr));
+  if (vr_shell_) {
+    vr_shell_->SetUiCssSize(width, height, dpr);
+  }
+}
+
 void VrShellUIMessageHandler::SendCommandToUi(const base::Value& value) {
   CallJavascriptFunction("vrShellUi.command", value);
 }
diff --git a/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.h b/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.h
index bbb690d00..667ee3d 100644
--- a/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.h
+++ b/chrome/browser/ui/webui/vr_shell/vr_shell_ui_message_handler.h
@@ -34,6 +34,7 @@
   void HandleDomLoaded(const base::ListValue* args);
   void HandleUpdateScene(const base::ListValue* args);
   void HandleDoAction(const base::ListValue* args);
+  void HandleSetUiCssSize(const base::ListValue* args);
 
   base::WeakPtr<vr_shell::VrShell> vr_shell_;
 
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 14a1efcf..008275679 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -279,10 +279,6 @@
 // Disables the QUIC protocol.
 const char kDisableQuic[] = "disable-quic";
 
-// Disable use of Chromium's port selection for the ephemeral port via bind().
-// This only has an effect if QUIC protocol is enabled.
-const char kDisableQuicPortSelection[] = "disable-quic-port-selection";
-
 // Disable settings in a separate browser window per profile
 // (see SettingsWindowEnabled() below).
 const char kDisableSettingsWindow[]          = "disable-settings-window";
@@ -426,10 +422,6 @@
 // Enables the QUIC protocol.  This is a temporary testing flag.
 const char kEnableQuic[] = "enable-quic";
 
-// Enable use of Chromium's port selection for the ephemeral port via bind().
-// This only has an effect if the QUIC protocol is enabled.
-const char kEnableQuicPortSelection[] = "enable-quic-port-selection";
-
 // Switches 'Save as...' context and app menu labels to 'Download...'.
 const char kEnableSaveAsMenuLabelExperiment[] = "saveas-menu-label";
 
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 7d12de903..8b56a6d 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -95,7 +95,6 @@
 extern const char kDisablePromptOnRepost[];
 extern const char kDisablePushApiBackgroundMode[];
 extern const char kDisableQuic[];
-extern const char kDisableQuicPortSelection[];
 extern const char kDisableSettingsWindow[];
 extern const char kDisableWebNotificationCustomLayouts[];
 extern const char kDisableWebUsbSecurity[];
@@ -134,7 +133,6 @@
 extern const char kEnableProfiling[];
 extern const char kEnablePushApiBackgroundMode[];
 extern const char kEnableQuic[];
-extern const char kEnableQuicPortSelection[];
 extern const char kEnableSaveAsMenuLabelExperiment[];
 extern const char kEnableSettingsWindow[];
 extern const char kEnableSiteEngagementAppBanner[];
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_rules.cc b/chrome/common/extensions/permissions/chrome_permission_message_rules.cc
index 1f05d5b..1f5011b 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_rules.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_rules.cc
@@ -255,30 +255,10 @@
 
 }  // namespace
 
-// Convenience constructors to allow inline initialization of the permission
-// ID sets.
-// TODO(treib): Once we're allowed to use uniform initialization (and
-// std::initializer_list), get rid of this helper.
-class ChromePermissionMessageRule::PermissionIDSetInitializer
-    : public std::set<APIPermission::ID> {
- public:
-  template <typename... IDs>
-  PermissionIDSetInitializer(IDs... ids) {
-    // This effectively calls insert() with each of the ids.
-    ExpandHelper(insert(ids)...);
-  }
-
-  virtual ~PermissionIDSetInitializer() {}
-
- private:
-  template <typename... Args>
-  void ExpandHelper(Args&&...) {}
-};
-
 ChromePermissionMessageRule::ChromePermissionMessageRule(
     int message_id,
-    const PermissionIDSetInitializer& required,
-    const PermissionIDSetInitializer& optional)
+    const std::initializer_list<APIPermission::ID>& required,
+    const std::initializer_list<APIPermission::ID>& optional)
     : ChromePermissionMessageRule(
           new DefaultPermissionMessageFormatter(message_id),
           required,
@@ -286,8 +266,8 @@
 
 ChromePermissionMessageRule::ChromePermissionMessageRule(
     ChromePermissionMessageFormatter* formatter,
-    const PermissionIDSetInitializer& required,
-    const PermissionIDSetInitializer& optional)
+    const std::initializer_list<APIPermission::ID>& required,
+    const std::initializer_list<APIPermission::ID>& optional)
     : required_permissions_(required),
       optional_permissions_(optional),
       formatter_(formatter) {
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_rules.h b/chrome/common/extensions/permissions/chrome_permission_message_rules.h
index 0256c07..3f75e04 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_rules.h
+++ b/chrome/common/extensions/permissions/chrome_permission_message_rules.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_CHROME_PERMISSION_MESSAGE_RULES_H_
 #define CHROME_COMMON_EXTENSIONS_PERMISSIONS_CHROME_PERMISSION_MESSAGE_RULES_H_
 
+#include <initializer_list>
 #include <set>
 #include <vector>
 
@@ -69,17 +70,17 @@
       const PermissionIDSet& permissions) const;
 
  private:
-  class PermissionIDSetInitializer;
-
   // Create a rule using the default formatter (display the message with ID
   // |message_id|).
-  ChromePermissionMessageRule(int message_id,
-                              const PermissionIDSetInitializer& required,
-                              const PermissionIDSetInitializer& optional);
+  ChromePermissionMessageRule(
+      int message_id,
+      const std::initializer_list<APIPermission::ID>& required,
+      const std::initializer_list<APIPermission::ID>& optional);
   // Create a rule with a custom formatter. Takes ownership of |formatter|.
-  ChromePermissionMessageRule(ChromePermissionMessageFormatter* formatter,
-                              const PermissionIDSetInitializer& required,
-                              const PermissionIDSetInitializer& optional);
+  ChromePermissionMessageRule(
+      ChromePermissionMessageFormatter* formatter,
+      const std::initializer_list<APIPermission::ID>& required,
+      const std::initializer_list<APIPermission::ID>& optional);
 
   std::set<APIPermission::ID> required_permissions_;
   std::set<APIPermission::ID> optional_permissions_;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e767d1a..04fd230 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -5027,6 +5027,8 @@
     ]
 
     data = [
+      "//chrome/test/data/extensions/api_test",
+
       # Needed for isolate script to execute.
       "//testing/scripts/common.py",
       "//testing/xvfb.py",
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 9a454506..3703eb9 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -445,8 +445,12 @@
     apk_name = "CastShell"
     android_manifest = "$root_gen_dir/cast_shell_manifest/AndroidManifest.xml"
     android_manifest_dep = "//chromecast/browser/android:cast_shell_manifest"
+
+    shared_libraries = [ "//chromecast/android:libcast_shell_android" ]
+
     deps = [
       ":cast_shell_apk_assets",
+      "//base:base_java",
       "//chromecast/android:libcast_shell_android",
       "//chromecast/browser/android:cast_shell_java",
     ]
diff --git a/chromecast/base/java/src/org/chromium/chromecast/base/DumpstateWriter.java b/chromecast/base/java/src/org/chromium/chromecast/base/DumpstateWriter.java
index f9edaee..3c417d6f 100644
--- a/chromecast/base/java/src/org/chromium/chromecast/base/DumpstateWriter.java
+++ b/chromecast/base/java/src/org/chromium/chromecast/base/DumpstateWriter.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chromecast.base;
 
+import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 
@@ -16,10 +17,12 @@
  */
 @JNINamespace("chromecast")
 public final class DumpstateWriter {
-    private Map<String, String> mDumpValues;
+    private static final String TAG = "DumpstateWriter";
 
     private static DumpstateWriter sDumpstateWriter;
 
+    private Map<String, String> mDumpValues;
+
     public DumpstateWriter() {
         sDumpstateWriter = this;
         mDumpValues = new HashMap<>();
@@ -34,8 +37,8 @@
     @CalledByNative
     private static void addDumpValue(String name, String value) {
         if (sDumpstateWriter == null) {
-            throw new IllegalStateException(
-                    "DumpstateWriter must be created before adding values.");
+            Log.w(TAG, "DumpstateWriter must be created before adding values: %s: %s", name, value);
+            return;
         }
         sDumpstateWriter.mDumpValues.put(name, value);
     }
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn
index 4b69a94..5b801d3 100644
--- a/chromecast/browser/android/BUILD.gn
+++ b/chromecast/browser/android/BUILD.gn
@@ -43,6 +43,7 @@
     "//base:base_java",
     "//chromecast/base:base_java",
     "//content/public/android:content_java",
+    "//device/geolocation:geolocation_java",
     "//media/base/android:media_java",
     "//net/android:net_java",
 
diff --git a/chromecast/browser/android/cast_window_android.h b/chromecast/browser/android/cast_window_android.h
index bb536328..83593e5 100644
--- a/chromecast/browser/android/cast_window_android.h
+++ b/chromecast/browser/android/cast_window_android.h
@@ -29,7 +29,6 @@
 
 namespace content {
 class BrowserContext;
-class SiteInstance;
 class WebContents;
 }  // namespace content
 
diff --git a/chromecast/browser/android/cast_window_manager.h b/chromecast/browser/android/cast_window_manager.h
index 8494951..32fac5e 100644
--- a/chromecast/browser/android/cast_window_manager.h
+++ b/chromecast/browser/android/cast_window_manager.h
@@ -12,10 +12,6 @@
 
 class CastWindowAndroid;
 
-namespace content {
-class BrowserContext;
-}
-
 namespace chromecast {
 namespace shell {
 
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 6a187df..0ed31c1 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -21,10 +21,6 @@
 class CrashHandlerHostLinux;
 }
 
-namespace media {
-class BrowserCdmFactory;
-}
-
 namespace metrics {
 class MetricsService;
 }
diff --git a/chromecast/browser/cast_content_window.h b/chromecast/browser/cast_content_window.h
index b26d964..aeeeab94 100644
--- a/chromecast/browser/cast_content_window.h
+++ b/chromecast/browser/cast_content_window.h
@@ -20,10 +20,6 @@
 class WebContents;
 }
 
-namespace gfx {
-class Size;
-}
-
 namespace chromecast {
 namespace shell {
 
diff --git a/chromecast/browser/devtools/remote_debugging_server.h b/chromecast/browser/devtools/remote_debugging_server.h
index 14cba66..e0aefe4e 100644
--- a/chromecast/browser/devtools/remote_debugging_server.h
+++ b/chromecast/browser/devtools/remote_debugging_server.h
@@ -15,8 +15,6 @@
 namespace chromecast {
 namespace shell {
 
-class CastDevToolsManagerDelegate;
-
 class RemoteDebuggingServer {
  public:
   explicit RemoteDebuggingServer(bool start_immediately);
diff --git a/chromecast/browser/metrics/cast_stability_metrics_provider.h b/chromecast/browser/metrics/cast_stability_metrics_provider.h
index ade89ca..1f9bd28 100644
--- a/chromecast/browser/metrics/cast_stability_metrics_provider.h
+++ b/chromecast/browser/metrics/cast_stability_metrics_provider.h
@@ -16,7 +16,6 @@
 
 namespace content {
 class RenderProcessHost;
-class WebContents;
 }
 
 namespace metrics {
diff --git a/chromecast/media/audio/cast_audio_manager.h b/chromecast/media/audio/cast_audio_manager.h
index d13db28..f9a733e 100644
--- a/chromecast/media/audio/cast_audio_manager.h
+++ b/chromecast/media/audio/cast_audio_manager.h
@@ -10,8 +10,6 @@
 
 namespace chromecast {
 
-class TaskRunnerImpl;
-
 namespace media {
 
 class CastAudioMixer;
diff --git a/chromecast/media/audio/cast_audio_mixer.h b/chromecast/media/audio/cast_audio_mixer.h
index a2016dc6..d0cc48e 100644
--- a/chromecast/media/audio/cast_audio_mixer.h
+++ b/chromecast/media/audio/cast_audio_mixer.h
@@ -20,7 +20,6 @@
 namespace media {
 
 class CastAudioManager;
-class CastAudioOutputStream;
 
 // CastAudioMixer mixes multiple AudioOutputStreams and passes the mixed
 // stream down to a single AudioOutputStream to be rendered by the CMA backend.
diff --git a/chromecast/media/cdm/cast_cdm.h b/chromecast/media/cdm/cast_cdm.h
index 93cc5c7..b5de75e 100644
--- a/chromecast/media/cdm/cast_cdm.h
+++ b/chromecast/media/cdm/cast_cdm.h
@@ -24,10 +24,6 @@
 #include "media/base/player_tracker.h"
 #include "media/cdm/json_web_key.h"
 
-namespace base {
-class SingleThreadTaskRunner;
-}
-
 namespace media {
 class PlayerTrackerImpl;
 }
diff --git a/chromecast/media/cma/backend/alsa/audio_decoder_alsa.h b/chromecast/media/cma/backend/alsa/audio_decoder_alsa.h
index 464b9115..04c963f0 100644
--- a/chromecast/media/cma/backend/alsa/audio_decoder_alsa.h
+++ b/chromecast/media/cma/backend/alsa/audio_decoder_alsa.h
@@ -15,7 +15,6 @@
 
 namespace base {
 class SingleThreadTaskRunner;
-class Thread;
 }  // namespace base
 
 namespace chromecast {
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.h b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.h
index cdad51d..53a48911 100644
--- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.h
+++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.h
@@ -28,7 +28,6 @@
 namespace chromecast {
 namespace media {
 class AlsaWrapper;
-class StreamMixerAlsaInputImpl;
 
 // Mixer implementation. The mixer has one or more input queues; these can be
 // added/removed at any time. When an input source pushes frames to an input
diff --git a/chromecast/media/cma/pipeline/decrypt_util.h b/chromecast/media/cma/pipeline/decrypt_util.h
index 627068e9..ed9bdb6 100644
--- a/chromecast/media/cma/pipeline/decrypt_util.h
+++ b/chromecast/media/cma/pipeline/decrypt_util.h
@@ -8,10 +8,6 @@
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 
-namespace crypto {
-class SymmetricKey;
-}
-
 namespace chromecast {
 namespace media {
 
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc
index 82dbe8e..aa3ae06 100644
--- a/chromecast/media/service/cast_renderer.cc
+++ b/chromecast/media/service/cast_renderer.cc
@@ -209,16 +209,6 @@
   return pipeline_->GetMediaTime();
 }
 
-bool CastRenderer::HasAudio() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return pipeline_->HasAudio();
-}
-
-bool CastRenderer::HasVideo() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return pipeline_->HasVideo();
-}
-
 void CastRenderer::OnVideoResolutionPolicyChanged() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   if (!video_resolution_policy_)
diff --git a/chromecast/media/service/cast_renderer.h b/chromecast/media/service/cast_renderer.h
index 4d486b9..3273e26 100644
--- a/chromecast/media/service/cast_renderer.h
+++ b/chromecast/media/service/cast_renderer.h
@@ -16,10 +16,6 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
-namespace media {
-class MediaLog;
-}  // namespace media
-
 namespace chromecast {
 class TaskRunnerImpl;
 
@@ -49,8 +45,6 @@
   void SetPlaybackRate(double playback_rate) final;
   void SetVolume(float volume) final;
   base::TimeDelta GetMediaTime() final;
-  bool HasAudio() final;
-  bool HasVideo() final;
 
   // VideoResolutionPolicy::Observer implementation.
   void OnVideoResolutionPolicyChanged() override;
diff --git a/chromecast/net/connectivity_checker.h b/chromecast/net/connectivity_checker.h
index a9711181..dff6e530 100644
--- a/chromecast/net/connectivity_checker.h
+++ b/chromecast/net/connectivity_checker.h
@@ -11,8 +11,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/observer_list_threadsafe.h"
 
-class GURL;
-
 namespace base {
 class SingleThreadTaskRunner;
 }
diff --git a/chromecast/net/network_change_notifier_factory_cast.h b/chromecast/net/network_change_notifier_factory_cast.h
index 058d5b9..a2a6d315 100644
--- a/chromecast/net/network_change_notifier_factory_cast.h
+++ b/chromecast/net/network_change_notifier_factory_cast.h
@@ -11,8 +11,6 @@
 
 namespace chromecast {
 
-class NetworkChangeNotifierCast;
-
 class NetworkChangeNotifierFactoryCast
     : public net::NetworkChangeNotifierFactory {
  public:
diff --git a/chromecast/public/media/media_pipeline_backend.h b/chromecast/public/media/media_pipeline_backend.h
index 7a8ff459..e6ef3c9 100644
--- a/chromecast/public/media/media_pipeline_backend.h
+++ b/chromecast/public/media/media_pipeline_backend.h
@@ -16,7 +16,6 @@
 
 namespace media {
 class CastDecoderBuffer;
-class DecryptContext;
 
 // Interface for platform-specific output of media.
 // A new MediaPipelineBackend will be instantiated for each media player
diff --git a/chromecast/public/video_plane.h b/chromecast/public/video_plane.h
index 8076d7e..3a52565 100644
--- a/chromecast/public/video_plane.h
+++ b/chromecast/public/video_plane.h
@@ -7,7 +7,6 @@
 
 namespace chromecast {
 struct RectF;
-struct Size;
 
 namespace media {
 
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h
index 1c9b91c..4377b4d 100644
--- a/chromecast/renderer/cast_content_renderer_client.h
+++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -11,10 +11,6 @@
 #include "build/build_config.h"
 #include "content/public/renderer/content_renderer_client.h"
 
-namespace IPC {
-class MessageFilter;
-}
-
 namespace network_hints {
 class PrescientNetworkingDispatcher;
 }  // namespace network_hints
@@ -25,8 +21,6 @@
 }
 
 namespace shell {
-class CastGinRunner;
-class CastRenderThreadObserver;
 
 void ExecuteJavaScript(content::RenderFrame* render_frame, int resourceId);
 
diff --git a/chromecast/service/cast_service.h b/chromecast/service/cast_service.h
index 6819b83d..fea3cf7 100644
--- a/chromecast/service/cast_service.h
+++ b/chromecast/service/cast_service.h
@@ -20,10 +20,6 @@
 class BrowserContext;
 }
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace chromecast {
 
 class CastService {
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 6a416a8..99d4b0a7 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -30,6 +30,7 @@
     "//base",
     "//base:i18n",
     "//base/third_party/dynamic_annotations",
+    "//chrome/browser/chromeos:device_policy_proto",
     "//components/device_event_log",
     "//components/onc",
     "//components/policy/proto",
diff --git a/chromeos/DEPS b/chromeos/DEPS
index 0c457ab..512e62d 100644
--- a/chromeos/DEPS
+++ b/chromeos/DEPS
@@ -2,6 +2,7 @@
 # low level Chrome OS system library that may be used by targets that need to
 # be kept as small as possible.
 include_rules = [
+  "+chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h",
   "+components/device_event_log",
   "+components/policy/proto",
   "+components/pref_registry",
diff --git a/chromeos/dbus/fake_auth_policy_client.cc b/chromeos/dbus/fake_auth_policy_client.cc
index edcf528..19647ea 100644
--- a/chromeos/dbus/fake_auth_policy_client.cc
+++ b/chromeos/dbus/fake_auth_policy_client.cc
@@ -1,8 +1,57 @@
 // Copyright (c) 2016 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 "chromeos/dbus/fake_auth_policy_client.h"
 
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/location.h"
+#include "base/path_service.h"
+#include "base/task_runner_util.h"
+#include "base/threading/worker_pool.h"
+#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
+#include "chromeos/chromeos_paths.h"
+#include "components/policy/proto/device_management_backend.pb.h"
+
+namespace em = enterprise_management;
+
+namespace {
+
+// Create minimal stub device policy file and drop it at the place where
+// SessionManagerClientStubImpl is looking for it.
+bool WriteDevicePolicyFile() {
+  em::ChromeDeviceSettingsProto policy;
+  em::PolicyData data;
+  policy.SerializeToString(data.mutable_policy_value());
+  data.set_policy_type("google/chromeos/device");
+
+  em::PolicyFetchResponse response;
+  data.SerializeToString(response.mutable_policy_data());
+  std::string serialized_response;
+  response.SerializeToString(&serialized_response);
+
+  base::FilePath owner_key_path;
+  if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path))
+    return false;
+
+  const base::FilePath device_policy_path =
+      owner_key_path.DirName().AppendASCII("stub_device_policy");
+
+  // Note that in theory there could be a short time window in which a
+  // concurrent reader sees a partial (and thus invalid) file, but given the
+  // small file size that seems very unlikely in practice.
+  const int bytes_written =
+      base::WriteFile(device_policy_path, serialized_response.c_str(),
+                      serialized_response.size());
+  if (bytes_written < 0)
+    return false;
+  return bytes_written == static_cast<int>(serialized_response.size());
+}
+
+}  // namespace
+
 namespace chromeos {
 
 FakeAuthPolicyClient::FakeAuthPolicyClient() {}
@@ -20,13 +69,17 @@
 
 void FakeAuthPolicyClient::RefreshDevicePolicy(
     const RefreshPolicyCallback& callback) {
-  callback.Run(true);
-};
+  if (!base::PostTaskAndReplyWithResult(
+          base::WorkerPool::GetTaskRunner(false /* task_is_slow */).get(),
+          FROM_HERE, base::Bind(&WriteDevicePolicyFile), callback)) {
+    callback.Run(false);
+  }
+}
 
 void FakeAuthPolicyClient::RefreshUserPolicy(
     const std::string& account_id,
     const RefreshPolicyCallback& callback) {
   callback.Run(true);
-};
+}
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/fake_auth_policy_client.h b/chromeos/dbus/fake_auth_policy_client.h
index 55da46f..04dde91 100644
--- a/chromeos/dbus/fake_auth_policy_client.h
+++ b/chromeos/dbus/fake_auth_policy_client.h
@@ -25,9 +25,9 @@
                     const std::string& user,
                     int password_fd,
                     const JoinCallback& callback) override;
-  void RefreshDevicePolicy(const RefreshPolicyCallback& calllback) override;
+  void RefreshDevicePolicy(const RefreshPolicyCallback& callback) override;
   void RefreshUserPolicy(const std::string& account_id,
-                         const RefreshPolicyCallback& calllback) override;
+                         const RefreshPolicyCallback& callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FakeAuthPolicyClient);
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index dd788794..99aef6c0 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -95,7 +95,7 @@
     "//ui/aura",
     "//ui/base:base",
     "//ui/base/ime",
-    "//ui/display:display",
+    "//ui/display/manager",
     "//ui/events",
     "//ui/events:dom_keycode_converter",
     "//ui/keyboard:keyboard",
diff --git a/components/arc/power/DEPS b/components/arc/power/DEPS
index f9e970a..aeeb731 100644
--- a/components/arc/power/DEPS
+++ b/components/arc/power/DEPS
@@ -1,4 +1,4 @@
 include_rules = [
   "+ash",
-  "+ui/display/chromeos",
+  "+ui/display/manager/chromeos",
 ]
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h
index 5bcffff..b35354e 100644
--- a/components/arc/power/arc_power_bridge.h
+++ b/components/arc/power/arc_power_bridge.h
@@ -12,7 +12,7 @@
 #include "components/arc/common/power.mojom.h"
 #include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace arc {
 
diff --git a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java
index f280506..cd7f4255 100644
--- a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java
+++ b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java
@@ -276,17 +276,6 @@
         }
 
         /**
-         * Sets experimental options to be used in Cronet.
-         *
-         * @param options JSON formatted experimental options.
-         * @return the builder to facilitate chaining.
-         */
-        public Builder setExperimentalOptions(String options) {
-            mBuilderDelegate.setExperimentalOptions(options);
-            return this;
-        }
-
-        /**
          * Build a {@link CronetEngine} using this builder's configuration.
          * @return constructed {@link CronetEngine}.
          */
diff --git a/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java b/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java
index ba4efa7..6fc67f4e 100644
--- a/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java
+++ b/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java
@@ -170,6 +170,17 @@
             return this;
         }
 
+        /**
+         * Sets experimental options to be used in Cronet.
+         *
+         * @param options JSON formatted experimental options.
+         * @return the builder to facilitate chaining.
+         */
+        public Builder setExperimentalOptions(String options) {
+            mBuilderDelegate.setExperimentalOptions(options);
+            return this;
+        }
+
         @VisibleForTesting
         ICronetEngineBuilder getBuilderDelegate() {
             return mBuilderDelegate;
@@ -240,12 +251,6 @@
         }
 
         @Override
-        public Builder setExperimentalOptions(String options) {
-            super.setExperimentalOptions(options);
-            return this;
-        }
-
-        @Override
         public ExperimentalCronetEngine build() {
             return mBuilderDelegate.build();
         }
diff --git a/components/cronet/android/cronet_bidirectional_stream_adapter.cc b/components/cronet/android/cronet_bidirectional_stream_adapter.cc
index 2bbd8ed..c40d9a2 100644
--- a/components/cronet/android/cronet_bidirectional_stream_adapter.cc
+++ b/components/cronet/android/cronet_bidirectional_stream_adapter.cc
@@ -24,7 +24,7 @@
 #include "net/http/http_status_code.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/http/http_util.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/spdy/spdy_header_block.h"
 #include "net/ssl/ssl_info.h"
 #include "net/url_request/http_user_agent_settings.h"
diff --git a/components/cronet/android/cronet_url_request_adapter.cc b/components/cronet/android/cronet_url_request_adapter.cc
index d80fc1e..253b0a5 100644
--- a/components/cronet/android/cronet_url_request_adapter.cc
+++ b/components/cronet/android/cronet_url_request_adapter.cc
@@ -25,7 +25,7 @@
 #include "net/http/http_status_code.h"
 #include "net/http/http_util.h"
 #include "net/proxy/proxy_server.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/ssl/ssl_info.h"
 #include "net/url_request/redirect_info.h"
 #include "net/url_request/url_request_context.h"
diff --git a/components/cronet/android/test/quic_test_server.cc b/components/cronet/android/test/quic_test_server.cc
index e704253..515b5ed 100644
--- a/components/cronet/android/test/quic_test_server.cc
+++ b/components/cronet/android/test/quic_test_server.cc
@@ -18,7 +18,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/quic/chromium/crypto/proof_source_chromium.h"
 #include "net/test/test_data_directory.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server.h"
 
 using base::android::JavaParamRef;
@@ -31,7 +31,7 @@
 static const int kServerPort = 6121;
 
 base::Thread* g_quic_server_thread = nullptr;
-net::QuicInMemoryCache* g_quic_in_memory_cache = nullptr;
+net::QuicHttpResponseCache* g_quic_response_cache = nullptr;
 net::QuicSimpleServer* g_quic_server = nullptr;
 
 void StartOnServerThread(const base::FilePath& test_files_root,
@@ -42,8 +42,8 @@
   // Set up in-memory cache.
   base::FilePath file_dir = test_files_root.Append("quic_data");
   CHECK(base::PathExists(file_dir)) << "Quic data does not exist";
-  g_quic_in_memory_cache = new net::QuicInMemoryCache();
-  g_quic_in_memory_cache->InitializeFromDirectory(file_dir.value());
+  g_quic_response_cache = new net::QuicHttpResponseCache();
+  g_quic_response_cache->InitializeFromDirectory(file_dir.value());
   net::QuicConfig config;
 
   // Set up server certs.
@@ -57,7 +57,7 @@
   g_quic_server = new net::QuicSimpleServer(
       std::move(proof_source), config,
       net::QuicCryptoServerConfig::ConfigOptions(), net::AllSupportedVersions(),
-      g_quic_in_memory_cache);
+      g_quic_response_cache);
 
   // Start listening.
   int rv = g_quic_server->Listen(
@@ -71,7 +71,7 @@
   DCHECK(g_quic_server_thread->task_runner()->BelongsToCurrentThread());
   g_quic_server->Shutdown();
   delete g_quic_server;
-  delete g_quic_in_memory_cache;
+  delete g_quic_response_cache;
 }
 
 }  // namespace
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index be05da5..78497f7 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -22,7 +22,7 @@
 #include "net/dns/host_resolver.h"
 #include "net/dns/mapped_host_resolver.h"
 #include "net/http/http_server_properties.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/url_request/url_request_context_builder.h"
diff --git a/components/domain_reliability/quic_error_mapping.cc b/components/domain_reliability/quic_error_mapping.cc
index d23fc4b..7a37026 100644
--- a/components/domain_reliability/quic_error_mapping.cc
+++ b/components/domain_reliability/quic_error_mapping.cc
@@ -255,7 +255,7 @@
 };
 
 // Must be updated any time a net::QuicErrorCode is deprecated in
-// net/quic/core/quic_protocol.h.
+// net/quic/core/quic_packets.h.
 const int kDeprecatedQuicErrorCount = 4;
 const int kActiveQuicErrorCount =
     net::QUIC_LAST_ERROR - kDeprecatedQuicErrorCount;
diff --git a/components/domain_reliability/quic_error_mapping.h b/components/domain_reliability/quic_error_mapping.h
index 4d1146b..f9d373b 100644
--- a/components/domain_reliability/quic_error_mapping.h
+++ b/components/domain_reliability/quic_error_mapping.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 // N.B. This file and the .cc are separate from util.h/.cc so that they can be
 // independently updated by folks working on QUIC when new errors are added.
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index bc63830..55100cd 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -57,6 +57,7 @@
     "//skia",
     "//ui/aura",
     "//ui/compositor",
+    "//ui/display/manager",
     "//ui/gfx",
     "//ui/gfx/geometry",
     "//ui/gl",
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn
index 712ac70..237e3f5 100644
--- a/components/exo/wayland/BUILD.gn
+++ b/components/exo/wayland/BUILD.gn
@@ -47,6 +47,7 @@
     "//third_party/wayland-protocols:xdg_shell_protocol",
     "//ui/aura",
     "//ui/base",
+    "//ui/display/manager",
     "//ui/events:dom_keycode_converter",
     "//ui/events:events_base",
     "//ui/views",
diff --git a/components/grpc_support/test/quic_test_server.cc b/components/grpc_support/test/quic_test_server.cc
index 8455cd6d..d57f94ce 100644
--- a/components/grpc_support/test/quic_test_server.cc
+++ b/components/grpc_support/test/quic_test_server.cc
@@ -18,7 +18,7 @@
 #include "net/quic/chromium/crypto/proof_source_chromium.h"
 #include "net/spdy/spdy_header_block.h"
 #include "net/test/test_data_directory.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server.h"
 
 namespace grpc_support {
@@ -41,18 +41,18 @@
 const char kHelloTrailerValue[] = "hello trailer value";
 
 base::Thread* g_quic_server_thread = nullptr;
-net::QuicInMemoryCache* g_quic_in_memory_cache = nullptr;
+net::QuicHttpResponseCache* g_quic_response_cache = nullptr;
 net::QuicSimpleServer* g_quic_server = nullptr;
 int g_quic_server_port = 0;
 
-void SetupQuicInMemoryCache() {
+void SetupQuicHttpResponseCache() {
   net::SpdyHeaderBlock headers;
   headers[kHelloHeaderName] = kHelloHeaderValue;
   headers[kStatusHeader] =  kHelloStatus;
   net::SpdyHeaderBlock trailers;
   trailers[kHelloTrailerName] = kHelloTrailerValue;
-  g_quic_in_memory_cache = new net::QuicInMemoryCache();
-  g_quic_in_memory_cache->AddResponse(base::StringPrintf("%s", kTestServerHost),
+  g_quic_response_cache = new net::QuicHttpResponseCache();
+  g_quic_response_cache->AddResponse(base::StringPrintf("%s", kTestServerHost),
                                       kHelloPath, std::move(headers),
                                       kHelloBodyValue, std::move(trailers));
 }
@@ -73,12 +73,12 @@
       directory.AppendASCII("quic_test.example.com.key.pkcs8"),
       directory.AppendASCII("quic_test.example.com.key.sct")));
 
-  SetupQuicInMemoryCache();
+  SetupQuicHttpResponseCache();
 
   g_quic_server = new net::QuicSimpleServer(
       std::move(proof_source), config,
       net::QuicCryptoServerConfig::ConfigOptions(), net::AllSupportedVersions(),
-      g_quic_in_memory_cache);
+      g_quic_response_cache);
 
   // Start listening on an unbound port.
   int rv = g_quic_server->Listen(
@@ -94,8 +94,8 @@
   g_quic_server->Shutdown();
   delete g_quic_server;
   g_quic_server = nullptr;
-  delete g_quic_in_memory_cache;
-  g_quic_in_memory_cache = nullptr;
+  delete g_quic_response_cache;
+  g_quic_response_cache = nullptr;
   server_stopped_event->Signal();
 }
 
diff --git a/components/metrics/drive_metrics_provider_linux.cc b/components/metrics/drive_metrics_provider_linux.cc
index 35c505a..194e1ee 100644
--- a/components/metrics/drive_metrics_provider_linux.cc
+++ b/components/metrics/drive_metrics_provider_linux.cc
@@ -11,6 +11,7 @@
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 
@@ -33,9 +34,11 @@
 bool DriveMetricsProvider::HasSeekPenalty(const base::FilePath& path,
                                           bool* has_seek_penalty) {
 #if defined(OS_CHROMEOS)
-  std::string board = base::SysInfo::GetLsbReleaseBoard();
-  if (board != "unknown" && board != "parrot") {
-    // All ChromeOS devices have SSDs. Except some parrots.
+  std::string board = base::SysInfo::GetStrippedReleaseBoard();
+  // There are "parrot", "parrot_ivb" and "parrot_freon" boards that have
+  // devices with rotating disks. All other ChromeOS devices have SSDs.
+  if (board != "unknown" &&
+      !base::StartsWith(board, "parrot", base::CompareCase::SENSITIVE)) {
     *has_seek_penalty = false;
     return true;
   }
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc
index 593da58..e1c9bb0 100644
--- a/components/network_session_configurator/network_session_configurator.cc
+++ b/components/network_session_configurator/network_session_configurator.cc
@@ -15,7 +15,7 @@
 #include "components/variations/variations_associated_data.h"
 #include "components/version_info/version_info.h"
 #include "net/http/http_stream_factory.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/url_request/url_fetcher.h"
 
@@ -316,8 +316,6 @@
         ShouldQuicDisableDiskCache(quic_trial_params);
     params->quic_prefer_aes = ShouldQuicPreferAes(quic_trial_params);
     params->quic_force_hol_blocking = ShouldForceHolBlocking(quic_trial_params);
-    // Default to disabling port selection on all channels.
-    params->enable_quic_port_selection = false;
     params->quic_connection_options =
         GetQuicConnectionOptions(quic_trial_params);
     params->quic_close_sessions_on_ip_change =
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc
index 26e5ad9eb..ccea4fb 100644
--- a/components/network_session_configurator/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/test/mock_entropy_provider.h"
 #include "components/variations/variations_associated_data.h"
 #include "net/http/http_stream_factory.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace test {
diff --git a/components/safe_browsing_db/v4_local_database_manager.cc b/components/safe_browsing_db/v4_local_database_manager.cc
index d479e30..ce08312 100644
--- a/components/safe_browsing_db/v4_local_database_manager.cc
+++ b/components/safe_browsing_db/v4_local_database_manager.cc
@@ -39,31 +39,39 @@
   //   for it, it can be changed to true.
   // - The list doesn't have hash prefixes to match. All requests lead to full
   //   hash checks. For instance: GetChromeUrlApiId()
+
+#if defined(GOOGLE_CHROME_BUILD)
+  const bool kSyncOnlyOnChromeBuilds = true;
+#else
+  const bool kSyncOnlyOnChromeBuilds = false;
+#endif
+  const bool kSyncAlways = true;
+  const bool kSyncNever = false;
   return ListInfos({
-      ListInfo(false, "CertCsdDownloadWhitelist.store",
+      ListInfo(kSyncOnlyOnChromeBuilds, "CertCsdDownloadWhitelist.store",
                GetCertCsdDownloadWhitelistId(), SB_THREAT_TYPE_UNUSED),
-      ListInfo(false, "ChromeFilenameClientIncident.store",
+      ListInfo(kSyncOnlyOnChromeBuilds, "ChromeFilenameClientIncident.store",
                GetChromeFilenameClientIncidentId(), SB_THREAT_TYPE_UNUSED),
-      ListInfo(true, "IpMalware.store", GetIpMalwareId(),
+      ListInfo(kSyncAlways, "IpMalware.store", GetIpMalwareId(),
                SB_THREAT_TYPE_UNUSED),
-      ListInfo(false, "UrlCsdDownloadWhitelist.store",
+      ListInfo(kSyncOnlyOnChromeBuilds, "UrlCsdDownloadWhitelist.store",
                GetUrlCsdDownloadWhitelistId(), SB_THREAT_TYPE_UNUSED),
-      ListInfo(false, "UrlCsdWhitelist.store", GetUrlCsdWhitelistId(),
-               SB_THREAT_TYPE_UNUSED),
-      ListInfo(true, "UrlSoceng.store", GetUrlSocEngId(),
+      ListInfo(kSyncOnlyOnChromeBuilds, "UrlCsdWhitelist.store",
+               GetUrlCsdWhitelistId(), SB_THREAT_TYPE_UNUSED),
+      ListInfo(kSyncAlways, "UrlSoceng.store", GetUrlSocEngId(),
                SB_THREAT_TYPE_URL_PHISHING),
-      ListInfo(true, "UrlMalware.store", GetUrlMalwareId(),
+      ListInfo(kSyncAlways, "UrlMalware.store", GetUrlMalwareId(),
                SB_THREAT_TYPE_URL_MALWARE),
-      ListInfo(true, "UrlUws.store", GetUrlUwsId(),
+      ListInfo(kSyncAlways, "UrlUws.store", GetUrlUwsId(),
                SB_THREAT_TYPE_URL_UNWANTED),
-      ListInfo(true, "UrlMalBin.store", GetUrlMalBinId(),
+      ListInfo(kSyncAlways, "UrlMalBin.store", GetUrlMalBinId(),
                SB_THREAT_TYPE_BINARY_MALWARE_URL),
-      ListInfo(true, "ChromeExtMalware.store", GetChromeExtensionMalwareId(),
+      ListInfo(kSyncAlways, "ChromeExtMalware.store", GetChromeExtMalwareId(),
                SB_THREAT_TYPE_EXTENSION),
-      ListInfo(false, "ChromeUrlClientIncident.store",
+      ListInfo(kSyncOnlyOnChromeBuilds, "ChromeUrlClientIncident.store",
                GetChromeUrlClientIncidentId(),
                SB_THREAT_TYPE_BLACKLISTED_RESOURCE),
-      ListInfo(false, "", GetChromeUrlApiId(), SB_THREAT_TYPE_API_ABUSE),
+      ListInfo(kSyncNever, "", GetChromeUrlApiId(), SB_THREAT_TYPE_API_ABUSE),
   });
 }
 
@@ -221,7 +229,7 @@
 
   std::unique_ptr<PendingCheck> check = base::MakeUnique<PendingCheck>(
       client, ClientCallbackType::CHECK_EXTENSION_IDS,
-      StoresToCheck({GetChromeExtensionMalwareId()}), extension_ids);
+      StoresToCheck({GetChromeExtMalwareId()}), extension_ids);
 
   return HandleCheck(std::move(check));
 }
@@ -243,25 +251,43 @@
 
 bool V4LocalDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!enabled_ || !v4_database_) {
+    // To make sure we are conservative we return true.
+    return true;
+  }
+
   return HandleUrlSynchronously(url, StoresToCheck({GetUrlCsdWhitelistId()}));
 }
 
 bool V4LocalDatabaseManager::MatchDownloadWhitelistString(
     const std::string& str) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!enabled_ || !v4_database_) {
+    // To make sure we are conservative we return true.
+    return true;
+  }
+
   return HandleHashSynchronously(
       str, StoresToCheck({GetCertCsdDownloadWhitelistId()}));
 }
 
 bool V4LocalDatabaseManager::MatchDownloadWhitelistUrl(const GURL& url) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!enabled_ || !v4_database_) {
+    // To make sure we are conservative we return true.
+    return true;
+  }
+
   return HandleUrlSynchronously(
       url, StoresToCheck({GetUrlCsdDownloadWhitelistId()}));
 }
 
 bool V4LocalDatabaseManager::MatchMalwareIP(const std::string& ip_address) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!enabled_) {
+  if (!enabled_ || !v4_database_) {
     return false;
   }
 
@@ -278,6 +304,12 @@
 bool V4LocalDatabaseManager::MatchModuleWhitelistString(
     const std::string& str) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!enabled_ || !v4_database_) {
+    // To make sure we are conservative we return true.
+    return true;
+  }
+
   return HandleHashSynchronously(
       str, StoresToCheck({GetChromeFilenameClientIncidentId()}));
 }
@@ -498,10 +530,6 @@
     const StoresToCheck& stores_to_check) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!enabled_ || !v4_database_) {
-    return false;
-  }
-
   std::set<FullHash> hashes{hash};
   std::unique_ptr<PendingCheck> check = base::MakeUnique<PendingCheck>(
       nullptr, ClientCallbackType::CHECK_OTHER, stores_to_check, hashes);
@@ -515,10 +543,6 @@
     const StoresToCheck& stores_to_check) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!enabled_ || !v4_database_) {
-    return false;
-  }
-
   std::unique_ptr<PendingCheck> check = base::MakeUnique<PendingCheck>(
       nullptr, ClientCallbackType::CHECK_OTHER, stores_to_check,
       std::vector<GURL>(1, url));
diff --git a/components/safe_browsing_db/v4_local_database_manager.h b/components/safe_browsing_db/v4_local_database_manager.h
index 4481a956..d786d61 100644
--- a/components/safe_browsing_db/v4_local_database_manager.h
+++ b/components/safe_browsing_db/v4_local_database_manager.h
@@ -203,9 +203,8 @@
   bool HandleCheck(std::unique_ptr<PendingCheck> check);
 
   // Checks |stores_to_check| in database synchronously for hash prefixes
-  // matching |hash|. Returns false if the database isn't ready or if there's no
-  // match; true otherwise. This is used for lists that have full hash
-  // information in the database.
+  // matching |hash|. Returns true if there's a match; false otherwise. This is
+  // used for lists that have full hash information in the database.
   bool HandleHashSynchronously(const FullHash& hash,
                                const StoresToCheck& stores_to_check);
 
diff --git a/components/safe_browsing_db/v4_protocol_manager_util.cc b/components/safe_browsing_db/v4_protocol_manager_util.cc
index 00937dc..dad0d79 100644
--- a/components/safe_browsing_db/v4_protocol_manager_util.cc
+++ b/components/safe_browsing_db/v4_protocol_manager_util.cc
@@ -91,7 +91,7 @@
   return ListIdentifier(GetCurrentPlatformType(), CERT, CSD_DOWNLOAD_WHITELIST);
 }
 
-const ListIdentifier GetChromeExtensionMalwareId() {
+const ListIdentifier GetChromeExtMalwareId() {
   return ListIdentifier(CHROME_PLATFORM, CHROME_EXTENSION, MALWARE_THREAT);
 }
 
diff --git a/components/safe_browsing_db/v4_protocol_manager_util.h b/components/safe_browsing_db/v4_protocol_manager_util.h
index c84413ec..707b82d 100644
--- a/components/safe_browsing_db/v4_protocol_manager_util.h
+++ b/components/safe_browsing_db/v4_protocol_manager_util.h
@@ -142,7 +142,7 @@
 
 PlatformType GetCurrentPlatformType();
 const ListIdentifier GetCertCsdDownloadWhitelistId();
-const ListIdentifier GetChromeExtensionMalwareId();
+const ListIdentifier GetChromeExtMalwareId();
 const ListIdentifier GetChromeUrlApiId();
 const ListIdentifier GetChromeFilenameClientIncidentId();
 const ListIdentifier GetChromeUrlClientIncidentId();
diff --git a/components/sync/driver/sync_stopped_reporter.cc b/components/sync/driver/sync_stopped_reporter.cc
index ba5fbc8..7daf57c 100644
--- a/components/sync/driver/sync_stopped_reporter.cc
+++ b/components/sync/driver/sync_stopped_reporter.cc
@@ -9,6 +9,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "components/data_use_measurement/core/data_use_user_data.h"
 #include "components/sync/protocol/sync.pb.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_status_code.h"
@@ -72,6 +73,8 @@
   fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
                          net::LOAD_DO_NOT_SAVE_COOKIES |
                          net::LOAD_DO_NOT_SEND_COOKIES);
+  data_use_measurement::DataUseUserData::AttachToFetcher(
+      fetcher_.get(), data_use_measurement::DataUseUserData::SYNC);
   fetcher_->Start();
   timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kRequestTimeoutSeconds),
                this, &SyncStoppedReporter::OnTimeout);
diff --git a/content/browser/media/android/media_player_renderer.cc b/content/browser/media/android/media_player_renderer.cc
index d227000..9723584 100644
--- a/content/browser/media/android/media_player_renderer.cc
+++ b/content/browser/media/android/media_player_renderer.cc
@@ -167,14 +167,6 @@
   return media_player_->GetCurrentTime();
 }
 
-bool MediaPlayerRenderer::HasAudio() {
-  return media_player_->HasAudio();
-}
-
-bool MediaPlayerRenderer::HasVideo() {
-  return media_player_->HasVideo();
-}
-
 media::MediaResourceGetter* MediaPlayerRenderer::GetMediaResourceGetter() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!media_resource_getter_.get()) {
diff --git a/content/browser/media/android/media_player_renderer.h b/content/browser/media/android/media_player_renderer.h
index 2ff2583..129e240 100644
--- a/content/browser/media/android/media_player_renderer.h
+++ b/content/browser/media/android/media_player_renderer.h
@@ -62,8 +62,6 @@
   void SetPlaybackRate(double playback_rate) override;
   void SetVolume(float volume) override;
   base::TimeDelta GetMediaTime() override;
-  bool HasAudio() override;
-  bool HasVideo() override;
 
   // media::MediaPlayerManager implementation
   media::MediaResourceGetter* GetMediaResourceGetter() override;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 70e60c4..c0daedb 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -561,7 +561,7 @@
   DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
   DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
   const display::Display& display =
-      display::Screen::GetScreen()->GetPrimaryDisplay();
+      display::Screen::GetScreen()->GetDisplayNearestWindow(GetNativeView());
   float device_scale_factor = display.device_scale_factor();
   DCHECK_GT(device_scale_factor, 0);
   gfx::Size dst_size(
@@ -1001,7 +1001,7 @@
 
   base::TimeTicks start_time = base::TimeTicks::Now();
   const display::Display& display =
-      display::Screen::GetScreen()->GetPrimaryDisplay();
+      display::Screen::GetScreen()->GetDisplayNearestWindow(GetNativeView());
   float device_scale_factor = display.device_scale_factor();
   gfx::Size dst_size_in_pixel =
       gfx::ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
diff --git a/content/renderer/media/android/media_player_renderer_client.cc b/content/renderer/media/android/media_player_renderer_client.cc
index 1b319a5..85d782f 100644
--- a/content/renderer/media/android/media_player_renderer_client.cc
+++ b/content/renderer/media/android/media_player_renderer_client.cc
@@ -104,24 +104,6 @@
   return mojo_renderer_->GetMediaTime();
 }
 
-bool MediaPlayerRendererClient::HasAudio() {
-  // We do not know whether or not the media has Audio before starting playback.
-  // Conservatively assume we do.
-  // TODO(tguilbert): Consider using MIME types to determine presence of audio.
-  // Alternatively, consider piping the HasAudio() from the MediaPlayerRenderer
-  // through the mojo::Renderer interface.
-  return true;
-}
-
-bool MediaPlayerRendererClient::HasVideo() {
-  // We do not know whether or not the media has Video before starting playback.
-  // Conservatively assume we do.
-  // TODO(tguilbert): Consider using MIME types to determine presence of video.
-  // Alternatively, consider piping the HasVideo() from the MediaPlayerRenderer
-  // through the mojo::Renderer interface.
-  return true;
-}
-
 void MediaPlayerRendererClient::OnFrameAvailable() {
   DCHECK(compositor_task_runner_->BelongsToCurrentThread());
   sink_->PaintSingleFrame(stream_texture_wrapper_->GetCurrentFrame(), true);
diff --git a/content/renderer/media/android/media_player_renderer_client.h b/content/renderer/media/android/media_player_renderer_client.h
index aa7811e..6e056e36 100644
--- a/content/renderer/media/android/media_player_renderer_client.h
+++ b/content/renderer/media/android/media_player_renderer_client.h
@@ -55,8 +55,6 @@
   void SetPlaybackRate(double playback_rate) override;
   void SetVolume(float volume) override;
   base::TimeDelta GetMediaTime() override;
-  bool HasAudio() override;
-  bool HasVideo() override;
 
   // media::RendererClient implementation.
   void OnError(media::PipelineStatus status) override;
diff --git a/content/renderer/text_input_client_observer.cc b/content/renderer/text_input_client_observer.cc
index eb9ef89..fd8d5d7 100644
--- a/content/renderer/text_input_client_observer.cc
+++ b/content/renderer/text_input_client_observer.cc
@@ -26,6 +26,13 @@
 
 namespace content {
 
+namespace {
+uint32_t GetCurrentCursorPositionInFrame(blink::WebLocalFrame* localFrame) {
+  blink::WebRange range = localFrame->selectionRange();
+  return range.isNull() ? 0U : static_cast<uint32_t>(range.startOffset());
+}
+}
+
 TextInputClientObserver::TextInputClientObserver(RenderWidget* render_widget)
     : render_widget_(render_widget) {}
 
@@ -133,8 +140,11 @@
     // See crbug.com/304341
     if (frame) {
       blink::WebRect web_rect;
-      frame->firstRectForCharacterRange(range.start(), range.length(),
-                                        web_rect);
+      // When request range is invalid we will try to obtain it from current
+      // frame selection. The fallback value will be 0.
+      uint32_t start = range.IsValid() ? range.start()
+                                       : GetCurrentCursorPositionInFrame(frame);
+      frame->firstRectForCharacterRange(start, range.length(), web_rect);
       rect = web_rect;
     }
   }
diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h
index 0e97afd..8feb409 100644
--- a/device/bluetooth/bluetooth_adapter.h
+++ b/device/bluetooth/bluetooth_adapter.h
@@ -36,7 +36,6 @@
 class BluetoothRemoteGattService;
 class BluetoothSocket;
 class BluetoothUUID;
-struct BluetoothAdapterDeleter;
 enum class UMABluetoothDiscoverySessionOutcome;
 
 // BluetoothAdapter represents a local Bluetooth adapter which may be used to
diff --git a/device/bluetooth/bluetooth_adapter_win.h b/device/bluetooth/bluetooth_adapter_win.h
index cdaeead7..d9b8570b 100644
--- a/device/bluetooth/bluetooth_adapter_win.h
+++ b/device/bluetooth/bluetooth_adapter_win.h
@@ -26,7 +26,6 @@
 
 namespace base {
 class SequencedTaskRunner;
-class Thread;
 }  // namespace base
 
 namespace device {
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h
index 1dc6bcd6..8102152 100644
--- a/device/bluetooth/bluetooth_device.h
+++ b/device/bluetooth/bluetooth_device.h
@@ -26,10 +26,6 @@
 #include "device/bluetooth/bluetooth_export.h"
 #include "device/bluetooth/bluetooth_uuid.h"
 
-namespace base {
-class BinaryValue;
-}
-
 namespace device {
 
 class BluetoothAdapter;
diff --git a/device/bluetooth/bluetooth_gatt_characteristic.h b/device/bluetooth/bluetooth_gatt_characteristic.h
index ed151ad..94af976 100644
--- a/device/bluetooth/bluetooth_gatt_characteristic.h
+++ b/device/bluetooth/bluetooth_gatt_characteristic.h
@@ -17,9 +17,6 @@
 
 namespace device {
 
-class BluetoothRemoteGattDescriptor;
-class BluetoothGattNotifySession;
-
 // BluetoothGattCharacteristic represents a local or remote GATT characteristic.
 // A GATT characteristic is a basic data element used to construct a GATT
 // service. Hence, instances of a BluetoothGattCharacteristic are associated
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.h b/device/bluetooth/bluetooth_low_energy_device_mac.h
index e8d4bd0..76b3130 100644
--- a/device/bluetooth/bluetooth_low_energy_device_mac.h
+++ b/device/bluetooth/bluetooth_low_energy_device_mac.h
@@ -27,7 +27,6 @@
 namespace device {
 
 class BluetoothAdapterMac;
-class BluetoothLowEnergyDiscoverManagerMac;
 class BluetoothRemoteGattServiceMac;
 
 class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyDeviceMac
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
index 486c203..486f3fc 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
@@ -16,7 +16,6 @@
 
 namespace device {
 
-class BluetoothAdapterWin;
 class BluetoothRemoteGattDescriptorWin;
 class BluetoothRemoteGattServiceWin;
 class BluetoothTaskManagerWin;
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_win.h b/device/bluetooth/bluetooth_remote_gatt_descriptor_win.h
index 4964cb4f..16fe810 100644
--- a/device/bluetooth/bluetooth_remote_gatt_descriptor_win.h
+++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_win.h
@@ -15,7 +15,6 @@
 
 namespace device {
 
-class BluetoothAdapterWin;
 class BluetoothRemoteGattCharacteristicWin;
 class BluetoothTaskManagerWin;
 
diff --git a/device/bluetooth/bluetooth_remote_gatt_service.h b/device/bluetooth/bluetooth_remote_gatt_service.h
index 08e6436..722b22d 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service.h
+++ b/device/bluetooth/bluetooth_remote_gatt_service.h
@@ -16,7 +16,6 @@
 
 class BluetoothDevice;
 class BluetoothRemoteGattCharacteristic;
-class BluetoothRemoteGattDescriptor;
 
 // BluetoothRemoteGattService represents a remote GATT service.
 //
diff --git a/device/bluetooth/bluetooth_socket.h b/device/bluetooth/bluetooth_socket.h
index 395c7cb..3356bf0 100644
--- a/device/bluetooth/bluetooth_socket.h
+++ b/device/bluetooth/bluetooth_socket.h
@@ -18,7 +18,6 @@
 namespace device {
 
 class BluetoothDevice;
-class BluetoothUUID;
 
 // BluetoothSocket represents a socket to a specific service on a
 // BluetoothDevice.  BluetoothSocket objects are ref counted and may outlive
diff --git a/device/bluetooth/bluez/bluetooth_gatt_descriptor_bluez.h b/device/bluetooth/bluez/bluetooth_gatt_descriptor_bluez.h
index c079b00..ac73948 100644
--- a/device/bluetooth/bluez/bluetooth_gatt_descriptor_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_gatt_descriptor_bluez.h
@@ -13,8 +13,6 @@
 
 namespace bluez {
 
-class BluetoothGattCharacteristicBlueZ;
-
 // The BluetoothGattDescriptorBlueZ class implements BluetoothGattDescriptor for
 // GATT characteristic descriptors for platforms that use BlueZ.
 class BluetoothGattDescriptorBlueZ
diff --git a/device/bluetooth/bluez/bluetooth_local_gatt_service_bluez.h b/device/bluetooth/bluez/bluetooth_local_gatt_service_bluez.h
index ebe7b727..bcb72df 100644
--- a/device/bluetooth/bluez/bluetooth_local_gatt_service_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_local_gatt_service_bluez.h
@@ -16,13 +16,6 @@
 #include "device/bluetooth/bluez/bluetooth_gatt_service_bluez.h"
 #include "device/bluetooth/bluez/bluetooth_local_gatt_characteristic_bluez.h"
 
-namespace device {
-
-class BluetoothAdapter;
-class BluetoothDevice;
-
-}  // namespace device
-
 namespace bluez {
 
 class BluetoothAdapterBlueZ;
diff --git a/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h b/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h
index e194392..c08375b 100644
--- a/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h
@@ -22,7 +22,6 @@
 
 namespace device {
 
-class BluetoothAdapter;
 class BluetoothDevice;
 class BluetoothRemoteGattCharacteristic;
 
diff --git a/device/bluetooth/bluez/bluetooth_service_record_bluez.h b/device/bluetooth/bluez/bluetooth_service_record_bluez.h
index 5fb6205..8965a33 100644
--- a/device/bluetooth/bluez/bluetooth_service_record_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_service_record_bluez.h
@@ -13,10 +13,6 @@
 #include "device/bluetooth/bluetooth_export.h"
 #include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
 
-namespace base {
-class Value;
-}
-
 namespace bluez {
 
 class DEVICE_BLUETOOTH_EXPORT BluetoothServiceRecordBlueZ {
diff --git a/device/bluetooth/dbus/bluez_dbus_manager.h b/device/bluetooth/dbus/bluez_dbus_manager.h
index 204cd2f8..46325db1 100644
--- a/device/bluetooth/dbus/bluez_dbus_manager.h
+++ b/device/bluetooth/dbus/bluez_dbus_manager.h
@@ -17,7 +17,6 @@
 
 namespace dbus {
 class Bus;
-class ObjectPath;
 class Response;
 class ErrorResponse;
 }  // namespace dbus
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_application_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_gatt_application_service_provider.h
index e6d3437..b42b2fe 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_application_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_application_service_provider.h
@@ -19,8 +19,6 @@
 
 namespace bluez {
 
-class BluetoothLocalGattCharacteristicBlueZ;
-class BluetoothLocalGattDescriptorBlueZ;
 class BluetoothLocalGattServiceBlueZ;
 
 // FakeBluetoothGattApplicationServiceProvider simulates behavior of a local
diff --git a/device/bluetooth/test/bluetooth_test_android.h b/device/bluetooth/test/bluetooth_test_android.h
index c91f0a1..4203b08 100644
--- a/device/bluetooth/test/bluetooth_test_android.h
+++ b/device/bluetooth/test/bluetooth_test_android.h
@@ -12,8 +12,6 @@
 
 namespace device {
 
-class BluetoothAdapterAndroid;
-
 // Android implementation of BluetoothTestBase.
 class BluetoothTestAndroid : public BluetoothTestBase {
  public:
diff --git a/device/bluetooth/test/bluetooth_test_win.h b/device/bluetooth/test/bluetooth_test_win.h
index 71cb042..9649d0f 100644
--- a/device/bluetooth/test/bluetooth_test_win.h
+++ b/device/bluetooth/test/bluetooth_test_win.h
@@ -16,7 +16,6 @@
 
 namespace device {
 class BluetoothAdapterWin;
-class BluetoothRemoteGattCharacteristicWin;
 
 // Windows implementation of BluetoothTestBase.
 class BluetoothTestWin : public BluetoothTestBase,
diff --git a/device/gamepad/gamepad_test_helpers.h b/device/gamepad/gamepad_test_helpers.h
index 4e482dc..14eb1767 100644
--- a/device/gamepad/gamepad_test_helpers.h
+++ b/device/gamepad/gamepad_test_helpers.h
@@ -17,8 +17,6 @@
 
 namespace device {
 
-class GamepadService;
-
 // Data fetcher that returns canned data for the gamepad provider.
 class MockGamepadDataFetcher : public GamepadDataFetcher {
  public:
diff --git a/device/generic_sensor/platform_sensor_ambient_light_mac.h b/device/generic_sensor/platform_sensor_ambient_light_mac.h
index a5665a6..a056b8b 100644
--- a/device/generic_sensor/platform_sensor_ambient_light_mac.h
+++ b/device/generic_sensor/platform_sensor_ambient_light_mac.h
@@ -11,10 +11,6 @@
 #include "base/mac/scoped_ioobject.h"
 #include "device/generic_sensor/platform_sensor.h"
 
-namespace base {
-class SingleThreadTaskRunner;
-}
-
 namespace device {
 
 // Implementation of PlatformSensor for macOS to query the ambient light sensor.
diff --git a/device/generic_sensor/platform_sensor_android.h b/device/generic_sensor/platform_sensor_android.h
index 8b8c8e7..82575e0 100644
--- a/device/generic_sensor/platform_sensor_android.h
+++ b/device/generic_sensor/platform_sensor_android.h
@@ -9,10 +9,6 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/ref_counted.h"
 
-namespace base {
-class SingleThreadTaskRunner;
-}
-
 namespace device {
 
 class PlatformSensorAndroid : public PlatformSensor {
diff --git a/device/hid/hid_service_linux.h b/device/hid/hid_service_linux.h
index fa6cef3..5f8084f8bf 100644
--- a/device/hid/hid_service_linux.h
+++ b/device/hid/hid_service_linux.h
@@ -17,8 +17,6 @@
 
 namespace device {
 
-class HidConnection;
-
 class HidServiceLinux : public HidService {
  public:
   HidServiceLinux(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
diff --git a/device/hid/hid_service_mac.h b/device/hid/hid_service_mac.h
index 00b62cc..f3af539 100644
--- a/device/hid/hid_service_mac.h
+++ b/device/hid/hid_service_mac.h
@@ -23,8 +23,6 @@
 
 namespace device {
 
-class HidConnection;
-
 class HidServiceMac : public HidService {
  public:
   HidServiceMac(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
diff --git a/device/hid/hid_service_win.h b/device/hid/hid_service_win.h
index b2219322..c8814f9 100644
--- a/device/hid/hid_service_win.h
+++ b/device/hid/hid_service_win.h
@@ -23,12 +23,6 @@
 #include "device/hid/hid_device_info.h"
 #include "device/hid/hid_service.h"
 
-namespace base {
-namespace win {
-class MessageWindow;
-}
-}
-
 namespace device {
 
 class HidServiceWin : public HidService, public DeviceMonitorWin::Observer {
diff --git a/device/udev_linux/udev_linux.h b/device/udev_linux/udev_linux.h
index 27057a5..f0467c1 100644
--- a/device/udev_linux/udev_linux.h
+++ b/device/udev_linux/udev_linux.h
@@ -48,7 +48,6 @@
 extern "C" {
 struct udev;
 struct udev_device;
-struct udev_monitor;
 }
 
 namespace device {
diff --git a/device/usb/mojo/device_impl.h b/device/usb/mojo/device_impl.h
index 493a98c..4f78ffcf 100644
--- a/device/usb/mojo/device_impl.h
+++ b/device/usb/mojo/device_impl.h
@@ -20,10 +20,6 @@
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 
-namespace net {
-class IOBuffer;
-}
-
 namespace device {
 namespace usb {
 
diff --git a/device/usb/mojo/device_manager_impl.h b/device/usb/mojo/device_manager_impl.h
index 418aa2d..924840d8 100644
--- a/device/usb/mojo/device_manager_impl.h
+++ b/device/usb/mojo/device_manager_impl.h
@@ -19,15 +19,9 @@
 #include "mojo/public/cpp/bindings/array.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 
-namespace base {
-class SequencedTaskRunner;
-}
-
 namespace device {
 
 class UsbDevice;
-class UsbDeviceFilter;
-class UsbDeviceHandle;
 
 namespace usb {
 
diff --git a/device/usb/usb_device_handle_impl.h b/device/usb/usb_device_handle_impl.h
index 82b0a5e..4d3401a 100644
--- a/device/usb/usb_device_handle_impl.h
+++ b/device/usb/usb_device_handle_impl.h
@@ -38,7 +38,6 @@
 };
 
 class UsbContext;
-struct UsbConfigDescriptor;
 class UsbDeviceImpl;
 
 typedef libusb_device_handle* PlatformUsbDeviceHandle;
diff --git a/device/usb/usb_device_impl.h b/device/usb/usb_device_impl.h
index d5a3ce56..7457501 100644
--- a/device/usb/usb_device_impl.h
+++ b/device/usb/usb_device_impl.h
@@ -30,10 +30,6 @@
 class SequencedTaskRunner;
 }
 
-namespace dbus {
-class FileDescriptor;
-}
-
 namespace device {
 
 class UsbDeviceHandleImpl;
diff --git a/device/usb/usb_device_linux.h b/device/usb/usb_device_linux.h
index 59158786..92a19c3 100644
--- a/device/usb/usb_device_linux.h
+++ b/device/usb/usb_device_linux.h
@@ -23,7 +23,6 @@
 
 namespace device {
 
-struct UsbConfigDescriptor;
 struct UsbDeviceDescriptor;
 
 class UsbDeviceLinux : public UsbDevice {
diff --git a/device/usb/usb_service_impl.h b/device/usb/usb_service_impl.h
index 0868c08..ddca3b5 100644
--- a/device/usb/usb_service_impl.h
+++ b/device/usb/usb_service_impl.h
@@ -27,7 +27,6 @@
 
 namespace base {
 class SequencedTaskRunner;
-class SingleThreadTaskRunner;
 }
 
 namespace device {
diff --git a/device/usb/usb_service_linux.h b/device/usb/usb_service_linux.h
index e50190c..02fcafc 100644
--- a/device/usb/usb_service_linux.h
+++ b/device/usb/usb_service_linux.h
@@ -12,7 +12,6 @@
 
 namespace base {
 class SequencedTaskRunner;
-class SingleThreadTaskRunner;
 }
 
 namespace device {
diff --git a/device/vr/android/gvr/gvr_device_provider.h b/device/vr/android/gvr/gvr_device_provider.h
index cfd903e1..f166d67 100644
--- a/device/vr/android/gvr/gvr_device_provider.h
+++ b/device/vr/android/gvr/gvr_device_provider.h
@@ -16,10 +16,8 @@
 
 namespace device {
 
-class GvrDelegateProvider;
 class GvrDelegate;
 class GvrDevice;
-class VRServiceImpl;
 
 class DEVICE_VR_EXPORT GvrDeviceProvider : public VRDeviceProvider {
  public:
diff --git a/device/vr/vr_device.h b/device/vr/vr_device.h
index 8de5491..c9ac243 100644
--- a/device/vr/vr_device.h
+++ b/device/vr/vr_device.h
@@ -9,14 +9,6 @@
 #include "device/vr/vr_export.h"
 #include "device/vr/vr_service.mojom.h"
 
-namespace blink {
-struct WebHMDSensorState;
-}
-
-namespace ui {
-class BaseWindow;
-}
-
 namespace device {
 
 class VRDisplayImpl;
diff --git a/device/vr/vr_device_provider.h b/device/vr/vr_device_provider.h
index 8983b34..d356673 100644
--- a/device/vr/vr_device_provider.h
+++ b/device/vr/vr_device_provider.h
@@ -10,7 +10,6 @@
 namespace device {
 
 class VRDevice;
-class VRServiceImpl;
 
 class VRDeviceProvider {
  public:
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index f50122b..684291f 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -171,7 +171,7 @@
     deps += [
       "//chromeos",
       "//ui/chromeos",
-      "//ui/display",
+      "//ui/display/manager",
     ]
   }
 
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc
index c419215..70b19aa 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -47,7 +47,7 @@
 #include "ui/display/types/display_snapshot.h"
 
 #if defined(USE_X11)
-#include "ui/display/chromeos/x11/native_display_delegate_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_delegate_x11.h"
 #endif
 
 #if defined(USE_OZONE)
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.h b/extensions/shell/browser/shell_desktop_controller_aura.h
index a45ece0..8a83179 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.h
+++ b/extensions/shell/browser/shell_desktop_controller_aura.h
@@ -17,7 +17,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/power_manager_client.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #endif
 
 namespace aura {
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 9f20f71d..39c7bbe 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1539,6 +1539,14 @@
       'GL_COMPARE_REF_TO_TEXTURE',
     ],
   },
+  'TextureSrgbDecodeExt': {
+    'type': 'GLenum',
+    'is_complete': True,
+    'valid': [
+      'GL_DECODE_EXT',
+      'GL_SKIP_DECODE_EXT',
+    ],
+  },
   'TextureSwizzle': {
     'type': 'GLenum',
     'is_complete': True,
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
index 64a72fc..1775e7d 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -96,6 +96,7 @@
     uint32_t value);
 static std::string GetStringTextureSizedTextureFilterableInternalFormat(
     uint32_t value);
+static std::string GetStringTextureSrgbDecodeExt(uint32_t value);
 static std::string GetStringTextureStencilRenderableInternalFormat(
     uint32_t value);
 static std::string GetStringTextureSwizzle(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 9d6b4a5..5a6325c 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -4828,6 +4828,15 @@
                                            arraysize(string_table), value);
 }
 
+std::string GLES2Util::GetStringTextureSrgbDecodeExt(uint32_t value) {
+  static const EnumToString string_table[] = {
+      {GL_DECODE_EXT, "GL_DECODE_EXT"},
+      {GL_SKIP_DECODE_EXT, "GL_SKIP_DECODE_EXT"},
+  };
+  return GLES2Util::GetQualifiedEnumString(string_table,
+                                           arraysize(string_table), value);
+}
+
 std::string GLES2Util::GetStringTextureStencilRenderableInternalFormat(
     uint32_t value) {
   static const EnumToString string_table[] = {
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index cd87ab2..ba0f616d 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -619,6 +619,12 @@
     }
   }
 
+  // The extension GL_EXT_texture_sRGB_decode is the same on desktop and GLES.
+  if (extensions.Contains("GL_EXT_texture_sRGB_decode") && !IsWebGLContext()) {
+    AddExtensionString("GL_EXT_texture_sRGB_decode");
+    validators_.texture_parameter.AddValue(GL_TEXTURE_SRGB_DECODE_EXT);
+  }
+
   // On desktop, GL_EXT_texture_sRGB is required regardless of GL version,
   // since the sRGB formats in OpenGL 3.0 Core do not support S3TC.
   // TODO(kainino): Support GL_EXT_texture_compression_s3tc_srgb once ratified.
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index 1223a22..2be3bab 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -344,6 +344,12 @@
 ValueValidator<GLenum> texture_parameter;
 ValueValidator<GLenum> texture_sized_color_renderable_internal_format;
 ValueValidator<GLenum> texture_sized_texture_filterable_internal_format;
+class TextureSrgbDecodeExtValidator {
+ public:
+  bool IsValid(const GLenum value) const;
+};
+TextureSrgbDecodeExtValidator texture_srgb_decode_ext;
+
 ValueValidator<GLenum> texture_stencil_renderable_internal_format;
 class TextureSwizzleValidator {
  public:
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 632eaeed..280f736 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -1216,6 +1216,16 @@
         GL_RGB_YCBCR_420V_CHROMIUM,
 };
 
+bool Validators::TextureSrgbDecodeExtValidator::IsValid(
+    const GLenum value) const {
+  switch (value) {
+    case GL_DECODE_EXT:
+    case GL_SKIP_DECODE_EXT:
+      return true;
+  }
+  return false;
+};
+
 static const GLenum
     valid_texture_stencil_renderable_internal_format_table_es3[] = {
         GL_STENCIL_INDEX8, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8,
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index b02272b..8522da8 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -1353,6 +1353,11 @@
       }
       swizzle_a_ = param;
       break;
+    case GL_TEXTURE_SRGB_DECODE_EXT:
+      if (!feature_info->validators()->texture_srgb_decode_ext.IsValid(param)) {
+        return GL_INVALID_ENUM;
+      }
+      break;
     case GL_TEXTURE_IMMUTABLE_FORMAT:
     case GL_TEXTURE_IMMUTABLE_LEVELS:
       return GL_INVALID_ENUM;
diff --git a/ios/chrome/app/OWNERS b/ios/chrome/app/OWNERS
new file mode 100644
index 0000000..9e2503a
--- /dev/null
+++ b/ios/chrome/app/OWNERS
@@ -0,0 +1,2 @@
+marq@chromium.org
+rohitrao@chromium.org
diff --git a/ios/chrome/app/spotlight/OWNERS b/ios/chrome/app/spotlight/OWNERS
new file mode 100644
index 0000000..3ebff38d
--- /dev/null
+++ b/ios/chrome/app/spotlight/OWNERS
@@ -0,0 +1 @@
+olivierrobin@chromium.org
diff --git a/ios/chrome/browser/OWNERS b/ios/chrome/browser/OWNERS
index 511eb4c7..3591f43 100644
--- a/ios/chrome/browser/OWNERS
+++ b/ios/chrome/browser/OWNERS
@@ -2,7 +2,3 @@
 per-file ios_chrome_io_thread*=mmenke@chromium.org
 per-file ios_chrome_io_thread*=rch@chromium.org
 per-file ios_chrome_io_thread*=rsleevi@chromium.org
-
-# These are for the common case of adding or renaming files. If you're doing
-# structural changes, please get a review from an OWNER.
-per-file BUILD.gn=*
diff --git a/ios/chrome/browser/browser_state/OWNERS b/ios/chrome/browser/browser_state/OWNERS
new file mode 100644
index 0000000..c5cd5cb
--- /dev/null
+++ b/ios/chrome/browser/browser_state/OWNERS
@@ -0,0 +1 @@
+sdefresne@chromium.org
diff --git a/ios/chrome/browser/context_menu/OWNERS b/ios/chrome/browser/context_menu/OWNERS
new file mode 100644
index 0000000..bf1620f
--- /dev/null
+++ b/ios/chrome/browser/context_menu/OWNERS
@@ -0,0 +1 @@
+noyau@chromium.org
diff --git a/ios/chrome/browser/first_run/OWNERS b/ios/chrome/browser/first_run/OWNERS
index 840bb46..f5e9e65 100644
--- a/ios/chrome/browser/first_run/OWNERS
+++ b/ios/chrome/browser/first_run/OWNERS
@@ -1,2 +1,2 @@
+bzanotti@chromium.org
 msarda@chromium.org
-pkl@chromium.org
diff --git a/ios/chrome/browser/infobars/OWNERS b/ios/chrome/browser/infobars/OWNERS
index 5bca21e..d2e1add 100644
--- a/ios/chrome/browser/infobars/OWNERS
+++ b/ios/chrome/browser/infobars/OWNERS
@@ -1,2 +1 @@
-droger@chromium.org
 jif@chromium.org
diff --git a/ios/chrome/browser/ios_chrome_io_thread.mm b/ios/chrome/browser/ios_chrome_io_thread.mm
index 72677ac..4338187 100644
--- a/ios/chrome/browser/ios_chrome_io_thread.mm
+++ b/ios/chrome/browser/ios_chrome_io_thread.mm
@@ -396,7 +396,6 @@
   }
 
   params_.ignore_certificate_errors = false;
-  params_.enable_quic_port_selection = false;
   params_.enable_user_alternate_protocol_ports = false;
 
   std::string quic_user_agent_id = ::GetChannelString();
diff --git a/ios/chrome/browser/itunes_links/OWNERS b/ios/chrome/browser/itunes_links/OWNERS
index 4d9d202..d2e1add 100644
--- a/ios/chrome/browser/itunes_links/OWNERS
+++ b/ios/chrome/browser/itunes_links/OWNERS
@@ -1,3 +1 @@
-jif@google.com
-
-per-file *_kiftest.*=baxley@google.com
+jif@chromium.org
diff --git a/ios/chrome/browser/native_app_launcher/OWNERS b/ios/chrome/browser/native_app_launcher/OWNERS
new file mode 100644
index 0000000..077a06e
--- /dev/null
+++ b/ios/chrome/browser/native_app_launcher/OWNERS
@@ -0,0 +1,2 @@
+lpromero@chromium.org
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/omaha/OWNERS b/ios/chrome/browser/omaha/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/omaha/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/passwords/OWNERS b/ios/chrome/browser/passwords/OWNERS
index de01c0e..349a187 100644
--- a/ios/chrome/browser/passwords/OWNERS
+++ b/ios/chrome/browser/passwords/OWNERS
@@ -1 +1,2 @@
 vabr@chromium.org
+melandory@chromium.org
diff --git a/ios/chrome/browser/payments/OWNERS b/ios/chrome/browser/payments/OWNERS
new file mode 100644
index 0000000..ca512d20e
--- /dev/null
+++ b/ios/chrome/browser/payments/OWNERS
@@ -0,0 +1 @@
+jdonnelly@chromium.org
diff --git a/ios/chrome/browser/sessions/OWNERS b/ios/chrome/browser/sessions/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/sessions/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/signin/OWNERS b/ios/chrome/browser/signin/OWNERS
index 3fa720f..f5e9e65 100644
--- a/ios/chrome/browser/signin/OWNERS
+++ b/ios/chrome/browser/signin/OWNERS
@@ -1,3 +1,2 @@
 bzanotti@chromium.org
 msarda@chromium.org
-pkl@chromium.org
diff --git a/ios/chrome/browser/tabs/OWNERS b/ios/chrome/browser/tabs/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/tabs/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/translate/OWNERS b/ios/chrome/browser/translate/OWNERS
index bb5c3afc..ca1bcb6a 100644
--- a/ios/chrome/browser/translate/OWNERS
+++ b/ios/chrome/browser/translate/OWNERS
@@ -1 +1,2 @@
 file://components/translate/OWNERS
+droger@chromium.org
diff --git a/ios/chrome/browser/ui/OWNERS b/ios/chrome/browser/ui/OWNERS
index 48b6b01..7e77d32 100644
--- a/ios/chrome/browser/ui/OWNERS
+++ b/ios/chrome/browser/ui/OWNERS
@@ -1,3 +1,5 @@
+# Please prefer to use more specific OWNERS where possible. Don't
+# be reluctant to re-delegate to another OWNER, when a change seems
+# like it needs extra review, or is related to the Omnibox.
 marq@chromium.org
-pkl@chromium.org
 rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/activity_services/OWNERS b/ios/chrome/browser/ui/activity_services/OWNERS
new file mode 100644
index 0000000..d2e1add
--- /dev/null
+++ b/ios/chrome/browser/ui/activity_services/OWNERS
@@ -0,0 +1 @@
+jif@chromium.org
diff --git a/ios/chrome/browser/ui/alert_coordinator/OWNERS b/ios/chrome/browser/ui/alert_coordinator/OWNERS
index 833083f6..936c0336 100644
--- a/ios/chrome/browser/ui/alert_coordinator/OWNERS
+++ b/ios/chrome/browser/ui/alert_coordinator/OWNERS
@@ -1,2 +1 @@
-gambard@chromium.org
 jyquinn@chromium.org
diff --git a/ios/chrome/browser/ui/authentication/OWNERS b/ios/chrome/browser/ui/authentication/OWNERS
new file mode 100644
index 0000000..f5e9e65
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/OWNERS
@@ -0,0 +1,2 @@
+bzanotti@chromium.org
+msarda@chromium.org
diff --git a/ios/chrome/browser/ui/bookmarks/OWNERS b/ios/chrome/browser/ui/bookmarks/OWNERS
new file mode 100644
index 0000000..b33d408
--- /dev/null
+++ b/ios/chrome/browser/ui/bookmarks/OWNERS
@@ -0,0 +1,2 @@
+noyau@chromium.org
+lpromero@chromium.org
diff --git a/ios/chrome/browser/ui/collection_view/OWNERS b/ios/chrome/browser/ui/collection_view/OWNERS
new file mode 100644
index 0000000..077a06e
--- /dev/null
+++ b/ios/chrome/browser/ui/collection_view/OWNERS
@@ -0,0 +1,2 @@
+lpromero@chromium.org
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/colors/OWNERS b/ios/chrome/browser/ui/colors/OWNERS
new file mode 100644
index 0000000..4bb62eb
--- /dev/null
+++ b/ios/chrome/browser/ui/colors/OWNERS
@@ -0,0 +1 @@
+lpromero@chromium.org
diff --git a/ios/chrome/browser/ui/contextual_search/OWNERS b/ios/chrome/browser/ui/contextual_search/OWNERS
new file mode 100644
index 0000000..3141303
--- /dev/null
+++ b/ios/chrome/browser/ui/contextual_search/OWNERS
@@ -0,0 +1,2 @@
+marq@chromium.org
+olivierrobin@chromium.org
diff --git a/ios/chrome/browser/ui/dialogs/OWNERS b/ios/chrome/browser/ui/dialogs/OWNERS
index 6eb89c5..48efb49e 100644
--- a/ios/chrome/browser/ui/dialogs/OWNERS
+++ b/ios/chrome/browser/ui/dialogs/OWNERS
@@ -1,2 +1 @@
 kkhorimoto@chromium.org
-michaeldo@chromium.org
diff --git a/ios/chrome/browser/ui/fancy_ui/OWNERS b/ios/chrome/browser/ui/fancy_ui/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/ui/fancy_ui/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/find_bar/OWNERS b/ios/chrome/browser/ui/find_bar/OWNERS
new file mode 100644
index 0000000..ff2123f
--- /dev/null
+++ b/ios/chrome/browser/ui/find_bar/OWNERS
@@ -0,0 +1,2 @@
+justincohen@chromium.org
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/first_run/OWNERS b/ios/chrome/browser/ui/first_run/OWNERS
new file mode 100644
index 0000000..3281fe5b
--- /dev/null
+++ b/ios/chrome/browser/ui/first_run/OWNERS
@@ -0,0 +1,2 @@
+bzanotti@chromium.org
+kkhorimoto@chromium.org
diff --git a/ios/chrome/browser/ui/history/OWNERS b/ios/chrome/browser/ui/history/OWNERS
new file mode 100644
index 0000000..936c0336
--- /dev/null
+++ b/ios/chrome/browser/ui/history/OWNERS
@@ -0,0 +1 @@
+jyquinn@chromium.org
diff --git a/ios/chrome/browser/ui/infobars/OWNERS b/ios/chrome/browser/ui/infobars/OWNERS
new file mode 100644
index 0000000..d2e1add
--- /dev/null
+++ b/ios/chrome/browser/ui/infobars/OWNERS
@@ -0,0 +1 @@
+jif@chromium.org
diff --git a/ios/chrome/browser/ui/main/OWNERS b/ios/chrome/browser/ui/main/OWNERS
new file mode 100644
index 0000000..f49ed38
--- /dev/null
+++ b/ios/chrome/browser/ui/main/OWNERS
@@ -0,0 +1 @@
+marq@chromium.org
diff --git a/ios/chrome/browser/ui/no_tabs/OWNERS b/ios/chrome/browser/ui/no_tabs/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/ui/no_tabs/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/ntp/OWNERS b/ios/chrome/browser/ui/ntp/OWNERS
new file mode 100644
index 0000000..3306281
--- /dev/null
+++ b/ios/chrome/browser/ui/ntp/OWNERS
@@ -0,0 +1,2 @@
+rohitrao@chromium.org
+justincohen@chromium.org
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS b/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS
new file mode 100644
index 0000000..d2e1add
--- /dev/null
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS
@@ -0,0 +1 @@
+jif@chromium.org
diff --git a/ios/chrome/browser/ui/omnibox/OWNERS b/ios/chrome/browser/ui/omnibox/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/ui/omnibox/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/overscroll_actions/OWNERS b/ios/chrome/browser/ui/overscroll_actions/OWNERS
new file mode 100644
index 0000000..d2e1add
--- /dev/null
+++ b/ios/chrome/browser/ui/overscroll_actions/OWNERS
@@ -0,0 +1 @@
+jif@chromium.org
diff --git a/ios/chrome/browser/ui/product_tour/OWNERS b/ios/chrome/browser/ui/product_tour/OWNERS
new file mode 100644
index 0000000..48efb49e
--- /dev/null
+++ b/ios/chrome/browser/ui/product_tour/OWNERS
@@ -0,0 +1 @@
+kkhorimoto@chromium.org
diff --git a/ios/chrome/browser/ui/promos/OWNERS b/ios/chrome/browser/ui/promos/OWNERS
new file mode 100644
index 0000000..f49ed38
--- /dev/null
+++ b/ios/chrome/browser/ui/promos/OWNERS
@@ -0,0 +1 @@
+marq@chromium.org
diff --git a/ios/chrome/browser/ui/qr_scanner/OWNERS b/ios/chrome/browser/ui/qr_scanner/OWNERS
new file mode 100644
index 0000000..d2e1add
--- /dev/null
+++ b/ios/chrome/browser/ui/qr_scanner/OWNERS
@@ -0,0 +1 @@
+jif@chromium.org
diff --git a/ios/chrome/browser/ui/reader_mode/OWNERS b/ios/chrome/browser/ui/reader_mode/OWNERS
new file mode 100644
index 0000000..bf1620f
--- /dev/null
+++ b/ios/chrome/browser/ui/reader_mode/OWNERS
@@ -0,0 +1 @@
+noyau@chromium.org
diff --git a/ios/chrome/browser/ui/reading_list/OWNERS b/ios/chrome/browser/ui/reading_list/OWNERS
new file mode 100644
index 0000000..c6815f7
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/OWNERS
@@ -0,0 +1,2 @@
+noyau@chromium.org
+olivierrobin@chromium.org
diff --git a/ios/chrome/browser/ui/sad_tab/OWNERS b/ios/chrome/browser/ui/sad_tab/OWNERS
new file mode 100644
index 0000000..48efb49e
--- /dev/null
+++ b/ios/chrome/browser/ui/sad_tab/OWNERS
@@ -0,0 +1 @@
+kkhorimoto@chromium.org
diff --git a/ios/chrome/browser/ui/settings/OWNERS b/ios/chrome/browser/ui/settings/OWNERS
new file mode 100644
index 0000000..b79a55ef
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/OWNERS
@@ -0,0 +1,3 @@
+jyquinn@chromium.org
+lpromero@chromium.org
+sdefresne@chromium.org
diff --git a/ios/chrome/browser/ui/side_swipe/OWNERS b/ios/chrome/browser/ui/side_swipe/OWNERS
new file mode 100644
index 0000000..330cb31
--- /dev/null
+++ b/ios/chrome/browser/ui/side_swipe/OWNERS
@@ -0,0 +1 @@
+justincohen@chromium.org
diff --git a/ios/chrome/browser/ui/stack_view/OWNERS b/ios/chrome/browser/ui/stack_view/OWNERS
new file mode 100644
index 0000000..48efb49e
--- /dev/null
+++ b/ios/chrome/browser/ui/stack_view/OWNERS
@@ -0,0 +1 @@
+kkhorimoto@chromium.org
diff --git a/ios/chrome/browser/ui/sync/OWNERS b/ios/chrome/browser/ui/sync/OWNERS
new file mode 100644
index 0000000..f5e9e65
--- /dev/null
+++ b/ios/chrome/browser/ui/sync/OWNERS
@@ -0,0 +1,2 @@
+bzanotti@chromium.org
+msarda@chromium.org
diff --git a/ios/chrome/browser/ui/tab_switcher/OWNERS b/ios/chrome/browser/ui/tab_switcher/OWNERS
new file mode 100644
index 0000000..d2e1add
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/OWNERS
@@ -0,0 +1 @@
+jif@chromium.org
diff --git a/ios/chrome/browser/ui/tabs/OWNERS b/ios/chrome/browser/ui/tabs/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/ui/tabs/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/toolbar/OWNERS b/ios/chrome/browser/ui/toolbar/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/tools_menu/OWNERS b/ios/chrome/browser/ui/tools_menu/OWNERS
new file mode 100644
index 0000000..40a68c7
--- /dev/null
+++ b/ios/chrome/browser/ui/tools_menu/OWNERS
@@ -0,0 +1 @@
+rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/util/OWNERS b/ios/chrome/browser/ui/util/OWNERS
new file mode 100644
index 0000000..1f7a7b8
--- /dev/null
+++ b/ios/chrome/browser/ui/util/OWNERS
@@ -0,0 +1,2 @@
+kkhorimoto@chromium.org
+marq@chromium.org
diff --git a/ios/chrome/browser/ui/webui/OWNERS b/ios/chrome/browser/ui/webui/OWNERS
new file mode 100644
index 0000000..936c0336
--- /dev/null
+++ b/ios/chrome/browser/ui/webui/OWNERS
@@ -0,0 +1 @@
+jyquinn@chromium.org
diff --git a/ios/chrome/browser/web/OWNERS b/ios/chrome/browser/web/OWNERS
index ea2dcf4..5a2923e 100644
--- a/ios/chrome/browser/web/OWNERS
+++ b/ios/chrome/browser/web/OWNERS
@@ -1 +1,2 @@
 eugenebut@chromium.org
+# This directory needs to be carved into subdirs with more specific OWNERS.
diff --git a/ios/chrome/common/physical_web/physical_web_scanner.mm b/ios/chrome/common/physical_web/physical_web_scanner.mm
index 424d46e1..ce0fe0a9 100644
--- a/ios/chrome/common/physical_web/physical_web_scanner.mm
+++ b/ios/chrome/common/physical_web/physical_web_scanner.mm
@@ -161,9 +161,15 @@
   }
   pendingStart_ = NO;
   started_ = NO;
+  if (onLostDetectionEnabled_ && [devices_ count]) {
+    [delegate_ scannerUpdatedDevices:self];
+  }
 }
 
 - (NSArray*)devices {
+  if (![self bluetoothEnabled]) {
+    return [NSArray array];
+  }
   return [devices_ sortedArrayUsingComparator:^(id obj1, id obj2) {
     PhysicalWebDevice* device1 = obj1;
     PhysicalWebDevice* device2 = obj2;
@@ -266,11 +272,6 @@
 }
 
 - (void)reallyStop {
-  if (updateTimer_.get()) {
-    [updateTimer_ invalidate];
-    updateTimer_.reset();
-  }
-
   [centralManager_ stopScan];
 }
 
@@ -321,12 +322,19 @@
   // For unknown reasons, when scanning for longer periods (on the order of
   // minutes), the scanner is less reliable at detecting all nearby URLs. As a
   // workaround, we restart the scanner each time we check for lost URLs.
-  NSArray* serviceUUIDs = @[
-    [CBUUID UUIDWithString:kUriBeaconServiceUUID],
-    [CBUUID UUIDWithString:kEddystoneBeaconServiceUUID]
-  ];
-  [centralManager_ stopScan];
-  [centralManager_ scanForPeripheralsWithServices:serviceUUIDs options:nil];
+  if (!pendingStart_) {
+    NSArray* serviceUUIDs = @[
+      [CBUUID UUIDWithString:kUriBeaconServiceUUID],
+      [CBUUID UUIDWithString:kEddystoneBeaconServiceUUID]
+    ];
+    [centralManager_ stopScan];
+    [centralManager_ scanForPeripheralsWithServices:serviceUUIDs options:nil];
+  }
+
+  if (updateTimer_.get() && pendingStart_ && [devices_ count] == 0) {
+    [updateTimer_ invalidate];
+    updateTimer_.reset();
+  }
 }
 
 #pragma mark -
@@ -339,7 +347,6 @@
   } else {
     if (started_ && !pendingStart_) {
       pendingStart_ = YES;
-      [self reallyStop];
     }
   }
   [delegate_ scannerBluetoothStatusUpdated:self];
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc
index a654c1204..424450ea 100644
--- a/media/base/pipeline_impl_unittest.cc
+++ b/media/base/pipeline_impl_unittest.cc
@@ -171,8 +171,6 @@
     EXPECT_CALL(*renderer_, Initialize(_, _, _))
         .WillOnce(
             DoAll(SaveArg<1>(&renderer_client_), PostCallback<2>(PIPELINE_OK)));
-    EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(audio_stream()));
-    EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(video_stream()));
   }
 
   void AddTextStream() {
@@ -910,9 +908,6 @@
     streams.push_back(video_stream());
     SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
 
-    EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(true));
-    EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(true));
-
     if (state == kInitRenderer) {
       if (stop_or_error == kStop) {
         EXPECT_CALL(*renderer_, Initialize(_, _, _))
diff --git a/media/base/renderer.h b/media/base/renderer.h
index 18e1588..fe3a49a 100644
--- a/media/base/renderer.h
+++ b/media/base/renderer.h
@@ -57,12 +57,6 @@
   // Returns the current media time.
   virtual base::TimeDelta GetMediaTime() = 0;
 
-  // Returns whether |this| renders audio.
-  virtual bool HasAudio() = 0;
-
-  // Returns whether |this| renders video.
-  virtual bool HasVideo() = 0;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(Renderer);
 };
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 2abb0e64..08b948e 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -341,6 +341,7 @@
       "//media",
       "//testing/gtest",
       "//ui/base",
+      "//ui/display/manager",
       "//ui/gfx",
       "//ui/gfx:test_support",
       "//ui/gfx/geometry",
@@ -408,6 +409,7 @@
     ]
     deps = [
       ":gpu",
+      "//base/test:test_support",
       "//gpu:test_support",
       "//media/base/android",
       "//testing/gmock",
diff --git a/media/gpu/DEPS b/media/gpu/DEPS
index bd5343d..0f316510 100644
--- a/media/gpu/DEPS
+++ b/media/gpu/DEPS
@@ -6,7 +6,7 @@
   "+third_party/v4l-utils",
   "+third_party/webrtc/common_video",
   "+third_party/webrtc/system_wrappers",
-  "+ui/display/chromeos",
+  "+ui/display/manager/chromeos",
   "+ui/display/types",
   "+ui/platform_window",
 
diff --git a/media/gpu/avda_codec_allocator.cc b/media/gpu/avda_codec_allocator.cc
index c947f40..0c1239d 100644
--- a/media/gpu/avda_codec_allocator.cc
+++ b/media/gpu/avda_codec_allocator.cc
@@ -49,9 +49,6 @@
 CodecConfig::CodecConfig() {}
 CodecConfig::~CodecConfig() {}
 
-AVDACodecAllocator::TestInformation::TestInformation() {}
-AVDACodecAllocator::TestInformation::~TestInformation() {}
-
 AVDACodecAllocator::HangDetector::HangDetector(base::TickClock* tick_clock)
     : tick_clock_(tick_clock) {}
 
@@ -120,6 +117,13 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   clients_.erase(client);
+  if (!clients_.empty()) {
+    // If we aren't stopping, then signal immediately.
+    if (stop_event_for_testing_)
+      stop_event_for_testing_->Signal();
+    return;
+  }
+
   // Post a task to stop the thread through the thread's task runner and back
   // to this thread. This ensures that all pending tasks are run first. If the
   // thread is hung we don't post a task to avoid leaking an unbounded number
@@ -128,23 +132,15 @@
   // guaranteed to not run StopThreadTask() when the thread is hung because if
   // an AVDA queues tasks after DoNothing(), the StopThreadTask() reply will
   // be canceled by invalidating its weak pointer.
-  base::WaitableEvent* event =
-      (test_info_ ? test_info_->stop_event_.get() : nullptr);
-  if (!clients_.empty()) {
-    // If we aren't stopping, then signal immediately.
-    if (event)
-      event->Signal();
-    return;
-  }
-
   for (size_t i = 0; i < threads_.size(); i++) {
     if (threads_[i]->thread.IsRunning() &&
         !threads_[i]->hang_detector.IsThreadLikelyHung()) {
       threads_[i]->thread.task_runner()->PostTaskAndReply(
           FROM_HERE, base::Bind(&base::DoNothing),
-          base::Bind(&AVDACodecAllocator::StopThreadTask,
-                     weak_this_factory_.GetWeakPtr(), i,
-                     (i == TaskType::AUTO_CODEC ? event : nullptr)));
+          base::Bind(
+              &AVDACodecAllocator::StopThreadTask,
+              weak_this_factory_.GetWeakPtr(), i,
+              (i == TaskType::AUTO_CODEC ? stop_event_for_testing_ : nullptr)));
     }
   }
 }
@@ -370,21 +366,17 @@
   return threads_[task_type]->thread;
 }
 
-AVDACodecAllocator::AVDACodecAllocator(TestInformation* test_info)
-    : test_info_(test_info), weak_this_factory_(this) {
-  // If we're not provided with one, use real time.
-  // Note that we'll leak this, but that's okay since we're a singleton.
-  base::TickClock* tick_clock = nullptr;
-  if (!test_info_)
-    tick_clock = new base::DefaultTickClock();
-  else
-    tick_clock = test_info_->tick_clock_.get();
+AVDACodecAllocator::AVDACodecAllocator(base::TickClock* tick_clock,
+                                       base::WaitableEvent* stop_event)
+    : stop_event_for_testing_(stop_event), weak_this_factory_(this) {
+  // We leak the clock we create, but that's okay because we're a singleton.
+  auto clock = tick_clock ? tick_clock : new base::DefaultTickClock();
 
   // Create threads with names / indices that match up with TaskType.
   DCHECK_EQ(threads_.size(), TaskType::AUTO_CODEC);
-  threads_.push_back(new ThreadAndHangDetector("AVDAAutoThread", tick_clock));
+  threads_.push_back(new ThreadAndHangDetector("AVDAAutoThread", clock));
   DCHECK_EQ(threads_.size(), TaskType::SW_CODEC);
-  threads_.push_back(new ThreadAndHangDetector("AVDASWThread", tick_clock));
+  threads_.push_back(new ThreadAndHangDetector("AVDASWThread", clock));
 }
 
 AVDACodecAllocator::~AVDACodecAllocator() {
diff --git a/media/gpu/avda_codec_allocator.h b/media/gpu/avda_codec_allocator.h
index 796efbbe..4553ebf 100644
--- a/media/gpu/avda_codec_allocator.h
+++ b/media/gpu/avda_codec_allocator.h
@@ -177,18 +177,6 @@
   friend struct base::DefaultLazyInstanceTraits<AVDACodecAllocator>;
   friend class AVDACodecAllocatorTest;
 
-  // Things that our unit test needs.  We guarantee that we'll access none of
-  // it, from any thread, after we are destructed.
-  struct TestInformation {
-    TestInformation();
-    ~TestInformation();
-    // Optional clock source.
-    std::unique_ptr<base::TickClock> tick_clock_;
-
-    // Optional event that we'll signal when stopping the AUTO_CODEC thread.
-    std::unique_ptr<base::WaitableEvent> stop_event_;
-  };
-
   struct OwnerRecord {
     AVDACodecAllocatorClient* owner = nullptr;
     AVDACodecAllocatorClient* waiter = nullptr;
@@ -220,8 +208,9 @@
     HangDetector hang_detector;
   };
 
-  // |test_info| is owned by the unit test.
-  AVDACodecAllocator(TestInformation* test_info = nullptr);
+  // |tick_clock| and |stop_event| are for tests only.
+  AVDACodecAllocator(base::TickClock* tick_clock = nullptr,
+                     base::WaitableEvent* stop_event = nullptr);
   ~AVDACodecAllocator();
 
   void OnMediaCodecAndSurfaceReleased(int surface_id);
@@ -245,8 +234,7 @@
 
   base::ThreadChecker thread_checker_;
 
-  // Optional, used for unit testing.  We do not own this.
-  TestInformation* test_info_;
+  base::WaitableEvent* stop_event_for_testing_;
 
   // For canceling pending StopThreadTask()s.
   base::WeakPtrFactory<AVDACodecAllocator> weak_this_factory_;
diff --git a/media/gpu/avda_codec_allocator_unittest.cc b/media/gpu/avda_codec_allocator_unittest.cc
index 03c8284..5d4d1be1 100644
--- a/media/gpu/avda_codec_allocator_unittest.cc
+++ b/media/gpu/avda_codec_allocator_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "base/test/simple_test_tick_clock.h"
 #include "base/time/tick_clock.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -41,29 +42,6 @@
 }
 }
 
-class MockTickClock : public base::TickClock {
- public:
-  MockTickClock() {
-    // Don't start with the null time.
-    Advance(1000);
-  }
-  ~MockTickClock() override{};
-  base::TimeTicks NowTicks() override {
-    base::AutoLock auto_lock(lock_);
-    return now_;
-  }
-
-  // Handy utility.
-  void Advance(int msec) {
-    base::AutoLock auto_lock(lock_);
-    now_ += base::TimeDelta::FromMilliseconds(msec);
-  }
-
- private:
-  base::Lock lock_;
-  base::TimeTicks now_;
-};
-
 class MockClient : public AVDACodecAllocatorClient {
  public:
   MOCK_METHOD1(OnSurfaceAvailable, void(bool success));
@@ -79,7 +57,14 @@
 
 class AVDACodecAllocatorTest : public testing::Test {
  public:
-  AVDACodecAllocatorTest() : allocator_thread_("AllocatorThread") {}
+  AVDACodecAllocatorTest()
+      : allocator_thread_("AllocatorThread"),
+        stop_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                    base::WaitableEvent::InitialState::NOT_SIGNALED) {
+    // Don't start the clock at null.
+    tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
+  }
+
   ~AVDACodecAllocatorTest() override {}
 
  protected:
@@ -88,34 +73,14 @@
     // main thread.
     ASSERT_TRUE(allocator_thread_.Start());
 
-    // AVDACodecAllocator likes to post tasks to the current thread.
-
-    test_information_.reset(new AVDACodecAllocator::TestInformation());
-    test_information_->tick_clock_.reset(new MockTickClock());
-    test_information_->stop_event_.reset(new base::WaitableEvent(
-        base::WaitableEvent::ResetPolicy::AUTOMATIC,
-        base::WaitableEvent::InitialState::NOT_SIGNALED));
-
-    // Allocate the allocator on the appropriate thread.
+    // Create the first allocator on the allocator thread.
     allocator_ = PostAndWait(
         FROM_HERE, base::Bind(
-                       [](AVDACodecAllocator::TestInformation* test_info) {
-                         return new AVDACodecAllocator(test_info);
+                       [](base::TickClock* clock, base::WaitableEvent* event) {
+                         return new AVDACodecAllocator(clock, event);
                        },
-                       test_information_.get()));
-    allocator2_ = new AVDACodecAllocator(test_information_.get());
-
-    // All threads should be stopped
-    ASSERT_FALSE(IsThreadRunning(TaskType::AUTO_CODEC));
-    ASSERT_FALSE(IsThreadRunning(TaskType::SW_CODEC));
-
-    // Register an AVDA instance to start the allocator's threads.
-    ASSERT_TRUE(StartThread(avda1_));
-
-    // Assert that at least the AUTO_CODEC thread is started.  The other might
-    // not be.
-    ASSERT_TRUE(IsThreadRunning(TaskType::AUTO_CODEC));
-    ASSERT_EQ(TaskType::AUTO_CODEC, TaskTypeForAllocation());
+                       &tick_clock_, &stop_event_));
+    allocator2_ = new AVDACodecAllocator();
   }
 
   void TearDown() override {
@@ -157,7 +122,7 @@
                                allocator_, avda));
     // Note that we don't do this on the allocator thread, since that's the
     // thread that will signal it.
-    test_information_->stop_event_->Wait();
+    stop_event_.Wait();
   }
 
   // Return the running state of |task_type|, doing the necessary thread hops.
@@ -202,8 +167,9 @@
 
   base::Thread allocator_thread_;
 
-  // Test info that we provide to the codec allocator.
-  std::unique_ptr<AVDACodecAllocator::TestInformation> test_information_;
+  // The test params for |allocator_|.
+  base::SimpleTestTickClock tick_clock_;
+  base::WaitableEvent stop_event_;
 
   // Allocators that we own. The first is intialized to be used on the allocator
   // thread and the second one is initialized on the test thread. Each test
@@ -218,29 +184,26 @@
   NiceMock<MockClient>* avda3_ = &client3_;
 };
 
-TEST_F(AVDACodecAllocatorTest, TestMultiInstance) {
-  // Add an avda instance.  This one must succeed immediately, since the last
-  // one is still running.
-  ASSERT_TRUE(StartThread(avda2_));
-
-  // Stop the original avda instance.
-  StopThread(avda1_);
-
-  // Verify that the AUTO_CODEC thread is still running.
-  ASSERT_TRUE(IsThreadRunning(TaskType::AUTO_CODEC));
-  ASSERT_EQ(TaskType::AUTO_CODEC, TaskTypeForAllocation());
-
-  // Remove the second instance and wait for it to stop.  Remember that it
-  // stops after messages have been posted to the thread, so we don't know
-  // how long it will take.
-  StopThread(avda2_);
-
-  // Verify that the threads have stopped.
+TEST_F(AVDACodecAllocatorTest, ThreadsStartWhenClientsStart) {
   ASSERT_FALSE(IsThreadRunning(TaskType::AUTO_CODEC));
   ASSERT_FALSE(IsThreadRunning(TaskType::SW_CODEC));
+  ASSERT_TRUE(StartThread(avda1_));
+  // Assert that the AUTO_CODEC thread is started. The other might not be.
+  ASSERT_TRUE(IsThreadRunning(TaskType::AUTO_CODEC));
+}
+
+TEST_F(AVDACodecAllocatorTest, ThreadsStopAfterAllClientsStop) {
+  StartThread(avda1_);
+  StartThread(avda2_);
+  StopThread(avda1_);
+  ASSERT_TRUE(IsThreadRunning(TaskType::AUTO_CODEC));
+  StopThread(avda2_);
+  ASSERT_FALSE(IsThreadRunning(TaskType::AUTO_CODEC));
+  // Note the SW_CODEC thread might still be running.
 }
 
 TEST_F(AVDACodecAllocatorTest, TestHangThread) {
+  StartThread(avda1_);
   ASSERT_EQ(TaskType::AUTO_CODEC, TaskTypeForAllocation());
 
   // Hang the AUTO_CODEC thread.
@@ -257,8 +220,7 @@
   about_to_wait_event.Wait();
 
   // Verify that we've failed over after a long time has passed.
-  static_cast<MockTickClock*>(test_information_->tick_clock_.get())
-      ->Advance(1000);
+  tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
   // Note that this should return the SW codec task type even if that thread
   // failed to start.  TaskRunnerFor() will return the current thread in that
   // case too.
diff --git a/media/gpu/rendering_helper.cc b/media/gpu/rendering_helper.cc
index ecf79806..bcb1d0fe 100644
--- a/media/gpu/rendering_helper.cc
+++ b/media/gpu/rendering_helper.cc
@@ -47,7 +47,7 @@
 
 #if defined(USE_OZONE)
 #if defined(OS_CHROMEOS)
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/types/native_display_delegate.h"
 #endif  // defined(OS_CHROMEOS)
 #include "ui/ozone/public/ozone_platform.h"
diff --git a/media/mojo/clients/mojo_renderer.cc b/media/mojo/clients/mojo_renderer.cc
index 7d009d6..6670cb30 100644
--- a/media/mojo/clients/mojo_renderer.cc
+++ b/media/mojo/clients/mojo_renderer.cc
@@ -228,32 +228,6 @@
   return media_time_interpolator_.GetInterpolatedTime();
 }
 
-bool MojoRenderer::HasAudio() {
-  DVLOG(1) << __FUNCTION__;
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK(remote_renderer_.is_bound());
-
-  if (demuxer_stream_provider_->GetType() == DemuxerStreamProvider::Type::URL) {
-    NOTIMPLEMENTED();
-    return false;
-  }
-
-  return !!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
-}
-
-bool MojoRenderer::HasVideo() {
-  DVLOG(1) << __FUNCTION__;
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK(remote_renderer_.is_bound());
-
-  if (demuxer_stream_provider_->GetType() == DemuxerStreamProvider::Type::URL) {
-    NOTIMPLEMENTED();
-    return false;
-  }
-
-  return !!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
-}
-
 void MojoRenderer::OnTimeUpdate(base::TimeDelta time,
                                 base::TimeDelta max_time,
                                 base::TimeTicks capture_time) {
diff --git a/media/mojo/clients/mojo_renderer.h b/media/mojo/clients/mojo_renderer.h
index 6bbbda2..995a0763 100644
--- a/media/mojo/clients/mojo_renderer.h
+++ b/media/mojo/clients/mojo_renderer.h
@@ -56,8 +56,6 @@
   void SetPlaybackRate(double playback_rate) override;
   void SetVolume(float volume) override;
   base::TimeDelta GetMediaTime() override;
-  bool HasAudio() override;
-  bool HasVideo() override;
 
   using ReceiveSurfaceRequestTokenCB =
       base::Callback<void(const base::UnguessableToken&)>;
diff --git a/media/remoting/remote_renderer_impl.cc b/media/remoting/remote_renderer_impl.cc
index 77fac89d..257b0844 100644
--- a/media/remoting/remote_renderer_impl.cc
+++ b/media/remoting/remote_renderer_impl.cc
@@ -218,16 +218,6 @@
   return current_media_time_;
 }
 
-bool RemoteRendererImpl::HasAudio() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  return audio_demuxer_stream_adapter_ ? true : false;
-}
-
-bool RemoteRendererImpl::HasVideo() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  return video_demuxer_stream_adapter_ ? true : false;
-}
-
 // static
 void RemoteRendererImpl::OnDataPipeCreatedOnMainThread(
     scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
diff --git a/media/remoting/remote_renderer_impl.h b/media/remoting/remote_renderer_impl.h
index 2b64be2..19b012d 100644
--- a/media/remoting/remote_renderer_impl.h
+++ b/media/remoting/remote_renderer_impl.h
@@ -78,8 +78,6 @@
   void SetPlaybackRate(double playback_rate) final;
   void SetVolume(float volume) final;
   base::TimeDelta GetMediaTime() final;
-  bool HasAudio() final;
-  bool HasVideo() final;
 
  private:
   friend class RemoteRendererImplTest;
diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc
index 4b2ed96..87212d8 100644
--- a/media/renderers/renderer_impl.cc
+++ b/media/renderers/renderer_impl.cc
@@ -310,16 +310,6 @@
   return time_source_->CurrentMediaTime();
 }
 
-bool RendererImpl::HasAudio() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return audio_renderer_ != NULL;
-}
-
-bool RendererImpl::HasVideo() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return video_renderer_ != NULL;
-}
-
 void RendererImpl::DisableUnderflowForTesting() {
   DVLOG(1) << __func__;
   DCHECK(task_runner_->BelongsToCurrentThread());
diff --git a/media/renderers/renderer_impl.h b/media/renderers/renderer_impl.h
index 0752805f..07ea224 100644
--- a/media/renderers/renderer_impl.h
+++ b/media/renderers/renderer_impl.h
@@ -59,8 +59,6 @@
   void SetPlaybackRate(double playback_rate) final;
   void SetVolume(float volume) final;
   base::TimeDelta GetMediaTime() final;
-  bool HasAudio() final;
-  bool HasVideo() final;
 
   void RestartStreamPlayback(DemuxerStream* stream,
                              bool enabled,
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 5f478187..abd9c740 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1124,8 +1124,8 @@
     "tools/quic/quic_client_session.h",
     "tools/quic/quic_dispatcher.cc",
     "tools/quic/quic_dispatcher.h",
-    "tools/quic/quic_in_memory_cache.cc",
-    "tools/quic/quic_in_memory_cache.h",
+    "tools/quic/quic_http_response_cache.cc",
+    "tools/quic/quic_http_response_cache.h",
     "tools/quic/quic_per_connection_packet_writer.cc",
     "tools/quic/quic_per_connection_packet_writer.h",
     "tools/quic/quic_process_packet_interface.h",
diff --git a/net/base/net_error_details.h b/net/base/net_error_details.h
index a7f239a..c08f96e1 100644
--- a/net/base/net_error_details.h
+++ b/net/base/net_error_details.h
@@ -7,7 +7,7 @@
 
 #include "net/base/net_export.h"
 #include "net/http/http_response_info.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/data/quic_in_memory_cache_data/quic-datatesturl.com/index.html b/net/data/quic_http_response_cache_data/quic-datatesturl.com/index.html
similarity index 100%
rename from net/data/quic_in_memory_cache_data/quic-datatesturl.com/index.html
rename to net/data/quic_http_response_cache_data/quic-datatesturl.com/index.html
diff --git a/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico b/net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/favicon.ico
similarity index 100%
rename from net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico
rename to net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/favicon.ico
Binary files differ
diff --git a/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index.html b/net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/index.html
similarity index 100%
rename from net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index.html
rename to net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/index.html
diff --git a/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html b/net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/index2.html
similarity index 100%
rename from net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html
rename to net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/index2.html
diff --git a/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg b/net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg
similarity index 100%
rename from net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg
rename to net/data/quic_http_response_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg
Binary files differ
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 2936e12e..2c05cd7 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -26,7 +26,7 @@
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/quic_clock.h"
 #include "net/quic/core/quic_crypto_client_stream_factory.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_tag.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/socket/client_socket_factory.h"
@@ -96,7 +96,6 @@
       enable_quic_alternative_service_with_different_host(true),
       enable_quic(false),
       disable_quic_on_timeout_with_open_streams(false),
-      enable_quic_port_selection(true),
       quic_always_require_handshake_confirmation(false),
       quic_disable_connection_pooling(false),
       quic_load_server_info_timeout_srtt_multiplier(0.25f),
@@ -165,7 +164,6 @@
           params.quic_max_packet_length,
           params.quic_user_agent_id,
           params.quic_supported_versions,
-          params.enable_quic_port_selection,
           params.quic_always_require_handshake_confirmation,
           params.quic_disable_connection_pooling,
           params.quic_load_server_info_timeout_srtt_multiplier,
@@ -291,8 +289,6 @@
   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
   dict->Set("sessions", quic_stream_factory_.QuicStreamFactoryInfoToValue());
   dict->SetBoolean("quic_enabled", params_.enable_quic);
-  dict->SetBoolean("enable_quic_port_selection",
-                   params_.enable_quic_port_selection);
   std::unique_ptr<base::ListValue> connection_options(new base::ListValue);
   for (QuicTagVector::const_iterator it =
            params_.quic_connection_options.begin();
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 8986dcf..5f01694 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -109,9 +109,6 @@
     bool enable_quic;
     // Disable QUIC if a connection times out with open streams.
     bool disable_quic_on_timeout_with_open_streams;
-    // Instruct QUIC to use consistent ephemeral ports when talking to
-    // the same server.
-    bool enable_quic_port_selection;
     // Disables QUIC's 0-RTT behavior.
     bool quic_always_require_handshake_confirmation;
     // Disables QUIC connection pooling.
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index 8bff8df..36e587eb 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -15,7 +15,7 @@
 #include "net/base/port_util.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_response_headers.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/spdy/spdy_alt_svc_wire_format.h"
 #include "url/gurl.h"
 
diff --git a/net/log/net_log_util.cc b/net/log/net_log_util.cc
index c91f931..75c88ea 100644
--- a/net/log/net_log_util.cc
+++ b/net/log/net_log_util.cc
@@ -38,7 +38,7 @@
 #include "net/proxy/proxy_retry_info.h"
 #include "net/proxy/proxy_service.h"
 #include "net/quic/core/quic_error_codes.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
diff --git a/net/net.gypi b/net/net.gypi
index 539fd926..c6eeabb 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -881,8 +881,6 @@
       'quic/chromium/crypto/proof_verifier_chromium.h',
       'quic/chromium/network_connection.cc',
       'quic/chromium/network_connection.h',
-      'quic/chromium/port_suggester.cc',
-      'quic/chromium/port_suggester.h',
       'quic/chromium/quic_chromium_alarm_factory.cc',
       'quic/chromium/quic_chromium_alarm_factory.h',
       'quic/chromium/quic_chromium_client_session.cc',
@@ -1003,6 +1001,32 @@
       'quic/core/crypto/strike_register_client.h',
       'quic/core/interval.h',
       'quic/core/interval_set.h',
+      'quic/core/frames/quic_ack_frame.cc',
+      'quic/core/frames/quic_ack_frame.h',
+      'quic/core/frames/quic_blocked_frame.cc',
+      'quic/core/frames/quic_blocked_frame.h',
+      'quic/core/frames/quic_connection_close_frame.cc',
+      'quic/core/frames/quic_connection_close_frame.h',
+      'quic/core/frames/quic_frame.cc',
+      'quic/core/frames/quic_frame.h',
+      'quic/core/frames/quic_goaway_frame.cc',
+      'quic/core/frames/quic_goaway_frame.h',
+      'quic/core/frames/quic_mtu_discovery_frame.h',
+      'quic/core/frames/quic_padding_frame.cc',
+      'quic/core/frames/quic_padding_frame.h',
+      'quic/core/frames/quic_path_close_frame.cc',
+      'quic/core/frames/quic_path_close_frame.h',
+      'quic/core/frames/quic_ping_frame.h',
+      'quic/core/frames/quic_rst_stream_frame.cc',
+      'quic/core/frames/quic_rst_stream_frame.h',
+      'quic/core/frames/quic_stop_waiting_frame.cc',
+      'quic/core/frames/quic_stop_waiting_frame.h',
+      'quic/core/frames/quic_stream_frame.cc',
+      'quic/core/frames/quic_stream_frame.h',
+      'quic/core/frames/quic_window_update_frame.cc',
+      'quic/core/frames/quic_window_update_frame.h',
+      'quic/core/quic_ack_listener_interface.cc',
+      'quic/core/quic_ack_listener_interface.h',
       'quic/core/quic_address_mismatch.cc',
       'quic/core/quic_address_mismatch.h',
       'quic/core/quic_alarm.cc',
@@ -1074,8 +1098,9 @@
       'quic/core/quic_packet_generator.cc',
       'quic/core/quic_packet_generator.h',
       'quic/core/quic_packet_writer.h',
-      'quic/core/quic_protocol.cc',
-      'quic/core/quic_protocol.h',
+      'quic/core/quic_packets.cc',
+      'quic/core/quic_packets.h',
+      'quic/core/quic_pending_retransmission.h',
       'quic/core/quic_received_packet_manager.cc',
       'quic/core/quic_received_packet_manager.h',
       'quic/core/quic_sent_packet_manager.cc',
@@ -1108,12 +1133,16 @@
       'quic/core/quic_tag.h',
       'quic/core/quic_time.cc',
       'quic/core/quic_time.h',
+      'quic/core/quic_transmission_info.cc',
+      'quic/core/quic_transmission_info.h',
       'quic/core/quic_types.cc',
       'quic/core/quic_types.h',
       'quic/core/quic_unacked_packet_map.cc',
       'quic/core/quic_unacked_packet_map.h',
       'quic/core/quic_utils.cc',
       'quic/core/quic_utils.h',
+      'quic/core/quic_version_manager.cc',
+      'quic/core/quic_version_manager.h',
       'quic/core/quic_versions.cc',
       'quic/core/quic_versions.h',
       'quic/core/quic_write_blocked_list.cc',
@@ -1694,7 +1723,6 @@
       'quic/chromium/mock_quic_data.cc',
       'quic/chromium/mock_quic_data.h',
       'quic/chromium/network_connection_unittest.cc',
-      'quic/chromium/port_suggester_unittest.cc',
       'quic/chromium/quic_chromium_alarm_factory_test.cc',
       'quic/chromium/quic_chromium_client_session_peer.cc',
       'quic/chromium/quic_chromium_client_session_peer.h',
@@ -1742,6 +1770,7 @@
       'quic/core/crypto/quic_crypto_server_config_test.cc',
       'quic/core/crypto/quic_random_test.cc',
       'quic/core/crypto/strike_register_test.cc',
+      'quic/core/frames/quic_frame_test.cc',
       'quic/core/interval_set_test.cc',
       'quic/core/interval_test.cc',
       'quic/core/quic_address_mismatch_test.cc',
@@ -1770,7 +1799,6 @@
       'quic/core/quic_one_block_arena_test.cc',
       'quic/core/quic_packet_creator_test.cc',
       'quic/core/quic_packet_generator_test.cc',
-      'quic/core/quic_protocol_test.cc',
       'quic/core/quic_received_packet_manager_test.cc',
       'quic/core/quic_sent_packet_manager_test.cc',
       'quic/core/quic_server_id_test.cc',
@@ -1787,6 +1815,7 @@
       'quic/core/quic_time_test.cc',
       'quic/core/quic_unacked_packet_map_test.cc',
       'quic/core/quic_utils_test.cc',
+      'quic/core/quic_version_manager_test.cc',
       'quic/core/quic_versions_test.cc',
       'quic/core/quic_write_blocked_list_test.cc',
       'quic/core/spdy_utils_test.cc',
@@ -2027,7 +2056,7 @@
       'tools/quic/quic_epoll_alarm_factory_test.cc',
       'tools/quic/quic_epoll_clock_test.cc',
       'tools/quic/quic_epoll_connection_helper_test.cc',
-      'tools/quic/quic_in_memory_cache_test.cc',
+      'tools/quic/quic_http_response_cache_test.cc',
       'tools/quic/quic_server_test.cc',
       'tools/quic/quic_simple_server_session_helper_test.cc',
       'tools/quic/quic_simple_server_session_test.cc',
diff --git a/net/quic/chromium/mock_quic_data.h b/net/quic/chromium/mock_quic_data.h
index 8a1e1d2..69eab08e 100644
--- a/net/quic/chromium/mock_quic_data.h
+++ b/net/quic/chromium/mock_quic_data.h
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/socket/socket_test_util.h"
 
 namespace net {
diff --git a/net/quic/chromium/port_suggester.cc b/net/quic/chromium/port_suggester.cc
deleted file mode 100644
index b88ce0d..0000000
--- a/net/quic/chromium/port_suggester.cc
+++ /dev/null
@@ -1,47 +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 "net/quic/chromium/port_suggester.h"
-
-#include "base/logging.h"
-
-namespace net {
-
-PortSuggester::PortSuggester(const HostPortPair& server, uint64_t seed)
-    : call_count_(0), previous_suggestion_(-1) {
-  unsigned char hash_bytes[base::kSHA1Length];
-  base::SHA1HashBytes(
-      reinterpret_cast<const unsigned char*>(server.host().data()),
-      server.host().length(), hash_bytes);
-  static_assert(sizeof(seed_) < sizeof(hash_bytes), "seed larger than hash");
-  memcpy(&seed_, hash_bytes, sizeof(seed_));
-  seed_ ^= seed ^ server.port();
-}
-
-int PortSuggester::SuggestPort(int min, int max) {
-  // Sometimes our suggestion can't be used, so we ensure that if additional
-  // calls are made, then each call (probably) provides a new suggestion.
-  if (++call_count_ > 1) {
-    // Evolve the seed.
-    unsigned char hash_bytes[base::kSHA1Length];
-    base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(&seed_),
-                        sizeof(seed_), hash_bytes);
-    memcpy(&seed_, hash_bytes, sizeof(seed_));
-  }
-  DCHECK_LE(min, max);
-  DCHECK_GT(min, 0);
-  int range = max - min + 1;
-  // Ports (and hence the extent of the |range|) are generally under 2^16, so
-  // the tiny non-uniformity in the pseudo-random distribution is not
-  // significant.
-  previous_suggestion_ = static_cast<int>(seed_ % range) + min;
-  return previous_suggestion_;
-}
-
-int PortSuggester::previous_suggestion() const {
-  DCHECK_LT(0u, call_count_);
-  return previous_suggestion_;
-}
-
-}  // namespace net
diff --git a/net/quic/chromium/port_suggester.h b/net/quic/chromium/port_suggester.h
deleted file mode 100644
index d3f41a3..0000000
--- a/net/quic/chromium/port_suggester.h
+++ /dev/null
@@ -1,51 +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 NET_QUIC_PORT_SUGGESTER_H_
-#define NET_QUIC_PORT_SUGGESTER_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sha1.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-// We provide a pseudo-random number generator that is always seeded the same
-// way for a given destination host-port pair.  The generator is used to
-// consistently suggest (for that host-port pair) an ephemeral source port,
-// and hence increase the likelihood that a server's load balancer will direct
-// a repeated connection to the same server (with QUIC, further increasing the
-// chance of connection establishment with 0-RTT).
-class NET_EXPORT_PRIVATE PortSuggester
-    : public base::RefCounted<PortSuggester> {
- public:
-  PortSuggester(const HostPortPair& server, uint64_t seed);
-
-  // Generate a pseudo-random int in the inclusive range from |min| to |max|.
-  // Will (probably) return different numbers when called repeatedly.
-  int SuggestPort(int min, int max);
-
-  uint32_t call_count() const { return call_count_; }
-  int previous_suggestion() const;
-
- private:
-  friend class base::RefCounted<PortSuggester>;
-
-  virtual ~PortSuggester() {}
-
-  // We maintain the first 8 bytes of a hash as our seed_ state.
-  uint64_t seed_;
-  uint32_t call_count_;  // Number of suggestions made.
-  int previous_suggestion_;
-
-  DISALLOW_COPY_AND_ASSIGN(PortSuggester);
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_PORT_SUGGESTER_H_
diff --git a/net/quic/chromium/port_suggester_unittest.cc b/net/quic/chromium/port_suggester_unittest.cc
deleted file mode 100644
index 5bf757b..0000000
--- a/net/quic/chromium/port_suggester_unittest.cc
+++ /dev/null
@@ -1,108 +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 "net/quic/chromium/port_suggester.h"
-
-#include <set>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace test {
-
-class PortSuggesterTest : public ::testing::Test {
- protected:
-  PortSuggesterTest()
-      : entropy_(1345689),
-        min_ephemeral_port_(1025),
-        max_ephemeral_port_(65535) {}
-
-  uint64_t entropy_;
-  int min_ephemeral_port_;
-  int max_ephemeral_port_;
-};
-
-TEST_F(PortSuggesterTest, SmallRangeTest) {
-  // When the range is small (one wide), we always get that as our answer.
-  scoped_refptr<PortSuggester> port_suggester =
-      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
-  // Test this for a few different (small) ranges.
-  for (int port = 2000; port < 2010; ++port) {
-    // Use |port| for both |min| and |max| delimiting the suggestion range.
-    EXPECT_EQ(port, port_suggester->SuggestPort(port, port));
-    EXPECT_EQ(port, port_suggester->previous_suggestion());
-  }
-}
-
-TEST_F(PortSuggesterTest, SuggestAllPorts) {
-  // We should eventually fill out any range, but we'll just ensure that we
-  // fill out a small range of ports.
-  scoped_refptr<PortSuggester> port_suggester =
-      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
-  std::set<int> ports;
-  const uint32_t port_range = 20;
-  const int insertion_limit = 200;  // We should be done by then.
-  for (int i = 0; i < insertion_limit; ++i) {
-    ports.insert(port_suggester->SuggestPort(
-        min_ephemeral_port_, min_ephemeral_port_ + port_range - 1));
-    if (ports.size() == port_range) {
-      break;
-    }
-  }
-  EXPECT_EQ(port_range, ports.size());
-}
-
-TEST_F(PortSuggesterTest, AvoidDuplication) {
-  // When the range is large, duplicates are rare, but we'll ask for a few
-  // suggestions and make sure they are unique.
-  scoped_refptr<PortSuggester> port_suggester =
-      new PortSuggester(HostPortPair("www.example.com", 80), entropy_);
-  std::set<int> ports;
-  const size_t port_count = 200;
-  for (size_t i = 0; i < port_count; ++i) {
-    ports.insert(
-        port_suggester->SuggestPort(min_ephemeral_port_, max_ephemeral_port_));
-  }
-  EXPECT_EQ(port_suggester->call_count(), port_count);
-  EXPECT_EQ(port_count, ports.size());
-}
-
-TEST_F(PortSuggesterTest, ConsistentPorts) {
-  // For given hostname, port, and entropy, we should always get the same
-  // suggestions.
-  scoped_refptr<PortSuggester> port_suggester1 =
-      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
-  scoped_refptr<PortSuggester> port_suggester2 =
-      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
-  for (int test_count = 20; test_count > 0; --test_count) {
-    EXPECT_EQ(
-        port_suggester1->SuggestPort(min_ephemeral_port_, min_ephemeral_port_),
-        port_suggester2->SuggestPort(min_ephemeral_port_, min_ephemeral_port_));
-  }
-}
-
-TEST_F(PortSuggesterTest, DifferentHostPortEntropy) {
-  // When we have different hosts, port, or entropy, we probably won't collide.
-  scoped_refptr<PortSuggester> port_suggester[] = {
-      new PortSuggester(HostPortPair("www.example.com", 80), entropy_),
-      new PortSuggester(HostPortPair("www.example.ORG", 80), entropy_),
-      new PortSuggester(HostPortPair("www.example.com", 443), entropy_),
-      new PortSuggester(HostPortPair("www.example.com", 80), entropy_ + 123456),
-  };
-
-  std::set<int> ports;
-  const int port_count = 40;
-  size_t insertion_count = 0;
-  for (size_t j = 0; j < arraysize(port_suggester); ++j) {
-    for (int i = 0; i < port_count; ++i) {
-      ports.insert(port_suggester[j]->SuggestPort(min_ephemeral_port_,
-                                                  max_ephemeral_port_));
-      ++insertion_count;
-    }
-  }
-  EXPECT_EQ(insertion_count, ports.size());
-}
-
-}  // namespace test
-}  // namespace net
diff --git a/net/quic/chromium/quic_chromium_alarm_factory.h b/net/quic/chromium/quic_chromium_alarm_factory.h
index 436379c8..ba04427 100644
--- a/net/quic/chromium/quic_chromium_alarm_factory.h
+++ b/net/quic/chromium/quic_chromium_alarm_factory.h
@@ -15,7 +15,7 @@
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_alarm_factory.h"
 #include "net/quic/core/quic_clock.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace base {
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc
index 940dc94..31497b1 100644
--- a/net/quic/chromium/quic_chromium_client_session.cc
+++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -359,18 +359,15 @@
   if (round_trip_handshakes < 0 || !stream_factory_)
     return;
 
-  bool port_selected = stream_factory_->enable_port_selection();
   SSLInfo ssl_info;
   // QUIC supports only secure urls.
   if (GetSSLInfo(&ssl_info) && ssl_info.cert.get()) {
-    if (!port_selected) {
-      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTPS",
-                                  round_trip_handshakes, 1, 3, 4);
-      if (require_confirmation_) {
-        UMA_HISTOGRAM_CUSTOM_COUNTS(
-            "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTPS",
-            round_trip_handshakes, 1, 3, 4);
-      }
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTPS",
+                                round_trip_handshakes, 1, 3, 4);
+    if (require_confirmation_) {
+      UMA_HISTOGRAM_CUSTOM_COUNTS(
+          "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTPS",
+          round_trip_handshakes, 1, 3, 4);
     }
   }
   const QuicConnectionStats stats = connection()->GetStats();
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h
index dafa6cb..c032b4f 100644
--- a/net/quic/chromium/quic_chromium_client_session.h
+++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -34,7 +34,7 @@
 #include "net/quic/chromium/quic_connection_logger.h"
 #include "net/quic/core/quic_client_session_base.h"
 #include "net/quic/core/quic_crypto_client_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/quic_time.h"
 #include "net/socket/socket_performance_watcher.h"
diff --git a/net/quic/chromium/quic_chromium_client_session_peer.h b/net/quic/chromium/quic_chromium_client_session_peer.h
index a781fa5..03af673 100644
--- a/net/quic/chromium/quic_chromium_client_session_peer.h
+++ b/net/quic/chromium/quic_chromium_client_session_peer.h
@@ -10,7 +10,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/chromium/quic_chromium_connection_helper.h b/net/quic/chromium/quic_chromium_connection_helper.h
index 9271a6d..224ce457 100644
--- a/net/quic/chromium/quic_chromium_connection_helper.h
+++ b/net/quic/chromium/quic_chromium_connection_helper.h
@@ -12,7 +12,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_simple_buffer_allocator.h"
 #include "net/quic/core/quic_time.h"
 #include "net/socket/datagram_client_socket.h"
diff --git a/net/quic/chromium/quic_chromium_packet_reader.cc b/net/quic/chromium/quic_chromium_packet_reader.cc
index 1c5d660..a970b97 100644
--- a/net/quic/chromium/quic_chromium_packet_reader.cc
+++ b/net/quic/chromium/quic_chromium_packet_reader.cc
@@ -23,11 +23,9 @@
     : socket_(socket),
       visitor_(visitor),
       read_pending_(false),
-      num_packets_read_(0),
       clock_(clock),
       yield_after_packets_(yield_after_packets),
       yield_after_duration_(yield_after_duration),
-      yield_after_(QuicTime::Infinite()),
       read_buffer_(new IOBufferWithSize(static_cast<size_t>(kMaxPacketSize))),
       net_log_(net_log),
       weak_factory_(this) {}
@@ -38,42 +36,45 @@
   if (read_pending_)
     return;
 
-  if (num_packets_read_ == 0)
-    yield_after_ = clock_->Now() + yield_after_duration_;
+  int num_packets_read = 0;
+  QuicTime yield_after = clock_->Now() + yield_after_duration_;
 
   DCHECK(socket_);
-  read_pending_ = true;
-  int rv = socket_->Read(read_buffer_.get(), read_buffer_->size(),
-                         base::Bind(&QuicChromiumPacketReader::OnReadComplete,
-                                    weak_factory_.GetWeakPtr()));
-  UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING);
-  if (rv == ERR_IO_PENDING) {
-    num_packets_read_ = 0;
-    return;
-  }
-
-  if (++num_packets_read_ > yield_after_packets_ ||
-      clock_->Now() > yield_after_) {
-    num_packets_read_ = 0;
-    // Data was read, process it.
-    // Schedule the work through the message loop to 1) prevent infinite
-    // recursion and 2) avoid blocking the thread for too long.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&QuicChromiumPacketReader::OnReadComplete,
-                              weak_factory_.GetWeakPtr(), rv));
-  } else {
-    OnReadComplete(rv);
+  while (true) {
+    read_pending_ = true;
+    int rv = socket_->Read(read_buffer_.get(), read_buffer_->size(),
+                           base::Bind(&QuicChromiumPacketReader::OnReadComplete,
+                                      weak_factory_.GetWeakPtr()));
+    UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING);
+    if (rv == ERR_IO_PENDING)
+      return;
+    if (!OnPacketRead(rv))
+      return;
+    if (++num_packets_read > yield_after_packets_ ||
+        clock_->Now() > yield_after) {
+      // Schedule the work through the message loop to avoid blocking the thread
+      // for too long.
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::Bind(&QuicChromiumPacketReader::StartReading,
+                                weak_factory_.GetWeakPtr()));
+      return;
+    }
   }
 }
 
 void QuicChromiumPacketReader::OnReadComplete(int result) {
+  if (OnPacketRead(result))
+    StartReading();
+}
+
+bool QuicChromiumPacketReader::OnPacketRead(int result) {
   read_pending_ = false;
   if (result == 0)
     result = ERR_CONNECTION_CLOSED;
 
   if (result < 0) {
     visitor_->OnReadError(result, socket_);
-    return;
+    return false;
   }
 
   QuicReceivedPacket packet(read_buffer_->data(), result, clock_->Now());
@@ -81,10 +82,7 @@
   IPEndPoint peer_address;
   socket_->GetLocalAddress(&local_address);
   socket_->GetPeerAddress(&peer_address);
-  if (!visitor_->OnPacket(packet, local_address, peer_address))
-    return;
-
-  StartReading();
+  return visitor_->OnPacket(packet, local_address, peer_address);
 }
 
 }  // namespace net
diff --git a/net/quic/chromium/quic_chromium_packet_reader.h b/net/quic/chromium/quic_chromium_packet_reader.h
index 5e700a7e..71d0580a 100644
--- a/net/quic/chromium/quic_chromium_packet_reader.h
+++ b/net/quic/chromium/quic_chromium_packet_reader.h
@@ -11,7 +11,7 @@
 #include "net/base/io_buffer.h"
 #include "net/base/net_export.h"
 #include "net/log/net_log_with_source.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 #include "net/socket/datagram_client_socket.h"
 
@@ -53,14 +53,17 @@
   // A completion callback invoked when a read completes.
   void OnReadComplete(int result);
 
+  // Called when a packet is read and it should be processed.
+  // Returns false if the read was an error or the packet couldn't
+  // be processed.
+  bool OnPacketRead(int result);
+
   DatagramClientSocket* socket_;
   Visitor* visitor_;
   bool read_pending_;
-  int num_packets_read_;
   QuicClock* clock_;  // Owned by QuicStreamFactory
   int yield_after_packets_;
   QuicTime::Delta yield_after_duration_;
-  QuicTime yield_after_;
   scoped_refptr<IOBufferWithSize> read_buffer_;
   NetLogWithSource net_log_;
 
diff --git a/net/quic/chromium/quic_chromium_packet_writer.h b/net/quic/chromium/quic_chromium_packet_writer.h
index a416f8f..d4e9dc8 100644
--- a/net/quic/chromium/quic_chromium_packet_writer.h
+++ b/net/quic/chromium/quic_chromium_packet_writer.h
@@ -13,7 +13,7 @@
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_types.h"
 #include "net/socket/datagram_client_socket.h"
 
diff --git a/net/quic/chromium/quic_connection_logger.cc b/net/quic/chromium/quic_connection_logger.cc
index c5e5761..7a73609 100644
--- a/net/quic/chromium/quic_connection_logger.cc
+++ b/net/quic/chromium/quic_connection_logger.cc
@@ -26,7 +26,7 @@
 #include "net/quic/core/crypto/crypto_handshake_message.h"
 #include "net/quic/core/crypto/crypto_protocol.h"
 #include "net/quic/core/quic_address_mismatch.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_socket_address_coder.h"
 #include "net/quic/core/quic_time.h"
 
diff --git a/net/quic/chromium/quic_connection_logger.h b/net/quic/chromium/quic_connection_logger.h
index 346c020..9a24a006 100644
--- a/net/quic/chromium/quic_connection_logger.h
+++ b/net/quic/chromium/quic_connection_logger.h
@@ -17,7 +17,7 @@
 #include "net/log/net_log_with_source.h"
 #include "net/quic/core/crypto/crypto_handshake_message.h"
 #include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_spdy_session.h"
 #include "net/socket/socket_performance_watcher.h"
 
diff --git a/net/quic/chromium/quic_end_to_end_unittest.cc b/net/quic/chromium/quic_end_to_end_unittest.cc
index 8b7bde71..18a7c16 100644
--- a/net/quic/chromium/quic_end_to_end_unittest.cc
+++ b/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -36,7 +36,7 @@
 #include "net/test/cert_test_util.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_data_directory.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -179,7 +179,7 @@
     server_config_options_.token_binding_params = QuicTagVector{kTB10, kP256};
     server_.reset(new QuicSimpleServer(
         CryptoTestUtils::ProofSourceForTesting(), server_config_,
-        server_config_options_, AllSupportedVersions(), &in_memory_cache_));
+        server_config_options_, AllSupportedVersions(), &response_cache_));
     server_->Listen(server_address_);
     server_address_ = server_->server_address();
     server_->StartReading();
@@ -192,8 +192,8 @@
                   int response_code,
                   StringPiece response_detail,
                   StringPiece body) {
-    in_memory_cache_.AddSimpleResponse("test.example.com", path, response_code,
-                                       body);
+    response_cache_.AddSimpleResponse("test.example.com", path, response_code,
+                                      body);
   }
 
   // Populates |request_body_| with |length_| ASCII bytes.
@@ -248,7 +248,7 @@
   std::string request_body_;
   std::unique_ptr<UploadDataStream> upload_data_stream_;
   std::unique_ptr<QuicSimpleServer> server_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
   IPEndPoint server_address_;
   std::string server_hostname_;
   QuicConfig server_config_;
diff --git a/net/quic/chromium/quic_http_stream.h b/net/quic/chromium/quic_http_stream.h
index 4c78503..431d498 100644
--- a/net/quic/chromium/quic_http_stream.h
+++ b/net/quic/chromium/quic_http_stream.h
@@ -23,7 +23,7 @@
 #include "net/quic/chromium/quic_chromium_client_session.h"
 #include "net/quic/chromium/quic_chromium_client_stream.h"
 #include "net/quic/core/quic_client_push_promise_index.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index d7cc346d..f626b3c3 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -35,7 +35,6 @@
 #include "net/quic/chromium/bidirectional_stream_quic_impl.h"
 #include "net/quic/chromium/crypto/channel_id_chromium.h"
 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
-#include "net/quic/chromium/port_suggester.h"
 #include "net/quic/chromium/quic_chromium_alarm_factory.h"
 #include "net/quic/chromium/quic_chromium_connection_helper.h"
 #include "net/quic/chromium/quic_chromium_packet_reader.h"
@@ -719,7 +718,6 @@
     size_t max_packet_length,
     const std::string& user_agent_id,
     const QuicVersionVector& supported_versions,
-    bool enable_port_selection,
     bool always_require_handshake_confirmation,
     bool disable_connection_pooling,
     float load_server_info_timeout_srtt_multiplier,
@@ -765,7 +763,6 @@
                                     transport_security_state,
                                     cert_transparency_verifier))),
       supported_versions_(supported_versions),
-      enable_port_selection_(enable_port_selection),
       always_require_handshake_confirmation_(
           always_require_handshake_confirmation),
       disable_connection_pooling_(disable_connection_pooling),
@@ -797,7 +794,6 @@
       force_hol_blocking_(force_hol_blocking),
       race_cert_verification_(race_cert_verification),
       quic_do_not_fragment_(quic_do_not_fragment),
-      port_seed_(random_generator_->RandUint64()),
       check_persisted_supports_quic_(true),
       has_initialized_data_(false),
       num_push_streams_created_(0),
@@ -1619,26 +1615,11 @@
   }
   TRACE_EVENT0("net", "QuicStreamFactory::CreateSession");
   IPEndPoint addr = *address_list.begin();
-  bool enable_port_selection = enable_port_selection_;
-  if (enable_port_selection && base::ContainsKey(gone_away_aliases_, key)) {
-    // Disable port selection when the server is going away.
-    // There is no point in trying to return to the same server, if
-    // that server is no longer handling requests.
-    enable_port_selection = false;
-    gone_away_aliases_.erase(key);
-  }
   const QuicServerId& server_id = key.server_id();
-  scoped_refptr<PortSuggester> port_suggester =
-      new PortSuggester(server_id.host_port_pair(), port_seed_);
-  DatagramSocket::BindType bind_type =
-      enable_port_selection ? DatagramSocket::RANDOM_BIND
-                            :            // Use our callback.
-          DatagramSocket::DEFAULT_BIND;  // Use OS to randomize.
-
+  DatagramSocket::BindType bind_type = DatagramSocket::DEFAULT_BIND;
   std::unique_ptr<DatagramClientSocket> socket(
       client_socket_factory_->CreateDatagramClientSocket(
-          bind_type, base::Bind(&PortSuggester::SuggestPort, port_suggester),
-          net_log.net_log(), net_log.source()));
+          bind_type, RandIntCallback(), net_log.net_log(), net_log.source()));
 
   // Passing in kInvalidNetworkHandle binds socket to default network.
   int rv = ConfigureSocket(socket.get(), addr,
@@ -1646,11 +1627,6 @@
   if (rv != OK)
     return rv;
 
-  if (enable_port_selection)
-    DCHECK_LE(1u, port_suggester->call_count());
-  else
-    DCHECK_EQ(0u, port_suggester->call_count());
-
   if (!helper_.get()) {
     helper_.reset(
         new QuicChromiumConnectionHelper(clock_.get(), random_generator_));
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index afe0836..48623885 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -37,7 +37,7 @@
 #include "net/quic/core/quic_client_push_promise_index.h"
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_crypto_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/ssl/ssl_config_service.h"
 
@@ -199,7 +199,6 @@
       size_t max_packet_length,
       const std::string& user_agent_id,
       const QuicVersionVector& supported_versions,
-      bool enable_port_selection,
       bool always_require_handshake_confirmation,
       bool disable_connection_pooling,
       float load_server_info_timeout_srtt_multiplier,
@@ -369,8 +368,6 @@
 
   QuicChromiumAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
 
-  bool enable_port_selection() const { return enable_port_selection_; }
-
   bool has_quic_server_info_factory() {
     return quic_server_info_factory_.get() != nullptr;
   }
@@ -549,11 +546,6 @@
 
   QuicVersionVector supported_versions_;
 
-  // Determine if we should consistently select a client UDP port. If false,
-  // then we will just let the OS select a random client port for each new
-  // connection.
-  bool enable_port_selection_;
-
   // Set if we always require handshake confirmation. If true, this will
   // introduce at least one RTT for the handshake before the client sends data.
   bool always_require_handshake_confirmation_;
@@ -629,14 +621,6 @@
   // If set, configure QUIC sockets to not fragment packets.
   bool quic_do_not_fragment_;
 
-  // Each profile will (probably) have a unique port_seed_ value.  This value
-  // is used to help seed a pseudo-random number generator (PortSuggester) so
-  // that we consistently (within this profile) suggest the same ephemeral
-  // port when we re-connect to any given server/port.  The differences between
-  // profiles (probablistically) prevent two profiles from colliding in their
-  // ephemeral port requests.
-  uint64_t port_seed_;
-
   // Local address of socket that was created in CreateSession.
   IPEndPoint local_address_;
   bool check_persisted_supports_quic_;
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index d31369a..67841a64 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -243,7 +243,6 @@
         url3_(kServer3Url),
         url4_(kServer4Url),
         privacy_mode_(PRIVACY_MODE_DISABLED),
-        enable_port_selection_(true),
         always_require_handshake_confirmation_(false),
         disable_connection_pooling_(false),
         load_server_info_timeout_srtt_multiplier_(0.0f),
@@ -284,10 +283,10 @@
         /*SocketPerformanceWatcherFactory*/ nullptr,
         &crypto_client_stream_factory_, &random_generator_, clock_,
         kDefaultMaxPacketSize, string(), SupportedVersions(version_),
-        enable_port_selection_, always_require_handshake_confirmation_,
-        disable_connection_pooling_, load_server_info_timeout_srtt_multiplier_,
-        enable_connection_racing_, enable_non_blocking_io_, disable_disk_cache_,
-        prefer_aes_, receive_buffer_size_, delay_tcp_race_,
+        always_require_handshake_confirmation_, disable_connection_pooling_,
+        load_server_info_timeout_srtt_multiplier_, enable_connection_racing_,
+        enable_non_blocking_io_, disable_disk_cache_, prefer_aes_,
+        receive_buffer_size_, delay_tcp_race_,
         /*max_server_configs_stored_in_properties*/ 0,
         close_sessions_on_ip_change_,
         disable_quic_on_timeout_with_open_streams_,
@@ -735,7 +734,6 @@
   TestCompletionCallback callback_;
 
   // Variables to configure QuicStreamFactory.
-  bool enable_port_selection_;
   bool always_require_handshake_confirmation_;
   bool disable_connection_pooling_;
   double load_server_info_timeout_srtt_multiplier_;
@@ -1513,41 +1511,6 @@
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
 }
 
-TEST_P(QuicStreamFactoryTest, CreateConsistentEphemeralPort) {
-  Initialize();
-  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-
-  // Sequentially connect to the default host, then another host, and then the
-  // default host.  Verify that the default host gets a consistent ephemeral
-  // port, that is different from the other host's connection.
-
-  string other_server_name = kServer2HostName;
-  EXPECT_NE(kDefaultServerHostName, other_server_name);
-  HostPortPair host_port_pair2(other_server_name, kDefaultServerPort);
-
-  int original_port = GetSourcePortForNewSession(host_port_pair_);
-  EXPECT_NE(original_port, GetSourcePortForNewSession(host_port_pair2));
-  EXPECT_EQ(original_port, GetSourcePortForNewSession(host_port_pair_));
-}
-
-TEST_P(QuicStreamFactoryTest, GoAwayDisablesConsistentEphemeralPort) {
-  Initialize();
-  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-
-  // Get a session to the host using the port suggester.
-  int original_port = GetSourcePortForNewSessionAndGoAway(host_port_pair_);
-  // Verify that the port is different after the goaway.
-  EXPECT_NE(original_port, GetSourcePortForNewSession(host_port_pair_));
-  // Since the previous session did not goaway we should see the original port.
-  EXPECT_EQ(original_port, GetSourcePortForNewSession(host_port_pair_));
-}
-
 TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
   Initialize();
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
diff --git a/net/quic/core/congestion_control/bandwidth_sampler.h b/net/quic/core/congestion_control/bandwidth_sampler.h
index fe59a606..b852604f 100644
--- a/net/quic/core/congestion_control/bandwidth_sampler.h
+++ b/net/quic/core/congestion_control/bandwidth_sampler.h
@@ -7,7 +7,7 @@
 
 #include "net/base/linked_hash_map.h"
 #include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc
index d8ab1ce..04908c2 100644
--- a/net/quic/core/congestion_control/bbr_sender.cc
+++ b/net/quic/core/congestion_control/bbr_sender.cc
@@ -98,7 +98,8 @@
       probe_rtt_round_passed_(false),
       last_sample_is_app_limited_(false),
       recovery_state_(NOT_IN_RECOVERY),
-      end_recovery_at_(0) {
+      end_recovery_at_(0),
+      recovery_window_(max_congestion_window_) {
   EnterStartupMode();
 }
 
diff --git a/net/quic/core/congestion_control/bbr_sender.h b/net/quic/core/congestion_control/bbr_sender.h
index e146eec..952568d 100644
--- a/net/quic/core/congestion_control/bbr_sender.h
+++ b/net/quic/core/congestion_control/bbr_sender.h
@@ -15,7 +15,7 @@
 #include "net/quic/core/congestion_control/windowed_filter.h"
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 #include "net/quic/core/quic_unacked_packet_map.h"
 
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc
index c50c8cd8..e85c86f4 100644
--- a/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -10,7 +10,7 @@
 
 #include "base/logging.h"
 #include "net/quic/core/congestion_control/rtt_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/quic_config_peer.h"
diff --git a/net/quic/core/congestion_control/cubic.cc b/net/quic/core/congestion_control/cubic.cc
index 385e160..7b7d9f8 100644
--- a/net/quic/core/congestion_control/cubic.cc
+++ b/net/quic/core/congestion_control/cubic.cc
@@ -10,7 +10,7 @@
 
 #include "base/logging.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 using std::max;
diff --git a/net/quic/core/congestion_control/cubic_bytes.cc b/net/quic/core/congestion_control/cubic_bytes.cc
index ec1c996e..6f62aa4 100644
--- a/net/quic/core/congestion_control/cubic_bytes.cc
+++ b/net/quic/core/congestion_control/cubic_bytes.cc
@@ -10,7 +10,7 @@
 
 #include "base/logging.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 using std::max;
 using std::min;
diff --git a/net/quic/core/congestion_control/general_loss_algorithm.cc b/net/quic/core/congestion_control/general_loss_algorithm.cc
index 6d7521c6..2694c95 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/net/quic/core/congestion_control/general_loss_algorithm.cc
@@ -7,7 +7,7 @@
 #include "net/quic/core/congestion_control/rtt_stats.h"
 #include "net/quic/core/quic_bug_tracker.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/congestion_control/general_loss_algorithm.h b/net/quic/core/congestion_control/general_loss_algorithm.h
index 7b2a253..bd5f0376 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm.h
+++ b/net/quic/core/congestion_control/general_loss_algorithm.h
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/congestion_control/loss_detection_interface.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 #include "net/quic/core/quic_unacked_packet_map.h"
 
diff --git a/net/quic/core/congestion_control/hybrid_slow_start.h b/net/quic/core/congestion_control/hybrid_slow_start.h
index 1ca1448..ad264e11 100644
--- a/net/quic/core/congestion_control/hybrid_slow_start.h
+++ b/net/quic/core/congestion_control/hybrid_slow_start.h
@@ -20,7 +20,7 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/loss_detection_interface.h b/net/quic/core/congestion_control/loss_detection_interface.h
index 5fce89f..5a16a68d 100644
--- a/net/quic/core/congestion_control/loss_detection_interface.h
+++ b/net/quic/core/congestion_control/loss_detection_interface.h
@@ -9,7 +9,7 @@
 
 #include "net/base/net_export.h"
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/pacing_sender.h b/net/quic/core/congestion_control/pacing_sender.h
index 8e839c9a5..4f6ff3c 100644
--- a/net/quic/core/congestion_control/pacing_sender.h
+++ b/net/quic/core/congestion_control/pacing_sender.h
@@ -21,7 +21,7 @@
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
 #include "net/quic/core/quic_bandwidth.h"
 #include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/pacing_sender_test.cc b/net/quic/core/congestion_control/pacing_sender_test.cc
index 3a6ab93..68a31fe 100644
--- a/net/quic/core/congestion_control/pacing_sender_test.cc
+++ b/net/quic/core/congestion_control/pacing_sender_test.cc
@@ -7,7 +7,7 @@
 #include <memory>
 
 #include "base/logging.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/core/congestion_control/prr_sender.cc b/net/quic/core/congestion_control/prr_sender.cc
index 0be617c9..bb8ac5c 100644
--- a/net/quic/core/congestion_control/prr_sender.cc
+++ b/net/quic/core/congestion_control/prr_sender.cc
@@ -4,7 +4,7 @@
 
 #include "net/quic/core/congestion_control/prr_sender.h"
 
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/congestion_control/prr_sender_test.cc b/net/quic/core/congestion_control/prr_sender_test.cc
index 8558e99..77bf30c 100644
--- a/net/quic/core/congestion_control/prr_sender_test.cc
+++ b/net/quic/core/congestion_control/prr_sender_test.cc
@@ -10,7 +10,7 @@
 #include "net/quic/core/crypto/crypto_protocol.h"
 #include "net/quic/core/quic_bandwidth.h"
 #include "net/quic/core/quic_constants.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/rtt_stats.h b/net/quic/core/congestion_control/rtt_stats.h
index 242e341..57253cc 100644
--- a/net/quic/core/congestion_control/rtt_stats.h
+++ b/net/quic/core/congestion_control/rtt_stats.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_bug_tracker.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/send_algorithm_interface.cc b/net/quic/core/congestion_control/send_algorithm_interface.cc
index 58d395e..bc44de0 100644
--- a/net/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/net/quic/core/congestion_control/send_algorithm_interface.cc
@@ -9,7 +9,7 @@
 #include "net/quic/core/congestion_control/tcp_cubic_sender_packets.h"
 #include "net/quic/core/quic_bug_tracker.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/congestion_control/send_algorithm_interface.h b/net/quic/core/congestion_control/send_algorithm_interface.h
index a9e06b32..69a236f 100644
--- a/net/quic/core/congestion_control/send_algorithm_interface.h
+++ b/net/quic/core/congestion_control/send_algorithm_interface.h
@@ -16,7 +16,7 @@
 #include "net/quic/core/quic_clock.h"
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 #include "net/quic/core/quic_unacked_packet_map.h"
 
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_base.h b/net/quic/core/congestion_control/tcp_cubic_sender_base.h
index 6a7ef23..d1ca16e 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_base.h
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_base.h
@@ -18,7 +18,7 @@
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
 #include "net/quic/core/quic_bandwidth.h"
 #include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index ab2a4c1..1359b64 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -17,7 +17,7 @@
 #include "net/quic/core/congestion_control/tcp_cubic_sender_base.h"
 #include "net/quic/core/quic_bandwidth.h"
 #include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index 171850d1..8f87a3fe 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -14,7 +14,7 @@
 #include "net/quic/core/crypto/crypto_protocol.h"
 #include "net/quic/core/proto/cached_network_parameters.pb.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/quic_config_peer.h"
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_packets.h b/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
index 8cb21db..8f2286de 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
@@ -18,7 +18,7 @@
 #include "net/quic/core/congestion_control/tcp_cubic_sender_base.h"
 #include "net/quic/core/quic_bandwidth.h"
 #include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc b/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
index fd0d6af..1cb2f32 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
@@ -13,7 +13,7 @@
 #include "net/quic/core/crypto/crypto_protocol.h"
 #include "net/quic/core/proto/cached_network_parameters.pb.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/quic_config_peer.h"
diff --git a/net/quic/core/congestion_control/windowed_filter_test.cc b/net/quic/core/congestion_control/windowed_filter_test.cc
index 92a8f60..cd5399b 100644
--- a/net/quic/core/congestion_control/windowed_filter_test.cc
+++ b/net/quic/core/congestion_control/windowed_filter_test.cc
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #include "net/quic/core/congestion_control/rtt_stats.h"
 #include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
diff --git a/net/quic/core/crypto/crypto_framer.h b/net/quic/core/crypto/crypto_framer.h
index 512a6b2..312efc3 100644
--- a/net/quic/core/crypto/crypto_framer.h
+++ b/net/quic/core/crypto/crypto_framer.h
@@ -15,7 +15,7 @@
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/crypto/crypto_handshake_message.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/crypto/crypto_framer_test.cc b/net/quic/core/crypto/crypto_framer_test.cc
index ae695d34..d99ebcdb 100644
--- a/net/quic/core/crypto/crypto_framer_test.cc
+++ b/net/quic/core/crypto/crypto_framer_test.cc
@@ -11,7 +11,7 @@
 #include "base/logging.h"
 #include "net/quic/core/crypto/crypto_handshake.h"
 #include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 
diff --git a/net/quic/core/crypto/crypto_handshake.h b/net/quic/core/crypto/crypto_handshake.h
index 48bee663..170a7b2c 100644
--- a/net/quic/core/crypto/crypto_handshake.h
+++ b/net/quic/core/crypto/crypto_handshake.h
@@ -13,7 +13,7 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/crypto/crypto_handshake_message.h b/net/quic/core/crypto/crypto_handshake_message.h
index 81bce9f..f09691d 100644
--- a/net/quic/core/crypto/crypto_handshake_message.h
+++ b/net/quic/core/crypto/crypto_handshake_message.h
@@ -15,7 +15,7 @@
 
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/crypto/crypto_protocol.h b/net/quic/core/crypto/crypto_protocol.h
index 4d088d7..432b9f5 100644
--- a/net/quic/core/crypto/crypto_protocol.h
+++ b/net/quic/core/crypto/crypto_protocol.h
@@ -152,6 +152,7 @@
 const QuicTag kAEAD = TAG('A', 'E', 'A', 'D');   // Authenticated
                                                  // encryption algorithms
 const QuicTag kCOPT = TAG('C', 'O', 'P', 'T');   // Connection options
+const QuicTag kCLOP = TAG('C', 'L', 'O', 'P');   // Client connection options
 const QuicTag kICSL = TAG('I', 'C', 'S', 'L');   // Idle network timeout
 const QuicTag kSCLS = TAG('S', 'C', 'L', 'S');   // Silently close on timeout
 const QuicTag kMSPC = TAG('M', 'S', 'P', 'C');   // Max streams per connection.
diff --git a/net/quic/core/crypto/crypto_utils.h b/net/quic/core/crypto/crypto_utils.h
index c0b4c1b..782cb44 100644
--- a/net/quic/core/crypto/crypto_utils.h
+++ b/net/quic/core/crypto/crypto_utils.h
@@ -18,7 +18,7 @@
 #include "net/quic/core/crypto/crypto_handshake.h"
 #include "net/quic/core/crypto/crypto_handshake_message.h"
 #include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/crypto/proof_source.h b/net/quic/core/crypto/proof_source.h
index ef59774..0fce4f4 100644
--- a/net/quic/core/crypto/proof_source.h
+++ b/net/quic/core/crypto/proof_source.h
@@ -12,7 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/crypto/quic_crypto_proof.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 
 namespace net {
diff --git a/net/quic/core/crypto/proof_verifier.h b/net/quic/core/crypto/proof_verifier.h
index c87b5c8c..9c224da1 100644
--- a/net/quic/core/crypto/proof_verifier.h
+++ b/net/quic/core/crypto/proof_verifier.h
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_types.h"
 
 namespace net {
diff --git a/net/quic/core/crypto/quic_crypto_client_config.h b/net/quic/core/crypto/quic_crypto_client_config.h
index ea7f99d3..24cc492 100644
--- a/net/quic/core/crypto/quic_crypto_client_config.h
+++ b/net/quic/core/crypto/quic_crypto_client_config.h
@@ -17,7 +17,7 @@
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/crypto/crypto_handshake.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 
 namespace net {
diff --git a/net/quic/core/crypto/quic_crypto_server_config.cc b/net/quic/core/crypto/quic_crypto_server_config.cc
index 9ae9e9c..a3f5e2b 100644
--- a/net/quic/core/crypto/quic_crypto_server_config.cc
+++ b/net/quic/core/crypto/quic_crypto_server_config.cc
@@ -35,7 +35,7 @@
 #include "net/quic/core/quic_bug_tracker.h"
 #include "net/quic/core/quic_clock.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_socket_address_coder.h"
 #include "net/quic/core/quic_utils.h"
 
diff --git a/net/quic/core/crypto/quic_decrypter.h b/net/quic/core/crypto/quic_decrypter.h
index 0a5eea3d..e620259b 100644
--- a/net/quic/core/crypto/quic_decrypter.h
+++ b/net/quic/core/crypto/quic_decrypter.h
@@ -9,7 +9,7 @@
 #include <stdint.h>
 
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/crypto/quic_encrypter.h b/net/quic/core/crypto/quic_encrypter.h
index fefd777..69f340dd 100644
--- a/net/quic/core/crypto/quic_encrypter.h
+++ b/net/quic/core/crypto/quic_encrypter.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/frames/quic_ack_frame.cc b/net/quic/core/frames/quic_ack_frame.cc
new file mode 100644
index 0000000..bf0cc63
--- /dev/null
+++ b/net/quic/core/frames/quic_ack_frame.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_ack_frame.h"
+
+#include "net/quic/core/quic_constants.h"
+
+using std::ostream;
+
+namespace net {
+
+bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
+                      QuicPacketNumber packet_number,
+                      QuicPacketNumber peer_least_packet_awaiting_ack) {
+  return packet_number >= peer_least_packet_awaiting_ack &&
+         !ack_frame.packets.Contains(packet_number);
+}
+
+QuicAckFrame::QuicAckFrame()
+    : largest_observed(0),
+      ack_delay_time(QuicTime::Delta::Infinite()),
+      path_id(kDefaultPathId) {}
+
+QuicAckFrame::QuicAckFrame(const QuicAckFrame& other) = default;
+
+QuicAckFrame::~QuicAckFrame() {}
+
+ostream& operator<<(std::ostream& os, const QuicAckFrame& ack_frame) {
+  os << "{ largest_observed: " << ack_frame.largest_observed
+     << ", ack_delay_time: " << ack_frame.ack_delay_time.ToMicroseconds()
+     << ", packets: [ " << ack_frame.packets << " ]"
+     << ", received_packets: [ ";
+  for (const std::pair<QuicPacketNumber, QuicTime>& p :
+       ack_frame.received_packet_times) {
+    os << p.first << " at " << p.second.ToDebuggingValue() << " ";
+  }
+  os << " ] }\n";
+  return os;
+}
+
+PacketNumberQueue::PacketNumberQueue() = default;
+PacketNumberQueue::PacketNumberQueue(const PacketNumberQueue& other) = default;
+PacketNumberQueue::PacketNumberQueue(PacketNumberQueue&& other) = default;
+PacketNumberQueue::~PacketNumberQueue() {}
+
+PacketNumberQueue& PacketNumberQueue::operator=(
+    const PacketNumberQueue& other) = default;
+PacketNumberQueue& PacketNumberQueue::operator=(PacketNumberQueue&& other) =
+    default;
+
+void PacketNumberQueue::Add(QuicPacketNumber packet_number) {
+  packet_number_intervals_.Add(packet_number, packet_number + 1);
+}
+
+void PacketNumberQueue::Add(QuicPacketNumber lower, QuicPacketNumber higher) {
+  packet_number_intervals_.Add(lower, higher);
+}
+
+void PacketNumberQueue::Remove(QuicPacketNumber packet_number) {
+  packet_number_intervals_.Difference(packet_number, packet_number + 1);
+}
+
+void PacketNumberQueue::Remove(QuicPacketNumber lower,
+                               QuicPacketNumber higher) {
+  packet_number_intervals_.Difference(lower, higher);
+}
+
+bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
+  if (Empty()) {
+    return false;
+  }
+  const QuicPacketNumber old_min = Min();
+  packet_number_intervals_.Difference(0, higher);
+  return Empty() || old_min != Min();
+}
+
+void PacketNumberQueue::Complement() {
+  if (Empty()) {
+    return;
+  }
+  packet_number_intervals_.Complement(Min(), Max() + 1);
+}
+
+bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
+  return packet_number_intervals_.Contains(packet_number);
+}
+
+bool PacketNumberQueue::Empty() const {
+  return packet_number_intervals_.Empty();
+}
+
+QuicPacketNumber PacketNumberQueue::Min() const {
+  DCHECK(!Empty());
+  return packet_number_intervals_.begin()->min();
+}
+
+QuicPacketNumber PacketNumberQueue::Max() const {
+  DCHECK(!Empty());
+  return packet_number_intervals_.rbegin()->max() - 1;
+}
+
+size_t PacketNumberQueue::NumPacketsSlow() const {
+  size_t num_packets = 0;
+  for (const auto& interval : packet_number_intervals_) {
+    num_packets += interval.Length();
+  }
+  return num_packets;
+}
+
+size_t PacketNumberQueue::NumIntervals() const {
+  return packet_number_intervals_.Size();
+}
+
+QuicPacketNumber PacketNumberQueue::LastIntervalLength() const {
+  DCHECK(!Empty());
+  return packet_number_intervals_.rbegin()->Length();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::lower_bound(
+    QuicPacketNumber packet_number) const {
+  // lower_bound returns the first interval that contains |packet_number| or the
+  // first interval after |packet_number|.
+  auto itr = packet_number_intervals_.Find(packet_number);
+  if (itr != packet_number_intervals_.end()) {
+    return itr;
+  }
+  for (itr = packet_number_intervals_.begin();
+       itr != packet_number_intervals_.end(); ++itr) {
+    if (packet_number < itr->min()) {
+      return itr;
+    }
+  }
+  return packet_number_intervals_.end();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::begin() const {
+  return packet_number_intervals_.begin();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::end() const {
+  return packet_number_intervals_.end();
+}
+
+PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rbegin() const {
+  return packet_number_intervals_.rbegin();
+}
+
+PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const {
+  return packet_number_intervals_.rend();
+}
+
+ostream& operator<<(ostream& os, const PacketNumberQueue& q) {
+  for (const Interval<QuicPacketNumber>& interval : q) {
+    for (QuicPacketNumber packet_number = interval.min();
+         packet_number < interval.max(); ++packet_number) {
+      os << packet_number << " ";
+    }
+  }
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_ack_frame.h b/net/quic/core/frames/quic_ack_frame.h
new file mode 100644
index 0000000..520d20bb
--- /dev/null
+++ b/net/quic/core/frames/quic_ack_frame.h
@@ -0,0 +1,132 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/quic/core/interval_set.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// A sequence of packet numbers where each number is unique. Intended to be used
+// in a sliding window fashion, where smaller old packet numbers are removed and
+// larger new packet numbers are added, with the occasional random access.
+class NET_EXPORT_PRIVATE PacketNumberQueue {
+ public:
+  using const_iterator = IntervalSet<QuicPacketNumber>::const_iterator;
+  using const_reverse_iterator =
+      IntervalSet<QuicPacketNumber>::const_reverse_iterator;
+
+  PacketNumberQueue();
+  PacketNumberQueue(const PacketNumberQueue& other);
+  PacketNumberQueue(PacketNumberQueue&& other);
+  ~PacketNumberQueue();
+
+  PacketNumberQueue& operator=(const PacketNumberQueue& other);
+  PacketNumberQueue& operator=(PacketNumberQueue&& other);
+
+  // Adds |packet_number| to the set of packets in the queue.
+  void Add(QuicPacketNumber packet_number);
+
+  // Adds packets between [lower, higher) to the set of packets in the queue. It
+  // is undefined behavior to call this with |higher| < |lower|.
+  void Add(QuicPacketNumber lower, QuicPacketNumber higher);
+
+  // Removes |packet_number| from the set of packets in the queue.
+  void Remove(QuicPacketNumber packet_number);
+
+  // Removes packets numbers between [lower, higher) to the set of packets in
+  // the queue. It is undefined behavior to call this with |higher| < |lower|.
+  void Remove(QuicPacketNumber lower, QuicPacketNumber higher);
+
+  // Removes packets with values less than |higher| from the set of packets in
+  // the queue. Returns true if packets were removed.
+  bool RemoveUpTo(QuicPacketNumber higher);
+
+  // Mutates packet number set so that it contains only those packet numbers
+  // from minimum to maximum packet number not currently in the set. Do nothing
+  // if packet number set is empty.
+  void Complement();
+
+  // Returns true if the queue contains |packet_number|.
+  bool Contains(QuicPacketNumber packet_number) const;
+
+  // Returns true if the queue is empty.
+  bool Empty() const;
+
+  // Returns the minimum packet number stored in the queue. It is undefined
+  // behavior to call this if the queue is empty.
+  QuicPacketNumber Min() const;
+
+  // Returns the maximum packet number stored in the queue. It is undefined
+  // behavior to call this if the queue is empty.
+  QuicPacketNumber Max() const;
+
+  // Returns the number of unique packets stored in the queue. Inefficient; only
+  // exposed for testing.
+  size_t NumPacketsSlow() const;
+
+  // Returns the number of disjoint packet number intervals contained in the
+  // queue.
+  size_t NumIntervals() const;
+
+  // Returns the length of last interval.
+  QuicPacketNumber LastIntervalLength() const;
+
+  // Returns iterators over the packet number intervals.
+  const_iterator begin() const;
+  const_iterator end() const;
+  const_reverse_iterator rbegin() const;
+  const_reverse_iterator rend() const;
+  const_iterator lower_bound(QuicPacketNumber packet_number) const;
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(
+      std::ostream& os,
+      const PacketNumberQueue& q);
+
+ private:
+  IntervalSet<QuicPacketNumber> packet_number_intervals_;
+};
+
+struct NET_EXPORT_PRIVATE QuicAckFrame {
+  QuicAckFrame();
+  QuicAckFrame(const QuicAckFrame& other);
+  ~QuicAckFrame();
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+                                                     const QuicAckFrame& s);
+
+  // The highest packet number we've observed from the peer.
+  QuicPacketNumber largest_observed;
+
+  // Time elapsed since largest_observed was received until this Ack frame was
+  // sent.
+  QuicTime::Delta ack_delay_time;
+
+  // Vector of <packet_number, time> for when packets arrived.
+  PacketTimeVector received_packet_times;
+
+  // Set of packets.
+  PacketNumberQueue packets;
+
+  // Path which this ack belongs to.
+  QuicPathId path_id;
+};
+
+// True if the packet number is greater than largest_observed or is listed
+// as missing.
+// Always returns false for packet numbers less than least_unacked.
+NET_EXPORT_PRIVATE bool IsAwaitingPacket(
+    const QuicAckFrame& ack_frame,
+    QuicPacketNumber packet_number,
+    QuicPacketNumber peer_least_packet_awaiting_ack);
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
diff --git a/net/quic/core/frames/quic_blocked_frame.cc b/net/quic/core/frames/quic_blocked_frame.cc
new file mode 100644
index 0000000..a707838
--- /dev/null
+++ b/net/quic/core/frames/quic_blocked_frame.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_blocked_frame.h"
+
+using std::ostream;
+
+namespace net {
+
+QuicBlockedFrame::QuicBlockedFrame(QuicStreamId stream_id)
+    : stream_id(stream_id) {}
+
+ostream& operator<<(ostream& os, const QuicBlockedFrame& blocked_frame) {
+  os << "{ stream_id: " << blocked_frame.stream_id << " }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_blocked_frame.h b/net/quic/core/frames/quic_blocked_frame.h
new file mode 100644
index 0000000..5a42642d2
--- /dev/null
+++ b/net/quic/core/frames/quic_blocked_frame.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
+
+#include "net/base/net_export.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// The BLOCKED frame is used to indicate to the remote endpoint that this
+// endpoint believes itself to be flow-control blocked but otherwise ready to
+// send data. The BLOCKED frame is purely advisory and optional.
+// Based on SPDY's BLOCKED frame (undocumented as of 2014-01-28).
+struct NET_EXPORT_PRIVATE QuicBlockedFrame {
+  QuicBlockedFrame() {}
+  explicit QuicBlockedFrame(QuicStreamId stream_id);
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+                                                     const QuicBlockedFrame& b);
+
+  // The stream this frame applies to.  0 is a special case meaning the overall
+  // connection rather than a specific stream.
+  QuicStreamId stream_id;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
diff --git a/net/quic/core/frames/quic_connection_close_frame.cc b/net/quic/core/frames/quic_connection_close_frame.cc
new file mode 100644
index 0000000..5f30163
--- /dev/null
+++ b/net/quic/core/frames/quic_connection_close_frame.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_connection_close_frame.h"
+
+using std::ostream;
+
+namespace net {
+
+QuicConnectionCloseFrame::QuicConnectionCloseFrame()
+    : error_code(QUIC_NO_ERROR) {}
+
+ostream& operator<<(std::ostream& os,
+                    const QuicConnectionCloseFrame& connection_close_frame) {
+  os << "{ error_code: " << connection_close_frame.error_code
+     << ", error_details: '" << connection_close_frame.error_details << "' }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_connection_close_frame.h b/net/quic/core/frames/quic_connection_close_frame.h
new file mode 100644
index 0000000..01187846
--- /dev/null
+++ b/net/quic/core/frames/quic_connection_close_frame.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
+
+#include <ostream>
+#include <string>
+
+#include "net/base/net_export.h"
+#include "net/quic/core/quic_error_codes.h"
+
+namespace net {
+
+struct NET_EXPORT_PRIVATE QuicConnectionCloseFrame {
+  QuicConnectionCloseFrame();
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(
+      std::ostream& os,
+      const QuicConnectionCloseFrame& c);
+
+  QuicErrorCode error_code;
+  std::string error_details;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
diff --git a/net/quic/core/frames/quic_frame.cc b/net/quic/core/frames/quic_frame.cc
new file mode 100644
index 0000000..c33cb74bd
--- /dev/null
+++ b/net/quic/core/frames/quic_frame.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_frame.h"
+
+using base::StringPiece;
+using std::ostream;
+using std::string;
+
+namespace net {
+
+QuicFrame::QuicFrame() {}
+
+QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
+    : type(PADDING_FRAME), padding_frame(padding_frame) {}
+
+QuicFrame::QuicFrame(QuicStreamFrame* stream_frame)
+    : type(STREAM_FRAME), stream_frame(stream_frame) {}
+
+QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame)
+    : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicStopWaitingFrame* frame)
+    : type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicPingFrame frame)
+    : type(PING_FRAME), ping_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicRstStreamFrame* frame)
+    : type(RST_STREAM_FRAME), rst_stream_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame)
+    : type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicGoAwayFrame* frame)
+    : type(GOAWAY_FRAME), goaway_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicWindowUpdateFrame* frame)
+    : type(WINDOW_UPDATE_FRAME), window_update_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicBlockedFrame* frame)
+    : type(BLOCKED_FRAME), blocked_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicPathCloseFrame* frame)
+    : type(PATH_CLOSE_FRAME), path_close_frame(frame) {}
+
+void DeleteFrames(QuicFrames* frames) {
+  for (QuicFrame& frame : *frames) {
+    switch (frame.type) {
+      // Frames smaller than a pointer are inlined, so don't need to be deleted.
+      case PADDING_FRAME:
+      case MTU_DISCOVERY_FRAME:
+      case PING_FRAME:
+        break;
+      case STREAM_FRAME:
+        delete frame.stream_frame;
+        break;
+      case ACK_FRAME:
+        delete frame.ack_frame;
+        break;
+      case STOP_WAITING_FRAME:
+        delete frame.stop_waiting_frame;
+        break;
+      case RST_STREAM_FRAME:
+        delete frame.rst_stream_frame;
+        break;
+      case CONNECTION_CLOSE_FRAME:
+        delete frame.connection_close_frame;
+        break;
+      case GOAWAY_FRAME:
+        delete frame.goaway_frame;
+        break;
+      case BLOCKED_FRAME:
+        delete frame.blocked_frame;
+        break;
+      case WINDOW_UPDATE_FRAME:
+        delete frame.window_update_frame;
+        break;
+      case PATH_CLOSE_FRAME:
+        delete frame.path_close_frame;
+        break;
+      case NUM_FRAME_TYPES:
+        DCHECK(false) << "Cannot delete type: " << frame.type;
+    }
+  }
+  frames->clear();
+}
+
+void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id) {
+  QuicFrames::iterator it = frames->begin();
+  while (it != frames->end()) {
+    if (it->type != STREAM_FRAME || it->stream_frame->stream_id != stream_id) {
+      ++it;
+      continue;
+    }
+    delete it->stream_frame;
+    it = frames->erase(it);
+  }
+}
+
+ostream& operator<<(ostream& os, const QuicFrame& frame) {
+  switch (frame.type) {
+    case PADDING_FRAME: {
+      os << "type { PADDING_FRAME } " << frame.padding_frame;
+      break;
+    }
+    case RST_STREAM_FRAME: {
+      os << "type { RST_STREAM_FRAME } " << *(frame.rst_stream_frame);
+      break;
+    }
+    case CONNECTION_CLOSE_FRAME: {
+      os << "type { CONNECTION_CLOSE_FRAME } "
+         << *(frame.connection_close_frame);
+      break;
+    }
+    case GOAWAY_FRAME: {
+      os << "type { GOAWAY_FRAME } " << *(frame.goaway_frame);
+      break;
+    }
+    case WINDOW_UPDATE_FRAME: {
+      os << "type { WINDOW_UPDATE_FRAME } " << *(frame.window_update_frame);
+      break;
+    }
+    case BLOCKED_FRAME: {
+      os << "type { BLOCKED_FRAME } " << *(frame.blocked_frame);
+      break;
+    }
+    case STREAM_FRAME: {
+      os << "type { STREAM_FRAME } " << *(frame.stream_frame);
+      break;
+    }
+    case ACK_FRAME: {
+      os << "type { ACK_FRAME } " << *(frame.ack_frame);
+      break;
+    }
+    case STOP_WAITING_FRAME: {
+      os << "type { STOP_WAITING_FRAME } " << *(frame.stop_waiting_frame);
+      break;
+    }
+    case PING_FRAME: {
+      os << "type { PING_FRAME } ";
+      break;
+    }
+    case MTU_DISCOVERY_FRAME: {
+      os << "type { MTU_DISCOVERY_FRAME } ";
+      break;
+    }
+    case PATH_CLOSE_FRAME: {
+      os << "type { PATH_CLOSE_FRAME } " << *(frame.path_close_frame);
+      break;
+    }
+    default: {
+      LOG(ERROR) << "Unknown frame type: " << frame.type;
+      break;
+    }
+  }
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_frame.h b/net/quic/core/frames/quic_frame.h
new file mode 100644
index 0000000..9e65ce2
--- /dev/null
+++ b/net/quic/core/frames/quic_frame.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_FRAME_H_
+
+#include <vector>
+
+#include "net/quic/core/frames/quic_ack_frame.h"
+#include "net/quic/core/frames/quic_blocked_frame.h"
+#include "net/quic/core/frames/quic_connection_close_frame.h"
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/frames/quic_goaway_frame.h"
+#include "net/quic/core/frames/quic_mtu_discovery_frame.h"
+#include "net/quic/core/frames/quic_padding_frame.h"
+#include "net/quic/core/frames/quic_path_close_frame.h"
+#include "net/quic/core/frames/quic_ping_frame.h"
+#include "net/quic/core/frames/quic_rst_stream_frame.h"
+#include "net/quic/core/frames/quic_stop_waiting_frame.h"
+#include "net/quic/core/frames/quic_stream_frame.h"
+#include "net/quic/core/frames/quic_window_update_frame.h"
+#include "net/quic/core/quic_constants.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+struct NET_EXPORT_PRIVATE QuicFrame {
+  QuicFrame();
+  explicit QuicFrame(QuicPaddingFrame padding_frame);
+  explicit QuicFrame(QuicMtuDiscoveryFrame frame);
+  explicit QuicFrame(QuicPingFrame frame);
+
+  explicit QuicFrame(QuicStreamFrame* stream_frame);
+  explicit QuicFrame(QuicAckFrame* frame);
+  explicit QuicFrame(QuicRstStreamFrame* frame);
+  explicit QuicFrame(QuicConnectionCloseFrame* frame);
+  explicit QuicFrame(QuicStopWaitingFrame* frame);
+  explicit QuicFrame(QuicGoAwayFrame* frame);
+  explicit QuicFrame(QuicWindowUpdateFrame* frame);
+  explicit QuicFrame(QuicBlockedFrame* frame);
+  explicit QuicFrame(QuicPathCloseFrame* frame);
+
+  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
+                                                     const QuicFrame& frame);
+
+  QuicFrameType type;
+  union {
+    // Frames smaller than a pointer are inline.
+    QuicPaddingFrame padding_frame;
+    QuicMtuDiscoveryFrame mtu_discovery_frame;
+    QuicPingFrame ping_frame;
+
+    // Frames larger than a pointer.
+    QuicStreamFrame* stream_frame;
+    QuicAckFrame* ack_frame;
+    QuicStopWaitingFrame* stop_waiting_frame;
+    QuicRstStreamFrame* rst_stream_frame;
+    QuicConnectionCloseFrame* connection_close_frame;
+    QuicGoAwayFrame* goaway_frame;
+    QuicWindowUpdateFrame* window_update_frame;
+    QuicBlockedFrame* blocked_frame;
+    QuicPathCloseFrame* path_close_frame;
+  };
+};
+// QuicFrameType consumes 8 bytes with padding.
+static_assert(sizeof(QuicFrame) <= 16,
+              "Frames larger than 8 bytes should be referenced by pointer.");
+
+typedef std::vector<QuicFrame> QuicFrames;
+
+// Deletes all the sub-frames contained in |frames|.
+NET_EXPORT_PRIVATE void DeleteFrames(QuicFrames* frames);
+
+// Deletes all the QuicStreamFrames for the specified |stream_id|.
+NET_EXPORT_PRIVATE void RemoveFramesForStream(QuicFrames* frames,
+                                              QuicStreamId stream_id);
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_FRAMES_H_
diff --git a/net/quic/core/quic_protocol_test.cc b/net/quic/core/frames/quic_frame_test.cc
similarity index 80%
rename from net/quic/core/quic_protocol_test.cc
rename to net/quic/core/frames/quic_frame_test.cc
index d9bacf5..3225d0e7 100644
--- a/net/quic/core/quic_protocol_test.cc
+++ b/net/quic/core/frames/quic_frame_test.cc
@@ -1,32 +1,119 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2016 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 "net/quic/core/quic_protocol.h"
+#include "net/quic/core/frames/quic_frame.h"
 
-#include <sstream>
-
-#include "base/stl_util.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
-#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
 namespace test {
 namespace {
 
-TEST(QuicProtocolTest, MakeQuicTag) {
-  QuicTag tag = MakeQuicTag('A', 'B', 'C', 'D');
-  char bytes[4];
-  memcpy(bytes, &tag, 4);
-  EXPECT_EQ('A', bytes[0]);
-  EXPECT_EQ('B', bytes[1]);
-  EXPECT_EQ('C', bytes[2]);
-  EXPECT_EQ('D', bytes[3]);
+using testing::_;
+
+TEST(QuicFramesTest, AckFrameToString) {
+  QuicAckFrame frame;
+  frame.largest_observed = 2;
+  frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
+  frame.packets.Add(4);
+  frame.packets.Add(5);
+  frame.received_packet_times = {
+      {6, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ(
+      "{ largest_observed: 2, ack_delay_time: 3, "
+      "packets: [ 4 5  ], received_packets: [ 6 at 7  ] }\n",
+      stream.str());
 }
 
-TEST(QuicProtocolTest, IsAwaitingPacket) {
+TEST(QuicFramesTest, PaddingFrameToString) {
+  QuicPaddingFrame frame;
+  frame.num_padding_bytes = 1;
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ("{ num_padding_bytes: 1 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, RstStreamFrameToString) {
+  QuicRstStreamFrame frame;
+  frame.stream_id = 1;
+  frame.error_code = QUIC_STREAM_CANCELLED;
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ("{ stream_id: 1, error_code: 6 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, ConnectionCloseFrameToString) {
+  QuicConnectionCloseFrame frame;
+  frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
+  frame.error_details = "No recent network activity.";
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ(
+      "{ error_code: 25, error_details: 'No recent network activity.' }\n",
+      stream.str());
+}
+
+TEST(QuicFramesTest, GoAwayFrameToString) {
+  QuicGoAwayFrame frame;
+  frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
+  frame.last_good_stream_id = 2;
+  frame.reason_phrase = "Reason";
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ(
+      "{ error_code: 25, last_good_stream_id: 2, reason_phrase: 'Reason' }\n",
+      stream.str());
+}
+
+TEST(QuicFramesTest, WindowUpdateFrameToString) {
+  QuicWindowUpdateFrame frame;
+  std::ostringstream stream;
+  frame.stream_id = 1;
+  frame.byte_offset = 2;
+  stream << frame;
+  EXPECT_EQ("{ stream_id: 1, byte_offset: 2 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, BlockedFrameToString) {
+  QuicBlockedFrame frame;
+  frame.stream_id = 1;
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ("{ stream_id: 1 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, StreamFrameToString) {
+  QuicStreamFrame frame;
+  frame.stream_id = 1;
+  frame.fin = false;
+  frame.offset = 2;
+  frame.data_length = 3;
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ("{ stream_id: 1, fin: 0, offset: 2, length: 3 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, StopWaitingFrameToString) {
+  QuicStopWaitingFrame frame;
+  frame.least_unacked = 2;
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ("{ least_unacked: 2 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, PathCloseFrameToString) {
+  QuicPathCloseFrame frame;
+  frame.path_id = 1;
+  std::ostringstream stream;
+  stream << frame;
+  EXPECT_EQ("{ path_id: 1 }\n", stream.str());
+}
+
+TEST(QuicFramesTest, IsAwaitingPacket) {
   QuicAckFrame ack_frame1;
   ack_frame1.largest_observed = 10u;
   ack_frame1.packets.Add(1, 11);
@@ -47,119 +134,6 @@
   EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 50u, 20u));
 }
 
-TEST(QuicProtocolTest, AckFrameToString) {
-  QuicAckFrame frame;
-  frame.largest_observed = 2;
-  frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
-  frame.packets.Add(4);
-  frame.packets.Add(5);
-  frame.received_packet_times = {
-      {6, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ(
-      "{ largest_observed: 2, ack_delay_time: 3, "
-      "packets: [ 4 5  ], received_packets: [ 6 at 7  ] }\n",
-      stream.str());
-}
-
-TEST(QuicProtocolTest, PaddingFrameToString) {
-  QuicPaddingFrame frame;
-  frame.num_padding_bytes = 1;
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ("{ num_padding_bytes: 1 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, RstStreamFrameToString) {
-  QuicRstStreamFrame frame;
-  frame.stream_id = 1;
-  frame.error_code = QUIC_STREAM_CANCELLED;
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ("{ stream_id: 1, error_code: 6 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, ConnectionCloseFrameToString) {
-  QuicConnectionCloseFrame frame;
-  frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
-  frame.error_details = "No recent network activity.";
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ(
-      "{ error_code: 25, error_details: 'No recent network activity.' }\n",
-      stream.str());
-}
-
-TEST(QuicProtocolTest, GoAwayFrameToString) {
-  QuicGoAwayFrame frame;
-  frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
-  frame.last_good_stream_id = 2;
-  frame.reason_phrase = "Reason";
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ(
-      "{ error_code: 25, last_good_stream_id: 2, reason_phrase: 'Reason' }\n",
-      stream.str());
-}
-
-TEST(QuicProtocolTest, WindowUpdateFrameToString) {
-  QuicWindowUpdateFrame frame;
-  std::ostringstream stream;
-  frame.stream_id = 1;
-  frame.byte_offset = 2;
-  stream << frame;
-  EXPECT_EQ("{ stream_id: 1, byte_offset: 2 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, BlockedFrameToString) {
-  QuicBlockedFrame frame;
-  frame.stream_id = 1;
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ("{ stream_id: 1 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, StreamFrameToString) {
-  QuicStreamFrame frame;
-  frame.stream_id = 1;
-  frame.fin = false;
-  frame.offset = 2;
-  frame.data_length = 3;
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ("{ stream_id: 1, fin: 0, offset: 2, length: 3 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, StopWaitingFrameToString) {
-  QuicStopWaitingFrame frame;
-  frame.least_unacked = 2;
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ("{ least_unacked: 2 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, PathCloseFrameToString) {
-  QuicPathCloseFrame frame;
-  frame.path_id = 1;
-  std::ostringstream stream;
-  stream << frame;
-  EXPECT_EQ("{ path_id: 1 }\n", stream.str());
-}
-
-TEST(QuicProtocolTest, QuicVersionManager) {
-  QuicFlagSaver flags;
-  FLAGS_quic_enable_version_36_v3 = false;
-  QuicVersionManager manager(AllSupportedVersions());
-  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
-            manager.GetSupportedVersions());
-  FLAGS_quic_enable_version_36_v3 = true;
-  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
-            manager.GetSupportedVersions());
-  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[1]);
-}
-
 // Tests that a queue contains the expected data after calls to Add().
 TEST(PacketNumberQueueTest, AddRange) {
   PacketNumberQueue queue;
diff --git a/net/quic/core/frames/quic_goaway_frame.cc b/net/quic/core/frames/quic_goaway_frame.cc
new file mode 100644
index 0000000..ded85b9
--- /dev/null
+++ b/net/quic/core/frames/quic_goaway_frame.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_goaway_frame.h"
+
+using std::ostream;
+using std::string;
+
+namespace net {
+
+QuicGoAwayFrame::QuicGoAwayFrame()
+    : error_code(QUIC_NO_ERROR), last_good_stream_id(0) {}
+
+QuicGoAwayFrame::QuicGoAwayFrame(QuicErrorCode error_code,
+                                 QuicStreamId last_good_stream_id,
+                                 const string& reason)
+    : error_code(error_code),
+      last_good_stream_id(last_good_stream_id),
+      reason_phrase(reason) {}
+
+ostream& operator<<(ostream& os, const QuicGoAwayFrame& goaway_frame) {
+  os << "{ error_code: " << goaway_frame.error_code
+     << ", last_good_stream_id: " << goaway_frame.last_good_stream_id
+     << ", reason_phrase: '" << goaway_frame.reason_phrase << "' }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_goaway_frame.h b/net/quic/core/frames/quic_goaway_frame.h
new file mode 100644
index 0000000..dedb893
--- /dev/null
+++ b/net/quic/core/frames/quic_goaway_frame.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
+
+#include <string>
+
+#include "net/base/net_export.h"
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+struct NET_EXPORT_PRIVATE QuicGoAwayFrame {
+  QuicGoAwayFrame();
+  QuicGoAwayFrame(QuicErrorCode error_code,
+                  QuicStreamId last_good_stream_id,
+                  const std::string& reason);
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+                                                     const QuicGoAwayFrame& g);
+
+  QuicErrorCode error_code;
+  QuicStreamId last_good_stream_id;
+  std::string reason_phrase;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
diff --git a/net/quic/core/frames/quic_mtu_discovery_frame.h b/net/quic/core/frames/quic_mtu_discovery_frame.h
new file mode 100644
index 0000000..2395a66
--- /dev/null
+++ b/net/quic/core/frames/quic_mtu_discovery_frame.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// A path MTU discovery frame contains no payload and is serialized as a ping
+// frame.
+struct NET_EXPORT_PRIVATE QuicMtuDiscoveryFrame {};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
diff --git a/net/quic/core/frames/quic_padding_frame.cc b/net/quic/core/frames/quic_padding_frame.cc
new file mode 100644
index 0000000..0f15af1
--- /dev/null
+++ b/net/quic/core/frames/quic_padding_frame.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_padding_frame.h"
+
+using std::ostream;
+using std::string;
+
+namespace net {
+
+ostream& operator<<(ostream& os, const QuicPaddingFrame& padding_frame) {
+  os << "{ num_padding_bytes: " << padding_frame.num_padding_bytes << " }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_padding_frame.h b/net/quic/core/frames/quic_padding_frame.h
new file mode 100644
index 0000000..bca71189
--- /dev/null
+++ b/net/quic/core/frames/quic_padding_frame.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
+
+#include <cstdint>
+#include <ostream>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// A padding frame contains no payload.
+struct NET_EXPORT_PRIVATE QuicPaddingFrame {
+  QuicPaddingFrame() : num_padding_bytes(-1) {}
+  explicit QuicPaddingFrame(int num_padding_bytes)
+      : num_padding_bytes(num_padding_bytes) {}
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+                                                     const QuicPaddingFrame& s);
+
+  // -1: full padding to the end of a max-sized packet
+  // otherwise: only pad up to num_padding_bytes bytes
+  int num_padding_bytes;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
diff --git a/net/quic/core/frames/quic_path_close_frame.cc b/net/quic/core/frames/quic_path_close_frame.cc
new file mode 100644
index 0000000..6e4fbed
--- /dev/null
+++ b/net/quic/core/frames/quic_path_close_frame.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_path_close_frame.h"
+
+using std::ostream;
+
+namespace net {
+
+QuicPathCloseFrame::QuicPathCloseFrame(QuicPathId path_id) : path_id(path_id) {}
+
+ostream& operator<<(ostream& os, const QuicPathCloseFrame& path_close_frame) {
+  os << "{ path_id: " << static_cast<int>(path_close_frame.path_id) << " }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_path_close_frame.h b/net/quic/core/frames/quic_path_close_frame.h
new file mode 100644
index 0000000..0af13628
--- /dev/null
+++ b/net/quic/core/frames/quic_path_close_frame.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_PATH_CLOSE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PATH_CLOSE_FRAME_H_
+
+#include "net/base/net_export.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// The PATH_CLOSE frame is used to explicitly close a path. Both endpoints can
+// send a PATH_CLOSE frame to initiate a path termination. A path is considered
+// to be closed either a PATH_CLOSE frame is sent or received. An endpoint drops
+// receive side of a closed path, and packets with retransmittable frames on a
+// closed path are marked as retransmissions which will be transmitted on other
+// paths.
+struct NET_EXPORT_PRIVATE QuicPathCloseFrame {
+  QuicPathCloseFrame() {}
+  explicit QuicPathCloseFrame(QuicPathId path_id);
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(
+      std::ostream& os,
+      const QuicPathCloseFrame& p);
+
+  QuicPathId path_id;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_FRAMES_H_
diff --git a/net/quic/core/frames/quic_ping_frame.h b/net/quic/core/frames/quic_ping_frame.h
new file mode 100644
index 0000000..9883bc5
--- /dev/null
+++ b/net/quic/core/frames/quic_ping_frame.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// A ping frame contains no payload, though it is retransmittable,
+// and ACK'd just like other normal frames.
+struct NET_EXPORT_PRIVATE QuicPingFrame {};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
diff --git a/net/quic/core/frames/quic_rst_stream_frame.cc b/net/quic/core/frames/quic_rst_stream_frame.cc
new file mode 100644
index 0000000..dc929fd
--- /dev/null
+++ b/net/quic/core/frames/quic_rst_stream_frame.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_rst_stream_frame.h"
+
+using std::ostream;
+
+namespace net {
+
+QuicRstStreamFrame::QuicRstStreamFrame()
+    : stream_id(0), error_code(QUIC_STREAM_NO_ERROR), byte_offset(0) {}
+
+QuicRstStreamFrame::QuicRstStreamFrame(QuicStreamId stream_id,
+                                       QuicRstStreamErrorCode error_code,
+                                       QuicStreamOffset bytes_written)
+    : stream_id(stream_id),
+      error_code(error_code),
+      byte_offset(bytes_written) {}
+
+ostream& operator<<(ostream& os, const QuicRstStreamFrame& rst_frame) {
+  os << "{ stream_id: " << rst_frame.stream_id
+     << ", error_code: " << rst_frame.error_code << " }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_rst_stream_frame.h b/net/quic/core/frames/quic_rst_stream_frame.h
new file mode 100644
index 0000000..4ba30c0
--- /dev/null
+++ b/net/quic/core/frames/quic_rst_stream_frame.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
+
+#include "net/base/net_export.h"
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+struct NET_EXPORT_PRIVATE QuicRstStreamFrame {
+  QuicRstStreamFrame();
+  QuicRstStreamFrame(QuicStreamId stream_id,
+                     QuicRstStreamErrorCode error_code,
+                     QuicStreamOffset bytes_written);
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(
+      std::ostream& os,
+      const QuicRstStreamFrame& r);
+
+  QuicStreamId stream_id;
+  QuicRstStreamErrorCode error_code;
+
+  // Used to update flow control windows. On termination of a stream, both
+  // endpoints must inform the peer of the number of bytes they have sent on
+  // that stream. This can be done through normal termination (data packet with
+  // FIN) or through a RST.
+  QuicStreamOffset byte_offset;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
diff --git a/net/quic/core/frames/quic_stop_waiting_frame.cc b/net/quic/core/frames/quic_stop_waiting_frame.cc
new file mode 100644
index 0000000..8a243b08
--- /dev/null
+++ b/net/quic/core/frames/quic_stop_waiting_frame.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_stop_waiting_frame.h"
+
+#include "net/quic/core/quic_constants.h"
+
+using std::ostream;
+
+namespace net {
+
+QuicStopWaitingFrame::QuicStopWaitingFrame()
+    : path_id(kDefaultPathId), least_unacked(0) {}
+
+QuicStopWaitingFrame::~QuicStopWaitingFrame() {}
+
+ostream& operator<<(ostream& os, const QuicStopWaitingFrame& sent_info) {
+  os << "{ least_unacked: " << sent_info.least_unacked << " }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_stop_waiting_frame.h b/net/quic/core/frames/quic_stop_waiting_frame.h
new file mode 100644
index 0000000..fcbbb74
--- /dev/null
+++ b/net/quic/core/frames/quic_stop_waiting_frame.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
+
+#include "net/base/net_export.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+struct NET_EXPORT_PRIVATE QuicStopWaitingFrame {
+  QuicStopWaitingFrame();
+  ~QuicStopWaitingFrame();
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(
+      std::ostream& os,
+      const QuicStopWaitingFrame& s);
+  // Path which this stop waiting frame belongs to.
+  QuicPathId path_id;
+  // The lowest packet we've sent which is unacked, and we expect an ack for.
+  QuicPacketNumber least_unacked;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
diff --git a/net/quic/core/frames/quic_stream_frame.cc b/net/quic/core/frames/quic_stream_frame.cc
new file mode 100644
index 0000000..022bf69
--- /dev/null
+++ b/net/quic/core/frames/quic_stream_frame.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_stream_frame.h"
+
+#include "base/logging.h"
+
+using base::StringPiece;
+using std::ostream;
+
+namespace net {
+
+void StreamBufferDeleter::operator()(char* buffer) const {
+  if (allocator_ != nullptr && buffer != nullptr) {
+    allocator_->Delete(buffer);
+  }
+}
+
+UniqueStreamBuffer NewStreamBuffer(QuicBufferAllocator* allocator,
+                                   size_t size) {
+  return UniqueStreamBuffer(allocator->New(size),
+                            StreamBufferDeleter(allocator));
+}
+
+QuicStreamFrame::QuicStreamFrame()
+    : QuicStreamFrame(0, false, 0, nullptr, 0, nullptr) {}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+                                 bool fin,
+                                 QuicStreamOffset offset,
+                                 StringPiece data)
+    : QuicStreamFrame(stream_id,
+                      fin,
+                      offset,
+                      data.data(),
+                      data.length(),
+                      nullptr) {}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+                                 bool fin,
+                                 QuicStreamOffset offset,
+                                 QuicPacketLength data_length,
+                                 UniqueStreamBuffer buffer)
+    : QuicStreamFrame(stream_id,
+                      fin,
+                      offset,
+                      nullptr,
+                      data_length,
+                      std::move(buffer)) {
+  DCHECK(this->buffer != nullptr);
+  DCHECK_EQ(data_buffer, this->buffer.get());
+}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+                                 bool fin,
+                                 QuicStreamOffset offset,
+                                 const char* data_buffer,
+                                 QuicPacketLength data_length,
+                                 UniqueStreamBuffer buffer)
+    : stream_id(stream_id),
+      fin(fin),
+      data_length(data_length),
+      data_buffer(data_buffer),
+      offset(offset),
+      buffer(std::move(buffer)) {
+  if (this->buffer != nullptr) {
+    DCHECK(data_buffer == nullptr);
+    this->data_buffer = this->buffer.get();
+  }
+}
+
+QuicStreamFrame::~QuicStreamFrame() {}
+
+ostream& operator<<(ostream& os, const QuicStreamFrame& stream_frame) {
+  os << "{ stream_id: " << stream_frame.stream_id
+     << ", fin: " << stream_frame.fin << ", offset: " << stream_frame.offset
+     << ", length: " << stream_frame.data_length << " }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_stream_frame.h b/net/quic/core/frames/quic_stream_frame.h
new file mode 100644
index 0000000..9efbd97
--- /dev/null
+++ b/net/quic/core/frames/quic_stream_frame.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
+
+#include <memory>
+
+#include "base/strings/string_piece.h"
+#include "net/quic/core/quic_buffer_allocator.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// Deleter for stream buffers. Copyable to support platforms where the deleter
+// of a unique_ptr must be copyable. Otherwise it would be nice for this to be
+// move-only.
+class NET_EXPORT_PRIVATE StreamBufferDeleter {
+ public:
+  StreamBufferDeleter() : allocator_(nullptr) {}
+  explicit StreamBufferDeleter(QuicBufferAllocator* allocator)
+      : allocator_(allocator) {}
+
+  // Deletes |buffer| using |allocator_|.
+  void operator()(char* buffer) const;
+
+ private:
+  // Not owned; must be valid so long as the buffer stored in the unique_ptr
+  // that owns |this| is valid.
+  QuicBufferAllocator* allocator_;
+};
+
+using UniqueStreamBuffer = std::unique_ptr<char[], StreamBufferDeleter>;
+
+// Allocates memory of size |size| using |allocator| for a QUIC stream buffer.
+NET_EXPORT_PRIVATE UniqueStreamBuffer
+NewStreamBuffer(QuicBufferAllocator* allocator, size_t size);
+
+struct NET_EXPORT_PRIVATE QuicStreamFrame {
+  QuicStreamFrame();
+  QuicStreamFrame(QuicStreamId stream_id,
+                  bool fin,
+                  QuicStreamOffset offset,
+                  base::StringPiece data);
+  QuicStreamFrame(QuicStreamId stream_id,
+                  bool fin,
+                  QuicStreamOffset offset,
+                  QuicPacketLength data_length,
+                  UniqueStreamBuffer buffer);
+  ~QuicStreamFrame();
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+                                                     const QuicStreamFrame& s);
+
+  QuicStreamId stream_id;
+  bool fin;
+  QuicPacketLength data_length;
+  const char* data_buffer;
+  QuicStreamOffset offset;  // Location of this data in the stream.
+  // nullptr when the QuicStreamFrame is received, and non-null when sent.
+  UniqueStreamBuffer buffer;
+
+ private:
+  QuicStreamFrame(QuicStreamId stream_id,
+                  bool fin,
+                  QuicStreamOffset offset,
+                  const char* data_buffer,
+                  QuicPacketLength data_length,
+                  UniqueStreamBuffer buffer);
+
+  DISALLOW_COPY_AND_ASSIGN(QuicStreamFrame);
+};
+static_assert(sizeof(QuicStreamFrame) <= 64,
+              "Keep the QuicStreamFrame size to a cacheline.");
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_FRAMES_H_
diff --git a/net/quic/core/frames/quic_window_update_frame.cc b/net/quic/core/frames/quic_window_update_frame.cc
new file mode 100644
index 0000000..24eb0cc
--- /dev/null
+++ b/net/quic/core/frames/quic_window_update_frame.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2016 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 "net/quic/core/frames/quic_window_update_frame.h"
+
+using std::ostream;
+
+namespace net {
+
+QuicWindowUpdateFrame::QuicWindowUpdateFrame(QuicStreamId stream_id,
+                                             QuicStreamOffset byte_offset)
+    : stream_id(stream_id), byte_offset(byte_offset) {}
+
+ostream& operator<<(ostream& os,
+                    const QuicWindowUpdateFrame& window_update_frame) {
+  os << "{ stream_id: " << window_update_frame.stream_id
+     << ", byte_offset: " << window_update_frame.byte_offset << " }\n";
+  return os;
+}
+
+}  // namespace net
diff --git a/net/quic/core/frames/quic_window_update_frame.h b/net/quic/core/frames/quic_window_update_frame.h
new file mode 100644
index 0000000..fa9b946
--- /dev/null
+++ b/net/quic/core/frames/quic_window_update_frame.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
+
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// Flow control updates per-stream and at the connection levoel.
+// Based on SPDY's WINDOW_UPDATE frame, but uses an absolute byte offset rather
+// than a window delta.
+// TODO(rjshade): A possible future optimization is to make stream_id and
+//                byte_offset variable length, similar to stream frames.
+struct NET_EXPORT_PRIVATE QuicWindowUpdateFrame {
+  QuicWindowUpdateFrame() {}
+  QuicWindowUpdateFrame(QuicStreamId stream_id, QuicStreamOffset byte_offset);
+
+  friend NET_EXPORT_PRIVATE std::ostream& operator<<(
+      std::ostream& os,
+      const QuicWindowUpdateFrame& w);
+
+  // The stream this frame applies to.  0 is a special case meaning the overall
+  // connection rather than a specific stream.
+  QuicStreamId stream_id;
+
+  // Byte offset in the stream or connection. The receiver of this frame must
+  // not send data which would result in this offset being exceeded.
+  QuicStreamOffset byte_offset;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
diff --git a/net/quic/core/quic_ack_listener_interface.cc b/net/quic/core/quic_ack_listener_interface.cc
new file mode 100644
index 0000000..35ec6103
--- /dev/null
+++ b/net/quic/core/quic_ack_listener_interface.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 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 "net/quic/core/quic_ack_listener_interface.h"
+
+namespace net {
+
+AckListenerWrapper::AckListenerWrapper(QuicAckListenerInterface* listener,
+                                       QuicPacketLength data_length)
+    : ack_listener(listener), length(data_length) {
+  DCHECK(listener != nullptr);
+}
+
+AckListenerWrapper::AckListenerWrapper(const AckListenerWrapper& other) =
+    default;
+
+AckListenerWrapper::~AckListenerWrapper() {}
+
+}  // namespace net
diff --git a/net/quic/core/quic_ack_listener_interface.h b/net/quic/core/quic_ack_listener_interface.h
new file mode 100644
index 0000000..9557210
--- /dev/null
+++ b/net/quic/core/quic_ack_listener_interface.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_QUIC_ACK_LISTENER_INTERFACE_H_
+#define NET_QUIC_CORE_QUIC_ACK_LISTENER_INTERFACE_H_
+
+#include "base/memory/ref_counted.h"
+#include "net/quic/core/quic_time.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// Pure virtual class to listen for packet acknowledgements.
+class NET_EXPORT_PRIVATE QuicAckListenerInterface
+    : public base::RefCounted<QuicAckListenerInterface> {
+ public:
+  QuicAckListenerInterface() {}
+
+  // Called when a packet is acked.  Called once per packet.
+  // |acked_bytes| is the number of data bytes acked.
+  virtual void OnPacketAcked(int acked_bytes,
+                             QuicTime::Delta ack_delay_time) = 0;
+
+  // Called when a packet is retransmitted.  Called once per packet.
+  // |retransmitted_bytes| is the number of data bytes retransmitted.
+  virtual void OnPacketRetransmitted(int retransmitted_bytes) = 0;
+
+ protected:
+  friend class base::RefCounted<QuicAckListenerInterface>;
+
+  // Delegates are ref counted.
+  virtual ~QuicAckListenerInterface() {}
+};
+
+struct NET_EXPORT_PRIVATE AckListenerWrapper {
+  AckListenerWrapper(QuicAckListenerInterface* listener,
+                     QuicPacketLength data_length);
+  AckListenerWrapper(const AckListenerWrapper& other);
+  ~AckListenerWrapper();
+
+  scoped_refptr<QuicAckListenerInterface> ack_listener;
+  QuicPacketLength length;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_ACK_LISTENER_INTERFACE_H_
diff --git a/net/quic/core/quic_buffered_packet_store.h b/net/quic/core/quic_buffered_packet_store.h
index 9a919bd3..c467a3e0 100644
--- a/net/quic/core/quic_buffered_packet_store.h
+++ b/net/quic/core/quic_buffered_packet_store.h
@@ -10,7 +10,7 @@
 #include "net/quic/core/quic_alarm.h"
 #include "net/quic/core/quic_alarm_factory.h"
 #include "net/quic/core/quic_clock.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 
diff --git a/net/quic/core/quic_client_promised_info.h b/net/quic/core/quic_client_promised_info.h
index 2506f5be..25238d7 100644
--- a/net/quic/core/quic_client_promised_info.h
+++ b/net/quic/core/quic_client_promised_info.h
@@ -12,7 +12,7 @@
 #include "net/quic/core/quic_alarm.h"
 #include "net/quic/core/quic_client_push_promise_index.h"
 #include "net/quic/core/quic_client_session_base.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_spdy_stream.h"
 #include "net/spdy/spdy_framer.h"
 
diff --git a/net/quic/core/quic_config.cc b/net/quic/core/quic_config.cc
index de1c2871..8dc68e9 100644
--- a/net/quic/core/quic_config.cc
+++ b/net/quic/core/quic_config.cc
@@ -326,6 +326,7 @@
       max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
       max_undecryptable_packets_(0),
       connection_options_(kCOPT, PRESENCE_OPTIONAL),
+      client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
       idle_network_timeout_seconds_(kICSL, PRESENCE_REQUIRED),
       silent_close_(kSCLS, PRESENCE_OPTIONAL),
       max_streams_per_connection_(kMSPC, PRESENCE_OPTIONAL),
@@ -392,6 +393,23 @@
   return false;
 }
 
+void QuicConfig::SetClientConnectionOptions(
+    const QuicTagVector& client_connection_options) {
+  client_connection_options_.SetSendValues(client_connection_options);
+}
+
+bool QuicConfig::HasClientRequestedIndependentOption(
+    QuicTag tag,
+    Perspective perspective) const {
+  if (perspective == Perspective::IS_SERVER) {
+    return (HasReceivedConnectionOptions() &&
+            ContainsQuicTag(ReceivedConnectionOptions(), tag));
+  }
+
+  return (client_connection_options_.HasSendValues() &&
+          ContainsQuicTag(client_connection_options_.GetSendValues(), tag));
+}
+
 void QuicConfig::SetIdleNetworkTimeout(
     QuicTime::Delta max_idle_network_timeout,
     QuicTime::Delta default_idle_network_timeout) {
diff --git a/net/quic/core/quic_config.h b/net/quic/core/quic_config.h
index c7f89b0..2d88127 100644
--- a/net/quic/core/quic_config.h
+++ b/net/quic/core/quic_config.h
@@ -11,7 +11,7 @@
 #include <string>
 
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
@@ -241,9 +241,19 @@
 
   // Returns true if the client is sending or the server has received a
   // connection option.
+  // TODO(ianswett): Rename to HasClientRequestedSharedOption
   bool HasClientSentConnectionOption(QuicTag tag,
                                      Perspective perspective) const;
 
+  void SetClientConnectionOptions(
+      const QuicTagVector& client_connection_options);
+
+  // Returns true if the client has requested the specified connection option.
+  // Checks the client connection options if the |perspective| is client and
+  // connection options if the |perspective| is the server.
+  bool HasClientRequestedIndependentOption(QuicTag tag,
+                                           Perspective perspective) const;
+
   void SetIdleNetworkTimeout(QuicTime::Delta max_idle_network_timeout,
                              QuicTime::Delta default_idle_network_timeout);
 
@@ -387,8 +397,11 @@
   // Maximum number of undecryptable packets stored before CHLO/SHLO.
   size_t max_undecryptable_packets_;
 
-  // Connection options.
+  // Connection options which affect the server side.  May also affect the
+  // client side in cases when identical behavior is desirable.
   QuicFixedTagVector connection_options_;
+  // Connection options which only affect the client side.
+  QuicFixedTagVector client_connection_options_;
   // Idle network timeout in seconds.
   QuicNegotiableUint32 idle_network_timeout_seconds_;
   // Whether to use silent close.  Defaults to 0 (false) and is otherwise true.
diff --git a/net/quic/core/quic_config_test.cc b/net/quic/core/quic_config_test.cc
index 890c3ac1..9cf0f33 100644
--- a/net/quic/core/quic_config_test.cc
+++ b/net/quic/core/quic_config_test.cc
@@ -7,7 +7,7 @@
 #include "net/quic/core/crypto/crypto_handshake_message.h"
 #include "net/quic/core/crypto/crypto_protocol.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/quic_config_peer.h"
@@ -252,6 +252,56 @@
       config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER));
 }
 
+TEST_F(QuicConfigTest, DontSendClientConnectionOptions) {
+  QuicConfig client_config;
+  QuicTagVector copt;
+  copt.push_back(kTBBR);
+  client_config.SetClientConnectionOptions(copt);
+
+  CryptoHandshakeMessage msg;
+  client_config.ToHandshakeMessage(&msg);
+
+  string error_details;
+  const QuicErrorCode error =
+      config_.ProcessPeerHello(msg, CLIENT, &error_details);
+  EXPECT_EQ(QUIC_NO_ERROR, error);
+  EXPECT_TRUE(config_.negotiated());
+
+  EXPECT_FALSE(config_.HasReceivedConnectionOptions());
+}
+
+TEST_F(QuicConfigTest, HasClientRequestedIndependentOption) {
+  QuicConfig client_config;
+  QuicTagVector client_opt;
+  client_opt.push_back(kRENO);
+  QuicTagVector copt;
+  copt.push_back(kTBBR);
+  client_config.SetClientConnectionOptions(client_opt);
+  client_config.SetConnectionOptionsToSend(copt);
+  EXPECT_TRUE(client_config.HasClientSentConnectionOption(
+      kTBBR, Perspective::IS_CLIENT));
+  EXPECT_TRUE(client_config.HasClientRequestedIndependentOption(
+      kRENO, Perspective::IS_CLIENT));
+  EXPECT_FALSE(client_config.HasClientRequestedIndependentOption(
+      kTBBR, Perspective::IS_CLIENT));
+
+  CryptoHandshakeMessage msg;
+  client_config.ToHandshakeMessage(&msg);
+
+  string error_details;
+  const QuicErrorCode error =
+      config_.ProcessPeerHello(msg, CLIENT, &error_details);
+  EXPECT_EQ(QUIC_NO_ERROR, error);
+  EXPECT_TRUE(config_.negotiated());
+
+  EXPECT_TRUE(config_.HasReceivedConnectionOptions());
+  EXPECT_EQ(1u, config_.ReceivedConnectionOptions().size());
+  EXPECT_FALSE(config_.HasClientRequestedIndependentOption(
+      kRENO, Perspective::IS_SERVER));
+  EXPECT_TRUE(config_.HasClientRequestedIndependentOption(
+      kTBBR, Perspective::IS_SERVER));
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc
index 2321912..61b14b8f 100644
--- a/net/quic/core/quic_connection.cc
+++ b/net/quic/core/quic_connection.cc
@@ -34,6 +34,7 @@
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_packet_generator.h"
+#include "net/quic/core/quic_pending_retransmission.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
 #include "net/quic/core/quic_utils.h"
 
@@ -1443,7 +1444,7 @@
   // Keep writing as long as there's a pending retransmission which can be
   // written.
   while (sent_packet_manager_->HasPendingRetransmissions()) {
-    const PendingRetransmission pending =
+    const QuicPendingRetransmission pending =
         sent_packet_manager_->NextPendingRetransmission();
     if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
       break;
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h
index 6a415d4..25108acb 100644
--- a/net/quic/core/quic_connection.h
+++ b/net/quic/core/quic_connection.h
@@ -42,7 +42,7 @@
 #include "net/quic/core/quic_packet_creator.h"
 #include "net/quic/core/quic_packet_generator.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_received_packet_manager.h"
 #include "net/quic/core/quic_sent_packet_manager_interface.h"
 #include "net/quic/core/quic_time.h"
diff --git a/net/quic/core/quic_connection_stats.cc b/net/quic/core/quic_connection_stats.cc
index 7d50bf8f5..7f7935b 100644
--- a/net/quic/core/quic_connection_stats.cc
+++ b/net/quic/core/quic_connection_stats.cc
@@ -48,4 +48,44 @@
 
 QuicConnectionStats::~QuicConnectionStats() {}
 
+ostream& operator<<(ostream& os, const QuicConnectionStats& s) {
+  os << "{ bytes_sent: " << s.bytes_sent;
+  os << " packets_sent: " << s.packets_sent;
+  os << " stream_bytes_sent: " << s.stream_bytes_sent;
+  os << " packets_discarded: " << s.packets_discarded;
+  os << " bytes_received: " << s.bytes_received;
+  os << " packets_received: " << s.packets_received;
+  os << " packets_processed: " << s.packets_processed;
+  os << " stream_bytes_received: " << s.stream_bytes_received;
+  os << " bytes_retransmitted: " << s.bytes_retransmitted;
+  os << " packets_retransmitted: " << s.packets_retransmitted;
+  os << " bytes_spuriously_retransmitted: " << s.bytes_spuriously_retransmitted;
+  os << " packets_spuriously_retransmitted: "
+     << s.packets_spuriously_retransmitted;
+  os << " packets_lost: " << s.packets_lost;
+  os << " slowstart_packets_sent: " << s.slowstart_packets_sent;
+  os << " slowstart_packets_lost: " << s.slowstart_packets_lost;
+  os << " slowstart_bytes_lost: " << s.slowstart_bytes_lost;
+  os << " packets_dropped: " << s.packets_dropped;
+  os << " crypto_retransmit_count: " << s.crypto_retransmit_count;
+  os << " loss_timeout_count: " << s.loss_timeout_count;
+  os << " tlp_count: " << s.tlp_count;
+  os << " rto_count: " << s.rto_count;
+  os << " min_rtt_us: " << s.min_rtt_us;
+  os << " srtt_us: " << s.srtt_us;
+  os << " max_packet_size: " << s.max_packet_size;
+  os << " max_received_packet_size: " << s.max_received_packet_size;
+  os << " estimated_bandwidth: " << s.estimated_bandwidth;
+  os << " packets_reordered: " << s.packets_reordered;
+  os << " max_sequence_reordering: " << s.max_sequence_reordering;
+  os << " max_time_reordering_us: " << s.max_time_reordering_us;
+  os << " tcp_loss_events: " << s.tcp_loss_events;
+  os << " connection_creation_time: "
+     << s.connection_creation_time.ToDebuggingValue();
+  os << " blocked_frames_received: " << s.blocked_frames_received;
+  os << " blocked_frames_sent: " << s.blocked_frames_sent << " }";
+
+  return os;
+}
+
 }  // namespace net
diff --git a/net/quic/core/quic_connection_stats.h b/net/quic/core/quic_connection_stats.h
index e125f291..1d7b9e66 100644
--- a/net/quic/core/quic_connection_stats.h
+++ b/net/quic/core/quic_connection_stats.h
@@ -12,7 +12,7 @@
 
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 
 namespace net {
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc
index a2541475..0c58039 100644
--- a/net/quic/core/quic_connection_test.cc
+++ b/net/quic/core/quic_connection_test.cc
@@ -20,7 +20,7 @@
 #include "net/quic/core/crypto/quic_decrypter.h"
 #include "net/quic/core/crypto/quic_encrypter.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_simple_buffer_allocator.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/mock_clock.h"
diff --git a/net/quic/core/quic_crypto_client_stream.cc b/net/quic/core/quic_crypto_client_stream.cc
index 5f9ce4eb..7287c2c0 100644
--- a/net/quic/core/quic_crypto_client_stream.cc
+++ b/net/quic/core/quic_crypto_client_stream.cc
@@ -14,7 +14,7 @@
 #include "net/quic/core/crypto/crypto_utils.h"
 #include "net/quic/core/crypto/null_encrypter.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
 #include "net/quic/core/quic_utils.h"
 
@@ -171,7 +171,7 @@
       crypto_config_->LookupOrCreate(server_id_);
   QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
       server_config_update, session()->connection()->clock()->WallNow(),
-      session()->connection()->version(), cached->chlo_hash(), cached,
+      session()->connection()->version(), chlo_hash_, cached,
       crypto_negotiated_params_, &error_details);
 
   if (error != QUIC_NO_ERROR) {
diff --git a/net/quic/core/quic_crypto_client_stream.h b/net/quic/core/quic_crypto_client_stream.h
index 94e3fda..2017027 100644
--- a/net/quic/core/quic_crypto_client_stream.h
+++ b/net/quic/core/quic_crypto_client_stream.h
@@ -99,6 +99,8 @@
   // ChannelIDSource operated asynchronously. Intended for testing.
   bool WasChannelIDSourceCallbackRun() const;
 
+  std::string chlo_hash() const { return chlo_hash_; }
+
  private:
   // ChannelIDSourceCallbackImpl is passed as the callback method to
   // GetChannelIDKey. The ChannelIDSource calls this class with the result of
diff --git a/net/quic/core/quic_crypto_client_stream_test.cc b/net/quic/core/quic_crypto_client_stream_test.cc
index c81c6b7..b839536d 100644
--- a/net/quic/core/quic_crypto_client_stream_test.cc
+++ b/net/quic/core/quic_crypto_client_stream_test.cc
@@ -10,7 +10,7 @@
 #include "net/quic/core/crypto/quic_decrypter.h"
 #include "net/quic/core/crypto/quic_encrypter.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
@@ -234,6 +234,41 @@
             QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
 }
 
+TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateWithCert) {
+  // Test that the crypto client stream can receive and use server config
+  // updates with certificates after the connection has been established.
+  CompleteCryptoHandshake();
+
+  // Build a server config update message with certificates
+  QuicCryptoServerConfig crypto_config(
+      QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
+      CryptoTestUtils::ProofSourceForTesting());
+  CryptoTestUtils::FakeServerOptions options;
+  CryptoTestUtils::SetupCryptoServerConfigForTest(
+      connection_->clock(), QuicRandom::GetInstance(), &crypto_config, options);
+  SourceAddressTokens tokens;
+  QuicCompressedCertsCache cache(1);
+  CachedNetworkParameters network_params;
+  CryptoHandshakeMessage server_config_update;
+  EXPECT_TRUE(crypto_config.BuildServerConfigUpdateMessage(
+      session_->connection()->version(), stream()->chlo_hash(), tokens,
+      QuicIpAddress::Loopback6(), QuicIpAddress::Loopback6(),
+      connection_->clock(), QuicRandom::GetInstance(), &cache,
+      stream()->crypto_negotiated_params(), &network_params, QuicTagVector(),
+      &server_config_update));
+
+  std::unique_ptr<QuicData> data(
+      CryptoFramer::ConstructHandshakeMessage(server_config_update));
+  stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
+                                          /*offset=*/0, data->AsStringPiece()));
+
+  // Recreate connection with the new config and verify a 0-RTT attempt.
+  CreateConnection();
+
+  stream()->CryptoConnect();
+  EXPECT_TRUE(session_->IsEncryptionEstablished());
+}
+
 TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
   EXPECT_CALL(
       *connection_,
diff --git a/net/quic/core/quic_crypto_server_stream.cc b/net/quic/core/quic_crypto_server_stream.cc
index e7b111e8..0a300def 100644
--- a/net/quic/core/quic_crypto_server_stream.cc
+++ b/net/quic/core/quic_crypto_server_stream.cc
@@ -15,7 +15,7 @@
 #include "net/quic/core/proto/cached_network_parameters.pb.h"
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
 
 using base::StringPiece;
diff --git a/net/quic/core/quic_crypto_server_stream_test.cc b/net/quic/core/quic_crypto_server_stream_test.cc
index 77980a9..a437a378 100644
--- a/net/quic/core/quic_crypto_server_stream_test.cc
+++ b/net/quic/core/quic_crypto_server_stream_test.cc
@@ -20,7 +20,7 @@
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/quic_crypto_client_stream.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
diff --git a/net/quic/core/quic_crypto_stream.h b/net/quic/core/quic_crypto_stream.h
index 185165a9..90f5fce 100644
--- a/net/quic/core/quic_crypto_stream.h
+++ b/net/quic/core/quic_crypto_stream.h
@@ -12,7 +12,7 @@
 #include "net/quic/core/crypto/crypto_framer.h"
 #include "net/quic/core/crypto/crypto_utils.h"
 #include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream.h"
 
 namespace net {
diff --git a/net/quic/core/quic_data_reader.cc b/net/quic/core/quic_data_reader.cc
index 72185cd..642a3c8 100644
--- a/net/quic/core/quic_data_reader.cc
+++ b/net/quic/core/quic_data_reader.cc
@@ -5,7 +5,7 @@
 #include "net/quic/core/quic_data_reader.h"
 
 #include "net/base/int128.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 using base::StringPiece;
 
diff --git a/net/quic/core/quic_data_writer.h b/net/quic/core/quic_data_writer.h
index 8dcc74a0..f7964209 100644
--- a/net/quic/core/quic_data_writer.h
+++ b/net/quic/core/quic_data_writer.h
@@ -16,7 +16,7 @@
 #include "base/strings/string_piece.h"
 #include "net/base/int128.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index 08c5b41..785f0b32 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -156,3 +156,7 @@
 // If true, fix version manager bug, in which version flag does not really
 // help.
 QUIC_FLAG(bool, FLAGS_quic_fix_version_manager, false)
+
+// Add a new client connection options field to QuicOptions which is only used
+// to configure client side features, such as congestion control.
+QUIC_FLAG(bool, FLAGS_quic_client_connection_options, true)
diff --git a/net/quic/core/quic_flow_controller.cc b/net/quic/core/quic_flow_controller.cc
index 3c556f34..7fd7b5a 100644
--- a/net/quic/core/quic_flow_controller.cc
+++ b/net/quic/core/quic_flow_controller.cc
@@ -8,7 +8,7 @@
 #include "net/quic/core/quic_bug_tracker.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/quic_flow_controller.h b/net/quic/core/quic_flow_controller.h
index 238b9b4..833e0ce 100644
--- a/net/quic/core/quic_flow_controller.h
+++ b/net/quic/core/quic_flow_controller.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/quic_frame_list.h b/net/quic/core/quic_frame_list.h
index 2e95455d..6f87b439 100644
--- a/net/quic/core/quic_frame_list.h
+++ b/net/quic/core/quic_frame_list.h
@@ -11,7 +11,7 @@
 
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream_sequencer_buffer_interface.h"
 
 namespace net {
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc
index e8b90f9..bdc6f8c 100644
--- a/net/quic/core/quic_framer.cc
+++ b/net/quic/core/quic_framer.cc
@@ -35,6 +35,9 @@
 
 namespace {
 
+#define ENDPOINT \
+  (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
+
 // Mask to select the lowest 48 bits of a packet number.
 const QuicPacketNumber k6ByteSequenceNumberMask = UINT64_C(0x0000FFFFFFFFFFFF);
 const QuicPacketNumber k4ByteSequenceNumberMask = UINT64_C(0x00000000FFFFFFFF);
@@ -305,19 +308,19 @@
   if (can_truncate) {
     // Truncate the frame so the packet will not exceed kMaxPacketSize.
     // Note that we may not use every byte of the writer in this case.
-    DVLOG(1) << "Truncating large frame, free bytes: " << free_bytes;
+    DVLOG(1) << ENDPOINT
+             << "Truncating large frame, free bytes: " << free_bytes;
     return free_bytes;
   }
   return 0;
 }
 
-QuicFramer::NewAckFrameInfo::NewAckFrameInfo()
+QuicFramer::AckFrameInfo::AckFrameInfo()
     : max_block_length(0), first_block_length(0), num_ack_blocks(0) {}
 
-QuicFramer::NewAckFrameInfo::NewAckFrameInfo(const NewAckFrameInfo& other) =
-    default;
+QuicFramer::AckFrameInfo::AckFrameInfo(const AckFrameInfo& other) = default;
 
-QuicFramer::NewAckFrameInfo::~NewAckFrameInfo() {}
+QuicFramer::AckFrameInfo::~AckFrameInfo() {}
 
 size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
                                    const QuicFrames& frames,
@@ -350,8 +353,8 @@
         }
         break;
       case ACK_FRAME:
-        if (!AppendNewAckFrameAndTypeByte(*frame.ack_frame, &writer)) {
-          QUIC_BUG << "AppendNewAckFrameAndTypeByte failed";
+        if (!AppendAckFrameAndTypeByte(*frame.ack_frame, &writer)) {
+          QUIC_BUG << "AppendAckFrameAndTypeByte failed";
           return 0;
         }
         break;
@@ -502,7 +505,9 @@
   // First parse the public header.
   QuicPacketPublicHeader public_header;
   if (!ProcessPublicHeader(&reader, &public_header)) {
-    DVLOG(1) << "Unable to process public header.";
+    DCHECK_NE("", detailed_error_);
+    DVLOG(1) << ENDPOINT
+             << "Unable to process public header. Error: " << detailed_error_;
     DCHECK_NE("", detailed_error_);
     return RaiseError(QUIC_INVALID_PACKET_HEADER);
   }
@@ -569,7 +574,10 @@
                                    size_t buffer_length) {
   QuicPacketHeader header(public_header);
   if (!ProcessUnauthenticatedHeader(encrypted_reader, &header)) {
-    DVLOG(1) << "Unable to process packet header.  Stopping parsing.";
+    DCHECK_NE("", detailed_error_);
+    DVLOG(1) << ENDPOINT
+             << "Unable to process packet header. Stopping parsing. Error: "
+             << detailed_error_;
     return false;
   }
 
@@ -600,7 +608,9 @@
   // Handle the payload.
   if (!ProcessFrameData(&reader, header)) {
     DCHECK_NE(QUIC_NO_ERROR, error_);  // ProcessFrameData sets the error.
-    DLOG(WARNING) << "Unable to process frame data.";
+    DCHECK_NE("", detailed_error_);
+    DLOG(WARNING) << ENDPOINT
+                  << "Unable to process frame data. Error: " << detailed_error_;
     return false;
   }
 
@@ -645,7 +655,7 @@
 
 bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
                                     QuicDataWriter* writer) {
-  DVLOG(1) << "Appending header: " << header;
+  DVLOG(1) << ENDPOINT << "Appending header: " << header;
   uint8_t public_flags = 0;
   if (header.public_header.reset_flag) {
     public_flags |= PACKET_PUBLIC_FLAGS_RST;
@@ -691,7 +701,7 @@
     DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
     QuicTag tag = QuicVersionToQuicTag(quic_version_);
     writer->WriteUInt32(tag);
-    DVLOG(1) << "version = " << quic_version_ << ", tag = '"
+    DVLOG(1) << ENDPOINT << "version = " << quic_version_ << ", tag = '"
              << QuicTagToString(tag) << "'";
   }
 
@@ -917,9 +927,9 @@
 }
 
 // static
-QuicFramer::NewAckFrameInfo QuicFramer::GetNewAckFrameInfo(
+QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo(
     const QuicAckFrame& frame) {
-  NewAckFrameInfo new_ack_info;
+  AckFrameInfo new_ack_info;
   if (frame.packets.Empty()) {
     return new_ack_info;
   }
@@ -960,6 +970,7 @@
   if (header->public_header.multipath_flag &&
       !IsValidPath(header->path_id, &base_packet_number)) {
     // Stop processing because path is closed.
+    set_detailed_error("Path is closed.");
     return false;
   }
 
@@ -976,6 +987,8 @@
   }
 
   if (!visitor_->OnUnauthenticatedHeader(*header)) {
+    set_detailed_error(
+        "Visitor asked to stop processing of unauthenticated header.");
     return false;
   }
   return true;
@@ -1027,7 +1040,7 @@
           return RaiseError(QUIC_INVALID_STREAM_DATA);
         }
         if (!visitor_->OnStreamFrame(frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1037,11 +1050,11 @@
       // Ack Frame
       if (frame_type & kQuicFrameTypeAckMask) {
         QuicAckFrame frame;
-        if (!ProcessNewAckFrame(reader, frame_type, &frame)) {
+        if (!ProcessAckFrame(reader, frame_type, &frame)) {
           return RaiseError(QUIC_INVALID_ACK_DATA);
         }
         if (!visitor_->OnAckFrame(frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1051,7 +1064,8 @@
       // This was a special frame type that did not match any
       // of the known ones. Error.
       set_detailed_error("Illegal frame type.");
-      DLOG(WARNING) << "Illegal frame type: " << static_cast<int>(frame_type);
+      DLOG(WARNING) << ENDPOINT
+                    << "Illegal frame type: " << static_cast<int>(frame_type);
       return RaiseError(QUIC_INVALID_FRAME_DATA);
     }
 
@@ -1085,7 +1099,7 @@
         }
 
         if (!visitor_->OnConnectionCloseFrame(frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1098,7 +1112,7 @@
           return RaiseError(QUIC_INVALID_GOAWAY_DATA);
         }
         if (!visitor_->OnGoAwayFrame(goaway_frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1111,7 +1125,7 @@
           return RaiseError(QUIC_INVALID_WINDOW_UPDATE_DATA);
         }
         if (!visitor_->OnWindowUpdateFrame(window_update_frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1124,7 +1138,7 @@
           return RaiseError(QUIC_INVALID_BLOCKED_DATA);
         }
         if (!visitor_->OnBlockedFrame(blocked_frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1137,7 +1151,7 @@
           return RaiseError(QUIC_INVALID_STOP_WAITING_DATA);
         }
         if (!visitor_->OnStopWaitingFrame(stop_waiting_frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1147,7 +1161,7 @@
         // Ping has no payload.
         QuicPingFrame ping_frame;
         if (!visitor_->OnPingFrame(ping_frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1159,7 +1173,7 @@
           return RaiseError(QUIC_INVALID_PATH_CLOSE_DATA);
         }
         if (!visitor_->OnPathCloseFrame(path_close_frame)) {
-          DVLOG(1) << "Visitor asked to stop further processing.";
+          DVLOG(1) << ENDPOINT << "Visitor asked to stop further processing.";
           // Returning true since there was no parsing error.
           return true;
         }
@@ -1168,7 +1182,8 @@
 
       default:
         set_detailed_error("Illegal frame type.");
-        DLOG(WARNING) << "Illegal frame type: " << static_cast<int>(frame_type);
+        DLOG(WARNING) << ENDPOINT
+                      << "Illegal frame type: " << static_cast<int>(frame_type);
         return RaiseError(QUIC_INVALID_FRAME_DATA);
     }
   }
@@ -1231,9 +1246,9 @@
   return true;
 }
 
-bool QuicFramer::ProcessNewAckFrame(QuicDataReader* reader,
-                                    uint8_t frame_type,
-                                    QuicAckFrame* ack_frame) {
+bool QuicFramer::ProcessAckFrame(QuicDataReader* reader,
+                                 uint8_t frame_type,
+                                 QuicAckFrame* ack_frame) {
   // Determine the two lengths from the frame type: largest acked length,
   // ack block length.
   const QuicPacketNumberLength ack_block_length =
@@ -1668,7 +1683,7 @@
   }
 
   if (!success) {
-    DVLOG(1) << "DecryptPacket failed for packet_number:"
+    DVLOG(1) << ENDPOINT << "DecryptPacket failed for packet_number:"
              << header.packet_number;
     return false;
   }
@@ -1689,7 +1704,7 @@
     QuicPacketNumberLength packet_number_length) {
   size_t ack_size = 0;
 
-  NewAckFrameInfo ack_info = GetNewAckFrameInfo(ack);
+  AckFrameInfo ack_info = GetAckFrameInfo(ack);
   QuicPacketNumberLength largest_acked_length =
       GetMinSequenceNumberLength(ack.largest_observed);
   QuicPacketNumberLength ack_block_length =
@@ -1867,9 +1882,9 @@
   quic_version_ = version;
 }
 
-bool QuicFramer::AppendNewAckFrameAndTypeByte(const QuicAckFrame& frame,
-                                              QuicDataWriter* writer) {
-  const NewAckFrameInfo new_ack_info = GetNewAckFrameInfo(frame);
+bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
+                                           QuicDataWriter* writer) {
+  const AckFrameInfo new_ack_info = GetAckFrameInfo(frame);
   QuicPacketNumber largest_acked = frame.largest_observed;
   QuicPacketNumberLength largest_acked_length =
       GetMinSequenceNumberLength(largest_acked);
@@ -2185,7 +2200,7 @@
 }
 
 bool QuicFramer::RaiseError(QuicErrorCode error) {
-  DVLOG(1) << "Error: " << QuicErrorCodeToString(error)
+  DVLOG(1) << ENDPOINT << "Error: " << QuicErrorCodeToString(error)
            << " detail: " << detailed_error_;
   set_error(error);
   visitor_->OnError(this);
diff --git a/net/quic/core/quic_framer.h b/net/quic/core/quic_framer.h
index 0eb341a..60d71d8 100644
--- a/net/quic/core/quic_framer.h
+++ b/net/quic/core/quic_framer.h
@@ -18,7 +18,7 @@
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
@@ -347,11 +347,10 @@
 
   typedef std::map<QuicPacketNumber, uint8_t> NackRangeMap;
 
-  // TODO(rch): Rename this to remove "New" from the name here, and elsewhere.
-  struct NewAckFrameInfo {
-    NewAckFrameInfo();
-    NewAckFrameInfo(const NewAckFrameInfo& other);
-    ~NewAckFrameInfo();
+  struct AckFrameInfo {
+    AckFrameInfo();
+    AckFrameInfo(const AckFrameInfo& other);
+    ~AckFrameInfo();
 
     // The maximum ack block length.
     QuicPacketNumber max_block_length;
@@ -390,9 +389,9 @@
   bool ProcessStreamFrame(QuicDataReader* reader,
                           uint8_t frame_type,
                           QuicStreamFrame* frame);
-  bool ProcessNewAckFrame(QuicDataReader* reader,
-                          uint8_t frame_type,
-                          QuicAckFrame* frame);
+  bool ProcessAckFrame(QuicDataReader* reader,
+                       uint8_t frame_type,
+                       QuicAckFrame* frame);
   bool ProcessTimestampsInAckFrame(QuicDataReader* reader, QuicAckFrame* frame);
   bool ProcessStopWaitingFrame(QuicDataReader* reader,
                                const QuicPacketHeader& public_header,
@@ -442,7 +441,7 @@
                          QuicPacketNumberLength packet_number_length);
 
   // Computes the wire size in bytes of the |ack| frame.
-  size_t GetNewAckFrameSize(const QuicAckFrame& ack);
+  size_t GetAckFrameSize(const QuicAckFrame& ack);
 
   // Computes the wire size in bytes of the payload of |frame|.
   size_t ComputeFrameLength(const QuicFrame& frame,
@@ -464,13 +463,13 @@
   static uint8_t GetSequenceNumberFlags(
       QuicPacketNumberLength packet_number_length);
 
-  static NewAckFrameInfo GetNewAckFrameInfo(const QuicAckFrame& frame);
+  static AckFrameInfo GetAckFrameInfo(const QuicAckFrame& frame);
 
   // The Append* methods attempt to write the provided header or frame using the
   // |writer|, and return true if successful.
 
-  bool AppendNewAckFrameAndTypeByte(const QuicAckFrame& frame,
-                                    QuicDataWriter* builder);
+  bool AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
+                                 QuicDataWriter* builder);
   bool AppendTimestampToAckFrame(const QuicAckFrame& frame,
                                  QuicDataWriter* builder);
   bool AppendStopWaitingFrame(const QuicPacketHeader& header,
diff --git a/net/quic/core/quic_framer_test.cc b/net/quic/core/quic_framer_test.cc
index 1e4ef61..695dd7f 100644
--- a/net/quic/core/quic_framer_test.cc
+++ b/net/quic/core/quic_framer_test.cc
@@ -17,7 +17,7 @@
 #include "net/quic/core/crypto/null_decrypter.h"
 #include "net/quic/core/crypto/quic_decrypter.h"
 #include "net/quic/core/crypto/quic_encrypter.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/quic_framer_peer.h"
 #include "net/quic/test_tools/quic_test_utils.h"
@@ -1115,9 +1115,7 @@
   header.public_header.version_flag = false;
   header.packet_number = kPacketNumber - 2;
 
-  QuicPaddingFrame padding_frame;
-  QuicFrames frames;
-  frames.push_back(QuicFrame(padding_frame));
+  QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
   std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != nullptr);
 
@@ -1618,7 +1616,7 @@
   ASSERT_FALSE(visitor_.header_.get());
 }
 
-TEST_P(QuicFramerTest, NewAckFrameOneAckBlock) {
+TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
   // clang-format off
   unsigned char packet[] = {
       // public flags (8 byte connection_id)
@@ -1687,7 +1685,7 @@
   }
 }
 
-TEST_P(QuicFramerTest, NewAckFrameTwoTimeStampsMultipleAckBlocks) {
+TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) {
   // clang-format off
   unsigned char packet[] = {
       // public flags (8 byte connection_id)
@@ -2551,10 +2549,7 @@
   header.public_header.version_flag = false;
   header.packet_number = kPacketNumber;
 
-  QuicPaddingFrame padding_frame;
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(padding_frame));
+  QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
 
   // clang-format off
   unsigned char packet[kMaxPacketSize] = {
@@ -2595,10 +2590,7 @@
   header.public_header.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
   header.packet_number = kPacketNumber;
 
-  QuicPaddingFrame padding_frame;
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(padding_frame));
+  QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
 
   // clang-format off
   unsigned char packet[kMaxPacketSize] = {
@@ -2638,10 +2630,7 @@
   header.public_header.packet_number_length = PACKET_2BYTE_PACKET_NUMBER;
   header.packet_number = kPacketNumber;
 
-  QuicPaddingFrame padding_frame;
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(padding_frame));
+  QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
 
   // clang-format off
   unsigned char packet[kMaxPacketSize] = {
@@ -2681,10 +2670,7 @@
   header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
   header.packet_number = kPacketNumber;
 
-  QuicPaddingFrame padding_frame;
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(padding_frame));
+  QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
 
   // clang-format off
   unsigned char packet[kMaxPacketSize] = {
@@ -2726,8 +2712,7 @@
   QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
                                StringPiece("hello world!"));
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&stream_frame));
+  QuicFrames frames = {QuicFrame(&stream_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -2771,9 +2756,7 @@
 
   QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
                                StringPiece("hello world!"));
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&stream_frame));
+  QuicFrames frames = {QuicFrame(&stream_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -2818,9 +2801,7 @@
 
   QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
                                StringPiece("hello world!"));
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&stream_frame));
+  QuicFrames frames = {QuicFrame(&stream_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -2868,9 +2849,7 @@
 
   QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
                                StringPiece("hello world!"));
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&stream_frame));
+  QuicFrames frames = {QuicFrame(&stream_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -2932,7 +2911,7 @@
                                       arraysize(packet));
 }
 
-TEST_P(QuicFramerTest, BuildNewAckFramePacketOneAckBlock) {
+TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
   QuicPacketHeader header;
   header.public_header.connection_id = kConnectionId;
   header.public_header.reset_flag = false;
@@ -2945,8 +2924,7 @@
   ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   ack_frame.packets.Add(1, kSmallLargestObserved + 1);
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&ack_frame));
+  QuicFrames frames = {QuicFrame(&ack_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -2979,7 +2957,7 @@
                                       arraysize(packet));
 }
 
-TEST_P(QuicFramerTest, BuildNewAckFramePacketMultipleAckBlocks) {
+TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
   QuicPacketHeader header;
   header.public_header.connection_id = kConnectionId;
   header.public_header.reset_flag = false;
@@ -2995,8 +2973,7 @@
   ack_frame.packets.Add(900, kSmallMissingPacket);
   ack_frame.packets.Add(kSmallMissingPacket + 1, kSmallLargestObserved + 1);
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&ack_frame));
+  QuicFrames frames = {QuicFrame(&ack_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3047,7 +3024,7 @@
                                       arraysize(packet));
 }
 
-TEST_P(QuicFramerTest, BuildNewAckFramePacketMaxAckBlocks) {
+TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
   QuicPacketHeader header;
   header.public_header.connection_id = kConnectionId;
   header.public_header.reset_flag = false;
@@ -3064,8 +3041,7 @@
   }
   ack_frame.packets.Add(600, kSmallLargestObserved + 1);
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&ack_frame));
+  QuicFrames frames = {QuicFrame(&ack_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3179,8 +3155,7 @@
   QuicStopWaitingFrame stop_waiting_frame;
   stop_waiting_frame.least_unacked = kLeastUnacked;
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&stop_waiting_frame));
+  QuicFrames frames = {QuicFrame(&stop_waiting_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3243,8 +3218,7 @@
   };
   // clang-format on
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&rst_frame));
+  QuicFrames frames = {QuicFrame(&rst_frame)};
 
   std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != nullptr);
@@ -3265,8 +3239,7 @@
   close_frame.error_code = static_cast<QuicErrorCode>(0x05060708);
   close_frame.error_details = "because I can";
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&close_frame));
+  QuicFrames frames = {QuicFrame(&close_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3313,8 +3286,7 @@
   goaway_frame.last_good_stream_id = kStreamId;
   goaway_frame.reason_phrase = "because I can";
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&goaway_frame));
+  QuicFrames frames = {QuicFrame(&goaway_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3362,8 +3334,7 @@
   window_update_frame.stream_id = kStreamId;
   window_update_frame.byte_offset = 0x1122334455667788;
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&window_update_frame));
+  QuicFrames frames = {QuicFrame(&window_update_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3404,8 +3375,7 @@
   QuicBlockedFrame blocked_frame;
   blocked_frame.stream_id = kStreamId;
 
-  QuicFrames frames;
-  frames.push_back(QuicFrame(&blocked_frame));
+  QuicFrames frames = {QuicFrame(&blocked_frame)};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3440,10 +3410,7 @@
   header.public_header.version_flag = false;
   header.packet_number = kPacketNumber;
 
-  QuicPingFrame ping_frame;
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(ping_frame));
+  QuicFrames frames = {QuicFrame(QuicPingFrame())};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3517,10 +3484,7 @@
   header.public_header.version_flag = false;
   header.packet_number = kPacketNumber;
 
-  QuicMtuDiscoveryFrame mtu_discovery_frame;
-
-  QuicFrames frames;
-  frames.push_back(QuicFrame(mtu_discovery_frame));
+  QuicFrames frames = {QuicFrame(QuicMtuDiscoveryFrame())};
 
   // clang-format off
   unsigned char packet[] = {
@@ -3928,11 +3892,7 @@
   QuicAckFrame ack_frame;
   // Create a packet with just the ack.
   ack_frame = MakeAckFrameWithAckBlocks(300, 0u);
-  QuicFrame frame;
-  frame.type = ACK_FRAME;
-  frame.ack_frame = &ack_frame;
-  QuicFrames frames;
-  frames.push_back(frame);
+  QuicFrames frames = {QuicFrame(&ack_frame)};
 
   // Build an ack packet with truncation due to limit in number of nack ranges.
   std::unique_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
@@ -3963,11 +3923,7 @@
   // Create a packet with just the ack.
   QuicAckFrame ack_frame;
   ack_frame = MakeAckFrameWithAckBlocks(300, 0u);
-  QuicFrame frame;
-  frame.type = ACK_FRAME;
-  frame.ack_frame = &ack_frame;
-  QuicFrames frames;
-  frames.push_back(frame);
+  QuicFrames frames = {QuicFrame(&ack_frame)};
 
   // Build an ack packet with truncation due to limit in number of nack ranges.
   std::unique_ptr<QuicPacket> raw_ack_packet(
@@ -4001,11 +3957,7 @@
   ack_frame.packets.Add(1, ack_frame.largest_observed);
 
   // Create a packet with just the ack.
-  QuicFrame frame;
-  frame.type = ACK_FRAME;
-  frame.ack_frame = &ack_frame;
-  QuicFrames frames;
-  frames.push_back(frame);
+  QuicFrames frames = {QuicFrame(&ack_frame)};
 
   std::unique_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
   ASSERT_TRUE(raw_ack_packet != nullptr);
@@ -4023,9 +3975,7 @@
   // Test for clean truncation of the ack by comparing the length of the
   // original packets to the re-serialized packets.
   frames.clear();
-  frame.type = ACK_FRAME;
-  frame.ack_frame = visitor_.ack_frames_[0].get();
-  frames.push_back(frame);
+  frames.push_back(QuicFrame(visitor_.ack_frames_[0].get()));
 
   size_t original_raw_length = raw_ack_packet->length();
   raw_ack_packet.reset(BuildDataPacket(header, frames));
diff --git a/net/quic/core/quic_header_list.cc b/net/quic/core/quic_header_list.cc
index 871c49a..269b439 100644
--- a/net/quic/core/quic_header_list.cc
+++ b/net/quic/core/quic_header_list.cc
@@ -7,7 +7,7 @@
 using std::string;
 
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/quic_headers_stream.cc b/net/quic/core/quic_headers_stream.cc
index dcb7e9a8..53ca278 100644
--- a/net/quic/core/quic_headers_stream.cc
+++ b/net/quic/core/quic_headers_stream.cc
@@ -21,7 +21,6 @@
 #include "net/spdy/spdy_protocol.h"
 
 using base::StringPiece;
-using net::HTTP2;
 using net::SpdyFrameType;
 using std::string;
 
@@ -299,7 +298,7 @@
   }
 
  private:
-  void CloseConnection(const std::string& details) {
+  void CloseConnection(const string& details) {
     if (stream_->IsConnected()) {
       stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
                                           details);
@@ -324,7 +323,6 @@
       supports_push_promise_(session->perspective() == Perspective::IS_CLIENT),
       cur_max_timestamp_(QuicTime::Zero()),
       prev_max_timestamp_(QuicTime::Zero()),
-      spdy_framer_(HTTP2),
       spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
   spdy_framer_.set_visitor(spdy_framer_visitor_.get());
   spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
@@ -371,60 +369,123 @@
   return frame.size();
 }
 
+void QuicHeadersStream::WriteDataFrame(
+    QuicStreamId id,
+    StringPiece data,
+    bool fin,
+    QuicAckListenerInterface* ack_notifier_delegate) {
+  SpdyDataIR spdy_data(id, data);
+  spdy_data.set_fin(fin);
+  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
+  scoped_refptr<ForceHolAckListener> ack_listener;
+  if (ack_notifier_delegate != nullptr) {
+    ack_listener = new ForceHolAckListener(ack_notifier_delegate,
+                                           frame.size() - data.length());
+  }
+  // Use buffered writes so that coherence of framing is preserved
+  // between streams.
+  WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
+                    ack_listener.get());
+}
+
 QuicConsumedData QuicHeadersStream::WritevStreamData(
     QuicStreamId id,
     QuicIOVector iov,
     QuicStreamOffset offset,
     bool fin,
     QuicAckListenerInterface* ack_notifier_delegate) {
-  const size_t max_len = kSpdyInitialFrameSizeLimit -
-                         SpdyConstants::GetDataFrameMinimumSize(HTTP2);
+  const size_t max_len =
+      kSpdyInitialFrameSizeLimit - SpdyConstants::kDataFrameMinimumSize;
 
   QuicConsumedData result(0, false);
   size_t total_length = iov.total_length;
 
-  // Encapsulate the data into HTTP/2 DATA frames.  The outer loop
-  // handles each element of the source iov, the inner loop handles
-  // the possibility of fragmenting eacho of those into multiple DATA
-  // frames, as the DATA frames have a max size of 16KB.
-  for (int i = 0; i < iov.iov_count; i++) {
-    size_t offset = 0;
-    const struct iovec* src_iov = &iov.iov[i];
-    do {
-      size_t len =
-          std::min(std::min(src_iov->iov_len - offset, max_len), total_length);
-      char* data = static_cast<char*>(src_iov->iov_base) + offset;
-      SpdyDataIR spdy_data(id, StringPiece(data, len));
-      offset += len;
-      // fin handling, set it only it only very last generated HTTP/2
-      // DATA frame.
-      bool last_iov = i == iov.iov_count - 1;
-      bool last_fragment_within_iov = offset >= src_iov->iov_len;
-      bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
-      spdy_data.set_fin(frame_fin);
-      if (frame_fin) {
-        result.fin_consumed = true;
-      }
-      SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
-      DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len "
-               << len << " fin " << spdy_data.fin() << " remaining "
-               << src_iov->iov_len - offset;
+  if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) {
+    // Encapsulate the data into HTTP/2 DATA frames.  The outer loop
+    // handles each element of the source iov, the inner loop handles
+    // the possibility of fragmenting eacho of those into multiple DATA
+    // frames, as the DATA frames have a max size of 16KB.
+    for (int i = 0; i < iov.iov_count; i++) {
+      size_t offset = 0;
+      const struct iovec* src_iov = &iov.iov[i];
+      do {
+        size_t len = std::min(std::min(src_iov->iov_len - offset, max_len),
+                              total_length);
+        char* data = static_cast<char*>(src_iov->iov_base) + offset;
+        SpdyDataIR spdy_data(id, StringPiece(data, len));
+        offset += len;
+        // fin handling, only set it for the final HTTP/2 DATA frame.
+        bool last_iov = i == iov.iov_count - 1;
+        bool last_fragment_within_iov = offset >= src_iov->iov_len;
+        bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
+        spdy_data.set_fin(frame_fin);
+        if (frame_fin) {
+          result.fin_consumed = true;
+        }
+        SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
+        DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len "
+                 << len << " fin " << spdy_data.fin() << " remaining "
+                 << src_iov->iov_len - offset;
 
-      scoped_refptr<ForceHolAckListener> ack_listener;
-      if (ack_notifier_delegate != nullptr) {
-        ack_listener =
-            new ForceHolAckListener(ack_notifier_delegate, frame.size() - len);
-      }
+        scoped_refptr<ForceHolAckListener> ack_listener;
+        if (ack_notifier_delegate != nullptr) {
+          ack_listener = new ForceHolAckListener(ack_notifier_delegate,
+                                                 frame.size() - len);
+        }
 
-      WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
-                        ack_listener.get());
-      result.bytes_consumed += len;
-      total_length -= len;
-      if (total_length <= 0) {
-        return result;
-      }
-    } while (offset < src_iov->iov_len);
+        WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
+                          ack_listener.get());
+        result.bytes_consumed += len;
+        total_length -= len;
+        if (total_length <= 0) {
+          return result;
+        }
+      } while (offset < src_iov->iov_len);
+    }
+  } else {
+    if (total_length == 0 && fin) {
+      WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate);
+      result.fin_consumed = true;
+      return result;
+    }
+
+    // Encapsulate the data into HTTP/2 DATA frames.  The outer loop
+    // handles each element of the source iov, the inner loop handles
+    // the possibility of fragmenting each of those into multiple DATA
+    // frames, as the DATA frames have a max size of 16KB.
+    for (int i = 0; i < iov.iov_count; i++) {
+      size_t src_iov_offset = 0;
+      const struct iovec* src_iov = &iov.iov[i];
+      do {
+        if (queued_data_bytes() > 0) {
+          // Limit the amount of buffering to the minimum needed to
+          // preserve framing.
+          return result;
+        }
+        size_t len = std::min(
+            std::min(src_iov->iov_len - src_iov_offset, max_len), total_length);
+        char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset;
+        src_iov_offset += len;
+        offset += len;
+        // fin handling, only set it for the final HTTP/2 DATA frame.
+        bool last_iov = i == iov.iov_count - 1;
+        bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len;
+        bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
+        WriteDataFrame(id, StringPiece(data, len), frame_fin,
+                       ack_notifier_delegate);
+        result.bytes_consumed += len;
+        if (frame_fin) {
+          result.fin_consumed = true;
+        }
+        DCHECK_GE(total_length, len);
+        total_length -= len;
+        if (total_length <= 0) {
+          return result;
+        }
+      } while (src_iov_offset < src_iov->iov_len);
+    }
   }
+
   return result;
 }
 
diff --git a/net/quic/core/quic_headers_stream.h b/net/quic/core/quic_headers_stream.h
index b10ec37..e5ffc6c 100644
--- a/net/quic/core/quic_headers_stream.h
+++ b/net/quic/core/quic_headers_stream.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream.h"
 #include "net/spdy/spdy_framer.h"
 
@@ -132,10 +132,15 @@
   void OnCompressedFrameSize(size_t frame_len);
 
   // For force HOL blocking, where stream frames from all streams are
-  // plumbed through headers stream as HTTP/2 data frames.  Return false
-  // if force_hol_blocking_ is false;
+  // plumbed through headers stream as HTTP/2 data frames.
+  // The following two return false if force_hol_blocking_ is false.
   bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin);
   bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len);
+  // Helper for |WritevStreamData()|.
+  void WriteDataFrame(QuicStreamId stream_id,
+                      base::StringPiece data,
+                      bool fin,
+                      QuicAckListenerInterface* ack_notifier_delegate);
 
   // Returns true if the session is still connected.
   bool IsConnected();
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc
index 93f5d74..667715a 100644
--- a/net/quic/core/quic_headers_stream_test.cc
+++ b/net/quic/core/quic_headers_stream_test.cc
@@ -237,7 +237,7 @@
     headers_[":version"] = "HTTP/1.1";
     headers_[":status"] = "200 Ok";
     headers_["content-length"] = "11";
-    framer_ = std::unique_ptr<SpdyFramer>(new SpdyFramer(HTTP2));
+    framer_ = std::unique_ptr<SpdyFramer>(new SpdyFramer);
     framer_->set_visitor(&visitor_);
     EXPECT_EQ(version(), session_.connection()->version());
     EXPECT_TRUE(headers_stream_ != nullptr);
@@ -255,6 +255,13 @@
     return QuicConsumedData(consumed, false);
   }
 
+  QuicConsumedData SaveIovShort(const QuicIOVector& data) {
+    const iovec* iov = data.iov;
+    int consumed = 1;
+    saved_data_.append(static_cast<char*>(iov[0].iov_base), consumed);
+    return QuicConsumedData(consumed, false);
+  }
+
   QuicConsumedData SaveIovAndNotifyAckListener(
       const QuicIOVector& data,
       QuicAckListenerInterface* ack_listener) {
@@ -937,7 +944,6 @@
   QuicStreamId id = kClientDataStreamId1;
   QuicStreamOffset offset = 0;
   struct iovec iov;
-  string data;
 
   // This test will issue a write that will require fragmenting into
   // multiple HTTP/2 DATA frames.
@@ -946,7 +952,7 @@
       kSpdyInitialFrameSizeLimit * kMinDataFrames + 1024;
   // Set headers stream send window large enough for data written below.
   headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4);
-  test::GenerateBody(&data, data_len);
+  string data(data_len, 'a');
 
   for (bool fin : {true, false}) {
     for (bool use_ack_listener : {true, false}) {
@@ -988,6 +994,66 @@
   }
 }
 
+TEST_P(QuicHeadersStreamTest, WritevStreamDataFinOnly) {
+  FLAGS_quic_bugfix_fhol_writev_fin_only_v2 = true;
+  struct iovec iov;
+  string data;
+
+  EXPECT_CALL(session_,
+              WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
+      .WillOnce(WithArgs<2, 5>(
+          Invoke(this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener)));
+
+  QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
+      kClientDataStreamId1, MakeIOVector(data, &iov), 0, true, nullptr);
+
+  EXPECT_EQ(consumed_data.bytes_consumed, 0u);
+  EXPECT_EQ(consumed_data.fin_consumed, true);
+}
+
+TEST_P(QuicHeadersStreamTest, WritevStreamDataSendBlocked) {
+  FLAGS_quic_bugfix_fhol_writev_fin_only_v2 = true;
+  QuicStreamId id = kClientDataStreamId1;
+  QuicStreamOffset offset = 0;
+  struct iovec iov;
+
+  // This test will issue a write that will require fragmenting into
+  // multiple HTTP/2 DATA frames.  It will ensure that only 1 frame
+  // will go out in the case that the underlying session becomes write
+  // blocked.  Buffering is required to preserve framing, but the
+  // amount of buffering is limited to one HTTP/2 data frame.
+  const int kMinDataFrames = 4;
+  const size_t data_len = kSpdyInitialFrameSizeLimit * kMinDataFrames + 1024;
+  // Set headers stream send window large enough for data written below.
+  headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4);
+  string data(data_len, 'a');
+
+  bool fin = true;
+  // So force the underlying |WritevData| to consume only 1 byte.
+  // In that case, |WritevStreamData| should consume just one
+  // HTTP/2 data frame's worth of data.
+  EXPECT_CALL(session_,
+              WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
+      .WillOnce(
+          WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIovShort)));
+
+  QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
+      id, MakeIOVector(data, &iov), offset, fin, nullptr);
+
+  // bytes_consumed is max HTTP/2 data frame size minus the HTTP/2
+  // data header size.
+  EXPECT_EQ(consumed_data.bytes_consumed,
+            kSpdyInitialFrameSizeLimit - SpdyConstants::kDataFrameMinimumSize);
+  EXPECT_EQ(consumed_data.fin_consumed, false);
+
+  // If session already blocked, then bytes_consumed should be zero.
+  consumed_data = headers_stream_->WritevStreamData(
+      id, MakeIOVector(data, &iov), offset, fin, nullptr);
+
+  EXPECT_EQ(consumed_data.bytes_consumed, 0u);
+  EXPECT_EQ(consumed_data.fin_consumed, false);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/core/quic_http_utils.h b/net/quic/core/quic_http_utils.h
index 6b3e38f..ffb7c37 100644
--- a/net/quic/core/quic_http_utils.h
+++ b/net/quic/core/quic_http_utils.h
@@ -8,7 +8,7 @@
 #include "base/values.h"
 #include "net/base/net_export.h"
 #include "net/base/request_priority.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/spdy/spdy_header_block.h"
 #include "net/spdy/spdy_protocol.h"
 
diff --git a/net/quic/core/quic_multipath_received_packet_manager.h b/net/quic/core/quic_multipath_received_packet_manager.h
index d85ace7..7d4a8854 100644
--- a/net/quic/core/quic_multipath_received_packet_manager.h
+++ b/net/quic/core/quic_multipath_received_packet_manager.h
@@ -13,7 +13,7 @@
 #include <vector>
 
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_received_packet_manager.h"
 
 namespace net {
diff --git a/net/quic/core/quic_multipath_sent_packet_manager.cc b/net/quic/core/quic_multipath_sent_packet_manager.cc
index 5d46ec10..8701037 100644
--- a/net/quic/core/quic_multipath_sent_packet_manager.cc
+++ b/net/quic/core/quic_multipath_sent_packet_manager.cc
@@ -129,7 +129,7 @@
   return path_manager != nullptr && path_manager->HasPendingRetransmissions();
 }
 
-PendingRetransmission
+QuicPendingRetransmission
 QuicMultipathSentPacketManager::NextPendingRetransmission() {
   // TODO(fayang): Move pending_retransmissions_ from path sent packet manager
   // to multipath sent packet manager.
@@ -138,9 +138,9 @@
   if (path_manager == nullptr) {
     OnUnrecoverablePathError(kDefaultPathId);
     QuicFrames retransmittable_frames;
-    return PendingRetransmission(kInvalidPathId, 0u, NOT_RETRANSMISSION,
-                                 retransmittable_frames, false, 0,
-                                 ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER);
+    return QuicPendingRetransmission(
+        kInvalidPathId, 0u, NOT_RETRANSMISSION, retransmittable_frames, false,
+        0, ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER);
   }
   return path_manager->NextPendingRetransmission();
 }
@@ -521,4 +521,14 @@
   }
 }
 
+const SendAlgorithmInterface* QuicMultipathSentPacketManager::GetSendAlgorithm()
+    const {
+  QuicSentPacketManagerInterface* path_manager =
+      MaybeGetSentPacketManagerForActivePath(kDefaultPathId);
+  if (path_manager == nullptr) {
+    return nullptr;
+  }
+  return path_manager->GetSendAlgorithm();
+}
+
 }  // namespace net
diff --git a/net/quic/core/quic_multipath_sent_packet_manager.h b/net/quic/core/quic_multipath_sent_packet_manager.h
index 5aff14a9..b5162480 100644
--- a/net/quic/core/quic_multipath_sent_packet_manager.h
+++ b/net/quic/core/quic_multipath_sent_packet_manager.h
@@ -9,7 +9,7 @@
 
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_connection_close_delegate_interface.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
 #include "net/quic/core/quic_sent_packet_manager_interface.h"
 
@@ -74,7 +74,7 @@
 
   // Retrieves the next pending retransmission.  Caller must ensure that
   // there are pending retransmissions prior to calling this function.
-  PendingRetransmission NextPendingRetransmission() override;
+  QuicPendingRetransmission NextPendingRetransmission() override;
 
   // Returns true if the any path has unacked packets.
   bool HasUnackedPackets() const override;
@@ -167,6 +167,8 @@
 
   void OnApplicationLimited() override;
 
+  const SendAlgorithmInterface* GetSendAlgorithm() const override;
+
  private:
   friend class test::QuicConnectionPeer;
   friend class test::QuicMultipathSentPacketManagerPeer;
diff --git a/net/quic/core/quic_multipath_sent_packet_manager_test.cc b/net/quic/core/quic_multipath_sent_packet_manager_test.cc
index 2a9bcf8..fdb5979 100644
--- a/net/quic/core/quic_multipath_sent_packet_manager_test.cc
+++ b/net/quic/core/quic_multipath_sent_packet_manager_test.cc
@@ -128,7 +128,7 @@
 TEST_F(QuicMultipathSentPacketManagerTest, NextPendingRetransmission) {
   SerializedPacket packet(kDefaultPathId, 1, PACKET_6BYTE_PACKET_NUMBER,
                           nullptr, 1250, false, false);
-  PendingRetransmission retransmission(
+  QuicPendingRetransmission retransmission(
       packet.path_id, packet.packet_number, LOSS_RETRANSMISSION,
       packet.retransmittable_frames, packet.has_crypto_handshake,
       packet.num_padding_bytes, packet.encryption_level,
diff --git a/net/quic/core/quic_multipath_transmissions_map.h b/net/quic/core/quic_multipath_transmissions_map.h
index 8802e4d..2b3779d 100644
--- a/net/quic/core/quic_multipath_transmissions_map.h
+++ b/net/quic/core/quic_multipath_transmissions_map.h
@@ -17,7 +17,7 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 
 namespace net {
diff --git a/net/quic/core/quic_packet_creator.cc b/net/quic/core/quic_packet_creator.cc
index 85a99f4..1240beac 100644
--- a/net/quic/core/quic_packet_creator.cc
+++ b/net/quic/core/quic_packet_creator.cc
@@ -272,7 +272,7 @@
 }
 
 void QuicPacketCreator::ReserializeAllFrames(
-    const PendingRetransmission& retransmission,
+    const QuicPendingRetransmission& retransmission,
     char* buffer,
     size_t buffer_len) {
   DCHECK(queued_frames_.empty());
@@ -335,11 +335,6 @@
 
   delegate_->OnSerializedPacket(&packet_);
   ClearPacket();
-  // Maximum packet size may be only enacted while no packet is currently being
-  // constructed, so here we have a good opportunity to actually change it.
-  if (CanSetMaxPacketLength()) {
-    SetMaxPacketLength(max_packet_length_);
-  }
 }
 
 void QuicPacketCreator::ClearPacket() {
diff --git a/net/quic/core/quic_packet_creator.h b/net/quic/core/quic_packet_creator.h
index f77ff08..573e083 100644
--- a/net/quic/core/quic_packet_creator.h
+++ b/net/quic/core/quic_packet_creator.h
@@ -24,7 +24,8 @@
 #include "net/quic/core/quic_connection_close_delegate_interface.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_iovector.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_pending_retransmission.h"
 
 namespace net {
 namespace test {
@@ -106,7 +107,7 @@
 
   // Re-serializes frames with the original packet's packet number length.
   // Used for retransmitting packets to ensure they aren't too long.
-  void ReserializeAllFrames(const PendingRetransmission& retransmission,
+  void ReserializeAllFrames(const QuicPendingRetransmission& retransmission,
                             char* buffer,
                             size_t buffer_len);
 
diff --git a/net/quic/core/quic_packet_creator_test.cc b/net/quic/core/quic_packet_creator_test.cc
index 49e3f75..ffddbbb 100644
--- a/net/quic/core/quic_packet_creator_test.cc
+++ b/net/quic/core/quic_packet_creator_test.cc
@@ -197,16 +197,16 @@
     return ::net::test::MakeIOVector(s, &iov_);
   }
 
-  PendingRetransmission CreateRetransmission(
+  QuicPendingRetransmission CreateRetransmission(
       const QuicFrames& retransmittable_frames,
       bool has_crypto_handshake,
       int num_padding_bytes,
       EncryptionLevel encryption_level,
       QuicPacketNumberLength packet_number_length) {
-    return PendingRetransmission(1u, 1u, NOT_RETRANSMISSION,
-                                 retransmittable_frames, has_crypto_handshake,
-                                 num_padding_bytes, encryption_level,
-                                 packet_number_length);
+    return QuicPendingRetransmission(1u, 1u, NOT_RETRANSMISSION,
+                                     retransmittable_frames,
+                                     has_crypto_handshake, num_padding_bytes,
+                                     encryption_level, packet_number_length);
   }
 
   static const QuicStreamOffset kOffset = 1u;
@@ -276,7 +276,7 @@
   QuicFrames frames;
   frames.push_back(QuicFrame(stream_frame));
   char buffer[kMaxPacketSize];
-  PendingRetransmission retransmission(CreateRetransmission(
+  QuicPendingRetransmission retransmission(CreateRetransmission(
       frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
       ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER));
   EXPECT_CALL(delegate_, OnSerializedPacket(_))
@@ -311,7 +311,7 @@
   frames.push_back(QuicFrame(stream_frame));
   creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
   char buffer[kMaxPacketSize];
-  PendingRetransmission retransmission(CreateRetransmission(
+  QuicPendingRetransmission retransmission(CreateRetransmission(
       frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
       ENCRYPTION_NONE,
       QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -329,7 +329,7 @@
   frames.push_back(QuicFrame(stream_frame));
   creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
   char buffer[kMaxPacketSize];
-  PendingRetransmission retransmission(CreateRetransmission(
+  QuicPendingRetransmission retransmission(CreateRetransmission(
       frames, false /* has_crypto_handshake */, 0 /* no padding */,
       ENCRYPTION_NONE,
       QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -348,7 +348,7 @@
   QuicFrames frames;
   frames.push_back(frame);
   char buffer[kMaxPacketSize];
-  PendingRetransmission retransmission(CreateRetransmission(
+  QuicPendingRetransmission retransmission(CreateRetransmission(
       frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
       ENCRYPTION_NONE,
       QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -371,7 +371,7 @@
     QuicFrames frames;
     frames.push_back(frame);
     char buffer[kMaxPacketSize];
-    PendingRetransmission retransmission(CreateRetransmission(
+    QuicPendingRetransmission retransmission(CreateRetransmission(
         frames, false /* has_crypto_handshake */,
         kNumPaddingBytes1 /* padding bytes */, ENCRYPTION_NONE,
         QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -385,7 +385,7 @@
   QuicFrames frames;
   frames.push_back(frame);
   char buffer[kMaxPacketSize];
-  PendingRetransmission retransmission(CreateRetransmission(
+  QuicPendingRetransmission retransmission(CreateRetransmission(
       frames, false /* has_crypto_handshake */,
       kNumPaddingBytes2 /* padding bytes */, ENCRYPTION_NONE,
       QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
@@ -413,7 +413,7 @@
     QuicFrames frames;
     frames.push_back(frame);
     char buffer[kMaxPacketSize];
-    PendingRetransmission retransmission(CreateRetransmission(
+    QuicPendingRetransmission retransmission(CreateRetransmission(
         frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
         ENCRYPTION_NONE,
         QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
diff --git a/net/quic/core/quic_packet_generator.cc b/net/quic/core/quic_packet_generator.cc
index 3a2d01c..fc7bbbb67 100644
--- a/net/quic/core/quic_packet_generator.cc
+++ b/net/quic/core/quic_packet_generator.cc
@@ -298,7 +298,7 @@
 }
 
 void QuicPacketGenerator::ReserializeAllFrames(
-    const PendingRetransmission& retransmission,
+    const QuicPendingRetransmission& retransmission,
     char* buffer,
     size_t buffer_len) {
   packet_creator_.ReserializeAllFrames(retransmission, buffer, buffer_len);
diff --git a/net/quic/core/quic_packet_generator.h b/net/quic/core/quic_packet_generator.h
index 75058aa..cdb9840 100644
--- a/net/quic/core/quic_packet_generator.h
+++ b/net/quic/core/quic_packet_generator.h
@@ -48,6 +48,7 @@
 #include "base/macros.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_packet_creator.h"
+#include "net/quic/core/quic_pending_retransmission.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
 #include "net/quic/core/quic_types.h"
 
@@ -140,7 +141,7 @@
 
   // Re-serializes frames with the original packet's packet number length.
   // Used for retransmitting packets to ensure they aren't too long.
-  void ReserializeAllFrames(const PendingRetransmission& retransmission,
+  void ReserializeAllFrames(const QuicPendingRetransmission& retransmission,
                             char* buffer,
                             size_t buffer_len);
 
diff --git a/net/quic/core/quic_packet_writer.h b/net/quic/core/quic_packet_writer.h
index 98252707..a4002af 100644
--- a/net/quic/core/quic_packet_writer.h
+++ b/net/quic/core/quic_packet_writer.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 
 namespace net {
diff --git a/net/quic/core/quic_packets.cc b/net/quic/core/quic_packets.cc
new file mode 100644
index 0000000..253155d
--- /dev/null
+++ b/net/quic/core/quic_packets.cc
@@ -0,0 +1,251 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/quic_packets.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/core/quic_versions.h"
+
+using base::StringPiece;
+using std::map;
+using std::numeric_limits;
+using std::ostream;
+using std::string;
+
+namespace net {
+
+size_t GetPacketHeaderSize(QuicVersion version,
+                           const QuicPacketHeader& header) {
+  return GetPacketHeaderSize(version, header.public_header.connection_id_length,
+                             header.public_header.version_flag,
+                             header.public_header.multipath_flag,
+                             header.public_header.nonce != nullptr,
+                             header.public_header.packet_number_length);
+}
+
+size_t GetPacketHeaderSize(QuicVersion version,
+                           QuicConnectionIdLength connection_id_length,
+                           bool include_version,
+                           bool include_path_id,
+                           bool include_diversification_nonce,
+                           QuicPacketNumberLength packet_number_length) {
+  return kPublicFlagsSize + connection_id_length +
+         (include_version ? kQuicVersionSize : 0) +
+         (include_path_id ? kQuicPathIdSize : 0) + packet_number_length +
+         (include_diversification_nonce ? kDiversificationNonceSize : 0);
+}
+
+size_t GetStartOfEncryptedData(QuicVersion version,
+                               const QuicPacketHeader& header) {
+  return GetPacketHeaderSize(version, header);
+}
+
+size_t GetStartOfEncryptedData(QuicVersion version,
+                               QuicConnectionIdLength connection_id_length,
+                               bool include_version,
+                               bool include_path_id,
+                               bool include_diversification_nonce,
+                               QuicPacketNumberLength packet_number_length) {
+  // Encryption starts before private flags.
+  return GetPacketHeaderSize(version, connection_id_length, include_version,
+                             include_path_id, include_diversification_nonce,
+                             packet_number_length);
+}
+
+QuicPacketPublicHeader::QuicPacketPublicHeader()
+    : connection_id(0),
+      connection_id_length(PACKET_8BYTE_CONNECTION_ID),
+      multipath_flag(false),
+      reset_flag(false),
+      version_flag(false),
+      packet_number_length(PACKET_6BYTE_PACKET_NUMBER),
+      nonce(nullptr) {}
+
+QuicPacketPublicHeader::QuicPacketPublicHeader(
+    const QuicPacketPublicHeader& other) = default;
+
+QuicPacketPublicHeader::~QuicPacketPublicHeader() {}
+
+QuicPacketHeader::QuicPacketHeader()
+    : packet_number(0), path_id(kDefaultPathId) {}
+
+QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
+    : public_header(header), packet_number(0), path_id(kDefaultPathId) {}
+
+QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default;
+
+QuicPublicResetPacket::QuicPublicResetPacket()
+    : nonce_proof(0), rejected_packet_number(0) {}
+
+QuicPublicResetPacket::QuicPublicResetPacket(
+    const QuicPacketPublicHeader& header)
+    : public_header(header), nonce_proof(0), rejected_packet_number(0) {}
+
+ostream& operator<<(ostream& os, const QuicPacketHeader& header) {
+  os << "{ connection_id: " << header.public_header.connection_id
+     << ", connection_id_length: " << header.public_header.connection_id_length
+     << ", packet_number_length: " << header.public_header.packet_number_length
+     << ", multipath_flag: " << header.public_header.multipath_flag
+     << ", reset_flag: " << header.public_header.reset_flag
+     << ", version_flag: " << header.public_header.version_flag;
+  if (header.public_header.version_flag) {
+    os << ", version:";
+    for (size_t i = 0; i < header.public_header.versions.size(); ++i) {
+      os << " ";
+      os << QuicVersionToString(header.public_header.versions[i]);
+    }
+  }
+  if (header.public_header.nonce != nullptr) {
+    os << ", diversification_nonce: "
+       << QuicUtils::HexEncode(StringPiece(header.public_header.nonce->data(),
+                                           header.public_header.nonce->size()));
+  }
+  os << ", path_id: " << static_cast<int>(header.path_id)
+     << ", packet_number: " << header.packet_number << " }\n";
+  return os;
+}
+
+QuicData::QuicData(const char* buffer, size_t length)
+    : buffer_(buffer), length_(length), owns_buffer_(false) {}
+
+QuicData::QuicData(const char* buffer, size_t length, bool owns_buffer)
+    : buffer_(buffer), length_(length), owns_buffer_(owns_buffer) {}
+
+QuicData::~QuicData() {
+  if (owns_buffer_) {
+    delete[] const_cast<char*>(buffer_);
+  }
+}
+
+QuicPacket::QuicPacket(char* buffer,
+                       size_t length,
+                       bool owns_buffer,
+                       QuicConnectionIdLength connection_id_length,
+                       bool includes_version,
+                       bool includes_path_id,
+                       bool includes_diversification_nonce,
+                       QuicPacketNumberLength packet_number_length)
+    : QuicData(buffer, length, owns_buffer),
+      buffer_(buffer),
+      connection_id_length_(connection_id_length),
+      includes_version_(includes_version),
+      includes_path_id_(includes_path_id),
+      includes_diversification_nonce_(includes_diversification_nonce),
+      packet_number_length_(packet_number_length) {}
+
+QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, size_t length)
+    : QuicData(buffer, length) {}
+
+QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer,
+                                         size_t length,
+                                         bool owns_buffer)
+    : QuicData(buffer, length, owns_buffer) {}
+
+std::unique_ptr<QuicEncryptedPacket> QuicEncryptedPacket::Clone() const {
+  char* buffer = new char[this->length()];
+  memcpy(buffer, this->data(), this->length());
+  return base::MakeUnique<QuicEncryptedPacket>(buffer, this->length(), true);
+}
+
+ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
+  os << s.length() << "-byte data";
+  return os;
+}
+
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+                                       size_t length,
+                                       QuicTime receipt_time)
+    : QuicEncryptedPacket(buffer, length),
+      receipt_time_(receipt_time),
+      ttl_(0) {}
+
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+                                       size_t length,
+                                       QuicTime receipt_time,
+                                       bool owns_buffer)
+    : QuicEncryptedPacket(buffer, length, owns_buffer),
+      receipt_time_(receipt_time),
+      ttl_(0) {}
+
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+                                       size_t length,
+                                       QuicTime receipt_time,
+                                       bool owns_buffer,
+                                       int ttl,
+                                       bool ttl_valid)
+    : QuicEncryptedPacket(buffer, length, owns_buffer),
+      receipt_time_(receipt_time),
+      ttl_(ttl_valid ? ttl : -1) {}
+
+std::unique_ptr<QuicReceivedPacket> QuicReceivedPacket::Clone() const {
+  char* buffer = new char[this->length()];
+  memcpy(buffer, this->data(), this->length());
+  return base::MakeUnique<QuicReceivedPacket>(
+      buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0);
+}
+
+ostream& operator<<(ostream& os, const QuicReceivedPacket& s) {
+  os << s.length() << "-byte data";
+  return os;
+}
+
+StringPiece QuicPacket::AssociatedData(QuicVersion version) const {
+  return StringPiece(
+      data(), GetStartOfEncryptedData(version, connection_id_length_,
+                                      includes_version_, includes_path_id_,
+                                      includes_diversification_nonce_,
+                                      packet_number_length_));
+}
+
+StringPiece QuicPacket::Plaintext(QuicVersion version) const {
+  const size_t start_of_encrypted_data = GetStartOfEncryptedData(
+      version, connection_id_length_, includes_version_, includes_path_id_,
+      includes_diversification_nonce_, packet_number_length_);
+  return StringPiece(data() + start_of_encrypted_data,
+                     length() - start_of_encrypted_data);
+}
+
+SerializedPacket::SerializedPacket(QuicPathId path_id,
+                                   QuicPacketNumber packet_number,
+                                   QuicPacketNumberLength packet_number_length,
+                                   const char* encrypted_buffer,
+                                   QuicPacketLength encrypted_length,
+                                   bool has_ack,
+                                   bool has_stop_waiting)
+    : encrypted_buffer(encrypted_buffer),
+      encrypted_length(encrypted_length),
+      has_crypto_handshake(NOT_HANDSHAKE),
+      num_padding_bytes(0),
+      path_id(path_id),
+      packet_number(packet_number),
+      packet_number_length(packet_number_length),
+      encryption_level(ENCRYPTION_NONE),
+      has_ack(has_ack),
+      has_stop_waiting(has_stop_waiting),
+      transmission_type(NOT_RETRANSMISSION),
+      original_path_id(kInvalidPathId),
+      original_packet_number(0) {}
+
+SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
+
+SerializedPacket::~SerializedPacket() {}
+
+void ClearSerializedPacket(SerializedPacket* serialized_packet) {
+  if (!serialized_packet->retransmittable_frames.empty()) {
+    DeleteFrames(&serialized_packet->retransmittable_frames);
+  }
+  serialized_packet->encrypted_buffer = nullptr;
+  serialized_packet->encrypted_length = 0;
+}
+
+char* CopyBuffer(const SerializedPacket& packet) {
+  char* dst_buffer = new char[packet.encrypted_length];
+  memcpy(dst_buffer, packet.encrypted_buffer, packet.encrypted_length);
+  return dst_buffer;
+}
+
+}  // namespace net
diff --git a/net/quic/core/quic_packets.h b/net/quic/core/quic_packets.h
new file mode 100644
index 0000000..ed23bce
--- /dev/null
+++ b/net/quic/core/quic_packets.h
@@ -0,0 +1,263 @@
+// 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.
+
+#ifndef NET_QUIC_QUIC_PROTOCOL_H_
+#define NET_QUIC_QUIC_PROTOCOL_H_
+
+#include <limits>
+#include <list>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_piece.h"
+#include "net/base/int128.h"
+#include "net/base/iovec.h"
+#include "net/base/net_export.h"
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/quic_ack_listener_interface.h"
+#include "net/quic/core/quic_bandwidth.h"
+#include "net/quic/core/quic_constants.h"
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_time.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/core/quic_versions.h"
+#include "net/quic/platform/api/quic_socket_address.h"
+
+namespace net {
+
+class QuicPacket;
+struct QuicPacketHeader;
+
+// Size in bytes of the data packet header.
+NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(QuicVersion version,
+                                              const QuicPacketHeader& header);
+
+NET_EXPORT_PRIVATE size_t
+GetPacketHeaderSize(QuicVersion version,
+                    QuicConnectionIdLength connection_id_length,
+                    bool include_version,
+                    bool include_path_id,
+                    bool include_diversification_nonce,
+                    QuicPacketNumberLength packet_number_length);
+
+// Index of the first byte in a QUIC packet of encrypted data.
+NET_EXPORT_PRIVATE size_t
+GetStartOfEncryptedData(QuicVersion version, const QuicPacketHeader& header);
+
+NET_EXPORT_PRIVATE size_t
+GetStartOfEncryptedData(QuicVersion version,
+                        QuicConnectionIdLength connection_id_length,
+                        bool include_version,
+                        bool include_path_id,
+                        bool include_diversification_nonce,
+                        QuicPacketNumberLength packet_number_length);
+
+struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
+  QuicPacketPublicHeader();
+  explicit QuicPacketPublicHeader(const QuicPacketPublicHeader& other);
+  ~QuicPacketPublicHeader();
+
+  // Universal header. All QuicPacket headers will have a connection_id and
+  // public flags.
+  QuicConnectionId connection_id;
+  QuicConnectionIdLength connection_id_length;
+  bool multipath_flag;
+  bool reset_flag;
+  bool version_flag;
+  QuicPacketNumberLength packet_number_length;
+  QuicVersionVector versions;
+  // nonce contains an optional, 32-byte nonce value. If not included in the
+  // packet, |nonce| will be empty.
+  DiversificationNonce* nonce;
+};
+
+// Header for Data packets.
+struct NET_EXPORT_PRIVATE QuicPacketHeader {
+  QuicPacketHeader();
+  explicit QuicPacketHeader(const QuicPacketPublicHeader& header);
+  QuicPacketHeader(const QuicPacketHeader& other);
+
+  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
+                                                     const QuicPacketHeader& s);
+
+  QuicPacketPublicHeader public_header;
+  QuicPacketNumber packet_number;
+  QuicPathId path_id;
+};
+
+struct NET_EXPORT_PRIVATE QuicPublicResetPacket {
+  QuicPublicResetPacket();
+  explicit QuicPublicResetPacket(const QuicPacketPublicHeader& header);
+
+  QuicPacketPublicHeader public_header;
+  QuicPublicResetNonceProof nonce_proof;
+  // TODO(fayang): remove rejected_packet_number when deprecating
+  // FLAGS_quic_remove_packet_number_from_public_reset.
+  QuicPacketNumber rejected_packet_number;
+  QuicSocketAddress client_address;
+};
+
+typedef QuicPacketPublicHeader QuicVersionNegotiationPacket;
+
+class NET_EXPORT_PRIVATE QuicData {
+ public:
+  QuicData(const char* buffer, size_t length);
+  QuicData(const char* buffer, size_t length, bool owns_buffer);
+  virtual ~QuicData();
+
+  base::StringPiece AsStringPiece() const {
+    return base::StringPiece(data(), length());
+  }
+
+  const char* data() const { return buffer_; }
+  size_t length() const { return length_; }
+
+ private:
+  const char* buffer_;
+  size_t length_;
+  bool owns_buffer_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicData);
+};
+
+class NET_EXPORT_PRIVATE QuicPacket : public QuicData {
+ public:
+  // TODO(fayang): 4 fields from public header are passed in as arguments.
+  // Consider to add a convenience method which directly accepts the entire
+  // public header.
+  QuicPacket(char* buffer,
+             size_t length,
+             bool owns_buffer,
+             QuicConnectionIdLength connection_id_length,
+             bool includes_version,
+             bool includes_path_id,
+             bool includes_diversification_nonce,
+             QuicPacketNumberLength packet_number_length);
+
+  base::StringPiece AssociatedData(QuicVersion version) const;
+  base::StringPiece Plaintext(QuicVersion version) const;
+
+  char* mutable_data() { return buffer_; }
+
+ private:
+  char* buffer_;
+  const QuicConnectionIdLength connection_id_length_;
+  const bool includes_version_;
+  const bool includes_path_id_;
+  const bool includes_diversification_nonce_;
+  const QuicPacketNumberLength packet_number_length_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicPacket);
+};
+
+class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
+ public:
+  QuicEncryptedPacket(const char* buffer, size_t length);
+  QuicEncryptedPacket(const char* buffer, size_t length, bool owns_buffer);
+
+  // Clones the packet into a new packet which owns the buffer.
+  std::unique_ptr<QuicEncryptedPacket> Clone() const;
+
+  // By default, gtest prints the raw bytes of an object. The bool data
+  // member (in the base class QuicData) causes this object to have padding
+  // bytes, which causes the default gtest object printer to read
+  // uninitialize memory. So we need to teach gtest how to print this object.
+  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
+      std::ostream& os,
+      const QuicEncryptedPacket& s);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
+};
+
+// A received encrypted QUIC packet, with a recorded time of receipt.
+class NET_EXPORT_PRIVATE QuicReceivedPacket : public QuicEncryptedPacket {
+ public:
+  QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time);
+  QuicReceivedPacket(const char* buffer,
+                     size_t length,
+                     QuicTime receipt_time,
+                     bool owns_buffer);
+  QuicReceivedPacket(const char* buffer,
+                     size_t length,
+                     QuicTime receipt_time,
+                     bool owns_buffer,
+                     int ttl,
+                     bool ttl_valid);
+
+  // Clones the packet into a new packet which owns the buffer.
+  std::unique_ptr<QuicReceivedPacket> Clone() const;
+
+  // Returns the time at which the packet was received.
+  QuicTime receipt_time() const { return receipt_time_; }
+
+  // This is the TTL of the packet, assuming ttl_vaild_ is true.
+  int ttl() const { return ttl_; }
+
+  // By default, gtest prints the raw bytes of an object. The bool data
+  // member (in the base class QuicData) causes this object to have padding
+  // bytes, which causes the default gtest object printer to read
+  // uninitialize memory. So we need to teach gtest how to print this object.
+  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
+      std::ostream& os,
+      const QuicReceivedPacket& s);
+
+ private:
+  const QuicTime receipt_time_;
+  int ttl_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacket);
+};
+
+struct NET_EXPORT_PRIVATE SerializedPacket {
+  SerializedPacket(QuicPathId path_id,
+                   QuicPacketNumber packet_number,
+                   QuicPacketNumberLength packet_number_length,
+                   const char* encrypted_buffer,
+                   QuicPacketLength encrypted_length,
+                   bool has_ack,
+                   bool has_stop_waiting);
+  SerializedPacket(const SerializedPacket& other);
+  ~SerializedPacket();
+
+  // Not owned.
+  const char* encrypted_buffer;
+  QuicPacketLength encrypted_length;
+  QuicFrames retransmittable_frames;
+  IsHandshake has_crypto_handshake;
+  // -1: full padding to the end of a max-sized packet
+  //  0: no padding
+  //  otherwise: only pad up to num_padding_bytes bytes
+  int16_t num_padding_bytes;
+  QuicPathId path_id;
+  QuicPacketNumber packet_number;
+  QuicPacketNumberLength packet_number_length;
+  EncryptionLevel encryption_level;
+  bool has_ack;
+  bool has_stop_waiting;
+  TransmissionType transmission_type;
+  QuicPathId original_path_id;
+  QuicPacketNumber original_packet_number;
+
+  // Optional notifiers which will be informed when this packet has been ACKed.
+  std::list<AckListenerWrapper> listeners;
+};
+
+// Deletes and clears all the frames and the packet from serialized packet.
+NET_EXPORT_PRIVATE void ClearSerializedPacket(
+    SerializedPacket* serialized_packet);
+
+// Allocates a new char[] of size |packet.encrypted_length| and copies in
+// |packet.encrypted_buffer|.
+NET_EXPORT_PRIVATE char* CopyBuffer(const SerializedPacket& packet);
+
+}  // namespace net
+
+#endif  // NET_QUIC_QUIC_PROTOCOL_H_
diff --git a/net/quic/core/quic_pending_retransmission.h b/net/quic/core/quic_pending_retransmission.h
new file mode 100644
index 0000000..71b01c4
--- /dev/null
+++ b/net/quic/core/quic_pending_retransmission.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
+#define NET_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
+
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// Struct to store the pending retransmission information.
+struct NET_EXPORT_PRIVATE QuicPendingRetransmission {
+  QuicPendingRetransmission(QuicPathId path_id,
+                            QuicPacketNumber packet_number,
+                            TransmissionType transmission_type,
+                            const QuicFrames& retransmittable_frames,
+                            bool has_crypto_handshake,
+                            int num_padding_bytes,
+                            EncryptionLevel encryption_level,
+                            QuicPacketNumberLength packet_number_length)
+      : packet_number(packet_number),
+        retransmittable_frames(retransmittable_frames),
+        transmission_type(transmission_type),
+        path_id(path_id),
+        has_crypto_handshake(has_crypto_handshake),
+        num_padding_bytes(num_padding_bytes),
+        encryption_level(encryption_level),
+        packet_number_length(packet_number_length) {}
+
+  QuicPacketNumber packet_number;
+  const QuicFrames& retransmittable_frames;
+  TransmissionType transmission_type;
+  QuicPathId path_id;
+  bool has_crypto_handshake;
+  int num_padding_bytes;
+  EncryptionLevel encryption_level;
+  QuicPacketNumberLength packet_number_length;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
diff --git a/net/quic/core/quic_protocol.cc b/net/quic/core/quic_protocol.cc
deleted file mode 100644
index 94445d5..0000000
--- a/net/quic/core/quic_protocol.cc
+++ /dev/null
@@ -1,775 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/core/quic_protocol.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_utils.h"
-#include "net/quic/core/quic_versions.h"
-
-using base::StringPiece;
-using std::map;
-using std::numeric_limits;
-using std::ostream;
-using std::string;
-
-namespace net {
-
-size_t GetPacketHeaderSize(QuicVersion version,
-                           const QuicPacketHeader& header) {
-  return GetPacketHeaderSize(version, header.public_header.connection_id_length,
-                             header.public_header.version_flag,
-                             header.public_header.multipath_flag,
-                             header.public_header.nonce != nullptr,
-                             header.public_header.packet_number_length);
-}
-
-size_t GetPacketHeaderSize(QuicVersion version,
-                           QuicConnectionIdLength connection_id_length,
-                           bool include_version,
-                           bool include_path_id,
-                           bool include_diversification_nonce,
-                           QuicPacketNumberLength packet_number_length) {
-  return kPublicFlagsSize + connection_id_length +
-         (include_version ? kQuicVersionSize : 0) +
-         (include_path_id ? kQuicPathIdSize : 0) + packet_number_length +
-         (include_diversification_nonce ? kDiversificationNonceSize : 0);
-}
-
-size_t GetStartOfEncryptedData(QuicVersion version,
-                               const QuicPacketHeader& header) {
-  return GetPacketHeaderSize(version, header);
-}
-
-size_t GetStartOfEncryptedData(QuicVersion version,
-                               QuicConnectionIdLength connection_id_length,
-                               bool include_version,
-                               bool include_path_id,
-                               bool include_diversification_nonce,
-                               QuicPacketNumberLength packet_number_length) {
-  // Encryption starts before private flags.
-  return GetPacketHeaderSize(version, connection_id_length, include_version,
-                             include_path_id, include_diversification_nonce,
-                             packet_number_length);
-}
-
-QuicPacketPublicHeader::QuicPacketPublicHeader()
-    : connection_id(0),
-      connection_id_length(PACKET_8BYTE_CONNECTION_ID),
-      multipath_flag(false),
-      reset_flag(false),
-      version_flag(false),
-      packet_number_length(PACKET_6BYTE_PACKET_NUMBER),
-      nonce(nullptr) {}
-
-QuicPacketPublicHeader::QuicPacketPublicHeader(
-    const QuicPacketPublicHeader& other) = default;
-
-QuicPacketPublicHeader::~QuicPacketPublicHeader() {}
-
-QuicPacketHeader::QuicPacketHeader()
-    : packet_number(0), path_id(kDefaultPathId) {}
-
-QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
-    : public_header(header), packet_number(0), path_id(kDefaultPathId) {}
-
-QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default;
-
-QuicPublicResetPacket::QuicPublicResetPacket()
-    : nonce_proof(0), rejected_packet_number(0) {}
-
-QuicPublicResetPacket::QuicPublicResetPacket(
-    const QuicPacketPublicHeader& header)
-    : public_header(header), nonce_proof(0), rejected_packet_number(0) {}
-
-void StreamBufferDeleter::operator()(char* buffer) const {
-  if (allocator_ != nullptr && buffer != nullptr) {
-    allocator_->Delete(buffer);
-  }
-}
-
-UniqueStreamBuffer NewStreamBuffer(QuicBufferAllocator* allocator,
-                                   size_t size) {
-  return UniqueStreamBuffer(allocator->New(size),
-                            StreamBufferDeleter(allocator));
-}
-
-QuicStreamFrame::QuicStreamFrame()
-    : QuicStreamFrame(0, false, 0, nullptr, 0, nullptr) {}
-
-QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
-                                 bool fin,
-                                 QuicStreamOffset offset,
-                                 StringPiece data)
-    : QuicStreamFrame(stream_id,
-                      fin,
-                      offset,
-                      data.data(),
-                      data.length(),
-                      nullptr) {}
-
-QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
-                                 bool fin,
-                                 QuicStreamOffset offset,
-                                 QuicPacketLength data_length,
-                                 UniqueStreamBuffer buffer)
-    : QuicStreamFrame(stream_id,
-                      fin,
-                      offset,
-                      nullptr,
-                      data_length,
-                      std::move(buffer)) {
-  DCHECK(this->buffer != nullptr);
-  DCHECK_EQ(data_buffer, this->buffer.get());
-}
-
-QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
-                                 bool fin,
-                                 QuicStreamOffset offset,
-                                 const char* data_buffer,
-                                 QuicPacketLength data_length,
-                                 UniqueStreamBuffer buffer)
-    : stream_id(stream_id),
-      fin(fin),
-      data_length(data_length),
-      data_buffer(data_buffer),
-      offset(offset),
-      buffer(std::move(buffer)) {
-  if (this->buffer != nullptr) {
-    DCHECK(data_buffer == nullptr);
-    this->data_buffer = this->buffer.get();
-  }
-}
-
-QuicStreamFrame::~QuicStreamFrame() {}
-
-ostream& operator<<(ostream& os, const QuicPacketHeader& header) {
-  os << "{ connection_id: " << header.public_header.connection_id
-     << ", connection_id_length: " << header.public_header.connection_id_length
-     << ", packet_number_length: " << header.public_header.packet_number_length
-     << ", multipath_flag: " << header.public_header.multipath_flag
-     << ", reset_flag: " << header.public_header.reset_flag
-     << ", version_flag: " << header.public_header.version_flag;
-  if (header.public_header.version_flag) {
-    os << ", version:";
-    for (size_t i = 0; i < header.public_header.versions.size(); ++i) {
-      os << " ";
-      os << QuicVersionToString(header.public_header.versions[i]);
-    }
-  }
-  if (header.public_header.nonce != nullptr) {
-    os << ", diversification_nonce: "
-       << QuicUtils::HexEncode(StringPiece(header.public_header.nonce->data(),
-                                           header.public_header.nonce->size()));
-  }
-  os << ", path_id: " << static_cast<int>(header.path_id)
-     << ", packet_number: " << header.packet_number << " }\n";
-  return os;
-}
-
-bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
-                      QuicPacketNumber packet_number,
-                      QuicPacketNumber peer_least_packet_awaiting_ack) {
-  return packet_number >= peer_least_packet_awaiting_ack &&
-         !ack_frame.packets.Contains(packet_number);
-}
-
-QuicStopWaitingFrame::QuicStopWaitingFrame()
-    : path_id(kDefaultPathId), least_unacked(0) {}
-
-QuicStopWaitingFrame::~QuicStopWaitingFrame() {}
-
-QuicAckFrame::QuicAckFrame()
-    : largest_observed(0),
-      ack_delay_time(QuicTime::Delta::Infinite()),
-      path_id(kDefaultPathId) {}
-
-QuicAckFrame::QuicAckFrame(const QuicAckFrame& other) = default;
-
-QuicAckFrame::~QuicAckFrame() {}
-
-QuicRstStreamFrame::QuicRstStreamFrame()
-    : stream_id(0), error_code(QUIC_STREAM_NO_ERROR), byte_offset(0) {}
-
-QuicRstStreamFrame::QuicRstStreamFrame(QuicStreamId stream_id,
-                                       QuicRstStreamErrorCode error_code,
-                                       QuicStreamOffset bytes_written)
-    : stream_id(stream_id),
-      error_code(error_code),
-      byte_offset(bytes_written) {}
-
-QuicConnectionCloseFrame::QuicConnectionCloseFrame()
-    : error_code(QUIC_NO_ERROR) {}
-
-QuicFrame::QuicFrame() {}
-
-QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
-    : type(PADDING_FRAME), padding_frame(padding_frame) {}
-
-QuicFrame::QuicFrame(QuicStreamFrame* stream_frame)
-    : type(STREAM_FRAME), stream_frame(stream_frame) {}
-
-QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame)
-    : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicStopWaitingFrame* frame)
-    : type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicPingFrame frame)
-    : type(PING_FRAME), ping_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicRstStreamFrame* frame)
-    : type(RST_STREAM_FRAME), rst_stream_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame)
-    : type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicGoAwayFrame* frame)
-    : type(GOAWAY_FRAME), goaway_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicWindowUpdateFrame* frame)
-    : type(WINDOW_UPDATE_FRAME), window_update_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicBlockedFrame* frame)
-    : type(BLOCKED_FRAME), blocked_frame(frame) {}
-
-QuicFrame::QuicFrame(QuicPathCloseFrame* frame)
-    : type(PATH_CLOSE_FRAME), path_close_frame(frame) {}
-
-void DeleteFrames(QuicFrames* frames) {
-  for (QuicFrame& frame : *frames) {
-    switch (frame.type) {
-      // Frames smaller than a pointer are inlined, so don't need to be deleted.
-      case PADDING_FRAME:
-      case MTU_DISCOVERY_FRAME:
-      case PING_FRAME:
-        break;
-      case STREAM_FRAME:
-        delete frame.stream_frame;
-        break;
-      case ACK_FRAME:
-        delete frame.ack_frame;
-        break;
-      case STOP_WAITING_FRAME:
-        delete frame.stop_waiting_frame;
-        break;
-      case RST_STREAM_FRAME:
-        delete frame.rst_stream_frame;
-        break;
-      case CONNECTION_CLOSE_FRAME:
-        delete frame.connection_close_frame;
-        break;
-      case GOAWAY_FRAME:
-        delete frame.goaway_frame;
-        break;
-      case BLOCKED_FRAME:
-        delete frame.blocked_frame;
-        break;
-      case WINDOW_UPDATE_FRAME:
-        delete frame.window_update_frame;
-        break;
-      case PATH_CLOSE_FRAME:
-        delete frame.path_close_frame;
-        break;
-      case NUM_FRAME_TYPES:
-        DCHECK(false) << "Cannot delete type: " << frame.type;
-    }
-  }
-  frames->clear();
-}
-
-void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id) {
-  QuicFrames::iterator it = frames->begin();
-  while (it != frames->end()) {
-    if (it->type != STREAM_FRAME || it->stream_frame->stream_id != stream_id) {
-      ++it;
-      continue;
-    }
-    delete it->stream_frame;
-    it = frames->erase(it);
-  }
-}
-
-ostream& operator<<(ostream& os, const QuicStopWaitingFrame& sent_info) {
-  os << "{ least_unacked: " << sent_info.least_unacked << " }\n";
-  return os;
-}
-
-PacketNumberQueue::PacketNumberQueue() = default;
-PacketNumberQueue::PacketNumberQueue(const PacketNumberQueue& other) = default;
-// TODO(rtenneti): on windows RValue reference gives errors.
-// PacketNumberQueue::PacketNumberQueue(PacketNumberQueue&& other) = default;
-PacketNumberQueue::~PacketNumberQueue() {}
-
-PacketNumberQueue& PacketNumberQueue::operator=(
-    const PacketNumberQueue& other) = default;
-// TODO(rtenneti): on windows RValue reference gives errors.
-// PacketNumberQueue& PacketNumberQueue::operator=(PacketNumberQueue&& other) =
-//    default;
-
-void PacketNumberQueue::Add(QuicPacketNumber packet_number) {
-  packet_number_intervals_.Add(packet_number, packet_number + 1);
-}
-
-void PacketNumberQueue::Add(QuicPacketNumber lower, QuicPacketNumber higher) {
-  packet_number_intervals_.Add(lower, higher);
-}
-
-void PacketNumberQueue::Remove(QuicPacketNumber packet_number) {
-  packet_number_intervals_.Difference(packet_number, packet_number + 1);
-}
-
-void PacketNumberQueue::Remove(QuicPacketNumber lower,
-                               QuicPacketNumber higher) {
-  packet_number_intervals_.Difference(lower, higher);
-}
-
-bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
-  if (Empty()) {
-    return false;
-  }
-  const QuicPacketNumber old_min = Min();
-  packet_number_intervals_.Difference(0, higher);
-  return Empty() || old_min != Min();
-}
-
-void PacketNumberQueue::Complement() {
-  if (Empty()) {
-    return;
-  }
-  packet_number_intervals_.Complement(Min(), Max() + 1);
-}
-
-bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
-  return packet_number_intervals_.Contains(packet_number);
-}
-
-bool PacketNumberQueue::Empty() const {
-  return packet_number_intervals_.Empty();
-}
-
-QuicPacketNumber PacketNumberQueue::Min() const {
-  DCHECK(!Empty());
-  return packet_number_intervals_.begin()->min();
-}
-
-QuicPacketNumber PacketNumberQueue::Max() const {
-  DCHECK(!Empty());
-  return packet_number_intervals_.rbegin()->max() - 1;
-}
-
-size_t PacketNumberQueue::NumPacketsSlow() const {
-  size_t num_packets = 0;
-  for (const auto& interval : packet_number_intervals_) {
-    num_packets += interval.Length();
-  }
-  return num_packets;
-}
-
-size_t PacketNumberQueue::NumIntervals() const {
-  return packet_number_intervals_.Size();
-}
-
-QuicPacketNumber PacketNumberQueue::LastIntervalLength() const {
-  DCHECK(!Empty());
-  return packet_number_intervals_.rbegin()->Length();
-}
-
-PacketNumberQueue::const_iterator PacketNumberQueue::lower_bound(
-    QuicPacketNumber packet_number) const {
-  // lower_bound returns the first interval that contains |packet_number| or the
-  // first interval after |packet_number|.
-  auto itr = packet_number_intervals_.Find(packet_number);
-  if (itr != packet_number_intervals_.end()) {
-    return itr;
-  }
-  for (itr = packet_number_intervals_.begin();
-       itr != packet_number_intervals_.end(); ++itr) {
-    if (packet_number < itr->min()) {
-      return itr;
-    }
-  }
-  return packet_number_intervals_.end();
-}
-
-PacketNumberQueue::const_iterator PacketNumberQueue::begin() const {
-  return packet_number_intervals_.begin();
-}
-
-PacketNumberQueue::const_iterator PacketNumberQueue::end() const {
-  return packet_number_intervals_.end();
-}
-
-PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rbegin() const {
-  return packet_number_intervals_.rbegin();
-}
-
-PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const {
-  return packet_number_intervals_.rend();
-}
-
-ostream& operator<<(ostream& os, const PacketNumberQueue& q) {
-  for (const Interval<QuicPacketNumber>& interval : q) {
-    for (QuicPacketNumber packet_number = interval.min();
-         packet_number < interval.max(); ++packet_number) {
-      os << packet_number << " ";
-    }
-  }
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) {
-  os << "{ largest_observed: " << ack_frame.largest_observed
-     << ", ack_delay_time: " << ack_frame.ack_delay_time.ToMicroseconds()
-     << ", packets: [ " << ack_frame.packets << " ]"
-     << ", received_packets: [ ";
-  for (const std::pair<QuicPacketNumber, QuicTime>& p :
-       ack_frame.received_packet_times) {
-    os << p.first << " at " << p.second.ToDebuggingValue() << " ";
-  }
-  os << " ] }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicFrame& frame) {
-  switch (frame.type) {
-    case PADDING_FRAME: {
-      os << "type { PADDING_FRAME } " << frame.padding_frame;
-      break;
-    }
-    case RST_STREAM_FRAME: {
-      os << "type { RST_STREAM_FRAME } " << *(frame.rst_stream_frame);
-      break;
-    }
-    case CONNECTION_CLOSE_FRAME: {
-      os << "type { CONNECTION_CLOSE_FRAME } "
-         << *(frame.connection_close_frame);
-      break;
-    }
-    case GOAWAY_FRAME: {
-      os << "type { GOAWAY_FRAME } " << *(frame.goaway_frame);
-      break;
-    }
-    case WINDOW_UPDATE_FRAME: {
-      os << "type { WINDOW_UPDATE_FRAME } " << *(frame.window_update_frame);
-      break;
-    }
-    case BLOCKED_FRAME: {
-      os << "type { BLOCKED_FRAME } " << *(frame.blocked_frame);
-      break;
-    }
-    case STREAM_FRAME: {
-      os << "type { STREAM_FRAME } " << *(frame.stream_frame);
-      break;
-    }
-    case ACK_FRAME: {
-      os << "type { ACK_FRAME } " << *(frame.ack_frame);
-      break;
-    }
-    case STOP_WAITING_FRAME: {
-      os << "type { STOP_WAITING_FRAME } " << *(frame.stop_waiting_frame);
-      break;
-    }
-    case PING_FRAME: {
-      os << "type { PING_FRAME } ";
-      break;
-    }
-    case MTU_DISCOVERY_FRAME: {
-      os << "type { MTU_DISCOVERY_FRAME } ";
-      break;
-    }
-    case PATH_CLOSE_FRAME: {
-      os << "type { PATH_CLOSE_FRAME } " << *(frame.path_close_frame);
-      break;
-    }
-    default: {
-      LOG(ERROR) << "Unknown frame type: " << frame.type;
-      break;
-    }
-  }
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicPaddingFrame& padding_frame) {
-  os << "{ num_padding_bytes: " << padding_frame.num_padding_bytes << " }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicRstStreamFrame& rst_frame) {
-  os << "{ stream_id: " << rst_frame.stream_id
-     << ", error_code: " << rst_frame.error_code << " }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os,
-                    const QuicConnectionCloseFrame& connection_close_frame) {
-  os << "{ error_code: " << connection_close_frame.error_code
-     << ", error_details: '" << connection_close_frame.error_details << "' }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicGoAwayFrame& goaway_frame) {
-  os << "{ error_code: " << goaway_frame.error_code
-     << ", last_good_stream_id: " << goaway_frame.last_good_stream_id
-     << ", reason_phrase: '" << goaway_frame.reason_phrase << "' }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os,
-                    const QuicWindowUpdateFrame& window_update_frame) {
-  os << "{ stream_id: " << window_update_frame.stream_id
-     << ", byte_offset: " << window_update_frame.byte_offset << " }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicBlockedFrame& blocked_frame) {
-  os << "{ stream_id: " << blocked_frame.stream_id << " }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicPathCloseFrame& path_close_frame) {
-  os << "{ path_id: " << static_cast<int>(path_close_frame.path_id) << " }\n";
-  return os;
-}
-
-ostream& operator<<(ostream& os, const QuicStreamFrame& stream_frame) {
-  os << "{ stream_id: " << stream_frame.stream_id
-     << ", fin: " << stream_frame.fin << ", offset: " << stream_frame.offset
-     << ", length: " << stream_frame.data_length << " }\n";
-  return os;
-}
-
-QuicGoAwayFrame::QuicGoAwayFrame()
-    : error_code(QUIC_NO_ERROR), last_good_stream_id(0) {}
-
-QuicGoAwayFrame::QuicGoAwayFrame(QuicErrorCode error_code,
-                                 QuicStreamId last_good_stream_id,
-                                 const string& reason)
-    : error_code(error_code),
-      last_good_stream_id(last_good_stream_id),
-      reason_phrase(reason) {}
-
-QuicData::QuicData(const char* buffer, size_t length)
-    : buffer_(buffer), length_(length), owns_buffer_(false) {}
-
-QuicData::QuicData(const char* buffer, size_t length, bool owns_buffer)
-    : buffer_(buffer), length_(length), owns_buffer_(owns_buffer) {}
-
-QuicData::~QuicData() {
-  if (owns_buffer_) {
-    delete[] const_cast<char*>(buffer_);
-  }
-}
-
-QuicWindowUpdateFrame::QuicWindowUpdateFrame(QuicStreamId stream_id,
-                                             QuicStreamOffset byte_offset)
-    : stream_id(stream_id), byte_offset(byte_offset) {}
-
-QuicBlockedFrame::QuicBlockedFrame(QuicStreamId stream_id)
-    : stream_id(stream_id) {}
-
-QuicPathCloseFrame::QuicPathCloseFrame(QuicPathId path_id) : path_id(path_id) {}
-
-QuicPacket::QuicPacket(char* buffer,
-                       size_t length,
-                       bool owns_buffer,
-                       QuicConnectionIdLength connection_id_length,
-                       bool includes_version,
-                       bool includes_path_id,
-                       bool includes_diversification_nonce,
-                       QuicPacketNumberLength packet_number_length)
-    : QuicData(buffer, length, owns_buffer),
-      buffer_(buffer),
-      connection_id_length_(connection_id_length),
-      includes_version_(includes_version),
-      includes_path_id_(includes_path_id),
-      includes_diversification_nonce_(includes_diversification_nonce),
-      packet_number_length_(packet_number_length) {}
-
-QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, size_t length)
-    : QuicData(buffer, length) {}
-
-QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer,
-                                         size_t length,
-                                         bool owns_buffer)
-    : QuicData(buffer, length, owns_buffer) {}
-
-std::unique_ptr<QuicEncryptedPacket> QuicEncryptedPacket::Clone() const {
-  char* buffer = new char[this->length()];
-  memcpy(buffer, this->data(), this->length());
-  return base::MakeUnique<QuicEncryptedPacket>(buffer, this->length(), true);
-}
-
-ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
-  os << s.length() << "-byte data";
-  return os;
-}
-
-QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
-                                       size_t length,
-                                       QuicTime receipt_time)
-    : QuicEncryptedPacket(buffer, length),
-      receipt_time_(receipt_time),
-      ttl_(0) {}
-
-QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
-                                       size_t length,
-                                       QuicTime receipt_time,
-                                       bool owns_buffer)
-    : QuicEncryptedPacket(buffer, length, owns_buffer),
-      receipt_time_(receipt_time),
-      ttl_(0) {}
-
-QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
-                                       size_t length,
-                                       QuicTime receipt_time,
-                                       bool owns_buffer,
-                                       int ttl,
-                                       bool ttl_valid)
-    : QuicEncryptedPacket(buffer, length, owns_buffer),
-      receipt_time_(receipt_time),
-      ttl_(ttl_valid ? ttl : -1) {}
-
-std::unique_ptr<QuicReceivedPacket> QuicReceivedPacket::Clone() const {
-  char* buffer = new char[this->length()];
-  memcpy(buffer, this->data(), this->length());
-  return base::MakeUnique<QuicReceivedPacket>(
-      buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0);
-}
-
-ostream& operator<<(ostream& os, const QuicReceivedPacket& s) {
-  os << s.length() << "-byte data";
-  return os;
-}
-
-StringPiece QuicPacket::AssociatedData(QuicVersion version) const {
-  return StringPiece(
-      data(), GetStartOfEncryptedData(version, connection_id_length_,
-                                      includes_version_, includes_path_id_,
-                                      includes_diversification_nonce_,
-                                      packet_number_length_));
-}
-
-StringPiece QuicPacket::Plaintext(QuicVersion version) const {
-  const size_t start_of_encrypted_data = GetStartOfEncryptedData(
-      version, connection_id_length_, includes_version_, includes_path_id_,
-      includes_diversification_nonce_, packet_number_length_);
-  return StringPiece(data() + start_of_encrypted_data,
-                     length() - start_of_encrypted_data);
-}
-
-QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
-    : enable_version_36_(FLAGS_quic_enable_version_36_v3),
-      allowed_supported_versions_(supported_versions),
-      filtered_supported_versions_(
-          FilterSupportedVersions(supported_versions)) {}
-
-QuicVersionManager::~QuicVersionManager() {}
-
-const QuicVersionVector& QuicVersionManager::GetSupportedVersions() {
-  MaybeRefilterSupportedVersions();
-  return filtered_supported_versions_;
-}
-
-void QuicVersionManager::MaybeRefilterSupportedVersions() {
-  if (enable_version_36_ != FLAGS_quic_enable_version_36_v3) {
-    enable_version_36_ = FLAGS_quic_enable_version_36_v3;
-    RefilterSupportedVersions();
-  }
-}
-
-void QuicVersionManager::RefilterSupportedVersions() {
-  filtered_supported_versions_ =
-      FilterSupportedVersions(allowed_supported_versions_);
-}
-
-AckListenerWrapper::AckListenerWrapper(QuicAckListenerInterface* listener,
-                                       QuicPacketLength data_length)
-    : ack_listener(listener), length(data_length) {
-  DCHECK(listener != nullptr);
-}
-
-AckListenerWrapper::AckListenerWrapper(const AckListenerWrapper& other) =
-    default;
-
-AckListenerWrapper::~AckListenerWrapper() {}
-
-SerializedPacket::SerializedPacket(QuicPathId path_id,
-                                   QuicPacketNumber packet_number,
-                                   QuicPacketNumberLength packet_number_length,
-                                   const char* encrypted_buffer,
-                                   QuicPacketLength encrypted_length,
-                                   bool has_ack,
-                                   bool has_stop_waiting)
-    : encrypted_buffer(encrypted_buffer),
-      encrypted_length(encrypted_length),
-      has_crypto_handshake(NOT_HANDSHAKE),
-      num_padding_bytes(0),
-      path_id(path_id),
-      packet_number(packet_number),
-      packet_number_length(packet_number_length),
-      encryption_level(ENCRYPTION_NONE),
-      has_ack(has_ack),
-      has_stop_waiting(has_stop_waiting),
-      transmission_type(NOT_RETRANSMISSION),
-      original_path_id(kInvalidPathId),
-      original_packet_number(0) {}
-
-SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
-
-SerializedPacket::~SerializedPacket() {}
-
-TransmissionInfo::TransmissionInfo()
-    : encryption_level(ENCRYPTION_NONE),
-      packet_number_length(PACKET_1BYTE_PACKET_NUMBER),
-      bytes_sent(0),
-      sent_time(QuicTime::Zero()),
-      transmission_type(NOT_RETRANSMISSION),
-      in_flight(false),
-      is_unackable(false),
-      has_crypto_handshake(false),
-      num_padding_bytes(0),
-      retransmission(0) {}
-
-void ClearSerializedPacket(SerializedPacket* serialized_packet) {
-  if (!serialized_packet->retransmittable_frames.empty()) {
-    DeleteFrames(&serialized_packet->retransmittable_frames);
-  }
-  serialized_packet->encrypted_buffer = nullptr;
-  serialized_packet->encrypted_length = 0;
-}
-
-char* CopyBuffer(const SerializedPacket& packet) {
-  char* dst_buffer = new char[packet.encrypted_length];
-  memcpy(dst_buffer, packet.encrypted_buffer, packet.encrypted_length);
-  return dst_buffer;
-}
-
-TransmissionInfo::TransmissionInfo(EncryptionLevel level,
-                                   QuicPacketNumberLength packet_number_length,
-                                   TransmissionType transmission_type,
-                                   QuicTime sent_time,
-                                   QuicPacketLength bytes_sent,
-                                   bool has_crypto_handshake,
-                                   int num_padding_bytes)
-    : encryption_level(level),
-      packet_number_length(packet_number_length),
-      bytes_sent(bytes_sent),
-      sent_time(sent_time),
-      transmission_type(transmission_type),
-      in_flight(false),
-      is_unackable(false),
-      has_crypto_handshake(has_crypto_handshake),
-      num_padding_bytes(num_padding_bytes),
-      retransmission(0) {}
-
-TransmissionInfo::TransmissionInfo(const TransmissionInfo& other) = default;
-
-TransmissionInfo::~TransmissionInfo() {}
-
-}  // namespace net
diff --git a/net/quic/core/quic_protocol.h b/net/quic/core/quic_protocol.h
deleted file mode 100644
index adb9d8f..0000000
--- a/net/quic/core/quic_protocol.h
+++ /dev/null
@@ -1,766 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_QUIC_PROTOCOL_H_
-#define NET_QUIC_QUIC_PROTOCOL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <array>
-#include <limits>
-#include <list>
-#include <map>
-#include <memory>
-#include <ostream>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_piece.h"
-#include "net/base/int128.h"
-#include "net/base/iovec.h"
-#include "net/base/net_export.h"
-#include "net/quic/core/interval_set.h"
-#include "net/quic/core/quic_bandwidth.h"
-#include "net/quic/core/quic_buffer_allocator.h"
-#include "net/quic/core/quic_constants.h"
-#include "net/quic/core/quic_error_codes.h"
-#include "net/quic/core/quic_time.h"
-#include "net/quic/core/quic_types.h"
-#include "net/quic/core/quic_versions.h"
-#include "net/quic/platform/api/quic_socket_address.h"
-
-namespace net {
-
-class QuicPacket;
-struct QuicPacketHeader;
-
-// Size in bytes of the data packet header.
-NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(QuicVersion version,
-                                              const QuicPacketHeader& header);
-
-NET_EXPORT_PRIVATE size_t
-GetPacketHeaderSize(QuicVersion version,
-                    QuicConnectionIdLength connection_id_length,
-                    bool include_version,
-                    bool include_path_id,
-                    bool include_diversification_nonce,
-                    QuicPacketNumberLength packet_number_length);
-
-// Index of the first byte in a QUIC packet of encrypted data.
-NET_EXPORT_PRIVATE size_t
-GetStartOfEncryptedData(QuicVersion version, const QuicPacketHeader& header);
-
-NET_EXPORT_PRIVATE size_t
-GetStartOfEncryptedData(QuicVersion version,
-                        QuicConnectionIdLength connection_id_length,
-                        bool include_version,
-                        bool include_path_id,
-                        bool include_diversification_nonce,
-                        QuicPacketNumberLength packet_number_length);
-
-struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
-  QuicPacketPublicHeader();
-  explicit QuicPacketPublicHeader(const QuicPacketPublicHeader& other);
-  ~QuicPacketPublicHeader();
-
-  // Universal header. All QuicPacket headers will have a connection_id and
-  // public flags.
-  QuicConnectionId connection_id;
-  QuicConnectionIdLength connection_id_length;
-  bool multipath_flag;
-  bool reset_flag;
-  bool version_flag;
-  QuicPacketNumberLength packet_number_length;
-  QuicVersionVector versions;
-  // nonce contains an optional, 32-byte nonce value. If not included in the
-  // packet, |nonce| will be empty.
-  DiversificationNonce* nonce;
-};
-
-// Header for Data packets.
-struct NET_EXPORT_PRIVATE QuicPacketHeader {
-  QuicPacketHeader();
-  explicit QuicPacketHeader(const QuicPacketPublicHeader& header);
-  QuicPacketHeader(const QuicPacketHeader& other);
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
-                                                     const QuicPacketHeader& s);
-
-  QuicPacketPublicHeader public_header;
-  QuicPacketNumber packet_number;
-  QuicPathId path_id;
-};
-
-struct NET_EXPORT_PRIVATE QuicPublicResetPacket {
-  QuicPublicResetPacket();
-  explicit QuicPublicResetPacket(const QuicPacketPublicHeader& header);
-
-  QuicPacketPublicHeader public_header;
-  QuicPublicResetNonceProof nonce_proof;
-  // TODO(fayang): remove rejected_packet_number when deprecating
-  // FLAGS_quic_remove_packet_number_from_public_reset.
-  QuicPacketNumber rejected_packet_number;
-  QuicSocketAddress client_address;
-};
-
-typedef QuicPacketPublicHeader QuicVersionNegotiationPacket;
-
-// A padding frame contains no payload.
-struct NET_EXPORT_PRIVATE QuicPaddingFrame {
-  QuicPaddingFrame() : num_padding_bytes(-1) {}
-  explicit QuicPaddingFrame(int num_padding_bytes)
-      : num_padding_bytes(num_padding_bytes) {}
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
-                                                     const QuicPaddingFrame& s);
-
-  // -1: full padding to the end of a max-sized packet
-  // otherwise: only pad up to num_padding_bytes bytes
-  int num_padding_bytes;
-};
-
-// A ping frame contains no payload, though it is retransmittable,
-// and ACK'd just like other normal frames.
-struct NET_EXPORT_PRIVATE QuicPingFrame {};
-
-// A path MTU discovery frame contains no payload and is serialized as a ping
-// frame.
-struct NET_EXPORT_PRIVATE QuicMtuDiscoveryFrame {};
-
-// Deleter for stream buffers. Copyable to support platforms where the deleter
-// of a unique_ptr must be copyable. Otherwise it would be nice for this to be
-// move-only.
-class NET_EXPORT_PRIVATE StreamBufferDeleter {
- public:
-  StreamBufferDeleter() : allocator_(nullptr) {}
-  explicit StreamBufferDeleter(QuicBufferAllocator* allocator)
-      : allocator_(allocator) {}
-
-  // Deletes |buffer| using |allocator_|.
-  void operator()(char* buffer) const;
-
- private:
-  // Not owned; must be valid so long as the buffer stored in the unique_ptr
-  // that owns |this| is valid.
-  QuicBufferAllocator* allocator_;
-};
-
-using UniqueStreamBuffer = std::unique_ptr<char[], StreamBufferDeleter>;
-
-// Allocates memory of size |size| using |allocator| for a QUIC stream buffer.
-NET_EXPORT_PRIVATE UniqueStreamBuffer
-NewStreamBuffer(QuicBufferAllocator* allocator, size_t size);
-
-struct NET_EXPORT_PRIVATE QuicStreamFrame {
-  QuicStreamFrame();
-  QuicStreamFrame(QuicStreamId stream_id,
-                  bool fin,
-                  QuicStreamOffset offset,
-                  base::StringPiece data);
-  QuicStreamFrame(QuicStreamId stream_id,
-                  bool fin,
-                  QuicStreamOffset offset,
-                  QuicPacketLength data_length,
-                  UniqueStreamBuffer buffer);
-  ~QuicStreamFrame();
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
-                                                     const QuicStreamFrame& s);
-
-  QuicStreamId stream_id;
-  bool fin;
-  QuicPacketLength data_length;
-  const char* data_buffer;
-  QuicStreamOffset offset;  // Location of this data in the stream.
-  // nullptr when the QuicStreamFrame is received, and non-null when sent.
-  UniqueStreamBuffer buffer;
-
- private:
-  QuicStreamFrame(QuicStreamId stream_id,
-                  bool fin,
-                  QuicStreamOffset offset,
-                  const char* data_buffer,
-                  QuicPacketLength data_length,
-                  UniqueStreamBuffer buffer);
-
-  DISALLOW_COPY_AND_ASSIGN(QuicStreamFrame);
-};
-static_assert(sizeof(QuicStreamFrame) <= 64,
-              "Keep the QuicStreamFrame size to a cacheline.");
-
-typedef std::vector<std::pair<QuicPacketNumber, QuicTime>> PacketTimeVector;
-
-struct NET_EXPORT_PRIVATE QuicStopWaitingFrame {
-  QuicStopWaitingFrame();
-  ~QuicStopWaitingFrame();
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const QuicStopWaitingFrame& s);
-  // Path which this stop waiting frame belongs to.
-  QuicPathId path_id;
-  // The lowest packet we've sent which is unacked, and we expect an ack for.
-  QuicPacketNumber least_unacked;
-};
-
-// A sequence of packet numbers where each number is unique. Intended to be used
-// in a sliding window fashion, where smaller old packet numbers are removed and
-// larger new packet numbers are added, with the occasional random access.
-class NET_EXPORT_PRIVATE PacketNumberQueue {
- public:
-  using const_iterator = IntervalSet<QuicPacketNumber>::const_iterator;
-  using const_reverse_iterator =
-      IntervalSet<QuicPacketNumber>::const_reverse_iterator;
-
-  PacketNumberQueue();
-  PacketNumberQueue(const PacketNumberQueue& other);
-  // TODO(rtenneti): on windows RValue reference gives errors.
-  // PacketNumberQueue(PacketNumberQueue&& other);
-  ~PacketNumberQueue();
-
-  PacketNumberQueue& operator=(const PacketNumberQueue& other);
-  // PacketNumberQueue& operator=(PacketNumberQueue&& other);
-
-  // Adds |packet_number| to the set of packets in the queue.
-  void Add(QuicPacketNumber packet_number);
-
-  // Adds packets between [lower, higher) to the set of packets in the queue. It
-  // is undefined behavior to call this with |higher| < |lower|.
-  void Add(QuicPacketNumber lower, QuicPacketNumber higher);
-
-  // Removes |packet_number| from the set of packets in the queue.
-  void Remove(QuicPacketNumber packet_number);
-
-  // Removes packets numbers between [lower, higher) to the set of packets in
-  // the queue. It is undefined behavior to call this with |higher| < |lower|.
-  void Remove(QuicPacketNumber lower, QuicPacketNumber higher);
-
-  // Removes packets with values less than |higher| from the set of packets in
-  // the queue. Returns true if packets were removed.
-  bool RemoveUpTo(QuicPacketNumber higher);
-
-  // Mutates packet number set so that it contains only those packet numbers
-  // from minimum to maximum packet number not currently in the set. Do nothing
-  // if packet number set is empty.
-  void Complement();
-
-  // Returns true if the queue contains |packet_number|.
-  bool Contains(QuicPacketNumber packet_number) const;
-
-  // Returns true if the queue is empty.
-  bool Empty() const;
-
-  // Returns the minimum packet number stored in the queue. It is undefined
-  // behavior to call this if the queue is empty.
-  QuicPacketNumber Min() const;
-
-  // Returns the maximum packet number stored in the queue. It is undefined
-  // behavior to call this if the queue is empty.
-  QuicPacketNumber Max() const;
-
-  // Returns the number of unique packets stored in the queue. Inefficient; only
-  // exposed for testing.
-  size_t NumPacketsSlow() const;
-
-  // Returns the number of disjoint packet number intervals contained in the
-  // queue.
-  size_t NumIntervals() const;
-
-  // Returns the length of last interval.
-  QuicPacketNumber LastIntervalLength() const;
-
-  // Returns iterators over the packet number intervals.
-  const_iterator begin() const;
-  const_iterator end() const;
-  const_reverse_iterator rbegin() const;
-  const_reverse_iterator rend() const;
-  const_iterator lower_bound(QuicPacketNumber packet_number) const;
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const PacketNumberQueue& q);
-
- private:
-  IntervalSet<QuicPacketNumber> packet_number_intervals_;
-};
-
-struct NET_EXPORT_PRIVATE QuicAckFrame {
-  QuicAckFrame();
-  QuicAckFrame(const QuicAckFrame& other);
-  ~QuicAckFrame();
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
-                                                     const QuicAckFrame& s);
-
-  // The highest packet number we've observed from the peer.
-  QuicPacketNumber largest_observed;
-
-  // Time elapsed since largest_observed was received until this Ack frame was
-  // sent.
-  QuicTime::Delta ack_delay_time;
-
-  // Vector of <packet_number, time> for when packets arrived.
-  PacketTimeVector received_packet_times;
-
-  // Set of packets.
-  PacketNumberQueue packets;
-
-  // Path which this ack belongs to.
-  QuicPathId path_id;
-};
-
-// True if the packet number is greater than largest_observed or is listed
-// as missing.
-// Always returns false for packet numbers less than least_unacked.
-bool NET_EXPORT_PRIVATE
-IsAwaitingPacket(const QuicAckFrame& ack_frame,
-                 QuicPacketNumber packet_number,
-                 QuicPacketNumber peer_least_packet_awaiting_ack);
-
-struct NET_EXPORT_PRIVATE QuicRstStreamFrame {
-  QuicRstStreamFrame();
-  QuicRstStreamFrame(QuicStreamId stream_id,
-                     QuicRstStreamErrorCode error_code,
-                     QuicStreamOffset bytes_written);
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const QuicRstStreamFrame& r);
-
-  QuicStreamId stream_id;
-  QuicRstStreamErrorCode error_code;
-
-  // Used to update flow control windows. On termination of a stream, both
-  // endpoints must inform the peer of the number of bytes they have sent on
-  // that stream. This can be done through normal termination (data packet with
-  // FIN) or through a RST.
-  QuicStreamOffset byte_offset;
-};
-
-struct NET_EXPORT_PRIVATE QuicConnectionCloseFrame {
-  QuicConnectionCloseFrame();
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const QuicConnectionCloseFrame& c);
-
-  QuicErrorCode error_code;
-  std::string error_details;
-};
-
-struct NET_EXPORT_PRIVATE QuicGoAwayFrame {
-  QuicGoAwayFrame();
-  QuicGoAwayFrame(QuicErrorCode error_code,
-                  QuicStreamId last_good_stream_id,
-                  const std::string& reason);
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
-                                                     const QuicGoAwayFrame& g);
-
-  QuicErrorCode error_code;
-  QuicStreamId last_good_stream_id;
-  std::string reason_phrase;
-};
-
-// Flow control updates per-stream and at the connection levoel.
-// Based on SPDY's WINDOW_UPDATE frame, but uses an absolute byte offset rather
-// than a window delta.
-// TODO(rjshade): A possible future optimization is to make stream_id and
-//                byte_offset variable length, similar to stream frames.
-struct NET_EXPORT_PRIVATE QuicWindowUpdateFrame {
-  QuicWindowUpdateFrame() {}
-  QuicWindowUpdateFrame(QuicStreamId stream_id, QuicStreamOffset byte_offset);
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const QuicWindowUpdateFrame& w);
-
-  // The stream this frame applies to.  0 is a special case meaning the overall
-  // connection rather than a specific stream.
-  QuicStreamId stream_id;
-
-  // Byte offset in the stream or connection. The receiver of this frame must
-  // not send data which would result in this offset being exceeded.
-  QuicStreamOffset byte_offset;
-};
-
-// The BLOCKED frame is used to indicate to the remote endpoint that this
-// endpoint believes itself to be flow-control blocked but otherwise ready to
-// send data. The BLOCKED frame is purely advisory and optional.
-// Based on SPDY's BLOCKED frame (undocumented as of 2014-01-28).
-struct NET_EXPORT_PRIVATE QuicBlockedFrame {
-  QuicBlockedFrame() {}
-  explicit QuicBlockedFrame(QuicStreamId stream_id);
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
-                                                     const QuicBlockedFrame& b);
-
-  // The stream this frame applies to.  0 is a special case meaning the overall
-  // connection rather than a specific stream.
-  QuicStreamId stream_id;
-};
-
-// The PATH_CLOSE frame is used to explicitly close a path. Both endpoints can
-// send a PATH_CLOSE frame to initiate a path termination. A path is considered
-// to be closed either a PATH_CLOSE frame is sent or received. An endpoint drops
-// receive side of a closed path, and packets with retransmittable frames on a
-// closed path are marked as retransmissions which will be transmitted on other
-// paths.
-struct NET_EXPORT_PRIVATE QuicPathCloseFrame {
-  QuicPathCloseFrame() {}
-  explicit QuicPathCloseFrame(QuicPathId path_id);
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const QuicPathCloseFrame& p);
-
-  QuicPathId path_id;
-};
-
-struct NET_EXPORT_PRIVATE QuicFrame {
-  QuicFrame();
-  explicit QuicFrame(QuicPaddingFrame padding_frame);
-  explicit QuicFrame(QuicMtuDiscoveryFrame frame);
-  explicit QuicFrame(QuicPingFrame frame);
-
-  explicit QuicFrame(QuicStreamFrame* stream_frame);
-  explicit QuicFrame(QuicAckFrame* frame);
-  explicit QuicFrame(QuicRstStreamFrame* frame);
-  explicit QuicFrame(QuicConnectionCloseFrame* frame);
-  explicit QuicFrame(QuicStopWaitingFrame* frame);
-  explicit QuicFrame(QuicGoAwayFrame* frame);
-  explicit QuicFrame(QuicWindowUpdateFrame* frame);
-  explicit QuicFrame(QuicBlockedFrame* frame);
-  explicit QuicFrame(QuicPathCloseFrame* frame);
-
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
-                                                     const QuicFrame& frame);
-
-  QuicFrameType type;
-  union {
-    // Frames smaller than a pointer are inline.
-    QuicPaddingFrame padding_frame;
-    QuicMtuDiscoveryFrame mtu_discovery_frame;
-    QuicPingFrame ping_frame;
-
-    // Frames larger than a pointer.
-    QuicStreamFrame* stream_frame;
-    QuicAckFrame* ack_frame;
-    QuicStopWaitingFrame* stop_waiting_frame;
-    QuicRstStreamFrame* rst_stream_frame;
-    QuicConnectionCloseFrame* connection_close_frame;
-    QuicGoAwayFrame* goaway_frame;
-    QuicWindowUpdateFrame* window_update_frame;
-    QuicBlockedFrame* blocked_frame;
-    QuicPathCloseFrame* path_close_frame;
-  };
-};
-// QuicFrameType consumes 8 bytes with padding.
-static_assert(sizeof(QuicFrame) <= 16,
-              "Frames larger than 8 bytes should be referenced by pointer.");
-
-typedef std::vector<QuicFrame> QuicFrames;
-
-// Deletes all the sub-frames contained in |frames|.
-NET_EXPORT_PRIVATE void DeleteFrames(QuicFrames* frames);
-
-// Deletes all the QuicStreamFrames for the specified |stream_id|.
-NET_EXPORT_PRIVATE void RemoveFramesForStream(QuicFrames* frames,
-                                              QuicStreamId stream_id);
-
-class NET_EXPORT_PRIVATE QuicData {
- public:
-  QuicData(const char* buffer, size_t length);
-  QuicData(const char* buffer, size_t length, bool owns_buffer);
-  virtual ~QuicData();
-
-  base::StringPiece AsStringPiece() const {
-    return base::StringPiece(data(), length());
-  }
-
-  const char* data() const { return buffer_; }
-  size_t length() const { return length_; }
-  bool owns_buffer() const { return owns_buffer_; }
-
- private:
-  const char* buffer_;
-  size_t length_;
-  bool owns_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicData);
-};
-
-class NET_EXPORT_PRIVATE QuicPacket : public QuicData {
- public:
-  // TODO(fayang): 4 fields from public header are passed in as arguments.
-  // Consider to add a convenience method which directly accepts the entire
-  // public header.
-  QuicPacket(char* buffer,
-             size_t length,
-             bool owns_buffer,
-             QuicConnectionIdLength connection_id_length,
-             bool includes_version,
-             bool includes_path_id,
-             bool includes_diversification_nonce,
-             QuicPacketNumberLength packet_number_length);
-
-  base::StringPiece AssociatedData(QuicVersion version) const;
-  base::StringPiece Plaintext(QuicVersion version) const;
-
-  char* mutable_data() { return buffer_; }
-
- private:
-  char* buffer_;
-  const QuicConnectionIdLength connection_id_length_;
-  const bool includes_version_;
-  const bool includes_path_id_;
-  const bool includes_diversification_nonce_;
-  const QuicPacketNumberLength packet_number_length_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicPacket);
-};
-
-class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
- public:
-  QuicEncryptedPacket(const char* buffer, size_t length);
-  QuicEncryptedPacket(const char* buffer, size_t length, bool owns_buffer);
-
-  // Clones the packet into a new packet which owns the buffer.
-  std::unique_ptr<QuicEncryptedPacket> Clone() const;
-
-  // By default, gtest prints the raw bytes of an object. The bool data
-  // member (in the base class QuicData) causes this object to have padding
-  // bytes, which causes the default gtest object printer to read
-  // uninitialize memory. So we need to teach gtest how to print this object.
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const QuicEncryptedPacket& s);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
-};
-
-// A received encrypted QUIC packet, with a recorded time of receipt.
-class NET_EXPORT_PRIVATE QuicReceivedPacket : public QuicEncryptedPacket {
- public:
-  QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time);
-  QuicReceivedPacket(const char* buffer,
-                     size_t length,
-                     QuicTime receipt_time,
-                     bool owns_buffer);
-  QuicReceivedPacket(const char* buffer,
-                     size_t length,
-                     QuicTime receipt_time,
-                     bool owns_buffer,
-                     int ttl,
-                     bool ttl_valid);
-
-  // Clones the packet into a new packet which owns the buffer.
-  std::unique_ptr<QuicReceivedPacket> Clone() const;
-
-  // Returns the time at which the packet was received.
-  QuicTime receipt_time() const { return receipt_time_; }
-
-  // This is the TTL of the packet, assuming ttl_vaild_ is true.
-  int ttl() const { return ttl_; }
-
-  // By default, gtest prints the raw bytes of an object. The bool data
-  // member (in the base class QuicData) causes this object to have padding
-  // bytes, which causes the default gtest object printer to read
-  // uninitialize memory. So we need to teach gtest how to print this object.
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os,
-      const QuicReceivedPacket& s);
-
- private:
-  const QuicTime receipt_time_;
-  int ttl_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacket);
-};
-
-// Pure virtual class to listen for packet acknowledgements.
-class NET_EXPORT_PRIVATE QuicAckListenerInterface
-    : public base::RefCounted<QuicAckListenerInterface> {
- public:
-  QuicAckListenerInterface() {}
-
-  // Called when a packet is acked.  Called once per packet.
-  // |acked_bytes| is the number of data bytes acked.
-  virtual void OnPacketAcked(int acked_bytes,
-                             QuicTime::Delta ack_delay_time) = 0;
-
-  // Called when a packet is retransmitted.  Called once per packet.
-  // |retransmitted_bytes| is the number of data bytes retransmitted.
-  virtual void OnPacketRetransmitted(int retransmitted_bytes) = 0;
-
- protected:
-  friend class base::RefCounted<QuicAckListenerInterface>;
-
-  // Delegates are ref counted.
-  virtual ~QuicAckListenerInterface() {}
-};
-
-// Used to generate filtered supported versions based on flags.
-class NET_EXPORT_PRIVATE QuicVersionManager {
- public:
-  explicit QuicVersionManager(QuicVersionVector supported_versions);
-  virtual ~QuicVersionManager();
-
-  // Returns currently supported QUIC versions.
-  const QuicVersionVector& GetSupportedVersions();
-
- protected:
-  // Maybe refilter filtered_supported_versions_ based on flags.
-  void MaybeRefilterSupportedVersions();
-
-  // Refilters filtered_supported_versions_.
-  virtual void RefilterSupportedVersions();
-
-  const QuicVersionVector& filtered_supported_versions() const {
-    return filtered_supported_versions_;
-  }
-
- private:
-  // FLAGS_quic_enable_version_36_v3
-  bool enable_version_36_;
-  // The list of versions that may be supported.
-  QuicVersionVector allowed_supported_versions_;
-  // This vector contains QUIC versions which are currently supported based
-  // on flags.
-  QuicVersionVector filtered_supported_versions_;
-};
-
-struct NET_EXPORT_PRIVATE AckListenerWrapper {
-  AckListenerWrapper(QuicAckListenerInterface* listener,
-                     QuicPacketLength data_length);
-  AckListenerWrapper(const AckListenerWrapper& other);
-  ~AckListenerWrapper();
-
-  scoped_refptr<QuicAckListenerInterface> ack_listener;
-  QuicPacketLength length;
-};
-
-struct NET_EXPORT_PRIVATE SerializedPacket {
-  SerializedPacket(QuicPathId path_id,
-                   QuicPacketNumber packet_number,
-                   QuicPacketNumberLength packet_number_length,
-                   const char* encrypted_buffer,
-                   QuicPacketLength encrypted_length,
-                   bool has_ack,
-                   bool has_stop_waiting);
-  SerializedPacket(const SerializedPacket& other);
-  ~SerializedPacket();
-
-  // Not owned.
-  const char* encrypted_buffer;
-  QuicPacketLength encrypted_length;
-  QuicFrames retransmittable_frames;
-  IsHandshake has_crypto_handshake;
-  // -1: full padding to the end of a max-sized packet
-  //  0: no padding
-  //  otherwise: only pad up to num_padding_bytes bytes
-  int16_t num_padding_bytes;
-  QuicPathId path_id;
-  QuicPacketNumber packet_number;
-  QuicPacketNumberLength packet_number_length;
-  EncryptionLevel encryption_level;
-  bool has_ack;
-  bool has_stop_waiting;
-  TransmissionType transmission_type;
-  QuicPathId original_path_id;
-  QuicPacketNumber original_packet_number;
-
-  // Optional notifiers which will be informed when this packet has been ACKed.
-  std::list<AckListenerWrapper> listeners;
-};
-
-// Deletes and clears all the frames and the packet from serialized packet.
-NET_EXPORT_PRIVATE void ClearSerializedPacket(
-    SerializedPacket* serialized_packet);
-
-// Allocates a new char[] of size |packet.encrypted_length| and copies in
-// |packet.encrypted_buffer|.
-NET_EXPORT_PRIVATE char* CopyBuffer(const SerializedPacket& packet);
-
-struct NET_EXPORT_PRIVATE TransmissionInfo {
-  // Used by STL when assigning into a map.
-  TransmissionInfo();
-
-  // Constructs a Transmission with a new all_transmissions set
-  // containing |packet_number|.
-  TransmissionInfo(EncryptionLevel level,
-                   QuicPacketNumberLength packet_number_length,
-                   TransmissionType transmission_type,
-                   QuicTime sent_time,
-                   QuicPacketLength bytes_sent,
-                   bool has_crypto_handshake,
-                   int num_padding_bytes);
-
-  TransmissionInfo(const TransmissionInfo& other);
-
-  ~TransmissionInfo();
-
-  QuicFrames retransmittable_frames;
-  EncryptionLevel encryption_level;
-  QuicPacketNumberLength packet_number_length;
-  QuicPacketLength bytes_sent;
-  QuicTime sent_time;
-  // Reason why this packet was transmitted.
-  TransmissionType transmission_type;
-  // In flight packets have not been abandoned or lost.
-  bool in_flight;
-  // True if the packet can never be acked, so it can be removed.  Occurs when
-  // a packet is never sent, after it is acknowledged once, or if it's a crypto
-  // packet we never expect to receive an ack for.
-  bool is_unackable;
-  // True if the packet contains stream data from the crypto stream.
-  bool has_crypto_handshake;
-  // Non-zero if the packet needs padding if it's retransmitted.
-  int16_t num_padding_bytes;
-  // Stores the packet number of the next retransmission of this packet.
-  // Zero if the packet has not been retransmitted.
-  QuicPacketNumber retransmission;
-  // Non-empty if there is a std::listener for this packet.
-  std::list<AckListenerWrapper> ack_listeners;
-};
-
-// Struct to store the pending retransmission information.
-struct PendingRetransmission {
-  PendingRetransmission(QuicPathId path_id,
-                        QuicPacketNumber packet_number,
-                        TransmissionType transmission_type,
-                        const QuicFrames& retransmittable_frames,
-                        bool has_crypto_handshake,
-                        int num_padding_bytes,
-                        EncryptionLevel encryption_level,
-                        QuicPacketNumberLength packet_number_length)
-      : packet_number(packet_number),
-        retransmittable_frames(retransmittable_frames),
-        transmission_type(transmission_type),
-        path_id(path_id),
-        has_crypto_handshake(has_crypto_handshake),
-        num_padding_bytes(num_padding_bytes),
-        encryption_level(encryption_level),
-        packet_number_length(packet_number_length) {}
-
-  QuicPacketNumber packet_number;
-  const QuicFrames& retransmittable_frames;
-  TransmissionType transmission_type;
-  QuicPathId path_id;
-  bool has_crypto_handshake;
-  int num_padding_bytes;
-  EncryptionLevel encryption_level;
-  QuicPacketNumberLength packet_number_length;
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_QUIC_PROTOCOL_H_
diff --git a/net/quic/core/quic_received_packet_manager.h b/net/quic/core/quic_received_packet_manager.h
index 1e5b59f..06ab94f 100644
--- a/net/quic/core/quic_received_packet_manager.h
+++ b/net/quic/core/quic_received_packet_manager.h
@@ -13,7 +13,7 @@
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc
index b71fe723..05909af 100644
--- a/net/quic/core/quic_sent_packet_manager.cc
+++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -45,7 +45,7 @@
 // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe.
 static const size_t kDefaultMaxTailLossProbes = 2;
 
-bool HasCryptoHandshake(const TransmissionInfo& transmission_info) {
+bool HasCryptoHandshake(const QuicTransmissionInfo& transmission_info) {
   DCHECK(!transmission_info.has_crypto_handshake ||
          !transmission_info.retransmittable_frames.empty());
   return transmission_info.has_crypto_handshake;
@@ -111,23 +111,47 @@
             min(kMaxInitialRoundTripTimeUs,
                 config.GetInitialRoundTripTimeUsToSend())));
   }
-  if (FLAGS_quic_allow_new_bbr && config.HasReceivedConnectionOptions() &&
-      ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) {
-    SetSendAlgorithm(kBBR);
-  }
-  if (config.HasReceivedConnectionOptions() &&
-      ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) {
-    if (ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
-      SetSendAlgorithm(kRenoBytes);
-    } else {
-      SetSendAlgorithm(kReno);
+  // Configure congestion control.
+  const bool enable_client_connection_options =
+      FLAGS_quic_client_connection_options;
+  if (enable_client_connection_options) {
+    if (FLAGS_quic_allow_new_bbr &&
+        config.HasClientRequestedIndependentOption(kTBBR, perspective_)) {
+      SetSendAlgorithm(kBBR);
     }
-  } else if (config.HasReceivedConnectionOptions() &&
-             ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
-    if (FLAGS_quic_default_enable_cubic_bytes) {
-      SetSendAlgorithm(kCubic);
-    } else {
-      SetSendAlgorithm(kCubicBytes);
+    if (config.HasClientRequestedIndependentOption(kRENO, perspective_)) {
+      if (config.HasClientRequestedIndependentOption(kBYTE, perspective_)) {
+        SetSendAlgorithm(kRenoBytes);
+      } else {
+        SetSendAlgorithm(kReno);
+      }
+    } else if (config.HasClientRequestedIndependentOption(kBYTE,
+                                                          perspective_)) {
+      if (FLAGS_quic_default_enable_cubic_bytes) {
+        SetSendAlgorithm(kCubic);
+      } else {
+        SetSendAlgorithm(kCubicBytes);
+      }
+    }
+  } else {
+    if (FLAGS_quic_allow_new_bbr && config.HasReceivedConnectionOptions() &&
+        ContainsQuicTag(config.ReceivedConnectionOptions(), kTBBR)) {
+      SetSendAlgorithm(kBBR);
+    }
+    if (config.HasReceivedConnectionOptions() &&
+        ContainsQuicTag(config.ReceivedConnectionOptions(), kRENO)) {
+      if (ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
+        SetSendAlgorithm(kRenoBytes);
+      } else {
+        SetSendAlgorithm(kReno);
+      }
+    } else if (config.HasReceivedConnectionOptions() &&
+               ContainsQuicTag(config.ReceivedConnectionOptions(), kBYTE)) {
+      if (FLAGS_quic_default_enable_cubic_bytes) {
+        SetSendAlgorithm(kCubic);
+      } else {
+        SetSendAlgorithm(kCubicBytes);
+      }
     }
   }
   using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests;
@@ -147,17 +171,31 @@
   if (config.HasClientSentConnectionOption(kNRTO, perspective_)) {
     use_new_rto_ = true;
   }
-  if (config.HasReceivedConnectionOptions() &&
-      ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME)) {
-    general_loss_algorithm_.SetLossDetectionType(kTime);
-  }
-  if (config.HasReceivedConnectionOptions() &&
-      ContainsQuicTag(config.ReceivedConnectionOptions(), kATIM)) {
-    general_loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
-  }
-  if (FLAGS_quic_enable_lazy_fack && config.HasReceivedConnectionOptions() &&
-      ContainsQuicTag(config.ReceivedConnectionOptions(), kLFAK)) {
-    general_loss_algorithm_.SetLossDetectionType(kLazyFack);
+  // Configure loss detection.
+  if (enable_client_connection_options) {
+    if (config.HasClientRequestedIndependentOption(kTIME, perspective_)) {
+      general_loss_algorithm_.SetLossDetectionType(kTime);
+    }
+    if (config.HasClientRequestedIndependentOption(kATIM, perspective_)) {
+      general_loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
+    }
+    if (FLAGS_quic_enable_lazy_fack &&
+        config.HasClientRequestedIndependentOption(kLFAK, perspective_)) {
+      general_loss_algorithm_.SetLossDetectionType(kLazyFack);
+    }
+  } else {
+    if (config.HasReceivedConnectionOptions() &&
+        ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME)) {
+      general_loss_algorithm_.SetLossDetectionType(kTime);
+    }
+    if (config.HasReceivedConnectionOptions() &&
+        ContainsQuicTag(config.ReceivedConnectionOptions(), kATIM)) {
+      general_loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
+    }
+    if (FLAGS_quic_enable_lazy_fack && config.HasReceivedConnectionOptions() &&
+        ContainsQuicTag(config.ReceivedConnectionOptions(), kLFAK)) {
+      general_loss_algorithm_.SetLossDetectionType(kLazyFack);
+    }
   }
   if (config.HasClientSentConnectionOption(kUNDO, perspective_)) {
     undo_pending_retransmits_ = true;
@@ -366,7 +404,7 @@
 void QuicSentPacketManager::MarkForRetransmission(
     QuicPacketNumber packet_number,
     TransmissionType transmission_type) {
-  const TransmissionInfo& transmission_info =
+  const QuicTransmissionInfo& transmission_info =
       unacked_packets_.GetTransmissionInfo(packet_number);
   QUIC_BUG_IF(transmission_info.retransmittable_frames.empty());
   // Both TLP and the new RTO leave the packets in flight and let the loss
@@ -390,7 +428,7 @@
 }
 
 void QuicSentPacketManager::RecordOneSpuriousRetransmission(
-    const TransmissionInfo& info) {
+    const QuicTransmissionInfo& info) {
   stats_->bytes_spuriously_retransmitted += info.bytes_sent;
   ++stats_->packets_spuriously_retransmitted;
   if (debug_delegate_ != nullptr) {
@@ -400,11 +438,11 @@
 }
 
 void QuicSentPacketManager::RecordSpuriousRetransmissions(
-    const TransmissionInfo& info,
+    const QuicTransmissionInfo& info,
     QuicPacketNumber acked_packet_number) {
   QuicPacketNumber retransmission = info.retransmission;
   while (retransmission != 0) {
-    const TransmissionInfo& retransmit_info =
+    const QuicTransmissionInfo& retransmit_info =
         unacked_packets_.GetTransmissionInfo(retransmission);
     retransmission = retransmit_info.retransmission;
     RecordOneSpuriousRetransmission(retransmit_info);
@@ -421,7 +459,7 @@
   return !pending_retransmissions_.empty();
 }
 
-PendingRetransmission QuicSentPacketManager::NextPendingRetransmission() {
+QuicPendingRetransmission QuicSentPacketManager::NextPendingRetransmission() {
   QUIC_BUG_IF(pending_retransmissions_.empty())
       << "Unexpected call to PendingRetransmissions() with empty pending "
       << "retransmission list. Corrupted memory usage imminent.";
@@ -439,21 +477,21 @@
     }
   }
   DCHECK(unacked_packets_.IsUnacked(packet_number)) << packet_number;
-  const TransmissionInfo& transmission_info =
+  const QuicTransmissionInfo& transmission_info =
       unacked_packets_.GetTransmissionInfo(packet_number);
   DCHECK(!transmission_info.retransmittable_frames.empty());
 
-  return PendingRetransmission(path_id_, packet_number, transmission_type,
-                               transmission_info.retransmittable_frames,
-                               transmission_info.has_crypto_handshake,
-                               transmission_info.num_padding_bytes,
-                               transmission_info.encryption_level,
-                               transmission_info.packet_number_length);
+  return QuicPendingRetransmission(path_id_, packet_number, transmission_type,
+                                   transmission_info.retransmittable_frames,
+                                   transmission_info.has_crypto_handshake,
+                                   transmission_info.num_padding_bytes,
+                                   transmission_info.encryption_level,
+                                   transmission_info.packet_number_length);
 }
 
 QuicPacketNumber QuicSentPacketManager::GetNewestRetransmission(
     QuicPacketNumber packet_number,
-    const TransmissionInfo& transmission_info) const {
+    const QuicTransmissionInfo& transmission_info) const {
   QuicPacketNumber retransmission = transmission_info.retransmission;
   while (retransmission != 0) {
     packet_number = retransmission;
@@ -470,7 +508,7 @@
     return;
   }
 
-  const TransmissionInfo& transmission_info =
+  const QuicTransmissionInfo& transmission_info =
       unacked_packets_.GetTransmissionInfo(packet_number);
   QuicPacketNumber newest_transmission =
       GetNewestRetransmission(packet_number, transmission_info);
@@ -487,7 +525,7 @@
 }
 
 void QuicSentPacketManager::MarkPacketHandled(QuicPacketNumber packet_number,
-                                              TransmissionInfo* info,
+                                              QuicTransmissionInfo* info,
                                               QuicTime::Delta ack_delay_time) {
   QuicPacketNumber newest_transmission =
       GetNewestRetransmission(packet_number, *info);
@@ -514,7 +552,7 @@
     // transmission of a crypto packet is in flight at once.
     // TODO(ianswett): Instead of handling all crypto packets special,
     // only handle nullptr encrypted packets in a special way.
-    const TransmissionInfo& newest_transmission_info =
+    const QuicTransmissionInfo& newest_transmission_info =
         unacked_packets_.GetTransmissionInfo(newest_transmission);
     if (HasCryptoHandshake(newest_transmission_info)) {
       unacked_packets_.RemoveFromInFlight(newest_transmission);
@@ -745,7 +783,7 @@
   }
   // We calculate the RTT based on the highest ACKed packet number, the lower
   // packet numbers will include the ACK aggregation delay.
-  const TransmissionInfo& transmission_info =
+  const QuicTransmissionInfo& transmission_info =
       unacked_packets_.GetTransmissionInfo(ack_frame.largest_observed);
   // Ensure the packet has a valid sent time.
   if (transmission_info.sent_time == QuicTime::Zero()) {
@@ -1011,7 +1049,7 @@
   return consecutive_tlp_count_;
 }
 
-TransmissionInfo* QuicSentPacketManager::GetMutableTransmissionInfo(
+QuicTransmissionInfo* QuicSentPacketManager::GetMutableTransmissionInfo(
     QuicPacketNumber packet_number) {
   return unacked_packets_.GetMutableTransmissionInfo(packet_number);
 }
@@ -1024,4 +1062,8 @@
   send_algorithm_->OnApplicationLimited(unacked_packets_.bytes_in_flight());
 }
 
+const SendAlgorithmInterface* QuicSentPacketManager::GetSendAlgorithm() const {
+  return send_algorithm_.get();
+}
+
 }  // namespace net
diff --git a/net/quic/core/quic_sent_packet_manager.h b/net/quic/core/quic_sent_packet_manager.h
index 4da97b0a..fdd7d34 100644
--- a/net/quic/core/quic_sent_packet_manager.h
+++ b/net/quic/core/quic_sent_packet_manager.h
@@ -21,7 +21,7 @@
 #include "net/quic/core/congestion_control/pacing_sender.h"
 #include "net/quic/core/congestion_control/rtt_stats.h"
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager_interface.h"
 #include "net/quic/core/quic_unacked_packet_map.h"
 
@@ -120,7 +120,7 @@
 
   // Retrieves the next pending retransmission.  You must ensure that
   // there are pending retransmissions prior to calling this function.
-  PendingRetransmission NextPendingRetransmission() override;
+  QuicPendingRetransmission NextPendingRetransmission() override;
 
   bool HasUnackedPackets() const override;
 
@@ -208,6 +208,8 @@
 
   void OnApplicationLimited() override;
 
+  const SendAlgorithmInterface* GetSendAlgorithm() const override;
+
  private:
   friend class test::QuicConnectionPeer;
   friend class test::QuicSentPacketManagerPeer;
@@ -257,7 +259,7 @@
   // Returns the newest transmission associated with a packet.
   QuicPacketNumber GetNewestRetransmission(
       QuicPacketNumber packet_number,
-      const TransmissionInfo& transmission_info) const;
+      const QuicTransmissionInfo& transmission_info) const;
 
   // Update the RTT if the ack is for the largest acked packet number.
   // Returns true if the rtt was updated.
@@ -291,7 +293,7 @@
   // Removes the retransmittability and in flight properties from the packet at
   // |info| due to receipt by the peer.
   void MarkPacketHandled(QuicPacketNumber packet_number,
-                         TransmissionInfo* info,
+                         QuicTransmissionInfo* info,
                          QuicTime::Delta ack_delay_time);
 
   // Request that |packet_number| be retransmitted after the other pending
@@ -300,20 +302,21 @@
   void MarkForRetransmission(QuicPacketNumber packet_number,
                              TransmissionType transmission_type);
 
-  // Notify observers that packet with TransmissionInfo |info| is a spurious
+  // Notify observers that packet with QuicTransmissionInfo |info| is a spurious
   // retransmission. It is caller's responsibility to guarantee the packet with
-  // TransmissionInfo |info| is a spurious retransmission before calling this
-  // function.
-  void RecordOneSpuriousRetransmission(const TransmissionInfo& info);
+  // QuicTransmissionInfo |info| is a spurious retransmission before calling
+  // this function.
+  void RecordOneSpuriousRetransmission(const QuicTransmissionInfo& info);
 
-  // Notify observers about spurious retransmits of packet with TransmissionInfo
-  // |info|.
-  void RecordSpuriousRetransmissions(const TransmissionInfo& info,
+  // Notify observers about spurious retransmits of packet with
+  // QuicTransmissionInfo |info|.
+  void RecordSpuriousRetransmissions(const QuicTransmissionInfo& info,
                                      QuicPacketNumber acked_packet_number);
 
-  // Returns mutable TransmissionInfo associated with |packet_number|, which
+  // Returns mutable QuicTransmissionInfo associated with |packet_number|, which
   // must be unacked.
-  TransmissionInfo* GetMutableTransmissionInfo(QuicPacketNumber packet_number);
+  QuicTransmissionInfo* GetMutableTransmissionInfo(
+      QuicPacketNumber packet_number);
 
   // Remove any packets no longer needed for retransmission, congestion, or
   // RTT measurement purposes.
diff --git a/net/quic/core/quic_sent_packet_manager_interface.h b/net/quic/core/quic_sent_packet_manager_interface.h
index 498f5cdc..b1860e4 100644
--- a/net/quic/core/quic_sent_packet_manager_interface.h
+++ b/net/quic/core/quic_sent_packet_manager_interface.h
@@ -7,7 +7,9 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/congestion_control/send_algorithm_interface.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_pending_retransmission.h"
 #include "net/quic/core/quic_sustained_bandwidth_recorder.h"
 
 namespace net {
@@ -98,7 +100,7 @@
 
   virtual bool HasPendingRetransmissions() const = 0;
 
-  virtual PendingRetransmission NextPendingRetransmission() = 0;
+  virtual QuicPendingRetransmission NextPendingRetransmission() = 0;
 
   // Returns true if the default path has unacked packets.
   virtual bool HasUnackedPackets() const = 0;
@@ -188,6 +190,10 @@
   // Signals to the congestion controller that the connection has no outstanding
   // data to send.
   virtual void OnApplicationLimited() = 0;
+
+  // Returns the currently used congestion control algorithm.  The manager
+  // retains the ownership of the algorithm.
+  virtual const SendAlgorithmInterface* GetSendAlgorithm() const = 0;
 };
 
 }  // namespace net
diff --git a/net/quic/core/quic_sent_packet_manager_test.cc b/net/quic/core/quic_sent_packet_manager_test.cc
index 6d5e6b8..4dc3d07 100644
--- a/net/quic/core/quic_sent_packet_manager_test.cc
+++ b/net/quic/core/quic_sent_packet_manager_test.cc
@@ -177,7 +177,7 @@
     QuicSentPacketManagerPeer::MarkForRetransmission(
         &manager_, kDefaultPathId, old_packet_number, transmission_type);
     EXPECT_TRUE(manager_.HasPendingRetransmissions());
-    PendingRetransmission next_retransmission =
+    QuicPendingRetransmission next_retransmission =
         manager_.NextPendingRetransmission();
     EXPECT_EQ(old_packet_number, next_retransmission.packet_number);
     EXPECT_EQ(transmission_type, next_retransmission.transmission_type);
@@ -253,7 +253,8 @@
                              HAS_RETRANSMITTABLE_DATA))
         .Times(1)
         .WillOnce(Return(true));
-    const PendingRetransmission pending = manager_.NextPendingRetransmission();
+    const QuicPendingRetransmission pending =
+        manager_.NextPendingRetransmission();
     SerializedPacket packet(CreatePacket(retransmission_packet_number, false));
     manager_.OnPacketSent(&packet, pending.path_id, pending.packet_number,
                           clock_.Now(), pending.transmission_type,
@@ -1430,6 +1431,60 @@
                             ->GetCongestionControlType());
 }
 
+TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) {
+  FLAGS_quic_allow_new_bbr = true;
+  FLAGS_quic_client_connection_options = true;
+  QuicConfig config;
+  QuicTagVector options;
+
+  // No change if the server receives client options.
+  const SendAlgorithmInterface* mock_sender =
+      QuicSentPacketManagerPeer::GetSendAlgorithm(manager_);
+  options.push_back(kRENO);
+  config.SetClientConnectionOptions(options);
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  EXPECT_EQ(mock_sender, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_));
+
+  // Change the congestion control on the client with client options.
+  QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  EXPECT_EQ(kReno, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                       ->GetCongestionControlType());
+
+  options.clear();
+  options.push_back(kTBBR);
+  config.SetClientConnectionOptions(options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  EXPECT_EQ(kBBR, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                      ->GetCongestionControlType());
+
+  options.clear();
+  options.push_back(kBYTE);
+  config.SetClientConnectionOptions(options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  if (FLAGS_quic_default_enable_cubic_bytes) {
+    EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                          ->GetCongestionControlType());
+  } else {
+    EXPECT_EQ(kCubicBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                               ->GetCongestionControlType());
+  }
+
+  options.clear();
+  options.push_back(kRENO);
+  options.push_back(kBYTE);
+  config.SetClientConnectionOptions(options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                            ->GetCongestionControlType());
+}
+
 TEST_F(QuicSentPacketManagerTest, NegotiateNumConnectionsFromOptions) {
   QuicConfig config;
   QuicTagVector options;
diff --git a/net/quic/core/quic_server_session_base.h b/net/quic/core/quic_server_session_base.h
index c3cc65603..fcf8cc2 100644
--- a/net/quic/core/quic_server_session_base.h
+++ b/net/quic/core/quic_server_session_base.h
@@ -19,7 +19,7 @@
 #include "net/base/net_export.h"
 #include "net/quic/core/crypto/quic_compressed_certs_cache.h"
 #include "net/quic/core/quic_crypto_server_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_spdy_session.h"
 
 namespace net {
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc
index cf31496a..5bcc109 100644
--- a/net/quic/core/quic_server_session_base_test.cc
+++ b/net/quic/core/quic_server_session_base_test.cc
@@ -84,14 +84,14 @@
                     QuicCryptoServerStream::Helper* helper,
                     const QuicCryptoServerConfig* crypto_config,
                     QuicCompressedCertsCache* compressed_certs_cache,
-                    QuicInMemoryCache* in_memory_cache)
+                    QuicHttpResponseCache* response_cache)
       : QuicServerSessionBase(config,
                               connection,
                               visitor,
                               helper,
                               crypto_config,
                               compressed_certs_cache),
-        in_memory_cache_(in_memory_cache) {}
+        response_cache_(response_cache) {}
 
   ~TestServerSession() override { delete connection(); };
 
@@ -101,7 +101,7 @@
       return nullptr;
     }
     QuicSpdyStream* stream =
-        new QuicSimpleServerStream(id, this, in_memory_cache_);
+        new QuicSimpleServerStream(id, this, response_cache_);
     ActivateStream(base::WrapUnique(stream));
     return stream;
   }
@@ -112,7 +112,7 @@
     }
 
     QuicSpdyStream* stream = new QuicSimpleServerStream(
-        GetNextOutgoingStreamId(), this, in_memory_cache_);
+        GetNextOutgoingStreamId(), this, response_cache_);
     stream->SetPriority(priority);
     ActivateStream(base::WrapUnique(stream));
     return stream;
@@ -127,7 +127,7 @@
   }
 
  private:
-  QuicInMemoryCache* in_memory_cache_;  // Owned by QuicServerSessionBaseTest.
+  QuicHttpResponseCache* response_cache_;  // Owned by QuicServerSessionBaseTest
 };
 
 const size_t kMaxStreamsForTest = 10;
@@ -157,7 +157,7 @@
         SupportedVersions(GetParam()));
     session_.reset(new TestServerSession(
         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
-        &compressed_certs_cache_, &in_memory_cache_));
+        &compressed_certs_cache_, &response_cache_));
     MockClock clock;
     handshake_message_.reset(crypto_config_.AddDefaultConfig(
         QuicRandom::GetInstance(), &clock,
@@ -174,7 +174,7 @@
   QuicConfig config_;
   QuicCryptoServerConfig crypto_config_;
   QuicCompressedCertsCache compressed_certs_cache_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
   std::unique_ptr<TestServerSession> session_;
   std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
   QuicConnectionVisitorInterface* visitor_;
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h
index 3a4e077..aae47eef 100644
--- a/net/quic/core/quic_session.h
+++ b/net/quic/core/quic_session.h
@@ -24,7 +24,7 @@
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_crypto_stream.h"
 #include "net/quic/core/quic_packet_creator.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream.h"
 #include "net/quic/core/quic_write_blocked_list.h"
 
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc
index 8be782f9f..0bb974c 100644
--- a/net/quic/core/quic_session_test.cc
+++ b/net/quic/core/quic_session_test.cc
@@ -16,7 +16,7 @@
 #include "net/quic/core/crypto/null_encrypter.h"
 #include "net/quic/core/quic_crypto_stream.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/quic_config_peer.h"
diff --git a/net/quic/core/quic_simple_buffer_allocator_test.cc b/net/quic/core/quic_simple_buffer_allocator_test.cc
index d999162..69cfad9 100644
--- a/net/quic/core/quic_simple_buffer_allocator_test.cc
+++ b/net/quic/core/quic_simple_buffer_allocator_test.cc
@@ -4,7 +4,7 @@
 
 #include "net/quic/core/quic_simple_buffer_allocator.h"
 
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/net/quic/core/quic_spdy_session.cc b/net/quic/core/quic_spdy_session.cc
index 444c35c4..b2bb42f 100644
--- a/net/quic/core/quic_spdy_session.cc
+++ b/net/quic/core/quic_spdy_session.cc
@@ -121,12 +121,24 @@
   if (FLAGS_quic_enable_force_hol_blocking && version > QUIC_VERSION_35 &&
       config()->ForceHolBlocking(perspective())) {
     force_hol_blocking_ = true;
-    // Autotuning makes sure that the headers stream flow control does
-    // not get in the way, and normal stream and connection level flow
-    // control are active anyway. This is really only for the client
-    // side (and mainly there just in tests and toys), where
-    // autotuning and/or large buffers are not enabled by default.
-    headers_stream_->flow_controller()->set_auto_tune_receive_window(true);
+    if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) {
+      // Autotuning makes sure that the headers stream flow control does
+      // not get in the way, and normal stream and connection level flow
+      // control are active anyway. This is really only for the client
+      // side (and mainly there just in tests and toys), where
+      // autotuning and/or large buffers are not enabled by default.
+      headers_stream_->flow_controller()->set_auto_tune_receive_window(true);
+    } else {
+      // Since all streams are tunneled through the headers stream, it
+      // is important that headers stream never flow control blocks.
+      // Otherwise, busy-loop behaviour can ensue where data streams
+      // data try repeatedly to write data not realizing that the
+      // tunnel through the headers stream is blocked.
+      headers_stream_->flow_controller()->UpdateReceiveWindowSize(
+          kStreamReceiveWindowLimit);
+      headers_stream_->flow_controller()->UpdateSendWindowOffset(
+          kStreamReceiveWindowLimit);
+    }
   }
 
   if (version > QUIC_VERSION_34) {
diff --git a/net/quic/core/quic_spdy_stream.h b/net/quic/core/quic_spdy_stream.h
index 4563003..19bcddc 100644
--- a/net/quic/core/quic_spdy_stream.h
+++ b/net/quic/core/quic_spdy_stream.h
@@ -21,7 +21,7 @@
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream.h"
 #include "net/quic/core/quic_stream_sequencer.h"
 #include "net/quic/platform/api/quic_socket_address.h"
diff --git a/net/quic/core/quic_spdy_stream_test.cc b/net/quic/core/quic_spdy_stream_test.cc
index f91f88a..2ac223e 100644
--- a/net/quic/core/quic_spdy_stream_test.cc
+++ b/net/quic/core/quic_spdy_stream_test.cc
@@ -388,9 +388,8 @@
 
   // Try to send more data than the flow control limit allows.
   string headers = SpdyUtils::SerializeUncompressedHeaders(headers_);
-  string body;
   const uint64_t kOverflow = 15;
-  GenerateBody(&body, kWindow + kOverflow);
+  string body(kWindow + kOverflow, 'a');
 
   EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1));
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
@@ -427,8 +426,8 @@
                          stream_->flow_controller()));
 
   // Stream receives enough data to fill a fraction of the receive window.
-  string body;
-  GenerateBody(&body, kWindow / 3);
+  string body(kWindow / 3, 'a');
+  auto headers = AsHeaderList(headers_);
   ProcessHeaders(false, headers_);
 
   QuicStreamFrame frame1(kClientDataStreamId1, false, 0, StringPiece(body));
@@ -463,8 +462,7 @@
                          stream_->flow_controller()));
 
   // Stream receives enough data to fill a fraction of the receive window.
-  string body;
-  GenerateBody(&body, kWindow / 3);
+  string body(kWindow / 3, 'a');
   ProcessHeaders(false, headers_);
   stream_->ConsumeHeaderList();
 
@@ -521,8 +519,7 @@
 
   // Each stream gets a quarter window of data. This should not trigger a
   // WINDOW_UPDATE for either stream, nor for the connection.
-  string body;
-  GenerateBody(&body, kWindow / 4);
+  string body(kWindow / 4, 'a');
   QuicStreamFrame frame1(kClientDataStreamId1, false, 0, StringPiece(body));
   stream_->OnStreamFrame(frame1);
   QuicStreamFrame frame2(kClientDataStreamId2, false, 0, StringPiece(body));
@@ -558,8 +555,7 @@
   ProcessHeaders(false, headers_);
 
   // Receive data to overflow the window, violating flow control.
-  string body;
-  GenerateBody(&body, kWindow + 1);
+  string body(kWindow + 1, 'a');
   QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
   EXPECT_CALL(*connection_,
               CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
@@ -596,8 +592,7 @@
   ProcessHeaders(false, headers_);
 
   // Send enough data to overflow the connection level flow control window.
-  string body;
-  GenerateBody(&body, kConnectionWindow + 1);
+  string body(kConnectionWindow + 1, 'a');
   EXPECT_LT(body.size(), kStreamWindow);
   QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
 
diff --git a/net/quic/core/quic_stream.h b/net/quic/core/quic_stream.h
index 37e97d4..aae9808 100644
--- a/net/quic/core/quic_stream.h
+++ b/net/quic/core/quic_stream.h
@@ -31,7 +31,7 @@
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_flow_controller.h"
 #include "net/quic/core/quic_iovector.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream_sequencer.h"
 #include "net/quic/core/quic_types.h"
 
diff --git a/net/quic/core/quic_stream_sequencer.cc b/net/quic/core/quic_stream_sequencer.cc
index f0b80a7..5886ba0 100644
--- a/net/quic/core/quic_stream_sequencer.cc
+++ b/net/quic/core/quic_stream_sequencer.cc
@@ -16,7 +16,7 @@
 #include "net/quic/core/quic_bug_tracker.h"
 #include "net/quic/core/quic_clock.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream.h"
 #include "net/quic/core/quic_stream_sequencer_buffer.h"
 #include "net/quic/core/quic_utils.h"
diff --git a/net/quic/core/quic_stream_sequencer.h b/net/quic/core/quic_stream_sequencer.h
index 3d3dcdb6..bb8a144 100644
--- a/net/quic/core/quic_stream_sequencer.h
+++ b/net/quic/core/quic_stream_sequencer.h
@@ -11,7 +11,7 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream_sequencer_buffer.h"
 
 namespace net {
diff --git a/net/quic/core/quic_stream_sequencer_buffer.h b/net/quic/core/quic_stream_sequencer_buffer.h
index 6ce341d..930dbd5f 100644
--- a/net/quic/core/quic_stream_sequencer_buffer.h
+++ b/net/quic/core/quic_stream_sequencer_buffer.h
@@ -68,7 +68,7 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/quic_stream_sequencer_buffer_interface.h b/net/quic/core/quic_stream_sequencer_buffer_interface.h
index 96b6bb9..d8ee7949 100644
--- a/net/quic/core/quic_stream_sequencer_buffer_interface.h
+++ b/net/quic/core/quic_stream_sequencer_buffer_interface.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/core/quic_tag_test.cc b/net/quic/core/quic_tag_test.cc
index 6b1cdd7..92a51d7b 100644
--- a/net/quic/core/quic_tag_test.cc
+++ b/net/quic/core/quic_tag_test.cc
@@ -22,6 +22,16 @@
   EXPECT_EQ("525092931", QuicTagToString(MakeQuicTag('C', 'H', 'L', '\x1f')));
 }
 
+TEST(QuicTagTest, MakeQuicTag) {
+  QuicTag tag = MakeQuicTag('A', 'B', 'C', 'D');
+  char bytes[4];
+  memcpy(bytes, &tag, 4);
+  EXPECT_EQ('A', bytes[0]);
+  EXPECT_EQ('B', bytes[1]);
+  EXPECT_EQ('C', bytes[2]);
+  EXPECT_EQ('D', bytes[3]);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/core/quic_transmission_info.cc b/net/quic/core/quic_transmission_info.cc
new file mode 100644
index 0000000..96cbfd24
--- /dev/null
+++ b/net/quic/core/quic_transmission_info.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2016 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 "net/quic/core/quic_transmission_info.h"
+
+namespace net {
+
+QuicTransmissionInfo::QuicTransmissionInfo()
+    : encryption_level(ENCRYPTION_NONE),
+      packet_number_length(PACKET_1BYTE_PACKET_NUMBER),
+      bytes_sent(0),
+      sent_time(QuicTime::Zero()),
+      transmission_type(NOT_RETRANSMISSION),
+      in_flight(false),
+      is_unackable(false),
+      has_crypto_handshake(false),
+      num_padding_bytes(0),
+      retransmission(0) {}
+
+QuicTransmissionInfo::QuicTransmissionInfo(
+    EncryptionLevel level,
+    QuicPacketNumberLength packet_number_length,
+    TransmissionType transmission_type,
+    QuicTime sent_time,
+    QuicPacketLength bytes_sent,
+    bool has_crypto_handshake,
+    int num_padding_bytes)
+    : encryption_level(level),
+      packet_number_length(packet_number_length),
+      bytes_sent(bytes_sent),
+      sent_time(sent_time),
+      transmission_type(transmission_type),
+      in_flight(false),
+      is_unackable(false),
+      has_crypto_handshake(has_crypto_handshake),
+      num_padding_bytes(num_padding_bytes),
+      retransmission(0) {}
+
+QuicTransmissionInfo::QuicTransmissionInfo(const QuicTransmissionInfo& other) =
+    default;
+
+QuicTransmissionInfo::~QuicTransmissionInfo() {}
+
+}  // namespace net
diff --git a/net/quic/core/quic_transmission_info.h b/net/quic/core/quic_transmission_info.h
new file mode 100644
index 0000000..56b90135
--- /dev/null
+++ b/net/quic/core/quic_transmission_info.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_QUIC_TRANSMISSION_INFO_H_
+#define NET_QUIC_CORE_QUIC_TRANSMISSION_INFO_H_
+
+#include <list>
+
+#include "net/quic/core/frames/quic_frame.h"
+#include "net/quic/core/quic_ack_listener_interface.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// Stores details of a single sent packet.
+struct NET_EXPORT_PRIVATE QuicTransmissionInfo {
+  // Used by STL when assigning into a map.
+  QuicTransmissionInfo();
+
+  // Constructs a Transmission with a new all_transmissions set
+  // containing |packet_number|.
+  QuicTransmissionInfo(EncryptionLevel level,
+                       QuicPacketNumberLength packet_number_length,
+                       TransmissionType transmission_type,
+                       QuicTime sent_time,
+                       QuicPacketLength bytes_sent,
+                       bool has_crypto_handshake,
+                       int num_padding_bytes);
+
+  QuicTransmissionInfo(const QuicTransmissionInfo& other);
+
+  ~QuicTransmissionInfo();
+
+  QuicFrames retransmittable_frames;
+  EncryptionLevel encryption_level;
+  QuicPacketNumberLength packet_number_length;
+  QuicPacketLength bytes_sent;
+  QuicTime sent_time;
+  // Reason why this packet was transmitted.
+  TransmissionType transmission_type;
+  // In flight packets have not been abandoned or lost.
+  bool in_flight;
+  // True if the packet can never be acked, so it can be removed.  Occurs when
+  // a packet is never sent, after it is acknowledged once, or if it's a crypto
+  // packet we never expect to receive an ack for.
+  bool is_unackable;
+  // True if the packet contains stream data from the crypto stream.
+  bool has_crypto_handshake;
+  // Non-zero if the packet needs padding if it's retransmitted.
+  int16_t num_padding_bytes;
+  // Stores the packet number of the next retransmission of this packet.
+  // Zero if the packet has not been retransmitted.
+  QuicPacketNumber retransmission;
+  // Non-empty if there is a listener for this packet.
+  std::list<AckListenerWrapper> ack_listeners;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_TRANSMISSION_INFO_H_
diff --git a/net/quic/core/quic_types.h b/net/quic/core/quic_types.h
index a46e7da..31e0425 100644
--- a/net/quic/core/quic_types.h
+++ b/net/quic/core/quic_types.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "net/base/net_export.h"
+#include "net/quic/core/quic_time.h"
 
 namespace net {
 
@@ -26,6 +27,7 @@
 typedef uint64_t QuicPublicResetNonceProof;
 typedef uint64_t QuicStreamOffset;
 typedef std::array<char, 32> DiversificationNonce;
+typedef std::vector<std::pair<QuicPacketNumber, QuicTime>> PacketTimeVector;
 
 // A struct for functions which consume data payloads and fins.
 struct NET_EXPORT_PRIVATE QuicConsumedData {
diff --git a/net/quic/core/quic_unacked_packet_map.cc b/net/quic/core/quic_unacked_packet_map.cc
index e42e1550..e5a0696 100644
--- a/net/quic/core/quic_unacked_packet_map.cc
+++ b/net/quic/core/quic_unacked_packet_map.cc
@@ -25,10 +25,8 @@
       pending_crypto_packet_count_(0) {}
 
 QuicUnackedPacketMap::~QuicUnackedPacketMap() {
-  QuicPacketNumber index = least_unacked_;
-  for (UnackedPacketMap::iterator it = unacked_packets_.begin();
-       it != unacked_packets_.end(); ++it, ++index) {
-    DeleteFrames(&it->retransmittable_frames);
+  for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
+    DeleteFrames(&(transmission_info.retransmittable_frames));
   }
 }
 
@@ -42,15 +40,15 @@
   QUIC_BUG_IF(largest_sent_packet_ >= packet_number) << packet_number;
   DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
   while (least_unacked_ + unacked_packets_.size() < packet_number) {
-    unacked_packets_.push_back(TransmissionInfo());
+    unacked_packets_.push_back(QuicTransmissionInfo());
     unacked_packets_.back().is_unackable = true;
   }
 
   const bool has_crypto_handshake =
       packet->has_crypto_handshake == IS_HANDSHAKE;
-  TransmissionInfo info(packet->encryption_level, packet->packet_number_length,
-                        transmission_type, sent_time, bytes_sent,
-                        has_crypto_handshake, packet->num_padding_bytes);
+  QuicTransmissionInfo info(
+      packet->encryption_level, packet->packet_number_length, transmission_type,
+      sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);
   if (old_packet_number > 0) {
     TransferRetransmissionInfo(old_packet_number, packet_number,
                                transmission_type, &info);
@@ -91,7 +89,7 @@
     QuicPacketNumber old_packet_number,
     QuicPacketNumber new_packet_number,
     TransmissionType transmission_type,
-    TransmissionInfo* info) {
+    QuicTransmissionInfo* info) {
   if (old_packet_number < least_unacked_) {
     // This can happen when a retransmission packet is queued because of write
     // blocked socket, and the original packet gets acked before the
@@ -99,14 +97,14 @@
     return;
   }
   if (old_packet_number > largest_sent_packet_) {
-    QUIC_BUG << "Old TransmissionInfo never existed for :" << old_packet_number
-             << " largest_sent:" << largest_sent_packet_;
+    QUIC_BUG << "Old QuicTransmissionInfo never existed for :"
+             << old_packet_number << " largest_sent:" << largest_sent_packet_;
     return;
   }
   DCHECK_GE(new_packet_number, least_unacked_ + unacked_packets_.size());
   DCHECK_NE(NOT_RETRANSMISSION, transmission_type);
 
-  TransmissionInfo* transmission_info =
+  QuicTransmissionInfo* transmission_info =
       &unacked_packets_.at(old_packet_number - least_unacked_);
   QuicFrames* frames = &transmission_info->retransmittable_frames;
   for (AckListenerWrapper& wrapper : transmission_info->ack_listeners) {
@@ -145,34 +143,32 @@
               .retransmittable_frames.empty();
 }
 
-void QuicUnackedPacketMap::RemoveRetransmittability(TransmissionInfo* info) {
+void QuicUnackedPacketMap::RemoveRetransmittability(
+    QuicTransmissionInfo* info) {
   while (info->retransmission != 0) {
     const QuicPacketNumber retransmission = info->retransmission;
     info->retransmission = 0;
     info = &unacked_packets_[retransmission - least_unacked_];
   }
-  MaybeRemoveRetransmittableFrames(info);
+
+  if (info->has_crypto_handshake) {
+    DCHECK(!info->retransmittable_frames.empty());
+    DCHECK_LT(0u, pending_crypto_packet_count_);
+    --pending_crypto_packet_count_;
+    info->has_crypto_handshake = false;
+  }
+  DeleteFrames(&info->retransmittable_frames);
 }
 
 void QuicUnackedPacketMap::RemoveRetransmittability(
     QuicPacketNumber packet_number) {
   DCHECK_GE(packet_number, least_unacked_);
   DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
-  TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+  QuicTransmissionInfo* info =
+      &unacked_packets_[packet_number - least_unacked_];
   RemoveRetransmittability(info);
 }
 
-void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames(
-    TransmissionInfo* transmission_info) {
-  if (transmission_info->has_crypto_handshake) {
-    DCHECK(!transmission_info->retransmittable_frames.empty());
-    DCHECK_LT(0u, pending_crypto_packet_count_);
-    --pending_crypto_packet_count_;
-    transmission_info->has_crypto_handshake = false;
-  }
-  DeleteFrames(&transmission_info->retransmittable_frames);
-}
-
 void QuicUnackedPacketMap::IncreaseLargestObserved(
     QuicPacketNumber largest_observed) {
   DCHECK_LE(largest_observed_, largest_observed);
@@ -181,20 +177,20 @@
 
 bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
     QuicPacketNumber packet_number,
-    const TransmissionInfo& info) const {
+    const QuicTransmissionInfo& info) const {
   // Packet can be used for RTT measurement if it may yet be acked as the
   // largest observed packet by the receiver.
   return !info.is_unackable && packet_number > largest_observed_;
 }
 
 bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
-    const TransmissionInfo& info) const {
+    const QuicTransmissionInfo& info) const {
   // Packet contributes to congestion control if it is considered inflight.
   return info.in_flight;
 }
 
 bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
-    const TransmissionInfo& info) const {
+    const QuicTransmissionInfo& info) const {
   // Packet may have retransmittable frames, or the data may have been
   // retransmitted with a new packet number.
   return !info.retransmittable_frames.empty() ||
@@ -202,8 +198,9 @@
          info.retransmission > largest_observed_;
 }
 
-bool QuicUnackedPacketMap::IsPacketUseless(QuicPacketNumber packet_number,
-                                           const TransmissionInfo& info) const {
+bool QuicUnackedPacketMap::IsPacketUseless(
+    QuicPacketNumber packet_number,
+    const QuicTransmissionInfo& info) const {
   return !IsPacketUsefulForMeasuringRtt(packet_number, info) &&
          !IsPacketUsefulForCongestionControl(info) &&
          !IsPacketUsefulForRetransmittableData(info);
@@ -232,11 +229,12 @@
     QuicTime::Delta ack_delay_time) {
   DCHECK_GE(packet_number, least_unacked_);
   DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
-  TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+  QuicTransmissionInfo* info =
+      &unacked_packets_[packet_number - least_unacked_];
   NotifyAndClearListeners(&info->ack_listeners, ack_delay_time);
 }
 
-void QuicUnackedPacketMap::RemoveFromInFlight(TransmissionInfo* info) {
+void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
   if (info->in_flight) {
     QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
     bytes_in_flight_ -= info->bytes_sent;
@@ -247,14 +245,16 @@
 void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
   DCHECK_GE(packet_number, least_unacked_);
   DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
-  TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+  QuicTransmissionInfo* info =
+      &unacked_packets_[packet_number - least_unacked_];
   RemoveFromInFlight(info);
 }
 
 void QuicUnackedPacketMap::RestoreToInFlight(QuicPacketNumber packet_number) {
   DCHECK_GE(packet_number, least_unacked_);
   DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
-  TransmissionInfo* info = &unacked_packets_[packet_number - least_unacked_];
+  QuicTransmissionInfo* info =
+      &unacked_packets_[packet_number - least_unacked_];
   DCHECK(!info->is_unackable);
   bytes_in_flight_ += info->bytes_sent;
   info->in_flight = true;
@@ -284,12 +284,12 @@
   return bytes_in_flight_ > 0;
 }
 
-const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
+const QuicTransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
     QuicPacketNumber packet_number) const {
   return unacked_packets_[packet_number - least_unacked_];
 }
 
-TransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
+QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
     QuicPacketNumber packet_number) {
   return &unacked_packets_[packet_number - least_unacked_];
 }
diff --git a/net/quic/core/quic_unacked_packet_map.h b/net/quic/core/quic_unacked_packet_map.h
index 082a18b..9871b5c 100644
--- a/net/quic/core/quic_unacked_packet_map.h
+++ b/net/quic/core/quic_unacked_packet_map.h
@@ -11,7 +11,8 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_transmission_info.h"
 
 namespace net {
 
@@ -31,7 +32,7 @@
   // |old_packet_number| is the packet number of the previous transmission,
   // or 0 if there was none.
   // Any AckNotifierWrappers in |serialized_packet| are swapped from the
-  // serialized packet into the TransmissionInfo.
+  // serialized packet into the QuicTransmissionInfo.
   void AddSentPacket(SerializedPacket* serialized_packet,
                      QuicPacketNumber old_packet_number,
                      TransmissionType transmission_type,
@@ -51,7 +52,7 @@
                                QuicTime::Delta delta_largest_observed);
 
   // Marks |info| as no longer in flight.
-  void RemoveFromInFlight(TransmissionInfo* info);
+  void RemoveFromInFlight(QuicTransmissionInfo* info);
 
   // Marks |packet_number| as no longer in flight.
   void RemoveFromInFlight(QuicPacketNumber packet_number);
@@ -94,7 +95,7 @@
   // been acked by the peer.  If there are no unacked packets, returns 0.
   QuicPacketNumber GetLeastUnacked() const;
 
-  typedef std::deque<TransmissionInfo> UnackedPacketMap;
+  typedef std::deque<QuicTransmissionInfo> UnackedPacketMap;
 
   typedef UnackedPacketMap::const_iterator const_iterator;
   typedef UnackedPacketMap::iterator iterator;
@@ -107,14 +108,15 @@
   // Returns true if there are unacked packets that are in flight.
   bool HasInFlightPackets() const;
 
-  // Returns the TransmissionInfo associated with |packet_number|, which
+  // Returns the QuicTransmissionInfo associated with |packet_number|, which
   // must be unacked.
-  const TransmissionInfo& GetTransmissionInfo(
+  const QuicTransmissionInfo& GetTransmissionInfo(
       QuicPacketNumber packet_number) const;
 
-  // Returns mutable TransmissionInfo associated with |packet_number|, which
+  // Returns mutable QuicTransmissionInfo associated with |packet_number|, which
   // must be unacked.
-  TransmissionInfo* GetMutableTransmissionInfo(QuicPacketNumber packet_number);
+  QuicTransmissionInfo* GetMutableTransmissionInfo(
+      QuicPacketNumber packet_number);
 
   // Returns the time that the last unacked packet was sent.
   QuicTime GetLastPacketSentTime() const;
@@ -131,9 +133,9 @@
   // Removes any retransmittable frames from this transmission or an associated
   // transmission.  It removes now useless transmissions, and disconnects any
   // other packets from other transmissions.
-  void RemoveRetransmittability(TransmissionInfo* info);
+  void RemoveRetransmittability(QuicTransmissionInfo* info);
 
-  // Looks up the TransmissionInfo by |packet_number| and calls
+  // Looks up the QuicTransmissionInfo by |packet_number| and calls
   // RemoveRetransmittability.
   void RemoveRetransmittability(QuicPacketNumber packet_number);
 
@@ -153,24 +155,24 @@
   void TransferRetransmissionInfo(QuicPacketNumber old_packet_number,
                                   QuicPacketNumber new_packet_number,
                                   TransmissionType transmission_type,
-                                  TransmissionInfo* info);
-
-  void MaybeRemoveRetransmittableFrames(TransmissionInfo* transmission_info);
+                                  QuicTransmissionInfo* info);
 
   // Returns true if packet may be useful for an RTT measurement.
   bool IsPacketUsefulForMeasuringRtt(QuicPacketNumber packet_number,
-                                     const TransmissionInfo& info) const;
+                                     const QuicTransmissionInfo& info) const;
 
   // Returns true if packet may be useful for congestion control purposes.
-  bool IsPacketUsefulForCongestionControl(const TransmissionInfo& info) const;
+  bool IsPacketUsefulForCongestionControl(
+      const QuicTransmissionInfo& info) const;
 
   // Returns true if packet may be associated with retransmittable data
   // directly or through retransmissions.
-  bool IsPacketUsefulForRetransmittableData(const TransmissionInfo& info) const;
+  bool IsPacketUsefulForRetransmittableData(
+      const QuicTransmissionInfo& info) const;
 
   // Returns true if the packet no longer has a purpose in the map.
   bool IsPacketUseless(QuicPacketNumber packet_number,
-                       const TransmissionInfo& info) const;
+                       const QuicTransmissionInfo& info) const;
 
   QuicPacketNumber largest_sent_packet_;
   // The largest sent packet we expect to receive an ack for.
diff --git a/net/quic/core/quic_version_manager.cc b/net/quic/core/quic_version_manager.cc
new file mode 100644
index 0000000..6bbfe801
--- /dev/null
+++ b/net/quic/core/quic_version_manager.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2016 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 "net/quic/core/quic_version_manager.h"
+
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_versions.h"
+
+namespace net {
+
+QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
+    : enable_version_36_(FLAGS_quic_enable_version_36_v3),
+      allowed_supported_versions_(supported_versions),
+      filtered_supported_versions_(
+          FilterSupportedVersions(supported_versions)) {}
+
+QuicVersionManager::~QuicVersionManager() {}
+
+const QuicVersionVector& QuicVersionManager::GetSupportedVersions() {
+  MaybeRefilterSupportedVersions();
+  return filtered_supported_versions_;
+}
+
+void QuicVersionManager::MaybeRefilterSupportedVersions() {
+  if (enable_version_36_ != FLAGS_quic_enable_version_36_v3) {
+    enable_version_36_ = FLAGS_quic_enable_version_36_v3;
+    RefilterSupportedVersions();
+  }
+}
+
+void QuicVersionManager::RefilterSupportedVersions() {
+  filtered_supported_versions_ =
+      FilterSupportedVersions(allowed_supported_versions_);
+}
+
+}  // namespace net
diff --git a/net/quic/core/quic_version_manager.h b/net/quic/core/quic_version_manager.h
new file mode 100644
index 0000000..cd8e9f95
--- /dev/null
+++ b/net/quic/core/quic_version_manager.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2016 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 NET_QUIC_CORE_QUIC_VERSION_MANAGER_H_
+#define NET_QUIC_CORE_QUIC_VERSION_MANAGER_H_
+
+#include "net/quic/core/quic_versions.h"
+
+namespace net {
+
+// Used to generate filtered supported versions based on flags.
+class NET_EXPORT_PRIVATE QuicVersionManager {
+ public:
+  explicit QuicVersionManager(QuicVersionVector supported_versions);
+  virtual ~QuicVersionManager();
+
+  // Returns currently supported QUIC versions.
+  const QuicVersionVector& GetSupportedVersions();
+
+ protected:
+  // Maybe refilter filtered_supported_versions_ based on flags.
+  void MaybeRefilterSupportedVersions();
+
+  // Refilters filtered_supported_versions_.
+  virtual void RefilterSupportedVersions();
+
+  const QuicVersionVector& filtered_supported_versions() const {
+    return filtered_supported_versions_;
+  }
+
+ private:
+  // FLAGS_quic_enable_version_36_v3
+  bool enable_version_36_;
+  // The list of versions that may be supported.
+  QuicVersionVector allowed_supported_versions_;
+  // This vector contains QUIC versions which are currently supported based on
+  // flags.
+  QuicVersionVector filtered_supported_versions_;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_VERSION_MANAGER_H_
diff --git a/net/quic/core/quic_version_manager_test.cc b/net/quic/core/quic_version_manager_test.cc
new file mode 100644
index 0000000..0529259
--- /dev/null
+++ b/net/quic/core/quic_version_manager_test.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2016 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 "net/quic/core/quic_version_manager.h"
+
+#include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_versions.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(QuicVersionManagerTest, QuicVersionManager) {
+  QuicFlagSaver flags;
+  FLAGS_quic_enable_version_36_v3 = false;
+  QuicVersionManager manager(AllSupportedVersions());
+  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+            manager.GetSupportedVersions());
+  FLAGS_quic_enable_version_36_v3 = true;
+  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+            manager.GetSupportedVersions());
+  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[1]);
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/core/quic_write_blocked_list.h b/net/quic/core/quic_write_blocked_list.h
index c7b6d446..7f3dd2dc 100644
--- a/net/quic/core/quic_write_blocked_list.h
+++ b/net/quic/core/quic_write_blocked_list.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/spdy/priority_write_scheduler.h"
 
 namespace net {
diff --git a/net/quic/core/spdy_utils.cc b/net/quic/core/spdy_utils.cc
index 2220013..c57f0b53 100644
--- a/net/quic/core/spdy_utils.cc
+++ b/net/quic/core/spdy_utils.cc
@@ -27,11 +27,9 @@
 
 // static
 string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) {
-  SpdyMajorVersion spdy_version = HTTP2;
-
-  size_t length = SpdyFramer::GetSerializedLength(spdy_version, &headers);
-  SpdyFrameBuilder builder(length, spdy_version);
-  SpdyFramer framer(spdy_version);
+  size_t length = SpdyFramer::GetSerializedLength(&headers);
+  SpdyFrameBuilder builder(length);
+  SpdyFramer framer;
   framer.SerializeHeaderBlockWithoutCompression(&builder, headers);
   SpdySerializedFrame block(builder.take());
   return string(block.data(), length);
@@ -42,7 +40,7 @@
                              uint32_t data_len,
                              int64_t* content_length,
                              SpdyHeaderBlock* headers) {
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   if (!framer.ParseHeaderBlockInBuffer(data, data_len, headers) ||
       headers->empty()) {
     return false;  // Headers were invalid.
@@ -93,7 +91,7 @@
                               uint32_t data_len,
                               size_t* final_byte_offset,
                               SpdyHeaderBlock* trailers) {
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   if (!framer.ParseHeaderBlockInBuffer(data, data_len, trailers) ||
       trailers->empty()) {
     DVLOG(1) << "Request Trailers are invalid.";
diff --git a/net/quic/core/spdy_utils.h b/net/quic/core/spdy_utils.h
index f69b447..0383332 100644
--- a/net/quic/core/spdy_utils.h
+++ b/net/quic/core/spdy_utils.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/spdy/spdy_framer.h"
 
 namespace net {
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index 503a7a8..9eef2c0 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -17,7 +17,7 @@
 #include "base/strings/string_piece.h"
 #include "net/quic/core/crypto/crypto_framer.h"
 #include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 
 namespace net {
diff --git a/net/quic/test_tools/mock_quic_client_promised_info.h b/net/quic/test_tools/mock_quic_client_promised_info.h
index 98643d7..4137b56 100644
--- a/net/quic/test_tools/mock_quic_client_promised_info.h
+++ b/net/quic/test_tools/mock_quic_client_promised_info.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace net {
diff --git a/net/quic/test_tools/mock_quic_dispatcher.cc b/net/quic/test_tools/mock_quic_dispatcher.cc
index efe4a80..e074e55 100644
--- a/net/quic/test_tools/mock_quic_dispatcher.cc
+++ b/net/quic/test_tools/mock_quic_dispatcher.cc
@@ -16,14 +16,14 @@
     std::unique_ptr<QuicConnectionHelperInterface> helper,
     std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
     std::unique_ptr<QuicAlarmFactory> alarm_factory,
-    QuicInMemoryCache* in_memory_cache)
+    QuicHttpResponseCache* response_cache)
     : QuicSimpleDispatcher(config,
                            crypto_config,
                            version_manager,
                            std::move(helper),
                            std::move(session_helper),
                            std::move(alarm_factory),
-                           in_memory_cache) {}
+                           response_cache) {}
 
 MockQuicDispatcher::~MockQuicDispatcher() {}
 
diff --git a/net/quic/test_tools/mock_quic_dispatcher.h b/net/quic/test_tools/mock_quic_dispatcher.h
index 33836374..a07dd80 100644
--- a/net/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/quic/test_tools/mock_quic_dispatcher.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "net/quic/core/crypto/quic_crypto_server_config.h"
 #include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/tools/quic/quic_simple_dispatcher.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -24,7 +24,7 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      QuicInMemoryCache* in_memory_cache);
+      QuicHttpResponseCache* response_cache);
 
   ~MockQuicDispatcher() override;
 
diff --git a/net/quic/test_tools/mock_quic_spdy_client_stream.h b/net/quic/test_tools/mock_quic_spdy_client_stream.h
index bfe225d1..5522cb6 100644
--- a/net/quic/test_tools/mock_quic_spdy_client_stream.h
+++ b/net/quic/test_tools/mock_quic_spdy_client_stream.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "net/quic/core/quic_header_list.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/tools/quic/quic_spdy_client_stream.h"
 #include "testing/gmock/include/gmock/gmock.h"
 // #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/test_tools/quic_config_peer.h b/net/quic/test_tools/quic_config_peer.h
index 4ac0febd..20c8f08d 100644
--- a/net/quic/test_tools/quic_config_peer.h
+++ b/net/quic/test_tools/quic_config_peer.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "net/quic/core/quic_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 3dae40c3..b60ac345 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -9,7 +9,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_connection_stats.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 
 namespace net {
diff --git a/net/quic/test_tools/quic_flow_controller_peer.cc b/net/quic/test_tools/quic_flow_controller_peer.cc
index 5fc7d42..73f20a27 100644
--- a/net/quic/test_tools/quic_flow_controller_peer.cc
+++ b/net/quic/test_tools/quic_flow_controller_peer.cc
@@ -7,7 +7,7 @@
 #include <list>
 
 #include "net/quic/core/quic_flow_controller.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 namespace test {
diff --git a/net/quic/test_tools/quic_flow_controller_peer.h b/net/quic/test_tools/quic_flow_controller_peer.h
index 7788980..cc42cde9 100644
--- a/net/quic/test_tools/quic_flow_controller_peer.h
+++ b/net/quic/test_tools/quic_flow_controller_peer.h
@@ -6,7 +6,7 @@
 #define NET_QUIC_TEST_TOOLS_QUIC_FLOW_CONTROLLER_PEER_H_
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/quic_framer_peer.cc b/net/quic/test_tools/quic_framer_peer.cc
index f884e7bf..9c873f7 100644
--- a/net/quic/test_tools/quic_framer_peer.cc
+++ b/net/quic/test_tools/quic_framer_peer.cc
@@ -6,7 +6,7 @@
 
 #include "base/stl_util.h"
 #include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 namespace test {
diff --git a/net/quic/test_tools/quic_framer_peer.h b/net/quic/test_tools/quic_framer_peer.h
index 3ab3830..7b8b1794 100644
--- a/net/quic/test_tools/quic_framer_peer.h
+++ b/net/quic/test_tools/quic_framer_peer.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "net/quic/core/crypto/quic_encrypter.h"
 #include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h
index cd12e71d..1cdb91b5d 100644
--- a/net/quic/test_tools/quic_packet_creator_peer.h
+++ b/net/quic/test_tools/quic_packet_creator_peer.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "net/quic/core/quic_iovector.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 class QuicPacketCreator;
diff --git a/net/quic/test_tools/quic_packet_generator_peer.h b/net/quic/test_tools/quic_packet_generator_peer.h
index 2aaa263b..7d0becda 100644
--- a/net/quic/test_tools/quic_packet_generator_peer.h
+++ b/net/quic/test_tools/quic_packet_generator_peer.h
@@ -6,7 +6,7 @@
 #define NET_QUIC_TEST_TOOLS_QUIC_PACKET_GENERATOR_PEER_H_
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/quic_received_packet_manager_peer.cc b/net/quic/test_tools/quic_received_packet_manager_peer.cc
index 2a6fc797..1e0ee002 100644
--- a/net/quic/test_tools/quic_received_packet_manager_peer.cc
+++ b/net/quic/test_tools/quic_received_packet_manager_peer.cc
@@ -4,7 +4,7 @@
 
 #include "net/quic/test_tools/quic_received_packet_manager_peer.h"
 
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_received_packet_manager.h"
 
 namespace net {
diff --git a/net/quic/test_tools/quic_received_packet_manager_peer.h b/net/quic/test_tools/quic_received_packet_manager_peer.h
index a2427b84..43a9d20 100644
--- a/net/quic/test_tools/quic_received_packet_manager_peer.h
+++ b/net/quic/test_tools/quic_received_packet_manager_peer.h
@@ -6,7 +6,7 @@
 #define NET_QUIC_TEST_TOOLS_QUIC_RECEIVED_PACKET_MANAGER_PEER_H_
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
index 1b617e5..7c4e7935 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -8,7 +8,7 @@
 #include "net/quic/core/congestion_control/loss_detection_interface.h"
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
 
 namespace net {
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.h b/net/quic/test_tools/quic_sent_packet_manager_peer.h
index c9eedc2c..db6250bb 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
 
 namespace net {
diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h
index 9be6cde..8874c7ac 100644
--- a/net/quic/test_tools/quic_session_peer.h
+++ b/net/quic/test_tools/quic_session_peer.h
@@ -11,7 +11,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
 #include "net/quic/core/quic_write_blocked_list.h"
 
diff --git a/net/quic/test_tools/quic_spdy_session_peer.h b/net/quic/test_tools/quic_spdy_session_peer.h
index 9cb9cfd..238ba1bb 100644
--- a/net/quic/test_tools/quic_spdy_session_peer.h
+++ b/net/quic/test_tools/quic_spdy_session_peer.h
@@ -6,7 +6,7 @@
 #define NET_QUIC_TEST_TOOLS_QUIC_SPDY_SESSION_PEER_H_
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_write_blocked_list.h"
 
 namespace net {
diff --git a/net/quic/test_tools/quic_stream_factory_peer.h b/net/quic/test_tools/quic_stream_factory_peer.h
index 38916b1..eeb1dc09 100644
--- a/net/quic/test_tools/quic_stream_factory_peer.h
+++ b/net/quic/test_tools/quic_stream_factory_peer.h
@@ -12,7 +12,7 @@
 #include "base/task_runner.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/privacy_mode.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/quic_time.h"
 
diff --git a/net/quic/test_tools/quic_stream_peer.h b/net/quic/test_tools/quic_stream_peer.h
index e39ac4bc..3d3f440 100644
--- a/net/quic/test_tools/quic_stream_peer.h
+++ b/net/quic/test_tools/quic_stream_peer.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_stream_sequencer.h"
 
 namespace net {
diff --git a/net/quic/test_tools/quic_stream_sequencer_peer.h b/net/quic/test_tools/quic_stream_sequencer_peer.h
index aa8773c..cc63e711 100644
--- a/net/quic/test_tools/quic_stream_sequencer_peer.h
+++ b/net/quic/test_tools/quic_stream_sequencer_peer.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc b/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc
index 6a70fa93..ad64391 100644
--- a/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc
+++ b/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc
@@ -4,7 +4,7 @@
 
 #include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
 
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sustained_bandwidth_recorder.h"
 
 namespace net {
diff --git a/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h b/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
index 4a0669a..5dbb4e3 100644
--- a/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
+++ b/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc
index a76b0c7d..d00aedf 100644
--- a/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -27,8 +27,6 @@
       connection_id_(connection_id),
       clock_(clock),
       host_(host),
-      spdy_request_framer_(HTTP2),
-      spdy_response_framer_(HTTP2),
       perspective_(perspective) {}
 
 QuicTestPacketMaker::~QuicTestPacketMaker() {}
diff --git a/net/quic/test_tools/quic_test_packet_maker.h b/net/quic/test_tools/quic_test_packet_maker.h
index 995b74841..944e1461d 100644
--- a/net/quic/test_tools/quic_test_packet_maker.h
+++ b/net/quic/test_tools/quic_test_packet_maker.h
@@ -15,7 +15,7 @@
 
 #include "base/macros.h"
 #include "net/base/request_priority.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/mock_random.h"
 #include "net/spdy/spdy_framer.h"
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index ca5712a5..6428c1e 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -26,7 +26,7 @@
 #include "net/quic/core/quic_connection_close_delegate_interface.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_iovector.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager_interface.h"
 #include "net/quic/core/quic_server_session_base.h"
 #include "net/quic/core/quic_session.h"
@@ -915,7 +915,7 @@
   MOCK_METHOD0(MaybeRetransmitTailLossProbe, bool(void));
   MOCK_METHOD0(NeuterUnencryptedPackets, void(void));
   MOCK_CONST_METHOD0(HasPendingRetransmissions, bool(void));
-  MOCK_METHOD0(NextPendingRetransmission, PendingRetransmission(void));
+  MOCK_METHOD0(NextPendingRetransmission, QuicPendingRetransmission(void));
   MOCK_CONST_METHOD0(HasUnackedPackets, bool(void));
   MOCK_CONST_METHOD1(GetLeastUnacked, QuicPacketNumber(QuicPathId));
   MOCK_METHOD6(OnPacketSent,
@@ -950,6 +950,7 @@
   MOCK_CONST_METHOD0(GetConsecutiveRtoCount, size_t(void));
   MOCK_CONST_METHOD0(GetConsecutiveTlpCount, size_t(void));
   MOCK_METHOD0(OnApplicationLimited, void(void));
+  MOCK_CONST_METHOD0(GetSendAlgorithm, const SendAlgorithmInterface*(void));
 };
 
 class MockConnectionCloseDelegate
diff --git a/net/quic/test_tools/simple_quic_framer.h b/net/quic/test_tools/simple_quic_framer.h
index 76f1b5f..d019f29 100644
--- a/net/quic/test_tools/simple_quic_framer.h
+++ b/net/quic/test_tools/simple_quic_framer.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
 #include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/quic/test_tools/simulator/port.h b/net/quic/test_tools/simulator/port.h
index 62c47f2..5975f873 100644
--- a/net/quic/test_tools/simulator/port.h
+++ b/net/quic/test_tools/simulator/port.h
@@ -8,7 +8,7 @@
 #include <string>
 #include <utility>
 
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/test_tools/simulator/actor.h"
 
 namespace net {
diff --git a/net/quic/test_tools/simulator/quic_endpoint.h b/net/quic/test_tools/simulator/quic_endpoint.h
index bded9842..6f4f30d0 100644
--- a/net/quic/test_tools/simulator/quic_endpoint.h
+++ b/net/quic/test_tools/simulator/quic_endpoint.h
@@ -8,7 +8,7 @@
 #include "net/quic/core/crypto/null_decrypter.h"
 #include "net/quic/core/crypto/null_encrypter.h"
 #include "net/quic/core/quic_connection.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/test_tools/simulator/link.h"
 #include "net/quic/test_tools/simulator/queue.h"
 #include "net/tools/quic/quic_default_packet_writer.h"
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc
index 2cc2f8e..ead180fc 100644
--- a/net/spdy/buffered_spdy_framer.cc
+++ b/net/spdy/buffered_spdy_framer.cc
@@ -20,8 +20,7 @@
 }  // namespace
 
 BufferedSpdyFramer::BufferedSpdyFramer()
-    : spdy_framer_(HTTP2),
-      visitor_(NULL),
+    : visitor_(NULL),
       header_buffer_valid_(false),
       header_stream_id_(SpdyFramer::kInvalidStream),
       frames_received_(0) {}
diff --git a/net/spdy/buffered_spdy_framer_unittest.cc b/net/spdy/buffered_spdy_framer_unittest.cc
index cc37316..ba6a67d 100644
--- a/net/spdy/buffered_spdy_framer_unittest.cc
+++ b/net/spdy/buffered_spdy_framer_unittest.cc
@@ -179,7 +179,7 @@
 class BufferedSpdyFramerTest : public PlatformTest {};
 
 TEST_F(BufferedSpdyFramerTest, OnSetting) {
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   SpdySettingsIR settings_ir;
   settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, false, false, 2);
   settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, false, false, 3);
diff --git a/net/spdy/spdy_deframer_visitor_test.cc b/net/spdy/spdy_deframer_visitor_test.cc
index 9e94798..7498303 100644
--- a/net/spdy/spdy_deframer_visitor_test.cc
+++ b/net/spdy/spdy_deframer_visitor_test.cc
@@ -31,7 +31,7 @@
 
 class SpdyDeframerVisitorTest : public ::testing::Test {
  protected:
-  SpdyDeframerVisitorTest() : encoder_(HTTP2), decoder_(HTTP2) {
+  SpdyDeframerVisitorTest() {
     decoder_.set_process_single_input_frame(true);
     auto collector = MakeUnique<DeframerCallbackCollector>(&collected_frames_);
     auto log_and_collect =
diff --git a/net/spdy/spdy_frame_builder.cc b/net/spdy/spdy_frame_builder.cc
index 8beced1..9996257 100644
--- a/net/spdy/spdy_frame_builder.cc
+++ b/net/spdy/spdy_frame_builder.cc
@@ -13,13 +13,8 @@
 
 namespace net {
 
-SpdyFrameBuilder::SpdyFrameBuilder(size_t size, SpdyMajorVersion version)
-    : buffer_(new char[size]),
-      capacity_(size),
-      length_(0),
-      offset_(0),
-      version_(version) {
-}
+SpdyFrameBuilder::SpdyFrameBuilder(size_t size)
+    : buffer_(new char[size]), capacity_(size), length_(0), offset_(0) {}
 
 SpdyFrameBuilder::~SpdyFrameBuilder() {
 }
@@ -44,13 +39,11 @@
                                      SpdyFrameType type,
                                      uint8_t flags,
                                      SpdyStreamId stream_id) {
-  DCHECK(SpdyConstants::IsValidFrameType(
-      version_, SpdyConstants::SerializeFrameType(version_, type)));
+  DCHECK(
+      SpdyConstants::IsValidFrameType(SpdyConstants::SerializeFrameType(type)));
   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
-  DCHECK_EQ(HTTP2, framer.protocol_version());
   bool success = true;
-  size_t frame_header_length =
-      SpdyConstants::GetFrameHeaderSize(framer.protocol_version());
+  size_t frame_header_length = SpdyConstants::kFrameHeaderSize;
   if (length_ > 0) {
     // Update length field for previous frame.
     OverwriteLength(framer, length_ - frame_header_length);
@@ -67,7 +60,7 @@
   // Don't check for length limits here because this may be larger than the
   // actual frame length.
   success &= WriteUInt24(capacity_ - offset_ - frame_header_length);
-  success &= WriteUInt8(SpdyConstants::SerializeFrameType(version_, type));
+  success &= WriteUInt8(SpdyConstants::SerializeFrameType(type));
   success &= WriteUInt8(flags);
   success &= WriteUInt32(stream_id);
   DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
@@ -124,7 +117,6 @@
 }
 
 bool SpdyFrameBuilder::OverwriteFlags(const SpdyFramer& framer, uint8_t flags) {
-  DCHECK_EQ(HTTP2, framer.protocol_version());
   bool success = false;
   const size_t old_length = length_;
   // Flags are the fifth octet in the frame prefix.
diff --git a/net/spdy/spdy_frame_builder.h b/net/spdy/spdy_frame_builder.h
index 159d898..c445a9a 100644
--- a/net/spdy/spdy_frame_builder.h
+++ b/net/spdy/spdy_frame_builder.h
@@ -31,7 +31,7 @@
 class NET_EXPORT_PRIVATE SpdyFrameBuilder {
  public:
   // Initializes a SpdyFrameBuilder with a buffer of given size
-  SpdyFrameBuilder(size_t size, SpdyMajorVersion version);
+  explicit SpdyFrameBuilder(size_t size);
 
   ~SpdyFrameBuilder();
 
@@ -51,10 +51,8 @@
   // GetWriteableBuffer() above.
   bool Seek(size_t length);
 
-  // Populates this frame with a HTTP2 frame prefix using version-specific
-  // information from the |framer| and length information from |capacity_|. The
-  // given type must be a control frame type.
-  // Used only for HTTP2.
+  // Populates this frame with a HTTP2 frame prefix using length information
+  // from |capacity_|. The given type must be a control frame type.
   bool BeginNewFrame(const SpdyFramer& framer,
                      SpdyFrameType type,
                      uint8_t flags,
@@ -62,11 +60,9 @@
 
   // Takes the buffer from the SpdyFrameBuilder.
   SpdySerializedFrame take() {
-    if (version_ == HTTP2) {
-      SPDY_BUG_IF(SpdyConstants::GetMaxFrameSizeLimit(version_) < length_)
-          << "Frame length " << length_
-          << " is longer than the maximum possible allowed length.";
-    }
+    SPDY_BUG_IF(SpdyConstants::kMaxFrameSizeLimit < length_)
+        << "Frame length " << length_
+        << " is longer than the maximum possible allowed length.";
     SpdySerializedFrame rv(buffer_.release(), length(), true);
     capacity_ = 0;
     length_ = 0;
@@ -117,7 +113,6 @@
 
   // Update (in-place) the flags field in the frame being built to reflect the
   // given flags value.
-  // Used only for SPDY versions >=4.
   bool OverwriteFlags(const SpdyFramer& framer, uint8_t flags);
 
  private:
@@ -129,8 +124,6 @@
   size_t capacity_;  // Allocation size of payload, set by constructor.
   size_t length_;    // Length of the latest frame in the buffer.
   size_t offset_;    // Position at which the latest frame begins.
-
-  const SpdyMajorVersion version_;
 };
 
 }  // namespace net
diff --git a/net/spdy/spdy_frame_builder_test.cc b/net/spdy/spdy_frame_builder_test.cc
index 158c0a5..921df698 100644
--- a/net/spdy/spdy_frame_builder_test.cc
+++ b/net/spdy/spdy_frame_builder_test.cc
@@ -12,7 +12,7 @@
 
 TEST(SpdyFrameBuilderTest, GetWritableBuffer) {
   const size_t kBuilderSize = 10;
-  SpdyFrameBuilder builder(kBuilderSize, HTTP2);
+  SpdyFrameBuilder builder(kBuilderSize);
   char* writable_buffer = builder.GetWritableBuffer(kBuilderSize);
   memset(writable_buffer, ~1, kBuilderSize);
   EXPECT_TRUE(builder.Seek(kBuilderSize));
@@ -27,10 +27,10 @@
   // Create an empty SETTINGS frame both via framer and manually via builder.
   // The one created via builder is initially given the incorrect length, but
   // then is corrected via RewriteLength().
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   SpdySettingsIR settings_ir;
   SpdySerializedFrame expected(framer.SerializeSettings(settings_ir));
-  SpdyFrameBuilder builder(expected.size() + 1, HTTP2);
+  SpdyFrameBuilder builder(expected.size() + 1);
   builder.BeginNewFrame(framer, SETTINGS, 0, 0);
   EXPECT_TRUE(builder.GetWritableBuffer(1) != NULL);
   builder.RewriteLength(framer);
@@ -42,10 +42,10 @@
 TEST(SpdyFrameBuilderTest, OverwriteFlags) {
   // Create a HEADERS frame both via framer and manually via builder with
   // different flags set, then make them match using OverwriteFlags().
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   SpdyHeadersIR headers_ir(1);
   SpdySerializedFrame expected(framer.SerializeHeaders(headers_ir));
-  SpdyFrameBuilder builder(expected.size(), HTTP2);
+  SpdyFrameBuilder builder(expected.size());
   builder.BeginNewFrame(framer, HEADERS, 0, 1);
   builder.OverwriteFlags(framer, HEADERS_FLAG_END_HEADERS);
   SpdySerializedFrame built(builder.take());
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index a884aaa..975b453 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -116,8 +116,7 @@
   } while (false)
 #endif
 
-SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(SpdyMajorVersion version,
-                                                      uint32_t wire) {
+SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(uint32_t wire) {
   return SettingsFlagsAndId(base::NetToHost32(wire) >> 24,
                             base::NetToHost32(wire) & 0x00ffffff);
 }
@@ -127,7 +126,7 @@
   SPDY_BUG_IF(id > (1u << 24)) << "HTTP2 setting ID too large: " << id;
 }
 
-uint32_t SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version) const {
+uint32_t SettingsFlagsAndId::GetWireFormat() const {
   return base::HostToNet32(id_ & 0x00ffffff) | base::HostToNet32(flags_ << 24);
 }
 
@@ -142,18 +141,15 @@
   return true;
 }
 
-SpdyFramer::SpdyFramer(SpdyMajorVersion version,
-                       SpdyFramer::DecoderAdapterFactoryFn adapter_factory)
+SpdyFramer::SpdyFramer(SpdyFramer::DecoderAdapterFactoryFn adapter_factory)
     : current_frame_buffer_(kControlFrameBufferSize),
       expect_continuation_(0),
       visitor_(NULL),
       debug_visitor_(NULL),
       header_handler_(nullptr),
-      protocol_version_(version),
       enable_compression_(true),
       probable_http_response_(false),
       end_stream_when_done_(false) {
-  DCHECK(protocol_version_ == HTTP2);
   // TODO(bnc): The way kMaxControlFrameSize is currently interpreted, it
   // includes the frame header, whereas kSpdyInitialFrameSizeLimit does not.
   // Therefore this assertion is unnecessarily strict.
@@ -161,13 +157,12 @@
                 "Our send limit should be at most our receive limit");
   Reset();
 
-  if (version == HTTP2 && adapter_factory != nullptr) {
+  if (adapter_factory != nullptr) {
     decoder_adapter_ = adapter_factory(this);
   }
 }
 
-SpdyFramer::SpdyFramer(SpdyMajorVersion version)
-    : SpdyFramer(version, &DecoderAdapterFactory) {}
+SpdyFramer::SpdyFramer() : SpdyFramer(&DecoderAdapterFactory) {}
 
 SpdyFramer::~SpdyFramer() {
 }
@@ -235,12 +230,12 @@
 }
 
 size_t SpdyFramer::GetDataFrameMinimumSize() const {
-  return SpdyConstants::GetDataFrameMinimumSize(protocol_version_);
+  return SpdyConstants::kDataFrameMinimumSize;
 }
 
 // Size, in bytes, of the control frame header.
 size_t SpdyFramer::GetFrameHeaderSize() const {
-  return SpdyConstants::GetFrameHeaderSize(protocol_version_);
+  return SpdyConstants::kFrameHeaderSize;
 }
 
 // TODO(jamessynge): Rename this to GetRstStreamSize as the frame is fixed size.
@@ -284,14 +279,12 @@
 }
 
 size_t SpdyFramer::GetBlockedSize() const {
-  DCHECK_EQ(HTTP2, protocol_version_);
   // Size, in bytes, of a BLOCKED frame.
   // The BLOCKED frame has no payload beyond the control frame header.
   return GetFrameHeaderSize();
 }
 
 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
-  DCHECK_EQ(HTTP2, protocol_version_);
   // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
   // Calculated as frame prefix + 4 (promised stream id)
   return GetFrameHeaderSize() + 4;
@@ -323,21 +316,12 @@
 }
 
 size_t SpdyFramer::GetFrameMaximumSize() const {
-  if (protocol_version_ == HTTP2) {
-    return send_frame_size_limit_ +
-           SpdyConstants::GetFrameHeaderSize(protocol_version_);
-  } else {
-    return SpdyConstants::GetMaxFrameSizeLimit(protocol_version_);
-  }
+  return send_frame_size_limit_ + SpdyConstants::kFrameHeaderSize;
 }
 
 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
-  if (protocol_version_ == HTTP2) {
-    return std::min(kMaxDataPayloadSendSize,
-                    GetFrameMaximumSize() - GetDataFrameMinimumSize());
-  } else {
-    return GetFrameMaximumSize() - GetDataFrameMinimumSize();
-  }
+  return std::min(kMaxDataPayloadSendSize,
+                  GetFrameMaximumSize() - GetDataFrameMinimumSize());
 }
 
 const char* SpdyFramer::StateToString(int state) {
@@ -557,8 +541,7 @@
       }
 
       case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
-        int bytes_read = ProcessControlFrameHeaderBlock(
-            data, len, protocol_version_ == HTTP2);
+        int bytes_read = ProcessControlFrameHeaderBlock(data, len);
         len -= bytes_read;
         data += bytes_read;
         break;
@@ -666,8 +649,8 @@
 SpdyFrameType SpdyFramer::ValidateFrameHeader(bool is_control_frame,
                                               int frame_type_field,
                                               size_t payload_length_field) {
-  if (!SpdyConstants::IsValidFrameType(protocol_version_, frame_type_field)) {
-    // In HTTP2 we ignore unknown frame types for extensibility, as long as
+  if (!SpdyConstants::IsValidFrameType(frame_type_field)) {
+    // We ignore unknown frame types for extensibility, as long as
     // the rest of the control frame header is valid.
     // We rely on the visitor to check validity of current_frame_stream_id_.
     bool valid_stream =
@@ -693,35 +676,31 @@
     return DATA;
   }
 
-  SpdyFrameType frame_type =
-      SpdyConstants::ParseFrameType(protocol_version_, frame_type_field);
+  SpdyFrameType frame_type = SpdyConstants::ParseFrameType(frame_type_field);
 
-  if (protocol_version_ == HTTP2) {
-    if (!SpdyConstants::IsValidHTTP2FrameStreamId(current_frame_stream_id_,
-                                                  frame_type)) {
-      DLOG(ERROR) << "The framer received an invalid streamID of "
-                  << current_frame_stream_id_ << " for a frame of type "
-                  << FrameTypeToString(frame_type);
-      set_error(SPDY_INVALID_STREAM_ID);
-      return frame_type;
-    }
-
-    // Ensure that we see a CONTINUATION frame iff we expect to.
-    if ((frame_type == CONTINUATION) != (expect_continuation_ != 0)) {
-      if (expect_continuation_ != 0) {
-        DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
-                    << "frame, but instead received a frame of type "
-                    << FrameTypeToString(frame_type);
-      } else {
-        DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
-      }
-      set_error(SPDY_UNEXPECTED_FRAME);
-      return frame_type;
-    }
+  if (!SpdyConstants::IsValidHTTP2FrameStreamId(current_frame_stream_id_,
+                                                frame_type)) {
+    DLOG(ERROR) << "The framer received an invalid streamID of "
+                << current_frame_stream_id_ << " for a frame of type "
+                << FrameTypeToString(frame_type);
+    set_error(SPDY_INVALID_STREAM_ID);
+    return frame_type;
   }
 
-  if (protocol_version_ == HTTP2 &&
-      payload_length_field > recv_frame_size_limit_) {
+  // Ensure that we see a CONTINUATION frame iff we expect to.
+  if ((frame_type == CONTINUATION) != (expect_continuation_ != 0)) {
+    if (expect_continuation_ != 0) {
+      DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
+                  << "frame, but instead received a frame of type "
+                  << FrameTypeToString(frame_type);
+    } else {
+      DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
+    }
+    set_error(SPDY_UNEXPECTED_FRAME);
+    return frame_type;
+  }
+
+  if (payload_length_field > recv_frame_size_limit_) {
     set_error(SPDY_OVERSIZED_PAYLOAD);
   }
 
@@ -750,8 +729,7 @@
                          current_frame_buffer_.len());
   bool is_control_frame = false;
 
-  int control_frame_type_field =
-      SpdyConstants::DataFrameType(protocol_version_);
+  int control_frame_type_field = SpdyConstants::kDataFrameType;
   // ProcessControlFrameHeader() will set current_frame_type_ to the
   // correct value if this is a valid control frame.
   current_frame_type_ = DATA;
@@ -765,8 +743,7 @@
   // We check control_frame_type_field's validity in
   // ProcessControlFrameHeader().
   control_frame_type_field = control_frame_type_field_uint8;
-  is_control_frame = control_frame_type_field !=
-                     SpdyConstants::SerializeFrameType(protocol_version_, DATA);
+  is_control_frame = control_frame_type_field != SpdyConstants::kDataFrameType;
 
   current_frame_length_ = length_field + GetFrameHeaderSize();
 
@@ -853,12 +830,10 @@
         DLOG(WARNING) << "Invalid length for SETTINGS frame: "
                       << current_frame_length_;
         set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
-      } else if (protocol_version_ == HTTP2 &&
-                 current_frame_flags_ & SETTINGS_FLAG_ACK &&
+      } else if (current_frame_flags_ & SETTINGS_FLAG_ACK &&
                  current_frame_length_ > GetSettingsMinimumSize()) {
         set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
-      } else if (protocol_version_ == HTTP2 &&
-                 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
+      } else if (current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
         VLOG(1) << "Undefined frame flags for SETTINGS frame: " << hex
                 << static_cast<int>(current_frame_flags_);
         current_frame_flags_ &= SETTINGS_FLAG_ACK;
@@ -869,8 +844,7 @@
       if (current_frame_length_ != GetPingSize()) {
         set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
       } else {
-        if (protocol_version_ == HTTP2 &&
-            current_frame_flags_ & ~PING_FLAG_ACK) {
+        if (current_frame_flags_ & ~PING_FLAG_ACK) {
           VLOG(1) << "Undefined frame flags for PING frame: " << hex
                   << static_cast<int>(current_frame_flags_);
           current_frame_flags_ &= PING_FLAG_ACK;
@@ -881,8 +855,7 @@
       {
       // For HTTP/2, optional opaque data may be appended to the
       // GOAWAY frame, thus there is only a minimal length restriction.
-      if (protocol_version_ == HTTP2 &&
-          current_frame_length_ < GetGoAwayMinimumSize()) {
+      if (current_frame_length_ < GetGoAwayMinimumSize()) {
         set_error(SPDY_INVALID_CONTROL_FRAME);
         } else if (current_frame_flags_ != 0) {
           VLOG(1) << "Undefined frame flags for GOAWAY frame: " << hex
@@ -894,18 +867,16 @@
     case HEADERS:
       {
         size_t min_size = GetHeadersMinimumSize();
-        if (protocol_version_ == HTTP2 &&
-            (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
+        if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
           min_size += 4;
         }
         if (current_frame_length_ < min_size) {
           // TODO(mlavan): check here for HEADERS with no payload?
           // (not allowed in HTTP2)
           set_error(SPDY_INVALID_CONTROL_FRAME);
-        } else if (protocol_version_ == HTTP2 &&
-                   current_frame_flags_ &
-                       ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
-                         HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PADDED)) {
+        } else if (current_frame_flags_ &
+                   ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
+                     HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PADDED)) {
           VLOG(1) << "Undefined frame flags for HEADERS frame: " << hex
                   << static_cast<int>(current_frame_flags_);
           current_frame_flags_ &=
@@ -935,10 +906,8 @@
     case PUSH_PROMISE:
       if (current_frame_length_ < GetPushPromiseMinimumSize()) {
         set_error(SPDY_INVALID_CONTROL_FRAME);
-      } else if (protocol_version_ == HTTP2 &&
-                 current_frame_flags_ &
-                     ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
-                       HEADERS_FLAG_PADDED)) {
+      } else if (current_frame_flags_ &
+                 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
         VLOG(1) << "Undefined frame flags for PUSH_PROMISE frame: " << hex
                 << static_cast<int>(current_frame_flags_);
         current_frame_flags_ &=
@@ -1010,21 +979,17 @@
       break;
     case HEADERS:
       frame_size_without_variable_data = GetHeadersMinimumSize();
-      if (protocol_version_ == HTTP2) {
-        if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
-          frame_size_without_variable_data += kPadLengthFieldSize;
-        }
-        if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
+      if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
+        frame_size_without_variable_data += kPadLengthFieldSize;
+      }
+      if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
         frame_size_without_variable_data +=
-            kPriorityDependencyPayloadSize +
-            kPriorityWeightPayloadSize;
-        }
+            kPriorityDependencyPayloadSize + kPriorityWeightPayloadSize;
       }
       break;
     case PUSH_PROMISE:
       frame_size_without_variable_data = GetPushPromiseMinimumSize();
-      if (protocol_version_ == HTTP2 &&
-          current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
+      if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
         frame_size_without_variable_data += kPadLengthFieldSize;
       }
       break;
@@ -1079,7 +1044,6 @@
 }
 
 size_t SpdyFramer::GetSerializedLength(
-    const SpdyMajorVersion spdy_version,
     const SpdyHeaderBlock* headers) {
   const size_t num_name_value_pairs_size = sizeof(uint32_t);
   const size_t length_of_name_size = num_name_value_pairs_size;
@@ -1120,14 +1084,12 @@
             set_error(SPDY_INVALID_CONTROL_FRAME);
             return original_len - len;
           }
-          if (protocol_version_ == HTTP2 &&
-              !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
+          if (!(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
               current_frame_type_ == HEADERS) {
             expect_continuation_ = current_frame_stream_id_;
             end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
           }
-          if (protocol_version_ == HTTP2 &&
-              current_frame_flags_ & HEADERS_FLAG_PADDED) {
+          if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
             uint8_t pad_payload_len = 0;
             DCHECK_EQ(remaining_padding_payload_length_, 0u);
             successful_read = reader.ReadUInt8(&pad_payload_len);
@@ -1139,7 +1101,7 @@
           int weight = 0;
           uint32_t parent_stream_id = 0;
           bool exclusive = false;
-          if (protocol_version_ == HTTP2 && has_priority) {
+          if (has_priority) {
             uint32_t stream_dependency;
             successful_read = reader.ReadUInt32(&stream_dependency);
             DCHECK(successful_read);
@@ -1170,14 +1132,12 @@
         break;
       case PUSH_PROMISE:
         {
-          DCHECK_EQ(HTTP2, protocol_version_);
           if (current_frame_stream_id_ == 0) {
             set_error(SPDY_INVALID_CONTROL_FRAME);
             return original_len - len;
           }
           bool successful_read = true;
-          if (protocol_version_ == HTTP2 &&
-              current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
+          if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
             DCHECK_EQ(remaining_padding_payload_length_, 0u);
             uint8_t pad_payload_len = 0;
             successful_read = reader.ReadUInt8(&pad_payload_len);
@@ -1261,8 +1221,7 @@
 // visitor or decompresses and then passes directly to the visitor, via
 // IncrementallyDeliverControlFrameHeaderData()
 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
-                                                  size_t data_len,
-                                                  bool is_hpack_header_block) {
+                                                  size_t data_len) {
   DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
 
   bool processed_successfully = true;
@@ -1278,16 +1237,10 @@
 
   size_t process_bytes = std::min(
       data_len, remaining_data_length_ - remaining_padding_payload_length_);
-  if (is_hpack_header_block) {
-    if (!GetHpackDecoder()->HandleControlFrameHeadersData(data,
-                                                          process_bytes)) {
-      // TODO(jgraettinger): Finer-grained HPACK error codes.
-      set_error(SPDY_DECOMPRESS_FAILURE);
-      processed_successfully = false;
-    }
-  } else if (process_bytes > 0) {
-    processed_successfully = IncrementallyDeliverControlFrameHeaderData(
-        current_frame_stream_id_, data, process_bytes);
+  if (!GetHpackDecoder()->HandleControlFrameHeadersData(data, process_bytes)) {
+    // TODO(jgraettinger): Finer-grained HPACK error codes.
+    set_error(SPDY_DECOMPRESS_FAILURE);
+    processed_successfully = false;
   }
   remaining_data_length_ -= process_bytes;
 
@@ -1295,23 +1248,16 @@
   if (remaining_data_length_ == remaining_padding_payload_length_ &&
       processed_successfully) {
     if (expect_continuation_ == 0) {
-      if (is_hpack_header_block) {
-        size_t compressed_len = 0;
-        if (GetHpackDecoder()->HandleControlFrameHeadersComplete(
-                &compressed_len)) {
-          visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true);
-          if (state_ == SPDY_ERROR) {
-            return data_len;
-          }
-        } else {
-          set_error(SPDY_DECOMPRESS_FAILURE);
-          processed_successfully = false;
-        }
-      } else {
+      size_t compressed_len = 0;
+      if (GetHpackDecoder()->HandleControlFrameHeadersComplete(
+              &compressed_len)) {
         visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true);
         if (state_ == SPDY_ERROR) {
           return data_len;
         }
+      } else {
+        set_error(SPDY_DECOMPRESS_FAILURE);
+        processed_successfully = false;
       }
     }
     if (processed_successfully) {
@@ -1340,8 +1286,7 @@
     remaining_data_length_ -= bytes_read;
   }
   if (remaining_control_header_ == 0) {
-    if (protocol_version_ == HTTP2 &&
-        current_frame_flags_ & SETTINGS_FLAG_ACK) {
+    if (current_frame_flags_ & SETTINGS_FLAG_ACK) {
       visitor_->OnSettingsAck();
       CHANGE_STATE(SPDY_FRAME_COMPLETE);
     } else {
@@ -1417,12 +1362,12 @@
   value = base::NetToHost32(*(reinterpret_cast<const uint32_t*>(data + 2)));
 
   // Validate id.
-  if (!SpdyConstants::IsValidSettingId(protocol_version_, id_field)) {
+  if (!SpdyConstants::IsValidSettingId(id_field)) {
     DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
-    // In HTTP2 we ignore unknown settings for extensibility.
+    // Ignore unknown settings for extensibility.
     return true;
   }
-  id = SpdyConstants::ParseSettingId(protocol_version_, id_field);
+  id = SpdyConstants::ParseSettingId(id_field);
 
   // Validation succeeded. Pass on to visitor.
   visitor_->OnSetting(id, flags, value);
@@ -1443,8 +1388,7 @@
     switch (current_frame_type_) {
       case PING: {
           SpdyPingId id = 0;
-          bool is_ack = protocol_version_ == HTTP2 &&
-                        (current_frame_flags_ & PING_FLAG_ACK);
+          bool is_ack = current_frame_flags_ & PING_FLAG_ACK;
           bool successful_read = true;
           successful_read = reader.ReadUInt64(&id);
           DCHECK(successful_read);
@@ -1463,13 +1407,11 @@
         }
         break;
       case BLOCKED: {
-          DCHECK_EQ(HTTP2, protocol_version_);
           DCHECK(reader.IsDoneReading());
           visitor_->OnBlocked(current_frame_stream_id_);
         }
         break;
       case PRIORITY: {
-          DCHECK_EQ(HTTP2, protocol_version_);
           uint32_t stream_dependency;
           uint32_t parent_stream_id;
           bool exclusive;
@@ -1531,15 +1473,12 @@
       uint32_t status_raw = GOAWAY_OK;
       successful_read = reader.ReadUInt32(&status_raw);
       DCHECK(successful_read);
-      if (SpdyConstants::IsValidGoAwayStatus(protocol_version_, status_raw)) {
-        status =
-            SpdyConstants::ParseGoAwayStatus(protocol_version_, status_raw);
+      if (SpdyConstants::IsValidGoAwayStatus(status_raw)) {
+        status = SpdyConstants::ParseGoAwayStatus(status_raw);
       } else {
-        if (protocol_version_ == HTTP2) {
-          // Treat unrecognized status codes as INTERNAL_ERROR as
-          // recommended by the HTTP/2 spec.
-          status = GOAWAY_INTERNAL_ERROR;
-        }
+        // Treat unrecognized status codes as INTERNAL_ERROR as
+        // recommended by the HTTP/2 spec.
+        status = GOAWAY_INTERNAL_ERROR;
       }
       // Finished parsing the GOAWAY header, call frame handler.
       visitor_->OnGoAway(current_frame_stream_id_, status);
@@ -1592,16 +1531,12 @@
       uint32_t status_raw = status;
       bool successful_read = reader.ReadUInt32(&status_raw);
       DCHECK(successful_read);
-      if (SpdyConstants::IsValidRstStreamStatus(protocol_version_,
-                                                status_raw)) {
-        status =
-            SpdyConstants::ParseRstStreamStatus(protocol_version_, status_raw);
+      if (SpdyConstants::IsValidRstStreamStatus(status_raw)) {
+        status = SpdyConstants::ParseRstStreamStatus(status_raw);
       } else {
-        if (protocol_version_ == HTTP2) {
-          // Treat unrecognized status codes as INTERNAL_ERROR as
-          // recommended by the HTTP/2 spec.
-          status = RST_STREAM_INTERNAL_ERROR;
-        }
+        // Treat unrecognized status codes as INTERNAL_ERROR as
+        // recommended by the HTTP/2 spec.
+        status = RST_STREAM_INTERNAL_ERROR;
       }
       // Finished parsing the RST_STREAM header, call frame handler.
       visitor_->OnRstStream(current_frame_stream_id_, status);
@@ -1795,7 +1730,7 @@
     const char* begin = temp.data();
     const char* end = begin;
     std::advance(end, temp.size());
-    if (protocol_version_ == HTTP2 && std::any_of(begin, end, isupper)) {
+    if (std::any_of(begin, end, isupper)) {
       DVLOG(1) << "Malformed header: Header name " << temp
                << " contains upper-case characters.";
       return false;
@@ -1867,7 +1802,7 @@
       // use GetSerializedLength() for an apples-to-apples comparision of
       // compression performance between HPACK and SPDY w/ deflate.
       size_t debug_payload_len =
-          framer_->GetSerializedLength(HTTP2, &headers_ir_->header_block());
+          framer_->GetSerializedLength(&headers_ir_->header_block());
       framer_->debug_visitor_->OnSendCompressedFrame(headers_ir_->stream_id(),
                                                      HEADERS, debug_payload_len,
                                                      debug_total_size_);
@@ -1901,7 +1836,7 @@
   const size_t size_with_padding = num_padding_fields + data_ir.data_len() +
                                    data_ir.padding_payload_len() +
                                    GetDataFrameMinimumSize();
-  SpdyFrameBuilder builder(size_with_padding, protocol_version_);
+  SpdyFrameBuilder builder(size_with_padding);
   builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id());
   if (data_ir.padded()) {
     builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
@@ -1924,25 +1859,19 @@
 
   size_t frame_size = GetDataFrameMinimumSize();
   size_t num_padding_fields = 0;
-  if (protocol_version_ == HTTP2) {
-    if (data_ir.padded()) {
-      flags |= DATA_FLAG_PADDED;
-      ++num_padding_fields;
-    }
+  if (data_ir.padded()) {
+    flags |= DATA_FLAG_PADDED;
+    ++num_padding_fields;
     frame_size += num_padding_fields;
   }
 
-  SpdyFrameBuilder builder(frame_size, protocol_version_);
+  SpdyFrameBuilder builder(frame_size);
   builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id());
-  if (protocol_version_ == HTTP2) {
-    if (data_ir.padded()) {
-      builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
-    }
-    builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() +
-                                       data_ir.padding_payload_len());
-  } else {
-    builder.OverwriteLength(*this, data_ir.data_len());
+  if (data_ir.padded()) {
+    builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
   }
+  builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() +
+                                     data_ir.padding_payload_len());
   DCHECK_EQ(frame_size, builder.length());
   return builder.take();
 }
@@ -1955,12 +1884,12 @@
   // commented but left in place to simplify future patching.
   // Compute the output buffer size, taking opaque data into account.
   size_t expected_length = GetRstStreamMinimumSize();
-  SpdyFrameBuilder builder(expected_length, protocol_version_);
+  SpdyFrameBuilder builder(expected_length);
 
   builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
 
-  builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
-      protocol_version_, rst_stream.status()));
+  builder.WriteUInt32(
+      SpdyConstants::SerializeRstStreamStatus(rst_stream.status()));
 
   DCHECK_EQ(expected_length, builder.length());
   return builder.take();
@@ -1979,11 +1908,11 @@
   // Size, in bytes, of this SETTINGS frame.
   const size_t size = GetSettingsMinimumSize() +
                       (values->size() * setting_size);
-  SpdyFrameBuilder builder(size, protocol_version_);
+  SpdyFrameBuilder builder(size);
   builder.BeginNewFrame(*this, SETTINGS, flags, 0);
 
   // If this is an ACK, payload should be empty.
-  if (protocol_version_ == HTTP2 && settings.is_ack()) {
+  if (settings.is_ack()) {
     return builder.take();
   }
 
@@ -1991,8 +1920,7 @@
   for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
        it != values->end();
        ++it) {
-    int setting_id =
-        SpdyConstants::SerializeSettingId(protocol_version_, it->first);
+    int setting_id = SpdyConstants::SerializeSettingId(it->first);
     DCHECK_GE(setting_id, 0);
     builder.WriteUInt16(static_cast<uint16_t>(setting_id));
     builder.WriteUInt32(it->second.value);
@@ -2002,7 +1930,7 @@
 }
 
 SpdySerializedFrame SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
-  SpdyFrameBuilder builder(GetPingSize(), protocol_version_);
+  SpdyFrameBuilder builder(GetPingSize());
   uint8_t flags = 0;
   if (ping.is_ack()) {
     flags |= PING_FLAG_ACK;
@@ -2017,10 +1945,8 @@
     const SpdyGoAwayIR& goaway) const {
   // Compute the output buffer size, take opaque data into account.
   size_t expected_length = GetGoAwayMinimumSize();
-  if (protocol_version_ == HTTP2) {
-    expected_length += goaway.description().size();
-  }
-  SpdyFrameBuilder builder(expected_length, protocol_version_);
+  expected_length += goaway.description().size();
+  SpdyFrameBuilder builder(expected_length);
 
   // Serialize the GOAWAY frame.
   builder.BeginNewFrame(*this, GOAWAY, 0, 0);
@@ -2029,11 +1955,10 @@
   builder.WriteUInt32(goaway.last_good_stream_id());
 
   // GOAWAY frames also specify the error status code.
-  builder.WriteUInt32(
-      SpdyConstants::SerializeGoAwayStatus(protocol_version_, goaway.status()));
+  builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(goaway.status()));
 
-  // In HTTP2, GOAWAY frames may also specify opaque data.
-  if ((protocol_version_ == HTTP2) && (goaway.description().size() > 0)) {
+  // GOAWAY frames may also specify opaque data.
+  if (!goaway.description().empty()) {
     builder.WriteBytes(goaway.description().data(),
                        goaway.description().size());
   }
@@ -2047,22 +1972,20 @@
   if (headers.fin()) {
     flags |= CONTROL_FLAG_FIN;
   }
-  if (protocol_version_ == HTTP2) {
-    // This will get overwritten if we overflow into a CONTINUATION frame.
-    flags |= HEADERS_FLAG_END_HEADERS;
-    if (headers.has_priority()) {
-      flags |= HEADERS_FLAG_PRIORITY;
-    }
-    if (headers.padded()) {
-      flags |= HEADERS_FLAG_PADDED;
-    }
+  // This will get overwritten if we overflow into a CONTINUATION frame.
+  flags |= HEADERS_FLAG_END_HEADERS;
+  if (headers.has_priority()) {
+    flags |= HEADERS_FLAG_PRIORITY;
+  }
+  if (headers.padded()) {
+    flags |= HEADERS_FLAG_PADDED;
   }
 
   // The size of this frame, including padding (if there is any) and
   // variable-length header block.
   size_t size = GetHeadersMinimumSize();
 
-  if (protocol_version_ == HTTP2 && headers.padded()) {
+  if (headers.padded()) {
     size += kPadLengthFieldSize;
     size += headers.padding_payload_len();
   }
@@ -2087,7 +2010,7 @@
     flags &= ~HEADERS_FLAG_END_HEADERS;
   }
 
-  SpdyFrameBuilder builder(size, protocol_version_);
+  SpdyFrameBuilder builder(size);
   builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id());
   DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
 
@@ -2109,8 +2032,7 @@
     // HTTP2 uses HPACK for header compression. However, continue to
     // use GetSerializedLength() for an apples-to-apples comparision of
     // compression performance between HPACK and SPDY w/ deflate.
-    const size_t payload_len =
-        GetSerializedLength(protocol_version_, &(headers.header_block()));
+    const size_t payload_len = GetSerializedLength(&(headers.header_block()));
     debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
                                           HEADERS,
                                           payload_len,
@@ -2122,7 +2044,7 @@
 
 SpdySerializedFrame SpdyFramer::SerializeWindowUpdate(
     const SpdyWindowUpdateIR& window_update) const {
-  SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version_);
+  SpdyFrameBuilder builder(GetWindowUpdateSize());
   builder.BeginNewFrame(*this, WINDOW_UPDATE, kNoFlags,
                         window_update.stream_id());
   builder.WriteUInt32(window_update.delta());
@@ -2132,15 +2054,13 @@
 
 SpdySerializedFrame SpdyFramer::SerializeBlocked(
     const SpdyBlockedIR& blocked) const {
-  DCHECK_EQ(HTTP2, protocol_version_);
-  SpdyFrameBuilder builder(GetBlockedSize(), protocol_version_);
+  SpdyFrameBuilder builder(GetBlockedSize());
   builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
   return builder.take();
 }
 
 SpdySerializedFrame SpdyFramer::SerializePushPromise(
     const SpdyPushPromiseIR& push_promise) {
-  DCHECK_EQ(HTTP2, protocol_version_);
   uint8_t flags = 0;
   // This will get overwritten if we overflow into a CONTINUATION frame.
   flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
@@ -2168,7 +2088,7 @@
     flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
   }
 
-  SpdyFrameBuilder builder(size, protocol_version_);
+  SpdyFrameBuilder builder(size);
   builder.BeginNewFrame(*this,
                         PUSH_PROMISE,
                         flags,
@@ -2197,7 +2117,7 @@
     // use GetSerializedLength() for an apples-to-apples comparision of
     // compression performance between HPACK and SPDY w/ deflate.
     const size_t payload_len =
-        GetSerializedLength(protocol_version_, &(push_promise.header_block()));
+        GetSerializedLength(&(push_promise.header_block()));
     debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
                                           PUSH_PROMISE,
                                           payload_len,
@@ -2210,10 +2130,8 @@
 SpdySerializedFrame SpdyFramer::SerializeHeadersGivenEncoding(
     const SpdyHeadersIR& headers,
     const string& encoding) const {
-  DCHECK_EQ(HTTP2, protocol_version_);
-
   size_t frame_size = GetHeaderFrameSizeSansBlock(headers) + encoding.size();
-  SpdyFrameBuilder builder(frame_size, protocol_version_);
+  SpdyFrameBuilder builder(frame_size);
   builder.BeginNewFrame(*this, HEADERS, SerializeHeaderFrameFlags(headers),
                         headers.stream_id());
   DCHECK_EQ(GetFrameHeaderSize(), builder.length());
@@ -2241,11 +2159,9 @@
 
 SpdySerializedFrame SpdyFramer::SerializeContinuation(
     const SpdyContinuationIR& continuation) const {
-  DCHECK_EQ(HTTP2, protocol_version_);
-
   const string& encoding = continuation.encoding();
   size_t frame_size = GetContinuationMinimumSize() + encoding.size();
-  SpdyFrameBuilder builder(frame_size, protocol_version_);
+  SpdyFrameBuilder builder(frame_size);
   uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0;
   builder.BeginNewFrame(*this, CONTINUATION, flags, continuation.stream_id());
   DCHECK_EQ(GetFrameHeaderSize(), builder.length());
@@ -2255,15 +2171,13 @@
 }
 
 SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
-  DCHECK_EQ(HTTP2, protocol_version_);
-
   size_t size = GetAltSvcMinimumSize();
   size += altsvc_ir.origin().length();
   string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
       altsvc_ir.altsvc_vector());
   size += value.length();
 
-  SpdyFrameBuilder builder(size, protocol_version_);
+  SpdyFrameBuilder builder(size);
   builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id());
 
   builder.WriteUInt16(altsvc_ir.origin().length());
@@ -2275,10 +2189,9 @@
 
 SpdySerializedFrame SpdyFramer::SerializePriority(
     const SpdyPriorityIR& priority) const {
-  DCHECK_EQ(HTTP2, protocol_version_);
   size_t size = GetPrioritySize();
 
-  SpdyFrameBuilder builder(size, protocol_version_);
+  SpdyFrameBuilder builder(size);
   builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
 
   builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(),
@@ -2350,7 +2263,6 @@
 }
 
 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
-  DCHECK_EQ(HTTP2, protocol_version_);
   DCHECK_GT(size, kMaxControlFrameSize);
   size_t overflow = size - kMaxControlFrameSize;
   size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
@@ -2444,7 +2356,6 @@
 }
 
 HpackEncoder* SpdyFramer::GetHpackEncoder() {
-  DCHECK_EQ(HTTP2, protocol_version_);
   if (hpack_encoder_.get() == nullptr) {
     hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
   }
@@ -2452,7 +2363,6 @@
 }
 
 HpackDecoderInterface* SpdyFramer::GetHpackDecoder() {
-  DCHECK_EQ(HTTP2, protocol_version_);
   if (hpack_decoder_.get() == nullptr) {
     hpack_decoder_.reset(new HpackDecoder());
   }
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h
index ea6448c..691826f6 100644
--- a/net/spdy/spdy_framer.h
+++ b/net/spdy/spdy_framer.h
@@ -52,15 +52,14 @@
 // Conveniently handles converstion to/from wire format.
 class NET_EXPORT_PRIVATE SettingsFlagsAndId {
  public:
-  static SettingsFlagsAndId FromWireFormat(SpdyMajorVersion version,
-                                           uint32_t wire);
+  static SettingsFlagsAndId FromWireFormat(uint32_t wire);
 
   SettingsFlagsAndId() : flags_(0), id_(0) {}
 
   // TODO(hkhalil): restrict to enums instead of free-form ints.
   SettingsFlagsAndId(uint8_t flags, uint32_t id);
 
-  uint32_t GetWireFormat(SpdyMajorVersion version) const;
+  uint32_t GetWireFormat() const;
 
   uint32_t id() const { return id_; }
   uint8_t flags() const { return flags_; }
@@ -171,14 +170,13 @@
   // Note that header block data is not included. See OnHeaderFrameStart().
   // |stream_id| The stream receiving the header.
   // |has_priority| Whether or not the headers frame included a priority value,
-  //     and, if protocol version == HTTP2, stream dependency info.
+  //     and stream dependency info.
   // |weight| If |has_priority| is true, then weight (in the range [1, 256])
   //     for the receiving stream, otherwise 0.
-  // |parent_stream_id| If |has_priority| is true and protocol
-  //     version == HTTP2, the parent stream of the receiving stream, else 0.
-  // |exclusive| If |has_priority| is true and protocol
-  //     version == HTTP2, the exclusivity of dependence on the parent stream,
-  //     else false.
+  // |parent_stream_id| If |has_priority| is true the parent stream of the
+  //     receiving stream, else 0.
+  // |exclusive| If |has_priority| is true the exclusivity of dependence on the
+  //     parent stream, else false.
   // |fin| Whether FIN flag is set in frame headers.
   // |end| False if HEADERs frame is to be followed by a CONTINUATION frame,
   //     or true if not.
@@ -339,17 +337,14 @@
       const SpdyHeaderBlock& header_block) const;
 
   // Retrieve serialized length of SpdyHeaderBlock.
-  static size_t GetSerializedLength(
-      const SpdyMajorVersion spdy_version,
-      const SpdyHeaderBlock* headers);
+  static size_t GetSerializedLength(const SpdyHeaderBlock* headers);
 
-  // Create a new Framer, provided a SPDY version.
-  explicit SpdyFramer(SpdyMajorVersion version);
+  SpdyFramer();
 
   // Used recursively from the above constructor in order to support
   // instantiating a SpdyFramerDecoderAdapter selected via flags or some other
   // means.
-  SpdyFramer(SpdyMajorVersion version, DecoderAdapterFactoryFn adapter_factory);
+  explicit SpdyFramer(DecoderAdapterFactoryFn adapter_factory);
 
   virtual ~SpdyFramer();
 
@@ -521,8 +516,6 @@
   static const char* StatusCodeToString(int status_code);
   static const char* FrameTypeToString(SpdyFrameType type);
 
-  SpdyMajorVersion protocol_version() const { return protocol_version_; }
-
   // Did the most recent frame header appear to be an HTTP/1.x (or earlier)
   // response (i.e. start with "HTTP/")?
   bool probable_http_response() const;
@@ -614,9 +607,7 @@
   // HPACK data is re-encoded as SPDY3 and re-entrantly delivered through
   // |ProcessControlFrameHeaderBlock()|. |is_hpack_header_block| controls
   // whether data is treated as HPACK- vs SPDY3-encoded.
-  size_t ProcessControlFrameHeaderBlock(const char* data,
-                                        size_t len,
-                                        bool is_hpack_header_block);
+  size_t ProcessControlFrameHeaderBlock(const char* data, size_t len);
   size_t ProcessDataFramePaddingLength(const char* data, size_t len);
   size_t ProcessFramePadding(const char* data, size_t len);
   size_t ProcessDataFramePayload(const char* data, size_t len);
@@ -766,9 +757,6 @@
   // Optional decoder to use instead of this instance.
   std::unique_ptr<SpdyFramerDecoderAdapter> decoder_adapter_;
 
-  // The protocol version to be spoken/understood by this framer.
-  const SpdyMajorVersion protocol_version_;
-
   // The flags field of the frame currently being read.
   uint8_t current_frame_flags_;
 
diff --git a/net/spdy/spdy_framer_decoder_adapter.cc b/net/spdy/spdy_framer_decoder_adapter.cc
index 8275201..83a479e7 100644
--- a/net/spdy/spdy_framer_decoder_adapter.cc
+++ b/net/spdy/spdy_framer_decoder_adapter.cc
@@ -184,7 +184,7 @@
 
  public:
   explicit NestedSpdyFramerDecoder(SpdyFramer* outer)
-      : framer_(HTTP2, nullptr), outer_(outer) {
+      : framer_(nullptr), outer_(outer) {
     DVLOG(1) << PRETTY_THIS;
   }
   ~NestedSpdyFramerDecoder() override { DVLOG(1) << PRETTY_THIS; }
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
index 707059f1e..96f1799 100644
--- a/net/spdy/spdy_framer_test.cc
+++ b/net/spdy/spdy_framer_test.cc
@@ -67,7 +67,7 @@
     CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
     CHECK_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer->state());
     framer->set_visitor(nullptr);
-    SpdyFramer serializer(framer->protocol_version());
+    SpdyFramer serializer;
     serializer.set_enable_compression(false);
     return serializer.SerializeFrame(visitor.GetFrame());
   }
@@ -270,9 +270,8 @@
   // are too long can spill over into CONTINUATION frames.
   static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
 
-  explicit TestSpdyVisitor(SpdyMajorVersion version)
-      : framer_(version),
-        use_compression_(false),
+  TestSpdyVisitor()
+      : use_compression_(false),
         error_count_(0),
         headers_frame_count_(0),
         push_promise_frame_count_(0),
@@ -514,9 +513,7 @@
   void InitHeaderStreaming(SpdyFrameType header_control_type,
                            SpdyStreamId stream_id) {
     if (!SpdyConstants::IsValidFrameType(
-            framer_.protocol_version(),
-            SpdyConstants::SerializeFrameType(framer_.protocol_version(),
-                                              header_control_type))) {
+            SpdyConstants::SerializeFrameType(header_control_type))) {
       DLOG(FATAL) << "Attempted to init header streaming with "
                   << "invalid control frame type: " << header_control_type;
     }
@@ -605,8 +602,7 @@
 
   uint8_t serialized_type;
   reader.ReadUInt8(&serialized_type);
-  SpdyFrameType type =
-      SpdyConstants::ParseFrameType(framer.protocol_version(), serialized_type);
+  SpdyFrameType type = SpdyConstants::ParseFrameType(serialized_type);
   DCHECK_EQ(HEADERS, type);
   uint8_t flags;
   reader.ReadUInt8(&flags);
@@ -637,14 +633,11 @@
         reinterpret_cast<const unsigned char*>(actual_frame.data()),
         actual_frame.size());
   }
-
-  // Version of SPDY protocol to be used.
-  SpdyMajorVersion spdy_version_ = HTTP2;
 };
 
 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
 TEST_F(SpdyFramerTest, HeaderBlockInBuffer) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
 
   // Encode the header block into a Headers frame.
@@ -654,7 +647,7 @@
   headers.SetHeader("cookie", "key1=value1; key2=value2");
   SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(&framer, headers));
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
                            frame.size());
@@ -665,7 +658,7 @@
 
 // Test that if there's not a full frame, we fail to parse it.
 TEST_F(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
 
   // Encode the header block into a Headers frame.
@@ -674,7 +667,7 @@
   headers.SetHeader("gamma", "charlie");
   SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(&framer, headers));
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
                            frame.size() - 2);
@@ -686,17 +679,17 @@
 // Test that we treat incoming upper-case or mixed-case header values as
 // malformed.
 TEST_F(SpdyFramerTest, RejectUpperCaseHeaderBlockValue) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
 
-  SpdyFrameBuilder frame(1024, spdy_version_);
+  SpdyFrameBuilder frame(1024);
   frame.BeginNewFrame(framer, HEADERS, 0, 1);
   frame.WriteUInt32(1);
   frame.WriteStringPiece32("Name1");
   frame.WriteStringPiece32("value1");
   frame.RewriteLength(framer);
 
-  SpdyFrameBuilder frame2(1024, spdy_version_);
+  SpdyFrameBuilder frame2(1024);
   frame2.BeginNewFrame(framer, HEADERS, 0, 1);
   frame2.WriteUInt32(2);
   frame2.WriteStringPiece32("name1");
@@ -721,7 +714,7 @@
 // Test that we can encode and decode stream dependency values in a header
 // frame.
 TEST_F(SpdyFramerTest, HeaderStreamDependencyValues) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
 
   const SpdyStreamId parent_stream_id_test_array[] = {0, 3};
@@ -735,7 +728,7 @@
       SpdySerializedFrame frame(
           SpdyFramerPeer::SerializeHeaders(&framer, headers));
 
-      TestSpdyVisitor visitor(spdy_version_);
+      TestSpdyVisitor visitor;
       visitor.use_compression_ = false;
       visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
                                frame.size());
@@ -751,7 +744,7 @@
 // advertised max size, we do not set an error in ProcessInput.
 TEST_F(SpdyFramerTest, AcceptMaxFrameSizeSetting) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // DATA frame with maximum allowed payload length.
@@ -776,7 +769,7 @@
 // advertised max size, we set an error of SPDY_INVALID_CONTROL_FRAME_SIZE.
 TEST_F(SpdyFramerTest, ExceedMaxFrameSizeSetting) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // DATA frame with too large payload length.
@@ -802,7 +795,7 @@
 // payload length, we set an error of SPDY_INVALID_PADDING
 TEST_F(SpdyFramerTest, OversizedDataPaddingError) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // DATA frame with invalid padding length.
@@ -837,7 +830,7 @@
 // payload length, we do not set an error of SPDY_INVALID_PADDING
 TEST_F(SpdyFramerTest, CorrectlySizedDataPaddingNoError) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // DATA frame with valid Padding length
@@ -872,7 +865,7 @@
 // payload length, we set an error of SPDY_INVALID_PADDING
 TEST_F(SpdyFramerTest, OversizedHeadersPaddingError) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // HEADERS frame with invalid padding length.
@@ -904,7 +897,7 @@
 // than the payload length, we do not set an error of SPDY_INVALID_PADDING
 TEST_F(SpdyFramerTest, CorrectlySizedHeadersPaddingNoError) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // HEADERS frame with invalid Padding length
@@ -931,7 +924,7 @@
 // (but don't crash).
 TEST_F(SpdyFramerTest, DataWithStreamIdZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   const char bytes[] = "hello";
@@ -950,7 +943,7 @@
 // (but don't crash).
 TEST_F(SpdyFramerTest, HeadersWithStreamIdZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyHeadersIR headers(0);
@@ -969,7 +962,7 @@
 // (but don't crash).
 TEST_F(SpdyFramerTest, PriorityWithStreamIdZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyPriorityIR priority_ir(0, 1, 16, true);
@@ -987,7 +980,7 @@
 // (but don't crash).
 TEST_F(SpdyFramerTest, RstStreamWithStreamIdZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyRstStreamIR rst_stream_ir(0, RST_STREAM_PROTOCOL_ERROR);
@@ -1005,7 +998,7 @@
 // we signal an error (but don't crash).
 TEST_F(SpdyFramerTest, SettingsWithStreamIdNotZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // Settings frame with invalid StreamID of 0x01
@@ -1032,7 +1025,7 @@
 // we signal an error (but don't crash).
 TEST_F(SpdyFramerTest, GoawayWithStreamIdNotZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // GOAWAY frame with invalid StreamID of 0x01
@@ -1060,7 +1053,7 @@
 // SPDY_INVALID_STREAM_ID.
 TEST_F(SpdyFramerTest, ContinuationWithStreamIdZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyContinuationIR continuation(0);
@@ -1082,7 +1075,7 @@
 // SPDY_INVALID_STREAM_ID.
 TEST_F(SpdyFramerTest, PushPromiseWithStreamIdZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyPushPromiseIR push_promise(0, 4);
@@ -1101,7 +1094,7 @@
 // signal SPDY_INVALID_STREAM_ID.
 TEST_F(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyPushPromiseIR push_promise(3, 0);
@@ -1117,9 +1110,9 @@
 }
 
 TEST_F(SpdyFramerTest, DuplicateHeader) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   // Frame builder with plentiful buffer size.
-  SpdyFrameBuilder frame(1024, spdy_version_);
+  SpdyFrameBuilder frame(1024);
   frame.BeginNewFrame(framer, HEADERS, 0, 3);
 
   frame.WriteUInt32(2);  // Number of headers.
@@ -1140,9 +1133,9 @@
 }
 
 TEST_F(SpdyFramerTest, MultiValueHeader) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   // Frame builder with plentiful buffer size.
-  SpdyFrameBuilder frame(1024, spdy_version_);
+  SpdyFrameBuilder frame(1024);
   frame.BeginNewFrame(framer, HEADERS,
                       HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, 3);
   frame.WriteUInt32(0);   // Priority exclusivity and dependent stream.
@@ -1162,7 +1155,7 @@
   framer.set_enable_compression(false);
   SpdySerializedFrame control_frame(frame.take());
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
@@ -1183,7 +1176,7 @@
   headers.SetHeader("content-length", "12");
   headers.SetHeader("x-empty-header", "");
 
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(true);
   SpdySerializedFrame frame1(
       SpdyFramerPeer::SerializeHeaders(&framer, headers));
@@ -1253,7 +1246,7 @@
   };
   // frame-format on
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
 
   EXPECT_EQ(24, visitor.data_bytes_);
@@ -1303,7 +1296,7 @@
   };
   // frame-format on
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
 
   EXPECT_EQ(0, visitor.error_count_);
@@ -1334,7 +1327,7 @@
   };
   // frame-format on
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
 
   EXPECT_EQ(0, visitor.error_count_);
@@ -1349,7 +1342,7 @@
 // Verify we can decompress the stream even if handed over to the
 // framer 1 byte at a time.
 TEST_F(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   framer.set_enable_compression(true);
 
@@ -1370,7 +1363,7 @@
   SpdySerializedFrame send_frame(framer.SerializeData(data_ir));
 
   // Run the inputs through the framer.
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = true;
   const unsigned char* data;
   data = reinterpret_cast<const unsigned char*>(headers_frame.data());
@@ -1394,7 +1387,7 @@
 }
 
 TEST_F(SpdyFramerTest, WindowUpdateFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdySerializedFrame frame(
       framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 0x12345678)));
 
@@ -1411,7 +1404,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreateDataFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   {
     const char kDescription[] = "'hello' data frame, no FIN";
@@ -1613,7 +1606,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreateRstStream) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   {
     const char kDescription[] = "RST_STREAM frame";
@@ -1659,7 +1652,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreateSettings) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   {
     const char kDescription[] = "Network byte order SETTINGS frame";
@@ -1706,19 +1699,19 @@
     };
 
     SpdySettingsIR settings_ir;
-    settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
+    settings_ir.AddSetting(SpdyConstants::ParseSettingId(1),
                            false,  // persist
                            false,  // persisted
                            5);
-    settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
+    settings_ir.AddSetting(SpdyConstants::ParseSettingId(2),
                            false,  // persist
                            false,  // persisted
                            6);
-    settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
+    settings_ir.AddSetting(SpdyConstants::ParseSettingId(3),
                            false,  // persist
                            false,  // persisted
                            7);
-    settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
+    settings_ir.AddSetting(SpdyConstants::ParseSettingId(4),
                            false,  // persist
                            false,  // persisted
                            8);
@@ -1743,7 +1736,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreatePingFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   {
     const char kDescription[] = "PING frame";
@@ -1780,7 +1773,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreateGoAway) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   {
     const char kDescription[] = "GOAWAY frame";
@@ -1816,7 +1809,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreateHeadersUncompressed) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
 
   {
@@ -2068,7 +2061,7 @@
 // to workaround http://crbug.com/139744.
 #if !defined(USE_SYSTEM_ZLIB)
 TEST_F(SpdyFramerTest, CreateHeadersCompressed) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(true);
 
   {
@@ -2083,7 +2076,7 @@
 #endif  // !defined(USE_SYSTEM_ZLIB)
 
 TEST_F(SpdyFramerTest, CreateWindowUpdate) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   {
     const char kDescription[] = "WINDOW_UPDATE frame";
@@ -2129,11 +2122,11 @@
 }
 
 TEST_F(SpdyFramerTest, SerializeBlocked) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   const char kDescription[] = "BLOCKED frame";
-  const unsigned char kType = static_cast<unsigned char>(
-      SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
+  const unsigned char kType =
+      static_cast<unsigned char>(SpdyConstants::SerializeFrameType(BLOCKED));
   const unsigned char kFrameData[] = {
       0x00,  0x00, 0x00,        // Length: 0
       kType,                    //   Type: BLOCKED
@@ -2146,7 +2139,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreateBlocked) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   const char kDescription[] = "BLOCKED frame";
   const SpdyStreamId kStreamId = 3;
@@ -2162,7 +2155,7 @@
 TEST_F(SpdyFramerTest, CreatePushPromiseUncompressed) {
   {
     // Test framing PUSH_PROMISE without padding.
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_enable_compression(false);
     const char kDescription[] = "PUSH_PROMISE frame without padding";
 
@@ -2197,7 +2190,7 @@
 
   {
     // Test framing PUSH_PROMISE with one byte of padding.
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_enable_compression(false);
     const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
 
@@ -2234,7 +2227,7 @@
 
   {
     // Test framing PUSH_PROMISE with 177 bytes of padding.
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_enable_compression(false);
     const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
 
@@ -2292,7 +2285,7 @@
 
 // Regression test for https://crbug.com/464748.
 TEST_F(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   EXPECT_EQ(1u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
                     &framer, 16383 + 16374));
   EXPECT_EQ(2u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
@@ -2304,7 +2297,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreateContinuationUncompressed) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
   const char kDescription[] = "CONTINUATION frame";
 
@@ -2348,7 +2341,7 @@
 // we signal an error (but don't crash).
 TEST_F(SpdyFramerTest, SendUnexpectedContinuation) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   // frame-format off
@@ -2387,7 +2380,7 @@
     // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
     // padding, cannot hold all the data payload, which is overflowed to the
     // consecutive CONTINUATION frame.
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_enable_compression(false);
     const char kDescription[] =
         "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
@@ -2484,11 +2477,11 @@
 }
 
 TEST_F(SpdyFramerTest, CreateAltSvc) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   const char kDescription[] = "ALTSVC frame";
-  const char kType = static_cast<unsigned char>(
-      SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
+  const char kType =
+      static_cast<unsigned char>(SpdyConstants::SerializeFrameType(ALTSVC));
   const unsigned char kFrameData[] = {
       0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o',
       'r',  'i',  'g',  'i',   'n',  'p',  'i',  'd',  '1',  '=',  '"',  'h',
@@ -2509,7 +2502,7 @@
 }
 
 TEST_F(SpdyFramerTest, CreatePriority) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   const char kDescription[] = "PRIORITY frame";
   const unsigned char kFrameData[] = {
@@ -2532,13 +2525,13 @@
 }
 
 TEST_F(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdyHeadersIR headers_ir(1);
   headers_ir.SetHeader("alpha", "beta");
   headers_ir.SetHeader("gamma", "delta");
   SpdySerializedFrame control_frame(
       SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = true;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
@@ -2551,14 +2544,14 @@
 }
 
 TEST_F(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdyHeadersIR headers_ir(1);
   headers_ir.set_fin(true);
   headers_ir.SetHeader("alpha", "beta");
   headers_ir.SetHeader("gamma", "delta");
   SpdySerializedFrame control_frame(
       SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = true;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
@@ -2571,7 +2564,7 @@
 }
 
 TEST_F(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
   SpdyHeadersIR headers(1);
   headers.set_padding_len(256);
@@ -2586,7 +2579,7 @@
   EXPECT_GT(control_frame.size(),
             TestSpdyVisitor::sent_control_frame_max_size());
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
       control_frame.size());
@@ -2598,7 +2591,7 @@
 }
 
 TEST_F(SpdyFramerTest, MultipleContinuationFramesWithIterator) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
   auto headers = base::MakeUnique<SpdyHeadersIR>(1);
   headers->set_padding_len(256);
@@ -2618,7 +2611,7 @@
   EXPECT_EQ(headers_frame.size(),
             TestSpdyVisitor::sent_control_frame_max_size());
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(headers_frame.data()),
       headers_frame.size());
@@ -2660,7 +2653,7 @@
 }
 
 TEST_F(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_enable_compression(false);
   SpdyPushPromiseIR push_promise(1, 2);
   push_promise.set_padding_len(256);
@@ -2674,7 +2667,7 @@
   EXPECT_GT(control_frame.size(),
             TestSpdyVisitor::sent_control_frame_max_size());
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
       control_frame.size());
@@ -2694,13 +2687,13 @@
       TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
   const size_t kBigValueSize = kHeaderBufferSize * 2;
   string big_value(kBigValueSize, 'x');
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdyHeadersIR headers(1);
   headers.set_fin(true);
   headers.SetHeader("aa", big_value);
   SpdySerializedFrame control_frame(
       SpdyFramerPeer::SerializeHeaders(&framer, headers));
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.set_header_buffer_size(kHeaderBufferSize);
   visitor.use_compression_ = true;
   visitor.SimulateInFramer(
@@ -2713,7 +2706,7 @@
 }
 
 TEST_F(SpdyFramerTest, ControlFrameSizesAreValidated) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   // Create a GoAway frame that has a few extra bytes at the end.
   // We create enough overhead to overflow the framer's control frame buffer.
   ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
@@ -2721,9 +2714,9 @@
 
   // HTTP/2 GOAWAY frames are only bound by a minimal length, since they may
   // carry opaque data. Verify that minimal length is tested.
-  ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetFrameHeaderSize());
+  ASSERT_GT(framer.GetGoAwayMinimumSize(), SpdyConstants::kFrameHeaderSize);
   const size_t less_than_min_length =
-      framer.GetGoAwayMinimumSize() - framer.GetFrameHeaderSize() - 1;
+      framer.GetGoAwayMinimumSize() - SpdyConstants::kFrameHeaderSize - 1;
   ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
   const unsigned char kH2Len = static_cast<unsigned char>(less_than_min_length);
   const unsigned char kH2FrameData[] = {
@@ -2735,9 +2728,9 @@
       0x00, 0x00, 0x00,          // Truncated Status Field
   };
   const size_t pad_length =
-      length + framer.GetFrameHeaderSize() - sizeof(kH2FrameData);
+      length + SpdyConstants::kFrameHeaderSize - sizeof(kH2FrameData);
   string pad(pad_length, 'A');
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
 
   visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
   visitor.SimulateInFramer(reinterpret_cast<const unsigned char*>(pad.c_str()),
@@ -2751,11 +2744,11 @@
 }
 
 TEST_F(SpdyFramerTest, ReadZeroLenSettingsFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdySettingsIR settings_ir;
   SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
-  SetFrameLength(&control_frame, 0, spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SetFrameLength(&control_frame, 0);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
@@ -2766,7 +2759,7 @@
 
 // Tests handling of SETTINGS frames with invalid length.
 TEST_F(SpdyFramerTest, ReadBogusLenSettingsFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdySettingsIR settings_ir;
 
   // Add a setting to pad the frame so that we don't get a buffer overflow when
@@ -2775,8 +2768,8 @@
                          0x00000002);
   SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
   const size_t kNewLength = 14;
-  SetFrameLength(&control_frame, kNewLength, spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SetFrameLength(&control_frame, kNewLength);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
@@ -2791,24 +2784,24 @@
 
 // Tests handling of SETTINGS frames larger than the frame buffer size.
 TEST_F(SpdyFramerTest, ReadLargeSettingsFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdySettingsIR settings_ir;
-  settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
+  settings_ir.AddSetting(SpdyConstants::ParseSettingId(1),
                          false,  // persist
                          false,  // persisted
                          5);
-  settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
+  settings_ir.AddSetting(SpdyConstants::ParseSettingId(2),
                          false,  // persist
                          false,  // persisted
                          6);
-  settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
+  settings_ir.AddSetting(SpdyConstants::ParseSettingId(3),
                          false,  // persist
                          false,  // persisted
                          7);
 
   SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
   EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame.size());
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
 
   // Read all at once.
@@ -2838,7 +2831,7 @@
 
 // Tests handling of SETTINGS frame with duplicate entries.
 TEST_F(SpdyFramerTest, ReadDuplicateSettings) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   const unsigned char kH2FrameData[] = {
       0x00, 0x00, 0x12,        // Length: 18
@@ -2853,7 +2846,7 @@
       0x00, 0x00, 0x00, 0x03,  //  Value: 3
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
 
@@ -2866,7 +2859,7 @@
 
 // Tests handling of SETTINGS frame with a setting we don't recognize.
 TEST_F(SpdyFramerTest, ReadUnknownSettingsId) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   const unsigned char kH2FrameData[] = {
       0x00, 0x00, 0x06,        // Length: 6
       0x04,                    //   Type: SETTINGS
@@ -2876,7 +2869,7 @@
       0x00, 0x00, 0x00, 0x02,  //  Value: 2
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
 
@@ -2887,7 +2880,7 @@
 
 // Tests handling of SETTINGS frame with entries out of order.
 TEST_F(SpdyFramerTest, ReadOutOfOrderSettings) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   const unsigned char kH2FrameData[] = {
       0x00, 0x00, 0x12,        // Length: 18
       0x04,                    //   Type: SETTINGS
@@ -2901,7 +2894,7 @@
       0x00, 0x00, 0x00, 0x03,  //  Value: 3
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
 
@@ -2911,7 +2904,7 @@
 }
 
 TEST_F(SpdyFramerTest, ProcessSettingsAckFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   const unsigned char kFrameData[] = {
       0x00, 0x00, 0x00,        // Length: 0
@@ -2920,7 +2913,7 @@
       0x00, 0x00, 0x00, 0x00,  // Stream: 0
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
 
@@ -2934,7 +2927,7 @@
   const char data_payload[] = "hello";
 
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyDataIR data_ir(1, data_payload);
@@ -2988,10 +2981,10 @@
 }
 
 TEST_F(SpdyFramerTest, ReadWindowUpdate) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdySerializedFrame control_frame(
       framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(
       reinterpret_cast<unsigned char*>(control_frame.data()),
       control_frame.size());
@@ -3000,12 +2993,12 @@
 }
 
 TEST_F(SpdyFramerTest, ReadCompressedPushPromise) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdyPushPromiseIR push_promise(42, 57);
   push_promise.SetHeader("foo", "bar");
   push_promise.SetHeader("bar", "foofoo");
   SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = true;
   visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
                            frame.size());
@@ -3056,8 +3049,8 @@
   };
   // frame-format on
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kInput, sizeof(kInput));
 
   EXPECT_EQ(0, visitor.error_count_);
@@ -3112,8 +3105,8 @@
   };
   // frame-format on
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kInput, sizeof(kInput));
 
   EXPECT_EQ(0, visitor.error_count_);
@@ -3160,8 +3153,8 @@
   };
   // frame-format on
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kInput, sizeof(kInput));
 
   EXPECT_EQ(0, visitor.error_count_);
@@ -3201,8 +3194,8 @@
       0x67, 0x00, 0x06, 0x63,  //
   };
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   // Assume the unknown frame is allowed
   visitor.on_unknown_frame_result_ = true;
   framer.set_visitor(&visitor);
@@ -3238,8 +3231,8 @@
       0x67, 0x00, 0x06, 0x63,  //
   };
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   framer.set_visitor(&visitor);
   visitor.SimulateInFramer(kInput, sizeof(kInput));
 
@@ -3263,8 +3256,8 @@
       0x3d, 0x62, 0x61, 0x72,  //
   };
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   framer.set_visitor(&visitor);
   visitor.SimulateInFramer(kInput, sizeof(kInput));
 
@@ -3294,8 +3287,8 @@
       0xde, 0xad, 0xbe, 0xef,  // Truncated Frame Header
   };
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   framer.set_visitor(&visitor);
   visitor.SimulateInFramer(kInput, sizeof(kInput));
 
@@ -3329,8 +3322,8 @@
       0x3d, 0x62, 0x61, 0x72,  //
   };
 
-  SpdyFramer framer(spdy_version_);
-  TestSpdyVisitor visitor(spdy_version_);
+  SpdyFramer framer;
+  TestSpdyVisitor visitor;
   framer.set_visitor(&visitor);
   visitor.SimulateInFramer(kInput, sizeof(kInput));
 
@@ -3344,17 +3337,17 @@
 }
 
 TEST_F(SpdyFramerTest, ReadGarbage) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   unsigned char garbage_frame[256];
   memset(garbage_frame, ~0, sizeof(garbage_frame));
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
   EXPECT_EQ(1, visitor.error_count_);
 }
 
 TEST_F(SpdyFramerTest, ReadUnknownExtensionFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
 
   // The unrecognized frame type should still have a valid length.
   const unsigned char unknown_frame[] = {
@@ -3365,7 +3358,7 @@
       0xff, 0xff, 0xff, 0xff,  // Payload
       0xff, 0xff, 0xff, 0xff,  //
   };
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
 
   // Simulate the case where the stream id validation checks out.
   visitor.on_unknown_frame_result_ = true;
@@ -3376,7 +3369,7 @@
   // Follow it up with a valid control frame to make sure we handle
   // subsequent frames correctly.
   SpdySettingsIR settings_ir;
-  settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
+  settings_ir.AddSetting(SpdyConstants::ParseSettingId(1),
                          false,  // persist
                          false,  // persisted
                          10);
@@ -3390,7 +3383,7 @@
 }
 
 TEST_F(SpdyFramerTest, ReadGarbageWithValidLength) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   const unsigned char kFrameData[] = {
       0x00, 0x00, 0x08,        // Length: 8
       0xff,                    //   Type: UnknownFrameType(255)
@@ -3399,7 +3392,7 @@
       0xff, 0xff, 0xff, 0xff,  // Payload
       0xff, 0xff, 0xff, 0xff,  //
   };
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
   visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
   EXPECT_EQ(1, visitor.error_count_);
@@ -3419,13 +3412,13 @@
       0xff,                    //
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kInput, arraysize(kInput));
   EXPECT_EQ(1, visitor.error_count_);
 }
 
 TEST_F(SpdyFramerTest, SizesTest) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
   EXPECT_EQ(9u, framer.GetFrameHeaderSize());
   EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
@@ -3550,12 +3543,12 @@
                                     << static_cast<int>(flags));
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
 
     SpdyDataIR data_ir(1, "hello");
     SpdySerializedFrame frame(framer.SerializeData(data_ir));
-    SetFrameFlags(&frame, flags, spdy_version_);
+    SetFrameFlags(&frame, flags);
 
     if (flags & ~valid_data_flags) {
       EXPECT_CALL(visitor, OnError(_));
@@ -3599,12 +3592,12 @@
                                     << static_cast<int>(flags));
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
 
     SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL);
     SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
-    SetFrameFlags(&frame, flags, spdy_version_);
+    SetFrameFlags(&frame, flags);
 
     EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
 
@@ -3623,13 +3616,13 @@
                                     << static_cast<int>(flags));
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
 
     SpdySettingsIR settings_ir;
     settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
     SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
-    SetFrameFlags(&frame, flags, spdy_version_);
+    SetFrameFlags(&frame, flags);
 
     if (flags & SETTINGS_FLAG_ACK) {
       EXPECT_CALL(visitor, OnError(_));
@@ -3661,12 +3654,12 @@
                                     << static_cast<int>(flags));
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
 
     SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
     SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
-    SetFrameFlags(&frame, flags, spdy_version_);
+    SetFrameFlags(&frame, flags);
 
     EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
 
@@ -3684,7 +3677,7 @@
                                     << static_cast<int>(flags));
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
 
     SpdyHeadersIR headers_ir(57);
@@ -3698,7 +3691,7 @@
     SpdySerializedFrame frame(
         SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
     uint8_t set_flags = flags & ~HEADERS_FLAG_PADDED;
-    SetFrameFlags(&frame, set_flags, spdy_version_);
+    SetFrameFlags(&frame, set_flags);
 
     // Expected callback values
     SpdyStreamId stream_id = 57;
@@ -3741,11 +3734,11 @@
                                     << static_cast<int>(flags));
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
 
     SpdySerializedFrame frame(framer.SerializePing(SpdyPingIR(42)));
-    SetFrameFlags(&frame, flags, spdy_version_);
+    SetFrameFlags(&frame, flags);
 
     if (flags & PING_FLAG_ACK) {
       EXPECT_CALL(visitor, OnPing(42, true));
@@ -3767,12 +3760,12 @@
                                     << static_cast<int>(flags));
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
 
     SpdySerializedFrame frame(
         framer.SerializeWindowUpdate(SpdyWindowUpdateIR(4, 1024)));
-    SetFrameFlags(&frame, flags, spdy_version_);
+    SetFrameFlags(&frame, flags);
 
     EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
 
@@ -3793,7 +3786,7 @@
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
     testing::StrictMock<test::MockDebugVisitor> debug_visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
     framer.set_debug_visitor(&debug_visitor);
 
@@ -3805,7 +3798,7 @@
     SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
     // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
     // and implement framing.
-    SetFrameFlags(&frame, flags & ~HEADERS_FLAG_PADDED, spdy_version_);
+    SetFrameFlags(&frame, flags & ~HEADERS_FLAG_PADDED);
 
     bool end = flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
     EXPECT_CALL(debug_visitor,
@@ -3831,7 +3824,7 @@
 
     testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
     testing::StrictMock<test::MockDebugVisitor> debug_visitor;
-    SpdyFramer framer(spdy_version_);
+    SpdyFramer framer;
     framer.set_visitor(&visitor);
     framer.set_debug_visitor(&debug_visitor);
 
@@ -3844,11 +3837,11 @@
     headers_ir.SetHeader("foo", "bar");
     SpdySerializedFrame frame0(
         SpdyFramerPeer::SerializeHeaders(&framer, headers_ir));
-    SetFrameFlags(&frame0, 0, spdy_version_);
+    SetFrameFlags(&frame0, 0);
 
     SpdyContinuationIR continuation(42);
     SpdySerializedFrame frame(framer.SerializeContinuation(continuation));
-    SetFrameFlags(&frame, flags, spdy_version_);
+    SetFrameFlags(&frame, flags);
 
     EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
     EXPECT_CALL(visitor, OnContinuation(42, flags & HEADERS_FLAG_END_HEADERS));
@@ -3875,10 +3868,10 @@
   const uint32_t kWireFormat = base::HostToNet32(0x01020304);
 
   SettingsFlagsAndId id_and_flags =
-      SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
+      SettingsFlagsAndId::FromWireFormat(kWireFormat);
   EXPECT_EQ(kId, id_and_flags.id());
   EXPECT_EQ(kFlags, id_and_flags.flags());
-  EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
+  EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat());
 }
 
 // Test handling of a RST_STREAM with out-of-bounds status codes.
@@ -3899,7 +3892,7 @@
   };
 
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_NO_ERROR));
@@ -3921,7 +3914,7 @@
 
 // Test handling of GOAWAY frames with out-of-bounds status code.
 TEST_F(SpdyFramerTest, GoAwayStatusBounds) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   const unsigned char kH2FrameData[] = {
       0x00, 0x00, 0x0a,        // Length: 10
       0x07,                    //   Type: GOAWAY
@@ -3954,7 +3947,7 @@
   };
 
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
@@ -3969,7 +3962,7 @@
   const SpdyStreamId kStreamId = 0;
 
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   EXPECT_CALL(visitor, OnBlocked(kStreamId));
@@ -3987,7 +3980,7 @@
   const SpdyStreamId kStreamId = 1;
 
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyAltSvcWireFormat::AlternativeService altsvc1(
@@ -4016,7 +4009,7 @@
   const SpdyStreamId kStreamId = 1;
 
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyAltSvcWireFormat::AlternativeService altsvc1(
@@ -4041,7 +4034,7 @@
 
 TEST_F(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
@@ -4064,7 +4057,7 @@
   const SpdyStreamId kStreamId = 1;
 
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_visitor(&visitor);
 
   SpdyAltSvcWireFormat::AlternativeService altsvc(
@@ -4086,7 +4079,7 @@
 
 // Tests handling of ALTSVC frames delivered in small chunks.
 TEST_F(SpdyFramerTest, ReadChunkedAltSvcFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdyAltSvcIR altsvc_ir(1);
   SpdyAltSvcWireFormat::AlternativeService altsvc1(
       "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
@@ -4096,7 +4089,7 @@
   altsvc_ir.add_altsvc(altsvc2);
 
   SpdySerializedFrame control_frame(framer.SerializeAltSvc(altsvc_ir));
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.use_compression_ = false;
 
   // Read data in small chunks.
@@ -4120,7 +4113,7 @@
 
 // Tests handling of PRIORITY frames.
 TEST_F(SpdyFramerTest, ReadPriority) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   SpdyPriorityIR priority(3, 1, 256, false);
   SpdySerializedFrame frame(framer.SerializePriority(priority));
   testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
@@ -4146,7 +4139,7 @@
       0x00, 0x00, 0x00, 0x01,  // Priority (Truncated)
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
 
   EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -4166,7 +4159,7 @@
       0x00, 0x00, 0x00, 0x01,  // Ping (Truncated)
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
 
   EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -4186,7 +4179,7 @@
       0x00, 0x00, 0x01,        // WindowUpdate (Truncated)
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
 
   EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -4206,7 +4199,7 @@
       0x00, 0x00, 0x01,        // RstStream (Truncated)
   };
 
-  TestSpdyVisitor visitor(spdy_version_);
+  TestSpdyVisitor visitor;
   visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
 
   EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
@@ -4218,8 +4211,8 @@
 // Test that SpdyFramer processes, by default, all passed input in one call
 // to ProcessInput (i.e. will not be calling set_process_single_input_frame()).
 TEST_F(SpdyFramerTest, ProcessAllInput) {
-  SpdyFramer framer(spdy_version_);
-  std::unique_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
+  SpdyFramer framer;
+  std::unique_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor);
   framer.set_visitor(visitor.get());
 
   // Create two input frames.
@@ -4267,7 +4260,7 @@
 // only processes the first when we give it the first frame split at any point,
 // or give it more than one frame in the input buffer.
 TEST_F(SpdyFramerTest, ProcessAtMostOneFrame) {
-  SpdyFramer framer(spdy_version_);
+  SpdyFramer framer;
   framer.set_process_single_input_frame(true);
   std::unique_ptr<TestSpdyVisitor> visitor;
 
@@ -4305,7 +4298,7 @@
 
   for (size_t first_size = 0; first_size <= buf_size; ++first_size) {
     VLOG(1) << "first_size = " << first_size;
-    visitor.reset(new TestSpdyVisitor(spdy_version_));
+    visitor.reset(new TestSpdyVisitor);
     framer.set_visitor(visitor.get());
 
     EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
diff --git a/net/spdy/spdy_headers_block_parser.cc b/net/spdy/spdy_headers_block_parser.cc
index 6eb16fb..5e6bc6f5 100644
--- a/net/spdy/spdy_headers_block_parser.cc
+++ b/net/spdy/spdy_headers_block_parser.cc
@@ -23,7 +23,6 @@
 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024;
 
 SpdyHeadersBlockParser::SpdyHeadersBlockParser(
-    SpdyMajorVersion spdy_version,
     SpdyHeadersHandlerInterface* handler)
     : state_(READING_HEADER_BLOCK_LEN),
       max_headers_in_block_(MaxNumberOfHeaders()),
@@ -31,8 +30,7 @@
       remaining_key_value_pairs_for_frame_(0),
       handler_(handler),
       stream_id_(kInvalidStreamId),
-      error_(NO_PARSER_ERROR),
-      spdy_version_(spdy_version) {
+      error_(NO_PARSER_ERROR) {
   // The handler that we set must not be NULL.
   DCHECK(handler_ != NULL);
 }
diff --git a/net/spdy/spdy_headers_block_parser.h b/net/spdy/spdy_headers_block_parser.h
index 6050591..1ad7ddf 100644
--- a/net/spdy/spdy_headers_block_parser.h
+++ b/net/spdy/spdy_headers_block_parser.h
@@ -29,8 +29,7 @@
 
   // Constructor. The handler's OnHeader will be called for every key
   // value pair that we parsed from the headers block.
-  SpdyHeadersBlockParser(SpdyMajorVersion spdy_version,
-                         SpdyHeadersHandlerInterface* handler);
+  explicit SpdyHeadersBlockParser(SpdyHeadersHandlerInterface* handler);
 
   virtual ~SpdyHeadersBlockParser();
 
@@ -57,8 +56,6 @@
   };
   ParserError get_error() const { return error_; }
 
-  SpdyMajorVersion spdy_version() const { return spdy_version_; }
-
   // Returns the maximal number of headers in a SPDY headers block.
   static size_t MaxNumberOfHeaders();
 
@@ -113,8 +110,6 @@
   SpdyStreamId stream_id_;
 
   ParserError error_;
-
-  const SpdyMajorVersion spdy_version_;
 };
 
 }  // namespace net
diff --git a/net/spdy/spdy_headers_block_parser_test.cc b/net/spdy/spdy_headers_block_parser_test.cc
index 44d8e7a..00f8fc4 100644
--- a/net/spdy/spdy_headers_block_parser_test.cc
+++ b/net/spdy/spdy_headers_block_parser_test.cc
@@ -35,15 +35,14 @@
   MOCK_METHOD2(OnHeader, void(StringPiece key, StringPiece value));
 };
 
-class SpdyHeadersBlockParserTest :
-    public ::testing::TestWithParam<SpdyMajorVersion> {
+class SpdyHeadersBlockParserTest : public ::testing::Test {
  public:
   ~SpdyHeadersBlockParserTest() override {}
 
  protected:
   void SetUp() override {
     // Create a parser using the mock handler.
-    parser_.reset(new SpdyHeadersBlockParser(HTTP2, &handler_));
+    parser_.reset(new SpdyHeadersBlockParser(&handler_));
   }
 
   // Create a header block with a specified number of headers.
@@ -225,7 +224,7 @@
     EXPECT_EQ(SpdyHeadersBlockParser::HEADER_BLOCK_TOO_LARGE,
               parser_->get_error());
   }
-  parser_.reset(new SpdyHeadersBlockParser(HTTP2, &handler_));
+  parser_.reset(new SpdyHeadersBlockParser(&handler_));
   // Header block with one header, which has a too-long key.
   {
     string headers = EncodeLength(1) + EncodeLength(
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index cb82d444..7b8a859 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -3239,9 +3239,9 @@
   SpdySerializedFrame reply_wrong_length(
       spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
   size_t right_size =
-      reply_wrong_length.size() - SpdyConstants::GetFrameHeaderSize(HTTP2);
+      reply_wrong_length.size() - SpdyConstants::kFrameHeaderSize;
   size_t wrong_size = right_size - 4;
-  test::SetFrameLength(&reply_wrong_length, wrong_size, HTTP2);
+  test::SetFrameLength(&reply_wrong_length, wrong_size);
 
   MockRead reads[] = {
       MockRead(ASYNC, reply_wrong_length.data(), reply_wrong_length.size() - 4,
@@ -3287,7 +3287,7 @@
   // Read WINDOW_UPDATE with incorrectly-sized payload.
   SpdySerializedFrame bad_window_update(
       spdy_util_.ConstructSpdyWindowUpdate(1, 1));
-  test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1, HTTP2);
+  test::SetFrameLength(&bad_window_update, bad_window_update.size() - 1);
   MockRead reads[] = {CreateMockRead(bad_window_update, 1)};
 
   SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
diff --git a/net/spdy/spdy_protocol.cc b/net/spdy/spdy_protocol.cc
index b9d84ec..6970ce7 100644
--- a/net/spdy/spdy_protocol.cc
+++ b/net/spdy/spdy_protocol.cc
@@ -45,29 +45,27 @@
   return static_cast<SpdyPriority>(7.f - (weight - 1) / kSteps);
 }
 
-bool SpdyConstants::IsValidFrameType(SpdyMajorVersion version,
-                                     int frame_type_field) {
+bool SpdyConstants::IsValidFrameType(int frame_type_field) {
   // Check for recognized extensions.
-  if (frame_type_field == SerializeFrameType(version, ALTSVC) ||
-      frame_type_field == SerializeFrameType(version, BLOCKED)) {
+  if (frame_type_field == SerializeFrameType(ALTSVC) ||
+      frame_type_field == SerializeFrameType(BLOCKED)) {
     return true;
   }
 
   // DATA is the first valid frame.
-  if (frame_type_field < SerializeFrameType(version, DATA)) {
+  if (frame_type_field < SerializeFrameType(DATA)) {
     return false;
   }
 
   // CONTINUATION is the last valid frame.
-  if (frame_type_field > SerializeFrameType(version, CONTINUATION)) {
+  if (frame_type_field > SerializeFrameType(CONTINUATION)) {
     return false;
   }
 
   return true;
 }
 
-SpdyFrameType SpdyConstants::ParseFrameType(SpdyMajorVersion /*version*/,
-                                            int frame_type_field) {
+SpdyFrameType SpdyConstants::ParseFrameType(int frame_type_field) {
   switch (frame_type_field) {
     case 0:
       return DATA;
@@ -98,11 +96,10 @@
   return DATA;
 }
 
-int SpdyConstants::SerializeFrameType(SpdyMajorVersion /*version*/,
-                                      SpdyFrameType frame_type) {
+int SpdyConstants::SerializeFrameType(SpdyFrameType frame_type) {
   switch (frame_type) {
     case DATA:
-      return 0;
+      return kDataFrameType;
     case HEADERS:
       return 1;
     case PRIORITY:
@@ -132,10 +129,6 @@
   }
 }
 
-int SpdyConstants::DataFrameType(SpdyMajorVersion version) {
-  return SerializeFrameType(version, DATA);
-}
-
 bool SpdyConstants::IsValidHTTP2FrameStreamId(
     SpdyStreamId current_frame_stream_id,
     SpdyFrameType frame_type_field) {
@@ -165,25 +158,21 @@
   }
 }
 
-bool SpdyConstants::IsValidSettingId(SpdyMajorVersion version,
-                                     int setting_id_field) {
+bool SpdyConstants::IsValidSettingId(int setting_id_field) {
   // HEADER_TABLE_SIZE is the first valid setting id.
-  if (setting_id_field <
-      SerializeSettingId(version, SETTINGS_HEADER_TABLE_SIZE)) {
+  if (setting_id_field < SerializeSettingId(SETTINGS_HEADER_TABLE_SIZE)) {
     return false;
   }
 
   // MAX_HEADER_LIST_SIZE is the last valid setting id.
-  if (setting_id_field >
-      SerializeSettingId(version, SETTINGS_MAX_HEADER_LIST_SIZE)) {
+  if (setting_id_field > SerializeSettingId(SETTINGS_MAX_HEADER_LIST_SIZE)) {
     return false;
   }
 
   return true;
 }
 
-SpdySettingsIds SpdyConstants::ParseSettingId(SpdyMajorVersion /*version*/,
-                                              int setting_id_field) {
+SpdySettingsIds SpdyConstants::ParseSettingId(int setting_id_field) {
   switch (setting_id_field) {
     case 1:
       return SETTINGS_HEADER_TABLE_SIZE;
@@ -202,8 +191,7 @@
   return SETTINGS_UPLOAD_BANDWIDTH;
 }
 
-int SpdyConstants::SerializeSettingId(SpdyMajorVersion /*version*/,
-                                      SpdySettingsIds id) {
+int SpdyConstants::SerializeSettingId(SpdySettingsIds id) {
   switch (id) {
     case SETTINGS_HEADER_TABLE_SIZE:
       return 1;
@@ -223,11 +211,9 @@
   }
 }
 
-bool SpdyConstants::IsValidRstStreamStatus(SpdyMajorVersion version,
-                                           int rst_stream_status_field) {
+bool SpdyConstants::IsValidRstStreamStatus(int rst_stream_status_field) {
   // NO_ERROR is the first valid status code.
-  if (rst_stream_status_field <
-      SerializeRstStreamStatus(version, RST_STREAM_NO_ERROR)) {
+  if (rst_stream_status_field < SerializeRstStreamStatus(RST_STREAM_NO_ERROR)) {
     return false;
   }
 
@@ -244,7 +230,7 @@
 
   // HTTP_1_1_REQUIRED is the last valid status code.
   if (rst_stream_status_field >
-      SerializeRstStreamStatus(version, RST_STREAM_HTTP_1_1_REQUIRED)) {
+      SerializeRstStreamStatus(RST_STREAM_HTTP_1_1_REQUIRED)) {
     return false;
   }
 
@@ -252,7 +238,6 @@
 }
 
 SpdyRstStreamStatus SpdyConstants::ParseRstStreamStatus(
-    SpdyMajorVersion /*version*/,
     int rst_stream_status_field) {
   switch (rst_stream_status_field) {
     case 0:
@@ -286,7 +271,6 @@
 }
 
 int SpdyConstants::SerializeRstStreamStatus(
-    SpdyMajorVersion /*version*/,
     SpdyRstStreamStatus rst_stream_status) {
   switch (rst_stream_status) {
     case RST_STREAM_NO_ERROR:
@@ -319,24 +303,21 @@
   }
 }
 
-bool SpdyConstants::IsValidGoAwayStatus(SpdyMajorVersion version,
-                                        int goaway_status_field) {
+bool SpdyConstants::IsValidGoAwayStatus(int goaway_status_field) {
   // GOAWAY_NO_ERROR is the first valid status.
-  if (goaway_status_field < SerializeGoAwayStatus(version, GOAWAY_NO_ERROR)) {
+  if (goaway_status_field < SerializeGoAwayStatus(GOAWAY_NO_ERROR)) {
     return false;
   }
 
   // GOAWAY_HTTP_1_1_REQUIRED is the last valid status.
-  if (goaway_status_field >
-      SerializeGoAwayStatus(version, GOAWAY_HTTP_1_1_REQUIRED)) {
+  if (goaway_status_field > SerializeGoAwayStatus(GOAWAY_HTTP_1_1_REQUIRED)) {
     return false;
   }
 
   return true;
 }
 
-SpdyGoAwayStatus SpdyConstants::ParseGoAwayStatus(SpdyMajorVersion /*version*/,
-                                                  int goaway_status_field) {
+SpdyGoAwayStatus SpdyConstants::ParseGoAwayStatus(int goaway_status_field) {
   switch (goaway_status_field) {
     case 0:
       return GOAWAY_NO_ERROR;
@@ -372,8 +353,7 @@
   return GOAWAY_PROTOCOL_ERROR;
 }
 
-int SpdyConstants::SerializeGoAwayStatus(SpdyMajorVersion /*version*/,
-                                         SpdyGoAwayStatus status) {
+int SpdyConstants::SerializeGoAwayStatus(SpdyGoAwayStatus status) {
   switch (status) {
     case GOAWAY_NO_ERROR:
       return 0;
@@ -409,47 +389,24 @@
   }
 }
 
-size_t SpdyConstants::GetFrameHeaderSize(SpdyMajorVersion /*version*/) {
-  return 9;
-}
+const int SpdyConstants::kDataFrameType = 0;
 
-size_t SpdyConstants::GetDataFrameMinimumSize(SpdyMajorVersion version) {
-  return GetFrameHeaderSize(version);
-}
+const size_t SpdyConstants::kFrameHeaderSize = 9;
 
-size_t SpdyConstants::GetMaxFrameSizeLimit(SpdyMajorVersion version) {
-  return kSpdyMaxFrameSizeLimit + GetFrameHeaderSize(version);
-}
+const size_t SpdyConstants::kDataFrameMinimumSize = kFrameHeaderSize;
 
-size_t SpdyConstants::GetSizeOfSizeField() {
-  return sizeof(uint32_t);
-}
+const size_t SpdyConstants::kMaxFrameSizeLimit =
+    kSpdyMaxFrameSizeLimit + kFrameHeaderSize;
 
-size_t SpdyConstants::GetPerHeaderOverhead(SpdyMajorVersion version) {
-  return (version == net::HTTP2) ? 32 : 0;
-}
+const size_t SpdyConstants::kSizeOfSizeField = sizeof(uint32_t);
 
-size_t SpdyConstants::GetSettingSize(SpdyMajorVersion version) {
-  return 6;
-}
+const size_t SpdyConstants::kPerHeaderOverhead = 32;
 
-int32_t SpdyConstants::GetInitialStreamWindowSize(SpdyMajorVersion version) {
-  return 64 * 1024 - 1;
-}
+const int32_t SpdyConstants::kInitialStreamWindowSize = 64 * 1024 - 1;
 
-int32_t SpdyConstants::GetInitialSessionWindowSize(SpdyMajorVersion version) {
-  return 64 * 1024 - 1;
-}
+const int32_t SpdyConstants::kInitialSessionWindowSize = 64 * 1024 - 1;
 
-std::string SpdyConstants::GetVersionString(SpdyMajorVersion version) {
-  switch (version) {
-    case HTTP2:
-      return "h2";
-    default:
-      SPDY_BUG << "Unsupported SPDY major version: " << version;
-      return "h2";
-  }
-}
+const char SpdyConstants::kHttp2Npn[] = "h2";
 
 SpdyFrameWithHeaderBlockIR::SpdyFrameWithHeaderBlockIR(
     SpdyStreamId stream_id,
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h
index dc906045..481abba 100644
--- a/net/spdy/spdy_protocol.h
+++ b/net/spdy/spdy_protocol.h
@@ -31,15 +31,7 @@
 
 namespace net {
 
-// The major versions of SPDY. Major version differences indicate
-// framer-layer incompatibility, as opposed to minor version numbers
-// which indicate application-layer incompatibility. It is NOT guaranteed
-// that the enum value SPDYn maps to the integer n.
-enum SpdyMajorVersion {
-  HTTP2 = 2,
-};
-
-// A SPDY stream id is a 31 bit entity.
+// A stream id is a 31 bit entity.
 typedef uint32_t SpdyStreamId;
 
 // Specifies the stream ID used to denote the current session (for
@@ -259,24 +251,16 @@
  public:
   // Returns true if a given on-the-wire enumeration of a frame type is valid
   // for a given protocol version, false otherwise.
-  static bool IsValidFrameType(SpdyMajorVersion version, int frame_type_field);
+  static bool IsValidFrameType(int frame_type_field);
 
-  // Parses a frame type from an on-the-wire enumeration of a given protocol
-  // version.
+  // Parses a frame type from an on-the-wire enumeration.
   // Behavior is undefined for invalid frame type fields; consumers should first
   // use IsValidFrameType() to verify validity of frame type fields.
-  static SpdyFrameType ParseFrameType(SpdyMajorVersion version,
-                                      int frame_type_field);
+  static SpdyFrameType ParseFrameType(int frame_type_field);
 
-  // Serializes a given frame type to the on-the-wire enumeration value for the
-  // given protocol version.
-  // Returns -1 on failure (I.E. Invalid frame type for the given version).
-  static int SerializeFrameType(SpdyMajorVersion version,
-                                SpdyFrameType frame_type);
-
-  // Returns the frame type for non-control (i.e. data) frames
-  // in the given SPDY version.
-  static int DataFrameType(SpdyMajorVersion version);
+  // Serializes a given frame type to the on-the-wire enumeration value.
+  // Returns -1 on failure (I.E. Invalid frame type).
+  static int SerializeFrameType(SpdyFrameType frame_type);
 
   // (HTTP/2) All standard frame types except WINDOW_UPDATE are
   // (stream-specific xor connection-level). Returns false iff we know
@@ -285,86 +269,65 @@
                                         SpdyFrameType frame_type_field);
 
   // Returns true if a given on-the-wire enumeration of a setting id is valid
-  // for a given protocol version, false otherwise.
-  static bool IsValidSettingId(SpdyMajorVersion version, int setting_id_field);
+  // false otherwise.
+  static bool IsValidSettingId(int setting_id_field);
 
-  // Parses a setting id from an on-the-wire enumeration of a given protocol
-  // version.
+  // Parses a setting id from an on-the-wire enumeration
   // Behavior is undefined for invalid setting id fields; consumers should first
   // use IsValidSettingId() to verify validity of setting id fields.
-  static SpdySettingsIds ParseSettingId(SpdyMajorVersion version,
-                                        int setting_id_field);
+  static SpdySettingsIds ParseSettingId(int setting_id_field);
 
-  // Serializes a given setting id to the on-the-wire enumeration value for the
-  // given protocol version.
-  // Returns -1 on failure (I.E. Invalid setting id for the given version).
-  static int SerializeSettingId(SpdyMajorVersion version, SpdySettingsIds id);
+  // Serializes a given setting id to the on-the-wire enumeration value.
+  // Returns -1 on failure (I.E. Invalid setting id).
+  static int SerializeSettingId(SpdySettingsIds id);
 
   // Returns true if a given on-the-wire enumeration of a RST_STREAM status code
-  // is valid for a given protocol version, false otherwise.
-  static bool IsValidRstStreamStatus(SpdyMajorVersion version,
-                                     int rst_stream_status_field);
+  // is valid, false otherwise.
+  static bool IsValidRstStreamStatus(int rst_stream_status_field);
 
-  // Parses a RST_STREAM status code from an on-the-wire enumeration of a given
-  // protocol version.
+  // Parses a RST_STREAM status code from an on-the-wire enumeration.
   // Behavior is undefined for invalid RST_STREAM status code fields; consumers
   // should first use IsValidRstStreamStatus() to verify validity of RST_STREAM
   // status code fields..
-  static SpdyRstStreamStatus ParseRstStreamStatus(SpdyMajorVersion version,
-                                                  int rst_stream_status_field);
+  static SpdyRstStreamStatus ParseRstStreamStatus(int rst_stream_status_field);
 
   // Serializes a given RST_STREAM status code to the on-the-wire enumeration
-  // value for the given protocol version.
+  // value.
   // Returns -1 on failure (I.E. Invalid RST_STREAM status code for the given
   // version).
-  static int SerializeRstStreamStatus(SpdyMajorVersion version,
-                                      SpdyRstStreamStatus rst_stream_status);
+  static int SerializeRstStreamStatus(SpdyRstStreamStatus rst_stream_status);
 
   // Returns true if a given on-the-wire enumeration of a GOAWAY status code is
-  // valid for the given protocol version, false otherwise.
-  static bool IsValidGoAwayStatus(SpdyMajorVersion version,
-                                  int goaway_status_field);
+  // valid, false otherwise.
+  static bool IsValidGoAwayStatus(int goaway_status_field);
 
-  // Parses a GOAWAY status from an on-the-wire enumeration of a given protocol
-  // version.
+  // Parses a GOAWAY status from an on-the-wire enumeration.
   // Behavior is undefined for invalid GOAWAY status fields; consumers should
   // first use IsValidGoAwayStatus() to verify validity of GOAWAY status fields.
-  static SpdyGoAwayStatus ParseGoAwayStatus(SpdyMajorVersion version,
-                                            int goaway_status_field);
+  static SpdyGoAwayStatus ParseGoAwayStatus(int goaway_status_field);
 
-  // Serializes a given GOAWAY status to the on-the-wire enumeration value for
-  // the given protocol version.
+  // Serializes a given GOAWAY status to the on-the-wire enumeration value.
   // Returns -1 on failure (I.E. Invalid GOAWAY status for the given version).
-  static int SerializeGoAwayStatus(SpdyMajorVersion version,
-                                   SpdyGoAwayStatus status);
+  static int SerializeGoAwayStatus(SpdyGoAwayStatus status);
 
-  // Size, in bytes, of the data frame header. Future versions of SPDY
-  // will likely vary this, so we allow for the flexibility of a function call
-  // for this value as opposed to a constant.
-  static size_t GetDataFrameMinimumSize(SpdyMajorVersion version);
-
+  // Frame type for non-control (i.e. data) frames.
+  static const int kDataFrameType;
+  // Size, in bytes, of the data frame header.
+  static const size_t kDataFrameMinimumSize;
   // Number of octets in the frame header.
-  static size_t GetFrameHeaderSize(SpdyMajorVersion version);
-
+  static const size_t kFrameHeaderSize;
   // Maximum possible configurable size of a frame in octets.
-  static size_t GetMaxFrameSizeLimit(SpdyMajorVersion version);
-
-  // Returns the size of a header block size field. Valid only for SPDY 3.
-  static size_t GetSizeOfSizeField();
-
-  // Returns the per-header overhead for block size accounting in bytes.
-  static size_t GetPerHeaderOverhead(SpdyMajorVersion version);
-
-  // Returns the size (in bytes) of a wire setting ID and value.
-  static size_t GetSettingSize(SpdyMajorVersion version);
-
+  static const size_t kMaxFrameSizeLimit;
+  // Size of a header block size field. Valid only for SPDY 3.
+  static const size_t kSizeOfSizeField;
+  // Per-header overhead for block size accounting in bytes.
+  static const size_t kPerHeaderOverhead;
   // Initial window size for a stream in bytes.
-  static int32_t GetInitialStreamWindowSize(SpdyMajorVersion version);
-
+  static const int32_t kInitialStreamWindowSize;
   // Initial window size for a session in bytes.
-  static int32_t GetInitialSessionWindowSize(SpdyMajorVersion version);
-
-  static std::string GetVersionString(SpdyMajorVersion version);
+  static const int32_t kInitialSessionWindowSize;
+  // The NPN string for HTTP2, "h2".
+  static const char kHttp2Npn[];
 };
 
 // Variant type (i.e. tagged union) that is either a SPDY 3.x priority value,
@@ -465,7 +428,7 @@
 
 class SpdyFrameVisitor;
 
-// Intermediate representation for SPDY frames.
+// Intermediate representation for HTTP2 frames.
 class NET_EXPORT_PRIVATE SpdyFrameIR {
  public:
   virtual ~SpdyFrameIR() {}
@@ -685,7 +648,6 @@
   explicit SpdyPingIR(SpdyPingId id) : id_(id), is_ack_(false) {}
   SpdyPingId id() const { return id_; }
 
-  // ACK logic is valid only for SPDY versions 4 and above.
   bool is_ack() const { return is_ack_; }
   void set_is_ack(bool is_ack) { is_ack_ = is_ack; }
 
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 0a9072d..37f3c525 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -144,7 +144,7 @@
     uint32_t value,
     NetLogCaptureMode /* capture_mode */) {
   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
-  dict->SetInteger("id", SpdyConstants::SerializeSettingId(HTTP2, id));
+  dict->SetInteger("id", SpdyConstants::SerializeSettingId(id));
   dict->SetInteger("flags", flags);
   dict->SetInteger("value", value);
   return std::move(dict);
@@ -161,8 +161,8 @@
     const SpdySettingsFlags flags = it->second.first;
     const uint32_t value = it->second.second;
     settings_list->AppendString(base::StringPrintf(
-        "[id:%u flags:%u value:%u]",
-        SpdyConstants::SerializeSettingId(HTTP2, id), flags, value));
+        "[id:%u flags:%u value:%u]", SpdyConstants::SerializeSettingId(id),
+        flags, value));
   }
   dict->Set("settings", std::move(settings_list));
   return std::move(dict);
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index 64d0f8e..ce3ec46 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -1281,7 +1281,7 @@
   EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
 
   int64_t reply_frame_len = reply.size();
-  int64_t data_header_len = SpdyConstants::GetDataFrameMinimumSize(HTTP2);
+  int64_t data_header_len = SpdyConstants::kDataFrameMinimumSize;
   int64_t data_frame_len = data_header_len + kPostBodyLength;
   int64_t response_len = reply_frame_len + data_frame_len;
 
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 37d2453..15d61736 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -686,11 +686,7 @@
   pool_->stream_max_recv_window_size_ = window;
 }
 
-SpdyTestUtil::SpdyTestUtil()
-    : headerless_spdy_framer_(HTTP2),
-      request_spdy_framer_(HTTP2),
-      response_spdy_framer_(HTTP2),
-      default_url_(GURL(kDefaultUrl)) {}
+SpdyTestUtil::SpdyTestUtil() : default_url_(GURL(kDefaultUrl)) {}
 
 SpdyTestUtil::~SpdyTestUtil() {}
 
@@ -1056,7 +1052,7 @@
 
 SpdySerializedFrame SpdyTestUtil::ConstructSpdyDataFrame(int stream_id,
                                                          bool fin) {
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   SpdyDataIR data_ir(stream_id,
                      base::StringPiece(kUploadData, kUploadDataSize));
   data_ir.set_fin(fin);
@@ -1067,7 +1063,7 @@
                                                          const char* data,
                                                          uint32_t len,
                                                          bool fin) {
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
   data_ir.set_fin(fin);
   return SpdySerializedFrame(framer.SerializeData(data_ir));
@@ -1078,7 +1074,7 @@
                                                          uint32_t len,
                                                          bool fin,
                                                          int padding_length) {
-  SpdyFramer framer(HTTP2);
+  SpdyFramer framer;
   SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
   data_ir.set_fin(fin);
   data_ir.set_padding_len(padding_length);
diff --git a/net/spdy/spdy_test_utils.cc b/net/spdy/spdy_test_utils.cc
index 70084e9..16d39db 100644
--- a/net/spdy/spdy_test_utils.cc
+++ b/net/spdy/spdy_test_utils.cc
@@ -94,15 +94,11 @@
       << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
 }
 
-void SetFrameFlags(SpdySerializedFrame* frame,
-                   uint8_t flags,
-                   SpdyMajorVersion spdy_version) {
+void SetFrameFlags(SpdySerializedFrame* frame, uint8_t flags) {
   frame->data()[4] = flags;
 }
 
-void SetFrameLength(SpdySerializedFrame* frame,
-                    size_t length,
-                    SpdyMajorVersion spdy_version) {
+void SetFrameLength(SpdySerializedFrame* frame, size_t length) {
   CHECK_GT(1u << 14, length);
   {
     int32_t wire_length = base::HostToNet32(length);
diff --git a/net/spdy/spdy_test_utils.h b/net/spdy/spdy_test_utils.h
index 8e68a49c4..eb27d66f 100644
--- a/net/spdy/spdy_test_utils.h
+++ b/net/spdy/spdy_test_utils.h
@@ -42,13 +42,9 @@
     const unsigned char* expected,
     const int expected_len);
 
-void SetFrameFlags(SpdySerializedFrame* frame,
-                   uint8_t flags,
-                   SpdyMajorVersion spdy_version);
+void SetFrameFlags(SpdySerializedFrame* frame, uint8_t flags);
 
-void SetFrameLength(SpdySerializedFrame* frame,
-                    size_t length,
-                    SpdyMajorVersion spdy_version);
+void SetFrameLength(SpdySerializedFrame* frame, size_t length);
 
 std::string a2b_hex(const char* hex_data);
 
diff --git a/net/tools/quic/chlo_extractor.h b/net/tools/quic/chlo_extractor.h
index 7820bb5..176ad047 100644
--- a/net/tools/quic/chlo_extractor.h
+++ b/net/tools/quic/chlo_extractor.h
@@ -6,7 +6,7 @@
 #define NET_TOOLS_QUIC_CHLO_EXTRACTOR_H_
 
 #include "net/quic/core/crypto/crypto_handshake_message.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index f84531f..a8f0909 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -26,7 +26,7 @@
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packet_creator.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/quic_session.h"
 #include "net/quic/core/quic_utils.h"
@@ -44,7 +44,7 @@
 #include "net/test/gtest_util.h"
 #include "net/tools/epoll_server/epoll_server.h"
 #include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_packet_writer_wrapper.h"
 #include "net/tools/quic/quic_server.h"
 #include "net/tools/quic/quic_simple_server_stream.h"
@@ -429,7 +429,7 @@
 
     auto test_server = new QuicTestServer(
         CryptoTestUtils::ProofSourceForTesting(), server_config_,
-        server_supported_versions_, &in_memory_cache_);
+        server_supported_versions_, &response_cache_);
     server_thread_.reset(new ServerThread(test_server, server_address_));
     if (chlo_multiplier_ != 0) {
       server_thread_->server()->SetChloMultiplier(chlo_multiplier_);
@@ -466,8 +466,8 @@
   }
 
   void AddToCache(StringPiece path, int response_code, StringPiece body) {
-    in_memory_cache_.AddSimpleResponse(server_hostname_, path, response_code,
-                                       body);
+    response_cache_.AddSimpleResponse(server_hostname_, path, response_code,
+                                      body);
   }
 
   void SetPacketLossPercentage(int32_t loss) {
@@ -557,7 +557,7 @@
   bool initialized_;
   QuicSocketAddress server_address_;
   string server_hostname_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
   std::unique_ptr<ServerThread> server_thread_;
   std::unique_ptr<QuicTestClient> client_;
   PacketDroppingTestWriter* client_writer_;
@@ -581,7 +581,7 @@
 
 TEST_P(EndToEndTest, HandshakeSuccessful) {
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   QuicCryptoStream* crypto_stream =
       QuicSessionPeer::GetCryptoStream(client_->client()->session());
   QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(crypto_stream);
@@ -729,11 +729,10 @@
 TEST_P(EndToEndTest, LargePostNoPacketLoss) {
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // 1 MB body.
-  string body;
-  GenerateBody(&body, 1024 * 1024);
+  string body(1024 * 1024, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -751,11 +750,10 @@
   ASSERT_TRUE(Initialize());
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(1000));
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // 100 KB body.
-  string body;
-  GenerateBody(&body, 100 * 1024);
+  string body(100 * 1024, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -779,12 +777,11 @@
   ASSERT_TRUE(Initialize());
 
   // Wait for the server SHLO before upping the packet loss.
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   SetPacketLossPercentage(30);
 
   // 10 KB body.
-  string body;
-  GenerateBody(&body, 1024 * 10);
+  string body(1024 * 10, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -807,13 +804,12 @@
   ASSERT_TRUE(Initialize());
 
   // Wait for the server SHLO before upping the packet loss.
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   SetPacketLossPercentage(10);
   client_writer_->set_fake_blocked_socket_percentage(10);
 
   // 10 KB body.
-  string body;
-  GenerateBody(&body, 1024 * 10);
+  string body(1024 * 10, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -827,14 +823,13 @@
 TEST_P(EndToEndTest, LargePostNoPacketLossWithDelayAndReordering) {
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   // Both of these must be called when the writer is not actively used.
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
   SetReorderPercentage(30);
 
   // 1 MB body.
-  string body;
-  GenerateBody(&body, 1024 * 1024);
+  string body(1024 * 1024, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -850,8 +845,7 @@
   // a 0-RTT handshake for the next request.
   ASSERT_TRUE(Initialize());
 
-  string body;
-  GenerateBody(&body, 20480);
+  string body(20480, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -961,8 +955,7 @@
   // a 0-RTT handshake for the next request.
   ASSERT_TRUE(Initialize());
 
-  string body;
-  GenerateBody(&body, 20480);
+  string body(20480, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -1034,7 +1027,7 @@
       initial_received_options));
 
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   EXPECT_FALSE(server_config_.SetInitialReceivedConnectionOptions(
@@ -1059,11 +1052,10 @@
   server_writer_->set_max_bandwidth_and_buffer_size(
       QuicBandwidth::FromBytesPerSecond(256 * 1024), 256 * 1024);
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // 1 MB body.
-  string body;
-  GenerateBody(&body, 1024 * 1024);
+  string body(1024 * 1024, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -1084,7 +1076,7 @@
   // an infinite loop in the EpollServer, as the alarm fires and is immediately
   // rescheduled.
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Ensure both stream and connection level are flow control blocked by setting
   // the send window offset to 0.
@@ -1119,10 +1111,9 @@
 
 TEST_P(EndToEndTest, InvalidStream) {
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
-  string body;
-  GenerateBody(&body, kMaxPacketSize);
+  string body(kMaxPacketSize, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -1142,10 +1133,9 @@
 // to send a request with overly large headers.
 TEST_P(EndToEndTest, LargeHeaders) {
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
-  string body;
-  GenerateBody(&body, kMaxPacketSize);
+  string body(kMaxPacketSize, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -1168,10 +1158,9 @@
 
 TEST_P(EndToEndTest, EarlyResponseWithQuicStreamNoError) {
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
-  string large_body;
-  GenerateBody(&large_body, 1024 * 1024);
+  string large_body(1024 * 1024, 'a');
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
@@ -1224,7 +1213,7 @@
   // Negotiate 1 max open stream.
   client_config_.SetMaxStreamsPerConnection(1, 1);
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   if (negotiated_version_ > QUIC_VERSION_34) {
     // Newer versions use max incoming dynamic streams.
@@ -1262,7 +1251,7 @@
   server_config_.SetMaxIncomingDynamicStreamsToSend(
       kServerMaxIncomingDynamicStreams);
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   if (negotiated_version_ <= QUIC_VERSION_34) {
     // Earlier versions negotiated max open streams.
@@ -1303,7 +1292,7 @@
   server_config_.SetMaxIncomingDynamicStreamsToSend(
       kServerMaxIncomingDynamicStreams);
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   if (negotiated_version_ <= QUIC_VERSION_34) {
     // Earlier versions negotiated max open streams.
@@ -1328,7 +1317,7 @@
   // static_cast here does not work.
   FLAGS_quic_enable_multipath = false;
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   CongestionControlType expected_congestion_control_type = kReno;
   switch (GetParam().congestion_control_tag) {
@@ -1362,7 +1351,7 @@
   client_config_.SetMaxStreamsPerConnection(10, 5);
 
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   if (negotiated_version_ > QUIC_VERSION_34) {
     // No negotiated max streams beyond version 34.
     return;
@@ -1377,7 +1366,7 @@
   client_config_.SetInitialRoundTripTimeUsToSend(kInitialRTT);
 
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   // Pause the server so we can access the server's internals without races.
@@ -1404,7 +1393,7 @@
                                                  kMaxInitialRoundTripTimeUs);
 
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   // Pause the server so we can access the server's internals without races.
@@ -1434,7 +1423,7 @@
   client_config_.SetInitialRoundTripTimeUsToSend(0);
 
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   // Pause the server so we can access the server's internals without races.
@@ -1518,13 +1507,12 @@
     SetPacketLossPercentage(1);
   }
   ASSERT_TRUE(Initialize());
-  string large_body;
-  GenerateBody(&large_body, 10240);
+  string large_body(10240, 'a');
   int max_streams = 100;
 
   AddToCache("/large_response", 200, large_body);
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   SetPacketLossPercentage(10);
 
   for (int i = 0; i < max_streams; ++i) {
@@ -1539,12 +1527,11 @@
 
 TEST_P(EndToEndTest, StreamCancelErrorTest) {
   ASSERT_TRUE(Initialize());
-  string small_body;
-  GenerateBody(&small_body, 256);
+  string small_body(256, 'a');
 
   AddToCache("/small_response", 200, small_body);
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   QuicSession* session = client_->client()->session();
   // Lose the request.
@@ -1672,7 +1659,7 @@
   ASSERT_TRUE(Initialize());
 
   // Values are exchanged during crypto handshake, so wait for that to finish.
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   // Open a data stream to make sure the stream level flow control is updated.
@@ -1725,7 +1712,7 @@
   // Wait for crypto handshake to finish. This should have contributed to the
   // crypto stream flow control window, but not affected the session flow
   // control window.
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   QuicCryptoStream* crypto_stream =
@@ -1768,7 +1755,7 @@
 
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   server_thread_->WaitForCryptoHandshakeConfirmed();
 
   server_thread_->Pause();
@@ -1868,7 +1855,7 @@
   ASSERT_TRUE(Initialize());
 
   // Wait for the server SHLO before upping the packet loss.
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   SetPacketLossPercentage(30);
   client_writer_->set_fake_blocked_socket_percentage(10);
 
@@ -1940,7 +1927,7 @@
 TEST_P(EndToEndTest, ServerSendPublicResetWithDifferentConnectionId) {
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Send the public reset.
   QuicConnectionId incorrect_connection_id =
@@ -2005,7 +1992,7 @@
 TEST_P(EndToEndTest, ServerSendVersionNegotiationWithDifferentConnectionId) {
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Send the version negotiation packet.
   QuicConnectionId incorrect_connection_id =
@@ -2147,9 +2134,9 @@
  public:
   ServerStreamWithErrorResponseBody(QuicStreamId id,
                                     QuicSpdySession* session,
-                                    QuicInMemoryCache* in_memory_cache,
+                                    QuicHttpResponseCache* response_cache,
                                     string response_body)
-      : QuicSimpleServerStream(id, session, in_memory_cache),
+      : QuicSimpleServerStream(id, session, response_cache),
         response_body_(std::move(response_body)) {}
 
   ~ServerStreamWithErrorResponseBody() override {}
@@ -2179,8 +2166,8 @@
   QuicSimpleServerStream* CreateStream(
       QuicStreamId id,
       QuicSpdySession* session,
-      QuicInMemoryCache* in_memory_cache) override {
-    return new ServerStreamWithErrorResponseBody(id, session, in_memory_cache,
+      QuicHttpResponseCache* response_cache) override {
+    return new ServerStreamWithErrorResponseBody(id, session, response_cache,
                                                  response_body_);
   }
 
@@ -2193,8 +2180,8 @@
  public:
   ServerStreamThatDropsBody(QuicStreamId id,
                             QuicSpdySession* session,
-                            QuicInMemoryCache* in_memory_cache)
-      : QuicSimpleServerStream(id, session, in_memory_cache) {}
+                            QuicHttpResponseCache* response_cache)
+      : QuicSimpleServerStream(id, session, response_cache) {}
 
   ~ServerStreamThatDropsBody() override {}
 
@@ -2236,8 +2223,8 @@
   QuicSimpleServerStream* CreateStream(
       QuicStreamId id,
       QuicSpdySession* session,
-      QuicInMemoryCache* in_memory_cache) override {
-    return new ServerStreamThatDropsBody(id, session, in_memory_cache);
+      QuicHttpResponseCache* response_cache) override {
+    return new ServerStreamThatDropsBody(id, session, response_cache);
   }
 };
 
@@ -2246,18 +2233,17 @@
  public:
   ServerStreamThatSendsHugeResponse(QuicStreamId id,
                                     QuicSpdySession* session,
-                                    QuicInMemoryCache* in_memory_cache,
+                                    QuicHttpResponseCache* response_cache,
                                     int64_t body_bytes)
-      : QuicSimpleServerStream(id, session, in_memory_cache),
+      : QuicSimpleServerStream(id, session, response_cache),
         body_bytes_(body_bytes) {}
 
   ~ServerStreamThatSendsHugeResponse() override {}
 
  protected:
   void SendResponse() override {
-    QuicInMemoryCache::Response response;
-    string body;
-    GenerateBody(&body, body_bytes_);
+    QuicHttpResponseCache::Response response;
+    string body(body_bytes_, 'a');
     response.set_body(body);
     SendHeadersAndBodyAndTrailers(response.headers().Clone(), response.body(),
                                   response.trailers().Clone());
@@ -2280,8 +2266,8 @@
   QuicSimpleServerStream* CreateStream(
       QuicStreamId id,
       QuicSpdySession* session,
-      QuicInMemoryCache* in_memory_cache) override {
-    return new ServerStreamThatSendsHugeResponse(id, session, in_memory_cache,
+      QuicHttpResponseCache* response_cache) override {
+    return new ServerStreamThatSendsHugeResponse(id, session, response_cache,
                                                  body_bytes_);
   }
 
@@ -2385,20 +2371,19 @@
   // receive the FIN of the request
   // send the FIN of the response
 
-  string response_body;
   // The response body must be larger than the flow control window so the server
   // must receive a window update from the client before it can finish sending
   // it.
   uint32_t response_body_size =
       2 * client_config_.GetInitialStreamFlowControlWindowToSend();
-  GenerateBody(&response_body, response_body_size);
+  string response_body(response_body_size, 'a');
 
   StreamWithErrorFactory stream_factory(response_body);
   SetSpdyStreamFactory(&stream_factory);
 
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // A POST that gets an early error response, after the headers are received
   // and before the body is received, due to invalid content-length.
@@ -2417,8 +2402,7 @@
   // before the request FIN is processed but receive the request FIN before the
   // response is sent completely.
   const uint32_t kRequestBodySize = kMaxPacketSize + 10;
-  string request_body;
-  GenerateBody(&request_body, kRequestBodySize);
+  string request_body(kRequestBodySize, 'a');
 
   // Send the request.
   client_->SendMessage(headers, request_body);
@@ -2453,7 +2437,7 @@
 
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // POST to a URL that gets an early error response, after the headers are
   // received and before the body is received.
@@ -2483,7 +2467,7 @@
 TEST_P(EndToEndTest, Trailers) {
   // Test sending and receiving HTTP/2 Trailers (trailing HEADERS frames).
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Set reordering to ensure that Trailers arriving before body is ok.
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2500,8 +2484,8 @@
   SpdyHeaderBlock trailers;
   trailers["some-trailing-header"] = "trailing-header-value";
 
-  in_memory_cache_.AddResponse(server_hostname_, "/trailer_url",
-                               std::move(headers), kBody, trailers.Clone());
+  response_cache_.AddResponse(server_hostname_, "/trailer_url",
+                              std::move(headers), kBody, trailers.Clone());
 
   EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url"));
   EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
@@ -2536,9 +2520,9 @@
     if (use_large_response) {
       // Generate a response common body larger than flow control window for
       // push response.
-      GenerateBody(&large_resource, resource_size);
+      large_resource = string(resource_size, 'a');
     }
-    std::list<QuicInMemoryCache::ServerPushInfo> push_resources;
+    std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
     for (size_t i = 0; i < num_resources; ++i) {
       string url = push_urls[i];
       GURL resource_url(url);
@@ -2549,11 +2533,11 @@
       response_headers[":version"] = "HTTP/1.1";
       response_headers[":status"] = "200";
       response_headers["content-length"] = IntToString(body.size());
-      push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
+      push_resources.push_back(QuicHttpResponseCache::ServerPushInfo(
           resource_url, std::move(response_headers), kV3LowestPriority, body));
     }
 
-    in_memory_cache_.AddSimpleResponseWithServerPushResources(
+    response_cache_.AddSimpleResponseWithServerPushResources(
         host, path, 200, response_body, push_resources);
   }
 };
@@ -2565,7 +2549,7 @@
 
 TEST_P(EndToEndTestServerPush, ServerPush) {
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2612,7 +2596,7 @@
   // them with requests later.
   ASSERT_TRUE(Initialize());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2659,7 +2643,7 @@
   // streams should still work because all response streams get closed
   // immediately after pushing resources.
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2717,7 +2701,7 @@
       kBodySize * kNumMaxStreams + 1024);
 
   ASSERT_TRUE(Initialize());
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
   SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -2830,7 +2814,7 @@
   // within a short time.
   client_->epoll_server()->set_timeout_in_us(0);
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   SetPacketLossPercentage(1);
   // To avoid storing the whole request body in memory, use a loop to repeatedly
   // send body size of kSizeBytes until the whole request body size is reached.
@@ -2838,8 +2822,7 @@
   // Request body size is 4G plus one more kSizeBytes.
   int64_t request_body_size_bytes = pow(2, 32) + kSizeBytes;
   ASSERT_LT(INT64_C(4294967296), request_body_size_bytes);
-  string body;
-  GenerateBody(&body, kSizeBytes);
+  string body(kSizeBytes, 'a');
 
   SpdyHeaderBlock headers;
   headers[":method"] = "POST";
@@ -2888,7 +2871,7 @@
   initialized_ = true;
   ASSERT_TRUE(client_->client()->connected());
 
-  client_->client()->WaitForCryptoHandshakeConfirmed();
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   SetPacketLossPercentage(1);
   client_->SendRequest("/huge_response");
   client_->WaitForResponse();
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index 005d90f8..c198265f 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -20,7 +20,7 @@
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_data_reader.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/spdy_utils.h"
 #include "net/tools/quic/quic_epoll_alarm_factory.h"
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc
index 2b2715bb..1b7ed1e 100644
--- a/net/tools/quic/quic_client_base.cc
+++ b/net/tools/quic/quic_client_base.cc
@@ -307,12 +307,16 @@
   }
 }
 
-void QuicClientBase::WaitForCryptoHandshakeConfirmed() {
+bool QuicClientBase::WaitForCryptoHandshakeConfirmed() {
   DCHECK(connected());
 
   while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
     WaitForEvents();
   }
+
+  // If the handshake fails due to a timeout, the connection will be closed.
+  LOG_IF(ERROR, !connected()) << "Handshake with server failed.";
+  return connected();
 }
 
 bool QuicClientBase::connected() const {
diff --git a/net/tools/quic/quic_client_base.h b/net/tools/quic/quic_client_base.h
index 021331fe..6647283 100644
--- a/net/tools/quic/quic_client_base.h
+++ b/net/tools/quic/quic_client_base.h
@@ -20,7 +20,7 @@
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 #include "net/tools/quic/quic_client_session.h"
 #include "net/tools/quic/quic_spdy_client_stream.h"
@@ -133,7 +133,8 @@
   void WaitForStreamToClose(QuicStreamId id);
 
   // Wait for events until the handshake is confirmed.
-  void WaitForCryptoHandshakeConfirmed();
+  // Returns true if the crypto handshake succeeds, false otherwise.
+  bool WaitForCryptoHandshakeConfirmed() WARN_UNUSED_RESULT;
 
   // Wait up to 50ms, and handle any events which occur.
   // Returns true if there are any outstanding requests.
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc
index 4722c42..8c979487 100644
--- a/net/tools/quic/quic_client_bin.cc
+++ b/net/tools/quic/quic_client_bin.cc
@@ -55,7 +55,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/platform/api/quic_socket_address.h"
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h
index a4cb542..c2b4bc4 100644
--- a/net/tools/quic/quic_client_session.h
+++ b/net/tools/quic/quic_client_session.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "net/quic/core/quic_client_session_base.h"
 #include "net/quic/core/quic_crypto_client_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/tools/quic/quic_spdy_client_stream.h"
 
 namespace net {
diff --git a/net/tools/quic/quic_default_packet_writer.h b/net/tools/quic/quic_default_packet_writer.h
index 853bb69..80b6021 100644
--- a/net/tools/quic/quic_default_packet_writer.h
+++ b/net/tools/quic/quic_default_packet_writer.h
@@ -38,7 +38,7 @@
   void set_fd(int fd) { fd_ = fd; }
 
  protected:
-  virtual void set_write_blocked(bool is_blocked);
+  void set_write_blocked(bool is_blocked);
   int fd() { return fd_; }
 
  private:
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 9f6f2ef6..ab724db 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -20,8 +20,9 @@
 #include "net/quic/core/quic_buffered_packet_store.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_crypto_server_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
+#include "net/quic/core/quic_version_manager.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 
 #include "net/tools/quic/quic_process_packet_interface.h"
diff --git a/net/tools/quic/quic_epoll_connection_helper.h b/net/tools/quic/quic_epoll_connection_helper.h
index 01964b3..811e70c 100644
--- a/net/tools/quic/quic_epoll_connection_helper.h
+++ b/net/tools/quic/quic_epoll_connection_helper.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_simple_buffer_allocator.h"
 #include "net/quic/core/quic_time.h"
 #include "net/tools/quic/quic_default_packet_writer.h"
diff --git a/net/tools/quic/quic_in_memory_cache.cc b/net/tools/quic/quic_http_response_cache.cc
similarity index 78%
rename from net/tools/quic/quic_in_memory_cache.cc
rename to net/tools/quic/quic_http_response_cache.cc
index 8f6ec92..7057a2db 100644
--- a/net/tools/quic/quic_in_memory_cache.cc
+++ b/net/tools/quic/quic_http_response_cache.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 "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 
 #include <utility>
 
@@ -24,26 +24,29 @@
 
 namespace net {
 
-QuicInMemoryCache::ServerPushInfo::ServerPushInfo(GURL request_url,
-                                                  SpdyHeaderBlock headers,
-                                                  net::SpdyPriority priority,
-                                                  string body)
+QuicHttpResponseCache::ServerPushInfo::ServerPushInfo(
+    GURL request_url,
+    SpdyHeaderBlock headers,
+    net::SpdyPriority priority,
+    string body)
     : request_url(request_url),
       headers(std::move(headers)),
       priority(priority),
       body(body) {}
 
-QuicInMemoryCache::ServerPushInfo::ServerPushInfo(const ServerPushInfo& other)
+QuicHttpResponseCache::ServerPushInfo::ServerPushInfo(
+    const ServerPushInfo& other)
     : request_url(other.request_url),
       headers(other.headers.Clone()),
       priority(other.priority),
       body(other.body) {}
 
-QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) {}
+QuicHttpResponseCache::Response::Response()
+    : response_type_(REGULAR_RESPONSE) {}
 
-QuicInMemoryCache::Response::~Response() {}
+QuicHttpResponseCache::Response::~Response() {}
 
-void QuicInMemoryCache::ResourceFile::Read() {
+void QuicHttpResponseCache::ResourceFile::Read() {
   base::ReadFileToString(FilePath(file_name_), &file_contents_);
 
   // First read the headers.
@@ -121,12 +124,14 @@
       StringPiece(file_contents_.data() + start, file_contents_.size() - start);
 }
 
-QuicInMemoryCache::ResourceFile::ResourceFile(const base::FilePath& file_name)
+QuicHttpResponseCache::ResourceFile::ResourceFile(
+    const base::FilePath& file_name)
     : file_name_(file_name), file_name_string_(file_name.AsUTF8Unsafe()) {}
 
-QuicInMemoryCache::ResourceFile::~ResourceFile() {}
+QuicHttpResponseCache::ResourceFile::~ResourceFile() {}
 
-void QuicInMemoryCache::ResourceFile::SetHostPathFromBase(StringPiece base) {
+void QuicHttpResponseCache::ResourceFile::SetHostPathFromBase(
+    StringPiece base) {
   size_t path_start = base.find_first_of('/');
   DCHECK_LT(0UL, path_start);
   host_ = base.substr(0, path_start);
@@ -138,7 +143,7 @@
   }
 }
 
-StringPiece QuicInMemoryCache::ResourceFile::RemoveScheme(StringPiece url) {
+StringPiece QuicHttpResponseCache::ResourceFile::RemoveScheme(StringPiece url) {
   if (base::StartsWith(url, "https://", base::CompareCase::INSENSITIVE_ASCII)) {
     url.remove_prefix(8);
   } else if (base::StartsWith(url, "http://",
@@ -148,14 +153,14 @@
   return url;
 }
 
-void QuicInMemoryCache::ResourceFile::HandleXOriginalUrl() {
+void QuicHttpResponseCache::ResourceFile::HandleXOriginalUrl() {
   StringPiece url(x_original_url_);
   // Remove the protocol so we can add it below.
   url = RemoveScheme(url);
   SetHostPathFromBase(url);
 }
 
-const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
+const QuicHttpResponseCache::Response* QuicHttpResponseCache::GetResponse(
     StringPiece host,
     StringPiece path) const {
   base::AutoLock lock(response_mutex_);
@@ -172,12 +177,12 @@
   return it->second.get();
 }
 
-typedef QuicInMemoryCache::ServerPushInfo ServerPushInfo;
+typedef QuicHttpResponseCache::ServerPushInfo ServerPushInfo;
 
-void QuicInMemoryCache::AddSimpleResponse(StringPiece host,
-                                          StringPiece path,
-                                          int response_code,
-                                          StringPiece body) {
+void QuicHttpResponseCache::AddSimpleResponse(StringPiece host,
+                                              StringPiece path,
+                                              int response_code,
+                                              StringPiece body) {
   SpdyHeaderBlock response_headers;
   response_headers[":status"] = IntToString(response_code);
   response_headers["content-length"] =
@@ -185,7 +190,7 @@
   AddResponse(host, path, std::move(response_headers), body);
 }
 
-void QuicInMemoryCache::AddSimpleResponseWithServerPushResources(
+void QuicHttpResponseCache::AddSimpleResponseWithServerPushResources(
     StringPiece host,
     StringPiece path,
     int response_code,
@@ -195,43 +200,45 @@
   MaybeAddServerPushResources(host, path, push_resources);
 }
 
-void QuicInMemoryCache::AddDefaultResponse(Response* response) {
+void QuicHttpResponseCache::AddDefaultResponse(Response* response) {
   base::AutoLock lock(response_mutex_);
   default_response_.reset(response);
 }
 
-void QuicInMemoryCache::AddResponse(StringPiece host,
-                                    StringPiece path,
-                                    SpdyHeaderBlock response_headers,
-                                    StringPiece response_body) {
+void QuicHttpResponseCache::AddResponse(StringPiece host,
+                                        StringPiece path,
+                                        SpdyHeaderBlock response_headers,
+                                        StringPiece response_body) {
   AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers),
                   response_body, SpdyHeaderBlock());
 }
 
-void QuicInMemoryCache::AddResponse(StringPiece host,
-                                    StringPiece path,
-                                    SpdyHeaderBlock response_headers,
-                                    StringPiece response_body,
-                                    SpdyHeaderBlock response_trailers) {
+void QuicHttpResponseCache::AddResponse(StringPiece host,
+                                        StringPiece path,
+                                        SpdyHeaderBlock response_headers,
+                                        StringPiece response_body,
+                                        SpdyHeaderBlock response_trailers) {
   AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers),
                   response_body, std::move(response_trailers));
 }
 
-void QuicInMemoryCache::AddSpecialResponse(StringPiece host,
-                                           StringPiece path,
-                                           SpecialResponseType response_type) {
+void QuicHttpResponseCache::AddSpecialResponse(
+    StringPiece host,
+    StringPiece path,
+    SpecialResponseType response_type) {
   AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "",
                   SpdyHeaderBlock());
 }
 
-QuicInMemoryCache::QuicInMemoryCache() {}
+QuicHttpResponseCache::QuicHttpResponseCache() {}
 
-void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
+void QuicHttpResponseCache::InitializeFromDirectory(
+    const string& cache_directory) {
   if (cache_directory.empty()) {
     QUIC_BUG << "cache_directory must not be empty.";
     return;
   }
-  VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: "
+  VLOG(1) << "Attempting to initialize QuicHttpResponseCache from directory: "
           << cache_directory;
   FilePath directory(FilePath::FromUTF8Unsafe(cache_directory));
   base::FileEnumerator file_list(directory, true, base::FileEnumerator::FILES);
@@ -279,7 +286,7 @@
   }
 }
 
-std::list<ServerPushInfo> QuicInMemoryCache::GetServerPushResources(
+std::list<ServerPushInfo> QuicHttpResponseCache::GetServerPushResources(
     string request_url) {
   base::AutoLock lock(response_mutex_);
 
@@ -293,19 +300,19 @@
   return resources;
 }
 
-QuicInMemoryCache::~QuicInMemoryCache() {
+QuicHttpResponseCache::~QuicHttpResponseCache() {
   {
     base::AutoLock lock(response_mutex_);
     responses_.clear();
   }
 }
 
-void QuicInMemoryCache::AddResponseImpl(StringPiece host,
-                                        StringPiece path,
-                                        SpecialResponseType response_type,
-                                        SpdyHeaderBlock response_headers,
-                                        StringPiece response_body,
-                                        SpdyHeaderBlock response_trailers) {
+void QuicHttpResponseCache::AddResponseImpl(StringPiece host,
+                                            StringPiece path,
+                                            SpecialResponseType response_type,
+                                            SpdyHeaderBlock response_headers,
+                                            StringPiece response_body,
+                                            SpdyHeaderBlock response_trailers) {
   base::AutoLock lock(response_mutex_);
 
   DCHECK(!host.empty()) << "Host must be populated, e.g. \"www.google.com\"";
@@ -323,11 +330,11 @@
   responses_[key] = std::move(new_response);
 }
 
-string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const {
+string QuicHttpResponseCache::GetKey(StringPiece host, StringPiece path) const {
   return host.as_string() + path.as_string();
 }
 
-void QuicInMemoryCache::MaybeAddServerPushResources(
+void QuicHttpResponseCache::MaybeAddServerPushResources(
     StringPiece request_host,
     StringPiece request_path,
     std::list<ServerPushInfo> push_resources) {
@@ -366,8 +373,9 @@
   }
 }
 
-bool QuicInMemoryCache::PushResourceExistsInCache(string original_request_url,
-                                                  ServerPushInfo resource) {
+bool QuicHttpResponseCache::PushResourceExistsInCache(
+    string original_request_url,
+    ServerPushInfo resource) {
   base::AutoLock lock(response_mutex_);
   auto resource_range =
       server_push_resources_.equal_range(original_request_url);
diff --git a/net/tools/quic/quic_in_memory_cache.h b/net/tools/quic/quic_http_response_cache.h
similarity index 97%
rename from net/tools/quic/quic_in_memory_cache.h
rename to net/tools/quic/quic_http_response_cache.h
index 1fdc340..3a1857c 100644
--- a/net/tools/quic/quic_in_memory_cache.h
+++ b/net/tools/quic/quic_http_response_cache.h
@@ -25,7 +25,7 @@
 // In-memory cache for HTTP responses.
 // Reads from disk cache generated by:
 // `wget -p --save_headers <url>`
-class QuicInMemoryCache {
+class QuicHttpResponseCache {
  public:
   // A ServerPushInfo contains path of the push request and everything needed in
   // comprising a response for the push request.
@@ -120,13 +120,13 @@
    private:
     base::StringPiece host_;
     base::StringPiece path_;
-    QuicInMemoryCache* cache_;
+    QuicHttpResponseCache* cache_;
 
     DISALLOW_COPY_AND_ASSIGN(ResourceFile);
   };
 
-  QuicInMemoryCache();
-  ~QuicInMemoryCache();
+  QuicHttpResponseCache();
+  ~QuicHttpResponseCache();
 
   // Retrieve a response from this cache for a given host and path..
   // If no appropriate response exists, nullptr is returned.
@@ -213,7 +213,7 @@
   // server threads accessing those responses.
   mutable base::Lock response_mutex_;
 
-  DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache);
+  DISALLOW_COPY_AND_ASSIGN(QuicHttpResponseCache);
 };
 
 }  // namespace net
diff --git a/net/tools/quic/quic_in_memory_cache_test.cc b/net/tools/quic/quic_http_response_cache_test.cc
similarity index 84%
rename from net/tools/quic/quic_in_memory_cache_test.cc
rename to net/tools/quic/quic_http_response_cache_test.cc
index 506a50a8..4979d4c 100644
--- a/net/tools/quic/quic_in_memory_cache_test.cc
+++ b/net/tools/quic/quic_http_response_cache_test.cc
@@ -11,7 +11,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "net/spdy/spdy_framer.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::ContainsKey;
@@ -25,11 +25,11 @@
 namespace test {
 
 namespace {
-typedef QuicInMemoryCache::Response Response;
-typedef QuicInMemoryCache::ServerPushInfo ServerPushInfo;
+typedef QuicHttpResponseCache::Response Response;
+typedef QuicHttpResponseCache::ServerPushInfo ServerPushInfo;
 };  // namespace
 
-class QuicInMemoryCacheTest : public ::testing::Test {
+class QuicHttpResponseCacheTest : public ::testing::Test {
  protected:
   void CreateRequest(string host, string path, SpdyHeaderBlock* headers) {
     (*headers)[":method"] = "GET";
@@ -42,27 +42,27 @@
     base::FilePath path;
     PathService::Get(base::DIR_SOURCE_ROOT, &path);
     path = path.AppendASCII("net").AppendASCII("data").AppendASCII(
-        "quic_in_memory_cache_data");
+        "quic_http_response_cache_data");
     // The file path is known to be an ascii string.
     return path.MaybeAsASCII();
   }
 
-  QuicInMemoryCache cache_;
+  QuicHttpResponseCache cache_;
 };
 
-TEST_F(QuicInMemoryCacheTest, GetResponseNoMatch) {
-  const QuicInMemoryCache::Response* response =
+TEST_F(QuicHttpResponseCacheTest, GetResponseNoMatch) {
+  const QuicHttpResponseCache::Response* response =
       cache_.GetResponse("mail.google.com", "/index.html");
   ASSERT_FALSE(response);
 }
 
-TEST_F(QuicInMemoryCacheTest, AddSimpleResponseGetResponse) {
+TEST_F(QuicHttpResponseCacheTest, AddSimpleResponseGetResponse) {
   string response_body("hello response");
   cache_.AddSimpleResponse("www.google.com", "/", 200, response_body);
 
   SpdyHeaderBlock request_headers;
   CreateRequest("www.google.com", "/", &request_headers);
-  const QuicInMemoryCache::Response* response =
+  const QuicHttpResponseCache::Response* response =
       cache_.GetResponse("www.google.com", "/");
   ASSERT_TRUE(response);
   ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
@@ -70,7 +70,7 @@
   EXPECT_EQ(response_body.size(), response->body().length());
 }
 
-TEST_F(QuicInMemoryCacheTest, AddResponse) {
+TEST_F(QuicHttpResponseCacheTest, AddResponse) {
   const string kRequestHost = "www.foo.com";
   const string kRequestPath = "/";
   const string kResponseBody("hello response");
@@ -88,16 +88,16 @@
   cache_.AddResponse(kRequestHost, "/", response_headers.Clone(), kResponseBody,
                      response_trailers.Clone());
 
-  const QuicInMemoryCache::Response* response =
+  const QuicHttpResponseCache::Response* response =
       cache_.GetResponse(kRequestHost, kRequestPath);
   EXPECT_EQ(response->headers(), response_headers);
   EXPECT_EQ(response->body(), kResponseBody);
   EXPECT_EQ(response->trailers(), response_trailers);
 }
 
-TEST_F(QuicInMemoryCacheTest, ReadsCacheDir) {
+TEST_F(QuicHttpResponseCacheTest, ReadsCacheDir) {
   cache_.InitializeFromDirectory(CacheDirectory());
-  const QuicInMemoryCache::Response* response =
+  const QuicHttpResponseCache::Response* response =
       cache_.GetResponse("quic.test.url", "/index.html");
   ASSERT_TRUE(response);
   ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
@@ -107,23 +107,23 @@
   EXPECT_LT(0U, response->body().length());
 }
 
-TEST_F(QuicInMemoryCacheTest, ReadsCacheDirWithServerPushResource) {
+TEST_F(QuicHttpResponseCacheTest, ReadsCacheDirWithServerPushResource) {
   cache_.InitializeFromDirectory(CacheDirectory() + "_with_push");
   list<ServerPushInfo> resources =
       cache_.GetServerPushResources("quic.test.url/");
   ASSERT_EQ(1UL, resources.size());
 }
 
-TEST_F(QuicInMemoryCacheTest, ReadsCacheDirWithServerPushResources) {
+TEST_F(QuicHttpResponseCacheTest, ReadsCacheDirWithServerPushResources) {
   cache_.InitializeFromDirectory(CacheDirectory() + "_with_push");
   list<ServerPushInfo> resources =
       cache_.GetServerPushResources("quic.test.url/index2.html");
   ASSERT_EQ(2UL, resources.size());
 }
 
-TEST_F(QuicInMemoryCacheTest, UsesOriginalUrl) {
+TEST_F(QuicHttpResponseCacheTest, UsesOriginalUrl) {
   cache_.InitializeFromDirectory(CacheDirectory());
-  const QuicInMemoryCache::Response* response =
+  const QuicHttpResponseCache::Response* response =
       cache_.GetResponse("quic.test.url", "/index.html");
   ASSERT_TRUE(response);
   ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
@@ -133,9 +133,9 @@
   EXPECT_LT(0U, response->body().length());
 }
 
-TEST_F(QuicInMemoryCacheTest, DefaultResponse) {
+TEST_F(QuicHttpResponseCacheTest, DefaultResponse) {
   // Verify GetResponse returns nullptr when no default is set.
-  const QuicInMemoryCache::Response* response =
+  const QuicHttpResponseCache::Response* response =
       cache_.GetResponse("www.google.com", "/");
   ASSERT_FALSE(response);
 
@@ -144,8 +144,8 @@
   response_headers[":version"] = "HTTP/1.1";
   response_headers[":status"] = "200";
   response_headers["content-length"] = "0";
-  QuicInMemoryCache::Response* default_response =
-      new QuicInMemoryCache::Response;
+  QuicHttpResponseCache::Response* default_response =
+      new QuicHttpResponseCache::Response;
   default_response->set_headers(std::move(response_headers));
   cache_.AddDefaultResponse(default_response);
 
@@ -169,12 +169,12 @@
   EXPECT_EQ("200", response->headers().find(":status")->second);
 }
 
-TEST_F(QuicInMemoryCacheTest, AddSimpleResponseWithServerPushResources) {
+TEST_F(QuicHttpResponseCacheTest, AddSimpleResponseWithServerPushResources) {
   string request_host = "www.foo.com";
   string response_body("hello response");
   const size_t kNumResources = 5;
   int NumResources = 5;
-  list<QuicInMemoryCache::ServerPushInfo> push_resources;
+  list<QuicHttpResponseCache::ServerPushInfo> push_resources;
   string scheme = "http";
   for (int i = 0; i < NumResources; ++i) {
     string path = "/server_push_src" + base::IntToString(i);
@@ -202,14 +202,14 @@
   }
 }
 
-TEST_F(QuicInMemoryCacheTest, GetServerPushResourcesAndPushResponses) {
+TEST_F(QuicHttpResponseCacheTest, GetServerPushResourcesAndPushResponses) {
   string request_host = "www.foo.com";
   string response_body("hello response");
   const size_t kNumResources = 4;
   int NumResources = 4;
   string scheme = "http";
   string push_response_status[kNumResources] = {"200", "200", "301", "404"};
-  list<QuicInMemoryCache::ServerPushInfo> push_resources;
+  list<QuicHttpResponseCache::ServerPushInfo> push_resources;
   for (int i = 0; i < NumResources; ++i) {
     string path = "/server_push_src" + base::IntToString(i);
     string url = scheme + "://" + request_host + path;
@@ -232,7 +232,7 @@
     GURL url = resources.front().request_url;
     string host = url.host();
     string path = url.path();
-    const QuicInMemoryCache::Response* response =
+    const QuicHttpResponseCache::Response* response =
         cache_.GetResponse(host, path);
     ASSERT_TRUE(response);
     ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
diff --git a/net/tools/quic/quic_packet_reader.h b/net/tools/quic/quic_packet_reader.h
index e9a634e0..3cb238d 100644
--- a/net/tools/quic/quic_packet_reader.h
+++ b/net/tools/quic/quic_packet_reader.h
@@ -12,7 +12,7 @@
 
 #include "base/macros.h"
 #include "net/quic/core/quic_clock.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 #include "net/tools/quic/quic_process_packet_interface.h"
 #include "net/tools/quic/quic_socket_utils.h"
diff --git a/net/tools/quic/quic_process_packet_interface.h b/net/tools/quic/quic_process_packet_interface.h
index a186b2b5..e960788 100644
--- a/net/tools/quic/quic_process_packet_interface.h
+++ b/net/tools/quic/quic_process_packet_interface.h
@@ -6,7 +6,7 @@
 #define NET_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 
 namespace net {
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index d29a9991..cab43dc0 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -20,12 +20,12 @@
 #include "net/quic/core/quic_clock.h"
 #include "net/quic/core/quic_crypto_stream.h"
 #include "net/quic/core/quic_data_reader.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/tools/quic/quic_dispatcher.h"
 #include "net/tools/quic/quic_epoll_alarm_factory.h"
 #include "net/tools/quic/quic_epoll_clock.h"
 #include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_packet_reader.h"
 #include "net/tools/quic/quic_simple_crypto_server_stream_helper.h"
 #include "net/tools/quic/quic_simple_dispatcher.h"
@@ -37,10 +37,10 @@
 namespace net {
 namespace {
 
-// Specifies the directory used during QuicInMemoryCache
+// Specifies the directory used during QuicHttpResponseCache
 // construction to seed the cache. Cache directory can be
 // generated using `wget -p --save-headers <url>`
-std::string FLAGS_quic_in_memory_cache_dir = "";
+std::string FLAGS_quic_response_cache_dir = "";
 
 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
 const char kSourceAddressTokenSecret[] = "secret";
@@ -50,19 +50,19 @@
 const size_t kNumSessionsToCreatePerSocketEvent = 16;
 
 QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source,
-                       QuicInMemoryCache* in_memory_cache)
+                       QuicHttpResponseCache* response_cache)
     : QuicServer(std::move(proof_source),
                  QuicConfig(),
                  QuicCryptoServerConfig::ConfigOptions(),
                  AllSupportedVersions(),
-                 in_memory_cache) {}
+                 response_cache) {}
 
 QuicServer::QuicServer(
     std::unique_ptr<ProofSource> proof_source,
     const QuicConfig& config,
     const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
     const QuicVersionVector& supported_versions,
-    QuicInMemoryCache* in_memory_cache)
+    QuicHttpResponseCache* response_cache)
     : port_(0),
       fd_(-1),
       packets_dropped_(0),
@@ -74,7 +74,7 @@
       crypto_config_options_(crypto_config_options),
       version_manager_(supported_versions),
       packet_reader_(new QuicPacketReader()),
-      in_memory_cache_(in_memory_cache) {
+      response_cache_(response_cache) {
   Initialize();
 }
 
@@ -96,8 +96,8 @@
 
   epoll_server_.set_timeout_in_us(50 * 1000);
 
-  if (!FLAGS_quic_in_memory_cache_dir.empty()) {
-    in_memory_cache_->InitializeFromDirectory(FLAGS_quic_in_memory_cache_dir);
+  if (!FLAGS_quic_response_cache_dir.empty()) {
+    response_cache_->InitializeFromDirectory(FLAGS_quic_response_cache_dir);
   }
 
   QuicEpollClock clock(&epoll_server_);
@@ -152,7 +152,7 @@
           new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
       std::unique_ptr<QuicEpollAlarmFactory>(
           new QuicEpollAlarmFactory(&epoll_server_)),
-      in_memory_cache_);
+      response_cache_);
 }
 
 void QuicServer::WaitForEvents() {
diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h
index 5e0db6b..7bce8e6b 100644
--- a/net/tools/quic/quic_server.h
+++ b/net/tools/quic/quic_server.h
@@ -20,10 +20,11 @@
 #include "net/quic/core/crypto/quic_crypto_server_config.h"
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_framer.h"
+#include "net/quic/core/quic_version_manager.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 #include "net/tools/epoll_server/epoll_server.h"
 #include "net/tools/quic/quic_default_packet_writer.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 
 namespace net {
 
@@ -37,12 +38,12 @@
 class QuicServer : public EpollCallbackInterface {
  public:
   QuicServer(std::unique_ptr<ProofSource> proof_source,
-             QuicInMemoryCache* in_memory_cache);
+             QuicHttpResponseCache* response_cache);
   QuicServer(std::unique_ptr<ProofSource> proof_source,
              const QuicConfig& config,
              const QuicCryptoServerConfig::ConfigOptions& server_config_options,
              const QuicVersionVector& supported_versions,
-             QuicInMemoryCache* in_memory_cache);
+             QuicHttpResponseCache* response_cache);
 
   ~QuicServer() override;
 
@@ -86,7 +87,7 @@
 
   QuicVersionManager* version_manager() { return &version_manager_; }
 
-  QuicInMemoryCache* in_memory_cache() { return in_memory_cache_; }
+  QuicHttpResponseCache* response_cache() { return response_cache_; }
 
  private:
   friend class net::test::QuicServerPeer;
@@ -129,7 +130,7 @@
   // space than allowed on the stack.
   std::unique_ptr<QuicPacketReader> packet_reader_;
 
-  QuicInMemoryCache* in_memory_cache_;  // unowned.
+  QuicHttpResponseCache* response_cache_;  // unowned.
 
   DISALLOW_COPY_AND_ASSIGN(QuicServer);
 };
diff --git a/net/tools/quic/quic_server_bin.cc b/net/tools/quic/quic_server_bin.cc
index 2b4528ca..6fc2524 100644
--- a/net/tools/quic/quic_server_bin.cc
+++ b/net/tools/quic/quic_server_bin.cc
@@ -13,9 +13,9 @@
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "net/quic/chromium/crypto/proof_source_chromium.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_server.h"
 
 // The port the quic server will listen on.
@@ -48,7 +48,7 @@
         "Options:\n"
         "-h, --help                  show this help message and exit\n"
         "--port=<port>               specify the port to listen on\n"
-        "--quic_in_memory_cache_dir  directory containing response data\n"
+        "--quic_response_cache_dir  directory containing response data\n"
         "                            to load\n"
         "--certificate_file=<file>   path to the certificate chain\n"
         "--key_file=<file>           path to the pkcs8 private key\n";
@@ -56,10 +56,10 @@
     exit(0);
   }
 
-  net::QuicInMemoryCache in_memory_cache;
-  if (line->HasSwitch("quic_in_memory_cache_dir")) {
-    in_memory_cache.InitializeFromDirectory(
-        line->GetSwitchValueASCII("quic_in_memory_cache_dir"));
+  net::QuicHttpResponseCache response_cache;
+  if (line->HasSwitch("quic_response_cache_dir")) {
+    response_cache.InitializeFromDirectory(
+        line->GetSwitchValueASCII("quic_response_cache_dir"));
   }
 
   if (line->HasSwitch("port")) {
@@ -84,7 +84,7 @@
       CreateProofSource(line->GetSwitchValuePath("certificate_file"),
                         line->GetSwitchValuePath("key_file")),
       config, net::QuicCryptoServerConfig::ConfigOptions(),
-      net::AllSupportedVersions(), &in_memory_cache);
+      net::AllSupportedVersions(), &response_cache);
 
   int rc = server.CreateUDPSocketAndListen(
       net::QuicSocketAddress(net::QuicIpAddress::Any6(), FLAGS_port));
diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc
index 4c7587f..ea381d9 100644
--- a/net/tools/quic/quic_server_test.cc
+++ b/net/tools/quic/quic_server_test.cc
@@ -33,14 +33,14 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      QuicInMemoryCache* in_memory_cache)
+      QuicHttpResponseCache* response_cache)
       : QuicSimpleDispatcher(config,
                              crypto_config,
                              version_manager,
                              std::move(helper),
                              std::move(session_helper),
                              std::move(alarm_factory),
-                             in_memory_cache) {}
+                             response_cache) {}
   ~MockQuicSimpleDispatcher() override {}
 
   MOCK_METHOD0(OnCanWrite, void());
@@ -52,8 +52,8 @@
 class TestQuicServer : public QuicServer {
  public:
   TestQuicServer()
-      : QuicServer(CryptoTestUtils::ProofSourceForTesting(),
-                   &in_memory_cache_) {}
+      : QuicServer(CryptoTestUtils::ProofSourceForTesting(), &response_cache_) {
+  }
 
   ~TestQuicServer() override {}
 
@@ -70,12 +70,12 @@
             new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
         std::unique_ptr<QuicEpollAlarmFactory>(
             new QuicEpollAlarmFactory(epoll_server())),
-        &in_memory_cache_);
+        &response_cache_);
     return mock_dispatcher_;
   }
 
   MockQuicSimpleDispatcher* mock_dispatcher_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
 };
 
 class QuicServerEpollInTest : public ::testing::Test {
@@ -162,7 +162,7 @@
                     QuicRandom::GetInstance())),
             std::unique_ptr<QuicEpollAlarmFactory>(
                 new QuicEpollAlarmFactory(&eps_)),
-            &in_memory_cache_) {
+            &response_cache_) {
     dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234));
   }
 
@@ -176,7 +176,7 @@
   QuicCryptoServerConfig crypto_config_;
   QuicVersionManager version_manager_;
   EpollServer eps_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
   MockQuicDispatcher dispatcher_;
 };
 
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index 0dab35c..bff89fb9 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -21,7 +21,7 @@
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/spdy_utils.h"
 #include "net/socket/udp_client_socket.h"
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc
index de9c0ac..cbc3c5c0 100644
--- a/net/tools/quic/quic_simple_client_bin.cc
+++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -57,7 +57,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
 #include "net/quic/core/quic_error_codes.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/spdy/spdy_header_block.h"
diff --git a/net/tools/quic/quic_simple_dispatcher.cc b/net/tools/quic/quic_simple_dispatcher.cc
index 4035769b..cab2925 100644
--- a/net/tools/quic/quic_simple_dispatcher.cc
+++ b/net/tools/quic/quic_simple_dispatcher.cc
@@ -15,14 +15,14 @@
     std::unique_ptr<QuicConnectionHelperInterface> helper,
     std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
     std::unique_ptr<QuicAlarmFactory> alarm_factory,
-    QuicInMemoryCache* in_memory_cache)
+    QuicHttpResponseCache* response_cache)
     : QuicDispatcher(config,
                      crypto_config,
                      version_manager,
                      std::move(helper),
                      std::move(session_helper),
                      std::move(alarm_factory)),
-      in_memory_cache_(in_memory_cache) {}
+      response_cache_(response_cache) {}
 
 QuicSimpleDispatcher::~QuicSimpleDispatcher() {}
 
@@ -37,7 +37,7 @@
 
   QuicServerSessionBase* session = new QuicSimpleServerSession(
       config(), connection, this, session_helper(), crypto_config(),
-      compressed_certs_cache(), in_memory_cache_);
+      compressed_certs_cache(), response_cache_);
   session->Initialize();
   return session;
 }
diff --git a/net/tools/quic/quic_simple_dispatcher.h b/net/tools/quic/quic_simple_dispatcher.h
index 3f4ef13..b9df6d9 100644
--- a/net/tools/quic/quic_simple_dispatcher.h
+++ b/net/tools/quic/quic_simple_dispatcher.h
@@ -7,7 +7,7 @@
 
 #include "net/quic/core/quic_server_session_base.h"
 #include "net/tools/quic/quic_dispatcher.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 
 namespace net {
 
@@ -20,7 +20,7 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      QuicInMemoryCache* in_memory_cache);
+      QuicHttpResponseCache* response_cache);
 
   ~QuicSimpleDispatcher() override;
 
@@ -29,10 +29,10 @@
       QuicConnectionId connection_id,
       const QuicSocketAddress& client_address) override;
 
-  QuicInMemoryCache* in_memory_cache() { return in_memory_cache_; }
+  QuicHttpResponseCache* response_cache() { return response_cache_; }
 
  private:
-  QuicInMemoryCache* in_memory_cache_;  // Unowned.
+  QuicHttpResponseCache* response_cache_;  // Unowned.
 };
 
 }  // namespace net
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc
index 3af6bb2560..a9714c2a 100644
--- a/net/tools/quic/quic_simple_server.cc
+++ b/net/tools/quic/quic_simple_server.cc
@@ -16,7 +16,7 @@
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/quic_crypto_stream.h"
 #include "net/quic/core/quic_data_reader.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/socket/udp_server_socket.h"
 #include "net/tools/quic/quic_simple_dispatcher.h"
 #include "net/tools/quic/quic_simple_per_connection_packet_writer.h"
@@ -41,7 +41,7 @@
     const QuicConfig& config,
     const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
     const QuicVersionVector& supported_versions,
-    QuicInMemoryCache* in_memory_cache)
+    QuicHttpResponseCache* response_cache)
     : version_manager_(supported_versions),
       helper_(
           new QuicChromiumConnectionHelper(&clock_, QuicRandom::GetInstance())),
@@ -56,7 +56,7 @@
       read_pending_(false),
       synchronous_read_count_(0),
       read_buffer_(new IOBufferWithSize(kReadBufferSize)),
-      in_memory_cache_(in_memory_cache),
+      response_cache_(response_cache),
       weak_factory_(this) {
   Initialize();
 }
@@ -131,7 +131,7 @@
       std::unique_ptr<QuicConnectionHelperInterface>(helper_),
       std::unique_ptr<QuicCryptoServerStream::Helper>(
           new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())),
-      std::unique_ptr<QuicAlarmFactory>(alarm_factory_), in_memory_cache_));
+      std::unique_ptr<QuicAlarmFactory>(alarm_factory_), response_cache_));
   QuicSimpleServerPacketWriter* writer =
       new QuicSimpleServerPacketWriter(socket_.get(), dispatcher_.get());
   dispatcher_->InitializeWithWriter(writer);
diff --git a/net/tools/quic/quic_simple_server.h b/net/tools/quic/quic_simple_server.h
index 9edb301..5d62a7b 100644
--- a/net/tools/quic/quic_simple_server.h
+++ b/net/tools/quic/quic_simple_server.h
@@ -19,7 +19,8 @@
 #include "net/quic/core/crypto/quic_crypto_server_config.h"
 #include "net/quic/core/quic_clock.h"
 #include "net/quic/core/quic_config.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/quic/core/quic_version_manager.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 
 namespace net {
 
@@ -39,7 +40,7 @@
       const QuicConfig& config,
       const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
       const QuicVersionVector& supported_versions,
-      QuicInMemoryCache* in_memory_cache);
+      QuicHttpResponseCache* response_cache);
 
   virtual ~QuicSimpleServer();
 
@@ -113,7 +114,7 @@
   // The log to use for the socket.
   NetLog net_log_;
 
-  QuicInMemoryCache* in_memory_cache_;
+  QuicHttpResponseCache* response_cache_;
 
   base::WeakPtrFactory<QuicSimpleServer> weak_factory_;
 
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc
index e8f0c92..a6529836 100644
--- a/net/tools/quic/quic_simple_server_bin.cc
+++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -15,8 +15,8 @@
 #include "net/base/ip_address.h"
 #include "net/base/ip_endpoint.h"
 #include "net/quic/chromium/crypto/proof_source_chromium.h"
-#include "net/quic/core/quic_protocol.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server.h"
 
 // The port the quic server will listen on.
@@ -49,7 +49,7 @@
         "Options:\n"
         "-h, --help                  show this help message and exit\n"
         "--port=<port>               specify the port to listen on\n"
-        "--quic_in_memory_cache_dir  directory containing response data\n"
+        "--quic_response_cache_dir  directory containing response data\n"
         "                            to load\n"
         "--certificate_file=<file>   path to the certificate chain\n"
         "--key_file=<file>           path to the pkcs8 private key\n";
@@ -57,10 +57,10 @@
     exit(0);
   }
 
-  net::QuicInMemoryCache in_memory_cache;
-  if (line->HasSwitch("quic_in_memory_cache_dir")) {
-    in_memory_cache.InitializeFromDirectory(
-        line->GetSwitchValueASCII("quic_in_memory_cache_dir"));
+  net::QuicHttpResponseCache response_cache;
+  if (line->HasSwitch("quic_response_cache_dir")) {
+    response_cache.InitializeFromDirectory(
+        line->GetSwitchValueASCII("quic_response_cache_dir"));
   }
 
   if (line->HasSwitch("port")) {
@@ -87,7 +87,7 @@
       CreateProofSource(line->GetSwitchValuePath("certificate_file"),
                         line->GetSwitchValuePath("key_file")),
       config, net::QuicCryptoServerConfig::ConfigOptions(),
-      net::AllSupportedVersions(), &in_memory_cache);
+      net::AllSupportedVersions(), &response_cache);
 
   int rc = server.Listen(net::IPEndPoint(ip, FLAGS_port));
   if (rc < 0) {
diff --git a/net/tools/quic/quic_simple_server_packet_writer.h b/net/tools/quic/quic_simple_server_packet_writer.h
index 8cbd4c2..74e52b0 100644
--- a/net/tools/quic/quic_simple_server_packet_writer.h
+++ b/net/tools/quic/quic_simple_server_packet_writer.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/tools/quic/quic_simple_server_session.cc b/net/tools/quic/quic_simple_server_session.cc
index 834e587c..8862ae7 100644
--- a/net/tools/quic/quic_simple_server_session.cc
+++ b/net/tools/quic/quic_simple_server_session.cc
@@ -26,7 +26,7 @@
     QuicCryptoServerStream::Helper* helper,
     const QuicCryptoServerConfig* crypto_config,
     QuicCompressedCertsCache* compressed_certs_cache,
-    QuicInMemoryCache* in_memory_cache)
+    QuicHttpResponseCache* response_cache)
     : QuicServerSessionBase(config,
                             connection,
                             visitor,
@@ -34,7 +34,7 @@
                             crypto_config,
                             compressed_certs_cache),
       highest_promised_stream_id_(0),
-      in_memory_cache_(in_memory_cache) {}
+      response_cache_(response_cache) {}
 
 QuicSimpleServerSession::~QuicSimpleServerSession() {
   delete connection();
@@ -69,14 +69,14 @@
 
 void QuicSimpleServerSession::PromisePushResources(
     const string& request_url,
-    const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
+    const std::list<QuicHttpResponseCache::ServerPushInfo>& resources,
     QuicStreamId original_stream_id,
     const SpdyHeaderBlock& original_request_headers) {
   if (!server_push_enabled()) {
     return;
   }
 
-  for (QuicInMemoryCache::ServerPushInfo resource : resources) {
+  for (QuicHttpResponseCache::ServerPushInfo resource : resources) {
     SpdyHeaderBlock headers = SynthesizePushRequestHeaders(
         request_url, resource, original_request_headers);
     highest_promised_stream_id_ += 2;
@@ -97,7 +97,7 @@
   }
 
   QuicSpdyStream* stream =
-      new QuicSimpleServerStream(id, this, in_memory_cache_);
+      new QuicSimpleServerStream(id, this, response_cache_);
   ActivateStream(base::WrapUnique(stream));
   return stream;
 }
@@ -109,7 +109,7 @@
   }
 
   QuicSimpleServerStream* stream = new QuicSimpleServerStream(
-      GetNextOutgoingStreamId(), this, in_memory_cache_);
+      GetNextOutgoingStreamId(), this, response_cache_);
   stream->SetPriority(priority);
   ActivateStream(base::WrapUnique(stream));
   return stream;
@@ -151,7 +151,7 @@
 
 SpdyHeaderBlock QuicSimpleServerSession::SynthesizePushRequestHeaders(
     string request_url,
-    QuicInMemoryCache::ServerPushInfo resource,
+    QuicHttpResponseCache::ServerPushInfo resource,
     const SpdyHeaderBlock& original_request_headers) {
   GURL push_request_url = resource.request_url;
   string path = push_request_url.path();
diff --git a/net/tools/quic/quic_simple_server_session.h b/net/tools/quic/quic_simple_server_session.h
index b098b8a..b8efb35 100644
--- a/net/tools/quic/quic_simple_server_session.h
+++ b/net/tools/quic/quic_simple_server_session.h
@@ -19,10 +19,10 @@
 
 #include "base/macros.h"
 #include "net/quic/core/quic_crypto_server_stream.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_session_base.h"
 #include "net/quic/core/quic_spdy_session.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server_stream.h"
 
 namespace net {
@@ -62,7 +62,7 @@
                           QuicCryptoServerStream::Helper* helper,
                           const QuicCryptoServerConfig* crypto_config,
                           QuicCompressedCertsCache* compressed_certs_cache,
-                          QuicInMemoryCache* in_memory_cache);
+                          QuicHttpResponseCache* response_cache);
 
   ~QuicSimpleServerSession() override;
 
@@ -80,7 +80,7 @@
   // later.
   virtual void PromisePushResources(
       const std::string& request_url,
-      const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
+      const std::list<QuicHttpResponseCache::ServerPushInfo>& resources,
       QuicStreamId original_stream_id,
       const SpdyHeaderBlock& original_request_headers);
 
@@ -103,7 +103,7 @@
       const QuicCryptoServerConfig* crypto_config,
       QuicCompressedCertsCache* compressed_certs_cache) override;
 
-  QuicInMemoryCache* in_memory_cache() { return in_memory_cache_; }
+  QuicHttpResponseCache* response_cache() { return response_cache_; }
 
  private:
   friend class test::QuicSimpleServerSessionPeer;
@@ -116,7 +116,7 @@
   // request, especially cookies.
   SpdyHeaderBlock SynthesizePushRequestHeaders(
       std::string request_url,
-      QuicInMemoryCache::ServerPushInfo resource,
+      QuicHttpResponseCache::ServerPushInfo resource,
       const SpdyHeaderBlock& original_request_headers);
 
   // Send PUSH_PROMISE frame on headers stream.
@@ -150,7 +150,7 @@
   // highest_promised_stream_id_.
   std::deque<PromisedStreamInfo> promised_streams_;
 
-  QuicInMemoryCache* in_memory_cache_;  // Not owned.
+  QuicHttpResponseCache* response_cache_;  // Not owned.
 
   DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerSession);
 };
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc
index 13409e47..f0db44e 100644
--- a/net/tools/quic/quic_simple_server_session_test.cc
+++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -196,7 +196,7 @@
         SupportedVersions(GetParam()));
     session_.reset(new QuicSimpleServerSession(
         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
-        &compressed_certs_cache_, &in_memory_cache_));
+        &compressed_certs_cache_, &response_cache_));
     MockClock clock;
     handshake_message_.reset(crypto_config_.AddDefaultConfig(
         QuicRandom::GetInstance(), &clock,
@@ -217,7 +217,7 @@
   QuicConfig config_;
   QuicCryptoServerConfig crypto_config_;
   QuicCompressedCertsCache compressed_certs_cache_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
   std::unique_ptr<QuicSimpleServerSession> session_;
   std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
   QuicConnectionVisitorInterface* visitor_;
@@ -436,7 +436,7 @@
         SupportedVersions(GetParam()));
     session_.reset(new QuicSimpleServerSession(
         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
-        &compressed_certs_cache_, &in_memory_cache_));
+        &compressed_certs_cache_, &response_cache_));
     session_->Initialize();
     // Needed to make new session flow control window and server push work.
     session_->OnConfigNegotiated();
@@ -469,17 +469,16 @@
     SpdyHeaderBlock request_headers;
     string resource_host = "www.google.com";
     string partial_push_resource_path = "/server_push_src";
-    std::list<QuicInMemoryCache::ServerPushInfo> push_resources;
+    std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
     string scheme = "http";
     for (unsigned int i = 1; i <= num_resources; ++i) {
       QuicStreamId stream_id = i * 2;
       string path = partial_push_resource_path + base::UintToString(i);
       string url = scheme + "://" + resource_host + path;
       GURL resource_url = GURL(url);
-      string body;
-      GenerateBody(&body, body_size);
-      in_memory_cache_.AddSimpleResponse(resource_host, path, 200, body);
-      push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
+      string body(body_size, 'a');
+      response_cache_.AddSimpleResponse(resource_host, path, 200, body);
+      push_resources.push_back(QuicHttpResponseCache::ServerPushInfo(
           resource_url, SpdyHeaderBlock(), kDefaultPriority, body));
       // PUSH_PROMISED are sent for all the resources.
       EXPECT_CALL(*headers_stream_,
diff --git a/net/tools/quic/quic_simple_server_stream.cc b/net/tools/quic/quic_simple_server_stream.cc
index ccfd6835..1d32f9c0 100644
--- a/net/tools/quic/quic_simple_server_stream.cc
+++ b/net/tools/quic/quic_simple_server_stream.cc
@@ -17,7 +17,7 @@
 #include "net/quic/core/quic_spdy_stream.h"
 #include "net/quic/core/spdy_utils.h"
 #include "net/spdy/spdy_protocol.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server_session.h"
 
 using base::StringPiece;
@@ -29,10 +29,10 @@
 QuicSimpleServerStream::QuicSimpleServerStream(
     QuicStreamId id,
     QuicSpdySession* session,
-    QuicInMemoryCache* in_memory_cache)
+    QuicHttpResponseCache* response_cache)
     : QuicSpdyStream(id, session),
       content_length_(-1),
-      in_memory_cache_(in_memory_cache) {}
+      response_cache_(response_cache) {}
 
 QuicSimpleServerStream::~QuicSimpleServerStream() {}
 
@@ -130,11 +130,11 @@
   }
 
   // Find response in cache. If not found, send error response.
-  const QuicInMemoryCache::Response* response = nullptr;
+  const QuicHttpResponseCache::Response* response = nullptr;
   auto authority = request_headers_.find(":authority");
   auto path = request_headers_.find(":path");
   if (authority != request_headers_.end() && path != request_headers_.end()) {
-    response = in_memory_cache_->GetResponse(authority->second, path->second);
+    response = response_cache_->GetResponse(authority->second, path->second);
   }
   if (response == nullptr) {
     DVLOG(1) << "Response not found in cache.";
@@ -142,13 +142,13 @@
     return;
   }
 
-  if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) {
+  if (response->response_type() == QuicHttpResponseCache::CLOSE_CONNECTION) {
     DVLOG(1) << "Special response: closing connection.";
     CloseConnectionWithDetails(QUIC_NO_ERROR, "Toy server forcing close");
     return;
   }
 
-  if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) {
+  if (response->response_type() == QuicHttpResponseCache::IGNORE_REQUEST) {
     DVLOG(1) << "Special response: ignoring request.";
     return;
   }
@@ -184,8 +184,8 @@
       return;
     }
   }
-  std::list<QuicInMemoryCache::ServerPushInfo> resources =
-      in_memory_cache_->GetServerPushResources(request_url);
+  std::list<QuicHttpResponseCache::ServerPushInfo> resources =
+      response_cache_->GetServerPushResources(request_url);
   DVLOG(1) << "Found " << resources.size() << " push resources for stream "
            << id();
 
diff --git a/net/tools/quic/quic_simple_server_stream.h b/net/tools/quic/quic_simple_server_stream.h
index fc23e3b2..7cb1819 100644
--- a/net/tools/quic/quic_simple_server_stream.h
+++ b/net/tools/quic/quic_simple_server_stream.h
@@ -10,10 +10,10 @@
 #include <string>
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_spdy_stream.h"
 #include "net/spdy/spdy_framer.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 
 namespace net {
 
@@ -28,7 +28,7 @@
  public:
   QuicSimpleServerStream(QuicStreamId id,
                          QuicSpdySession* session,
-                         QuicInMemoryCache* in_memory_cache);
+                         QuicHttpResponseCache* response_cache);
   ~QuicSimpleServerStream() override;
 
   // QuicSpdyStream
@@ -83,7 +83,7 @@
   int64_t content_length_;
   std::string body_;
 
-  QuicInMemoryCache* in_memory_cache_;  // Not owned.
+  QuicHttpResponseCache* response_cache_;  // Not owned.
 
   DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerStream);
 };
diff --git a/net/tools/quic/quic_simple_server_stream_test.cc b/net/tools/quic/quic_simple_server_stream_test.cc
index e253b2c..d0764a2 100644
--- a/net/tools/quic/quic_simple_server_stream_test.cc
+++ b/net/tools/quic/quic_simple_server_stream_test.cc
@@ -13,7 +13,7 @@
 #include "base/strings/string_piece.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/core/spdy_utils.h"
 #include "net/quic/platform/api/quic_socket_address.h"
@@ -22,7 +22,7 @@
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "net/test/gtest_util.h"
 #include "net/tools/epoll_server/epoll_server.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server_session.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -55,8 +55,8 @@
  public:
   QuicSimpleServerStreamPeer(QuicStreamId stream_id,
                              QuicSpdySession* session,
-                             QuicInMemoryCache* in_memory_cache)
-      : QuicSimpleServerStream(stream_id, session, in_memory_cache) {}
+                             QuicHttpResponseCache* response_cache)
+      : QuicSimpleServerStream(stream_id, session, response_cache) {}
 
   ~QuicSimpleServerStreamPeer() override{};
 
@@ -96,14 +96,14 @@
       MockQuicCryptoServerStreamHelper* helper,
       QuicCryptoServerConfig* crypto_config,
       QuicCompressedCertsCache* compressed_certs_cache,
-      QuicInMemoryCache* in_memory_cache)
+      QuicHttpResponseCache* response_cache)
       : QuicSimpleServerSession(DefaultQuicConfig(),
                                 connection,
                                 owner,
                                 helper,
                                 crypto_config,
                                 compressed_certs_cache,
-                                in_memory_cache) {
+                                response_cache) {
     set_max_open_incoming_streams(kMaxStreamsForTest);
     set_max_open_outgoing_streams(kMaxStreamsForTest);
     ON_CALL(*this, WritevData(_, _, _, _, _, _))
@@ -155,7 +155,7 @@
   // Matchers cannot be used on non-copyable types like SpdyHeaderBlock.
   void PromisePushResources(
       const string& request_url,
-      const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
+      const std::list<QuicHttpResponseCache::ServerPushInfo>& resources,
       QuicStreamId original_stream_id,
       const SpdyHeaderBlock& original_request_headers) override {
     original_request_headers_ = original_request_headers.Clone();
@@ -164,7 +164,7 @@
   }
   MOCK_METHOD4(PromisePushResourcesMock,
                void(const string&,
-                    const std::list<QuicInMemoryCache::ServerPushInfo>&,
+                    const std::list<QuicHttpResponseCache::ServerPushInfo>&,
                     QuicStreamId,
                     const SpdyHeaderBlock&));
 
@@ -198,7 +198,7 @@
                  &session_helper_,
                  crypto_config_.get(),
                  &compressed_certs_cache_,
-                 &in_memory_cache_),
+                 &response_cache_),
         body_("hello world") {
     header_list_.OnHeaderBlockStart();
     header_list_.OnHeader(":authority", "www.google.com");
@@ -215,7 +215,7 @@
     session_.config()->SetInitialSessionFlowControlWindowToSend(
         kInitialSessionFlowControlWindowForTest);
     stream_ = new QuicSimpleServerStreamPeer(::net::test::kClientDataStreamId1,
-                                             &session_, &in_memory_cache_);
+                                             &session_, &response_cache_);
     // Register stream_ in dynamic_stream_map_ and pass ownership to session_.
     session_.ActivateStream(base::WrapUnique(stream_));
   }
@@ -236,7 +236,7 @@
   StrictMock<MockQuicCryptoServerStreamHelper> session_helper_;
   std::unique_ptr<QuicCryptoServerConfig> crypto_config_;
   QuicCompressedCertsCache compressed_certs_cache_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
   StrictMock<MockQuicSimpleServerSession> session_;
   QuicSimpleServerStreamPeer* stream_;  // Owned by session_.
   string headers_string_;
@@ -324,8 +324,8 @@
   response_headers_[":status"] = "200 OK";
   response_headers_["content-length"] = "5";
   string body = "Yummm";
-  in_memory_cache_.AddResponse("www.google.com", "/bar",
-                               std::move(response_headers_), body);
+  response_cache_.AddResponse("www.google.com", "/bar",
+                              std::move(response_headers_), body);
 
   stream_->set_fin_received(true);
 
@@ -355,8 +355,8 @@
   response_headers_[":status"] = "+200";
   response_headers_["content-length"] = "5";
   string body = "Yummm";
-  in_memory_cache_.AddResponse("www.google.com", "/bar",
-                               std::move(response_headers_), body);
+  response_cache_.AddResponse("www.google.com", "/bar",
+                              std::move(response_headers_), body);
 
   stream_->set_fin_received(true);
 
@@ -376,7 +376,7 @@
 TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) {
   // Create a new promised stream with even id().
   QuicSimpleServerStreamPeer* promised_stream =
-      new QuicSimpleServerStreamPeer(2, &session_, &in_memory_cache_);
+      new QuicSimpleServerStreamPeer(2, &session_, &response_cache_);
   session_.ActivateStream(base::WrapUnique(promised_stream));
 
   // Send a push response with response status 404, which will be regarded as
@@ -391,8 +391,8 @@
   response_headers_[":status"] = "404";
   response_headers_["content-length"] = "8";
   string body = "NotFound";
-  in_memory_cache_.AddResponse("www.google.com", "/bar",
-                               std::move(response_headers_), body);
+  response_cache_.AddResponse("www.google.com", "/bar",
+                              std::move(response_headers_), body);
 
   InSequence s;
   EXPECT_CALL(session_,
@@ -413,8 +413,8 @@
   response_headers_[":status"] = "200";
   response_headers_["content-length"] = "5";
   string body = "Yummm";
-  in_memory_cache_.AddResponse("www.google.com", "/bar",
-                               std::move(response_headers_), body);
+  response_cache_.AddResponse("www.google.com", "/bar",
+                              std::move(response_headers_), body);
   stream_->set_fin_received(true);
 
   InSequence s;
@@ -438,11 +438,11 @@
   string request_path = "/foo";
   string body = "Yummm";
   string url = host + "/bar";
-  QuicInMemoryCache::ServerPushInfo push_info(GURL(url), SpdyHeaderBlock(),
-                                              kDefaultPriority, "Push body");
-  std::list<QuicInMemoryCache::ServerPushInfo> push_resources;
+  QuicHttpResponseCache::ServerPushInfo push_info(
+      GURL(url), SpdyHeaderBlock(), kDefaultPriority, "Push body");
+  std::list<QuicHttpResponseCache::ServerPushInfo> push_resources;
   push_resources.push_back(push_info);
-  in_memory_cache_.AddSimpleResponseWithServerPushResources(
+  response_cache_.AddSimpleResponseWithServerPushResources(
       host, request_path, 200, body, push_resources);
 
   SpdyHeaderBlock* request_headers = stream_->mutable_headers();
@@ -481,7 +481,7 @@
   // Create a server initiated stream and pass it to session_.
   QuicSimpleServerStreamPeer* server_initiated_stream =
       new QuicSimpleServerStreamPeer(kServerInitiatedStreamId, &session_,
-                                     &in_memory_cache_);
+                                     &response_cache_);
   session_.ActivateStream(base::WrapUnique(server_initiated_stream));
 
   const string kHost = "www.foo.com";
@@ -496,8 +496,8 @@
   response_headers_[":status"] = "200";
   response_headers_["content-length"] = "5";
   const string kBody = "Hello";
-  in_memory_cache_.AddResponse(kHost, kPath, std::move(response_headers_),
-                               kBody);
+  response_cache_.AddResponse(kHost, kPath, std::move(response_headers_),
+                              kBody);
 
   // Call PushResponse() should trigger stream to fetch response from cache
   // and send it back.
diff --git a/net/tools/quic/quic_simple_server_test.cc b/net/tools/quic/quic_simple_server_test.cc
index 991bb98..adac378 100644
--- a/net/tools/quic/quic_simple_server_test.cc
+++ b/net/tools/quic/quic_simple_server_test.cc
@@ -36,7 +36,7 @@
             std::unique_ptr<QuicCryptoServerStream::Helper>(
                 new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())),
             std::unique_ptr<MockAlarmFactory>(new net::test::MockAlarmFactory),
-            &in_memory_cache_) {
+            &response_cache_) {
     dispatcher_.InitializeWithWriter(nullptr);
   }
 
@@ -52,7 +52,7 @@
   QuicCryptoServerConfig crypto_config_;
   QuicVersionManager version_manager_;
   net::test::MockQuicDispatcher dispatcher_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
 };
 
 TEST_F(QuicChromeServerDispatchPacketTest, DispatchPacket) {
diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc
index e930d2d0..65ee67b 100644
--- a/net/tools/quic/quic_socket_utils.cc
+++ b/net/tools/quic/quic_socket_utils.cc
@@ -15,7 +15,7 @@
 #include "base/logging.h"
 #include "net/quic/core/quic_bug_tracker.h"
 #include "net/quic/core/quic_flags.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_socket_address.h"
 
 #ifndef SO_RXQ_OVFL
diff --git a/net/tools/quic/quic_spdy_client_stream.h b/net/tools/quic/quic_spdy_client_stream.h
index f87a3821..d2e58c4 100644
--- a/net/tools/quic/quic_spdy_client_stream.h
+++ b/net/tools/quic/quic_spdy_client_stream.h
@@ -11,7 +11,7 @@
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_spdy_stream.h"
 #include "net/spdy/spdy_framer.h"
 
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index c6b339f..0a438c42 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -18,7 +18,7 @@
 #include "net/quic/core/quic_clock.h"
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_framer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_server_session_base.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/platform/api/quic_socket_address.h"
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h
index 87b066f3..17eda88e 100644
--- a/net/tools/quic/quic_time_wait_list_manager.h
+++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -20,7 +20,7 @@
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
 
 namespace net {
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index 7d324f1..60bc1f3 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -15,7 +15,7 @@
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "net/quic/test_tools/quic_time_wait_list_manager_peer.h"
diff --git a/net/tools/quic/stateless_rejector.h b/net/tools/quic/stateless_rejector.h
index e259bb40..acfd818 100644
--- a/net/tools/quic/stateless_rejector.h
+++ b/net/tools/quic/stateless_rejector.h
@@ -8,7 +8,7 @@
 #include "base/strings/string_piece.h"
 #include "net/quic/core/crypto/crypto_framer.h"
 #include "net/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 
 namespace net {
 
diff --git a/net/tools/quic/test_tools/limited_mtu_test_writer.h b/net/tools/quic/test_tools/limited_mtu_test_writer.h
index 9dd13a0..fb43471e 100644
--- a/net/tools/quic/test_tools/limited_mtu_test_writer.h
+++ b/net/tools/quic/test_tools/limited_mtu_test_writer.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/tools/quic/quic_packet_writer_wrapper.h"
 
 namespace net {
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index dced767..d2b9c8d0 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -16,7 +16,7 @@
 #include "net/quic/core/proto/cached_network_parameters.pb.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packet_creator.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/tools/epoll_server/epoll_server.h"
 #include "net/tools/quic/quic_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/net/tools/quic/test_tools/quic_test_server.cc b/net/tools/quic/test_tools/quic_test_server.cc
index 2fb27b3..e5375ff 100644
--- a/net/tools/quic/test_tools/quic_test_server.cc
+++ b/net/tools/quic/test_tools/quic_test_server.cc
@@ -17,7 +17,7 @@
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_packet_writer.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/tools/quic/quic_epoll_alarm_factory.h"
 #include "net/tools/quic/quic_epoll_connection_helper.h"
 #include "net/tools/quic/quic_simple_crypto_server_stream_helper.h"
@@ -39,14 +39,14 @@
       QuicCompressedCertsCache* compressed_certs_cache,
       QuicTestServer::StreamFactory* stream_factory,
       QuicTestServer::CryptoStreamFactory* crypto_stream_factory,
-      QuicInMemoryCache* in_memory_cache)
+      QuicHttpResponseCache* response_cache)
       : QuicSimpleServerSession(config,
                                 connection,
                                 visitor,
                                 helper,
                                 crypto_config,
                                 compressed_certs_cache,
-                                in_memory_cache),
+                                response_cache),
         stream_factory_(stream_factory),
         crypto_stream_factory_(crypto_stream_factory) {}
 
@@ -56,7 +56,7 @@
     }
     if (stream_factory_) {
       QuicSpdyStream* stream =
-          stream_factory_->CreateStream(id, this, in_memory_cache());
+          stream_factory_->CreateStream(id, this, response_cache());
       ActivateStream(base::WrapUnique(stream));
       return stream;
     }
@@ -87,14 +87,14 @@
       std::unique_ptr<QuicConnectionHelperInterface> helper,
       std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
-      QuicInMemoryCache* in_memory_cache)
+      QuicHttpResponseCache* response_cache)
       : QuicSimpleDispatcher(config,
                              crypto_config,
                              version_manager,
                              std::move(helper),
                              std::move(session_helper),
                              std::move(alarm_factory),
-                             in_memory_cache),
+                             response_cache),
         session_factory_(nullptr),
         stream_factory_(nullptr),
         crypto_stream_factory_(nullptr) {}
@@ -117,11 +117,11 @@
       session = new CustomStreamSession(
           config(), connection, this, session_helper(), crypto_config(),
           compressed_certs_cache(), stream_factory_, crypto_stream_factory_,
-          in_memory_cache());
+          response_cache());
     } else {
       session = session_factory_->CreateSession(
           config(), connection, this, session_helper(), crypto_config(),
-          compressed_certs_cache(), in_memory_cache());
+          compressed_certs_cache(), response_cache());
     }
     session->Initialize();
     return session;
@@ -157,18 +157,18 @@
 };
 
 QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source,
-                               QuicInMemoryCache* in_memory_cache)
-    : QuicServer(std::move(proof_source), in_memory_cache) {}
+                               QuicHttpResponseCache* response_cache)
+    : QuicServer(std::move(proof_source), response_cache) {}
 
 QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source,
                                const QuicConfig& config,
                                const QuicVersionVector& supported_versions,
-                               QuicInMemoryCache* in_memory_cache)
+                               QuicHttpResponseCache* response_cache)
     : QuicServer(std::move(proof_source),
                  config,
                  QuicCryptoServerConfig::ConfigOptions(),
                  supported_versions,
-                 in_memory_cache) {}
+                 response_cache) {}
 
 QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
   return new QuicTestDispatcher(
@@ -179,7 +179,7 @@
           new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
       std::unique_ptr<QuicEpollAlarmFactory>(
           new QuicEpollAlarmFactory(epoll_server())),
-      in_memory_cache());
+      response_cache());
 }
 
 void QuicTestServer::SetSessionFactory(SessionFactory* factory) {
@@ -205,14 +205,14 @@
     QuicCryptoServerStream::Helper* helper,
     const QuicCryptoServerConfig* crypto_config,
     QuicCompressedCertsCache* compressed_certs_cache,
-    QuicInMemoryCache* in_memory_cache)
+    QuicHttpResponseCache* response_cache)
     : QuicSimpleServerSession(config,
                               connection,
                               visitor,
                               helper,
                               crypto_config,
                               compressed_certs_cache,
-                              in_memory_cache) {}
+                              response_cache) {}
 
 void ImmediateGoAwaySession::OnStreamFrame(const QuicStreamFrame& frame) {
   SendGoAway(QUIC_PEER_GOING_AWAY, "");
diff --git a/net/tools/quic/test_tools/quic_test_server.h b/net/tools/quic/test_tools/quic_test_server.h
index 3fbce5f6..26a8e766 100644
--- a/net/tools/quic/test_tools/quic_test_server.h
+++ b/net/tools/quic/test_tools/quic_test_server.h
@@ -38,7 +38,7 @@
         QuicCryptoServerStream::Helper* helper,
         const QuicCryptoServerConfig* crypto_config,
         QuicCompressedCertsCache* compressed_certs_cache,
-        QuicInMemoryCache* in_memory_cache) = 0;
+        QuicHttpResponseCache* response_cache) = 0;
   };
 
   // Factory for creating QuicSimpleServerStreams.
@@ -50,7 +50,7 @@
     virtual QuicSimpleServerStream* CreateStream(
         QuicStreamId id,
         QuicSpdySession* session,
-        QuicInMemoryCache* in_memory_cache) = 0;
+        QuicHttpResponseCache* response_cache) = 0;
   };
 
   class CryptoStreamFactory {
@@ -64,11 +64,11 @@
   };
 
   QuicTestServer(std::unique_ptr<ProofSource> proof_source,
-                 QuicInMemoryCache* in_memory_cache);
+                 QuicHttpResponseCache* response_cache);
   QuicTestServer(std::unique_ptr<ProofSource> proof_source,
                  const QuicConfig& config,
                  const QuicVersionVector& supported_versions,
-                 QuicInMemoryCache* in_memory_cache);
+                 QuicHttpResponseCache* response_cache);
 
   // Create a custom dispatcher which creates custom sessions.
   QuicDispatcher* CreateQuicDispatcher() override;
@@ -99,7 +99,7 @@
                          QuicCryptoServerStream::Helper* helper,
                          const QuicCryptoServerConfig* crypto_config,
                          QuicCompressedCertsCache* compressed_certs_cache,
-                         QuicInMemoryCache* in_memory_cache);
+                         QuicHttpResponseCache* response_cache);
 
   // Override to send GoAway.
   void OnStreamFrame(const QuicStreamFrame& frame) override;
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index e3acd8c..1f93bb6 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -35,7 +35,7 @@
 #include "net/net_features.h"
 #include "net/proxy/proxy_config_service.h"
 #include "net/proxy/proxy_service.h"
-#include "net/quic/core/quic_protocol.h"
+#include "net/quic/core/quic_packets.h"
 #include "net/socket/next_proto.h"
 #include "net/url_request/url_request_job_factory.h"
 
diff --git a/net/url_request/url_request_quic_unittest.cc b/net/url_request/url_request_quic_unittest.cc
index 9788128..c285100 100644
--- a/net/url_request/url_request_quic_unittest.cc
+++ b/net/url_request/url_request_quic_unittest.cc
@@ -20,7 +20,7 @@
 #include "net/test/cert_test_util.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_data_directory.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_http_response_cache.h"
 #include "net/tools/quic/quic_simple_server.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
@@ -92,8 +92,8 @@
  private:
   void StartQuicServer() {
     // Set up in-memory cache.
-    in_memory_cache_.AddSimpleResponse(kTestServerHost, kHelloPath,
-                                       kHelloStatus, kHelloBodyValue);
+    response_cache_.AddSimpleResponse(kTestServerHost, kHelloPath, kHelloStatus,
+                                      kHelloBodyValue);
     net::QuicConfig config;
     // Set up server certs.
     std::unique_ptr<net::ProofSourceChromium> proof_source(
@@ -106,7 +106,7 @@
     server_.reset(new QuicSimpleServer(
         test::CryptoTestUtils::ProofSourceForTesting(), config,
         net::QuicCryptoServerConfig::ConfigOptions(), AllSupportedVersions(),
-        &in_memory_cache_));
+        &response_cache_));
     int rv = server_->Listen(
         net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kTestServerPort));
     EXPECT_GE(rv, 0) << "Quic server fails to start";
@@ -124,7 +124,7 @@
   std::unique_ptr<MappedHostResolver> host_resolver_;
   std::unique_ptr<QuicSimpleServer> server_;
   std::unique_ptr<TestURLRequestContext> context_;
-  QuicInMemoryCache in_memory_cache_;
+  QuicHttpResponseCache response_cache_;
   MockCertVerifier cert_verifier_;
 };
 
diff --git a/services/ui/display/BUILD.gn b/services/ui/display/BUILD.gn
index e7d4fe1..76a50667 100644
--- a/services/ui/display/BUILD.gn
+++ b/services/ui/display/BUILD.gn
@@ -30,6 +30,7 @@
     deps += [
       "//services/ui/public/interfaces/display",
       "//skia",
+      "//ui/display/manager",
       "//ui/ozone",
     ]
   } else {
diff --git a/services/ui/display/platform_screen_ozone.h b/services/ui/display/platform_screen_ozone.h
index 1033d11..8e6bf27 100644
--- a/services/ui/display/platform_screen_ozone.h
+++ b/services/ui/display/platform_screen_ozone.h
@@ -19,8 +19,8 @@
 #include "services/ui/display/viewport_metrics.h"
 #include "services/ui/public/interfaces/display/display_controller.mojom.h"
 #include "services/ui/public/interfaces/display/test_display_controller.mojom.h"
-#include "ui/display/chromeos/display_configurator.h"
 #include "ui/display/display.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/display/types/fake_display_controller.h"
 
diff --git a/services/ui/ws/operation.h b/services/ui/ws/operation.h
index 6c98fba..9b6abe6 100644
--- a/services/ui/ws/operation.h
+++ b/services/ui/ws/operation.h
@@ -27,6 +27,7 @@
   REMOVE_WINDOW_FROM_PARENT,
   REORDER_WINDOW,
   SET_CAPTURE,
+  SET_CLIENT_AREA,
   SET_FOCUS,
   SET_WINDOW_BOUNDS,
   SET_WINDOW_OPACITY,
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc
index b75af49..830e8bab 100644
--- a/services/ui/ws/window_tree.cc
+++ b/services/ui/ws/window_tree.cc
@@ -1462,9 +1462,21 @@
                                    transport_additional_client_areas) {
   ServerWindow* window =
       GetWindowByClientId(ClientWindowId(transport_window_id));
-  if (!window || !access_policy_->CanSetClientArea(window))
+  DVLOG(3) << "SetClientArea client window_id=" << transport_window_id
+           << " global window_id="
+           << (window ? WindowIdToTransportId(window->id()) : 0)
+           << " insets=" << insets.top() << " " << insets.left() << " "
+           << insets.bottom() << " " << insets.right();
+  if (!window) {
+    DVLOG(1) << "SetClientArea failed, no window";
     return;
+  }
+  if (!access_policy_->CanSetClientArea(window)) {
+    DVLOG(1) << "SetClientArea failed, access denied";
+    return;
+  }
 
+  Operation op(this, window_server_, OperationType::SET_CLIENT_AREA);
   window->SetClientArea(insets, transport_additional_client_areas.value_or(
                                     std::vector<gfx::Rect>()));
 }
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index d0855c9..b239fa0 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
+import("//build/config/sanitizers/sanitizers.gni")
 import("//printing/features/features.gni")
 import("//testing/test.gni")
 import("//third_party/skia/gn/shared_sources.gni")
@@ -564,7 +565,14 @@
       ]
     }
     source_set("skia_opts_hsw") {
-      sources = skia_opts.hsw_sources
+      # SyzyAsan doesn't support the AVX2 and F16C instructions.
+      if (!is_syzyasan) {
+        sources = skia_opts.hsw_sources
+      } else {
+        sources = [
+          "ext/SkOpts_hsw_stub.cc",
+        ]
+      }
       if (!is_win) {
         cflags = [
           "-mavx2",
@@ -574,7 +582,7 @@
           "-mfma",
         ]
       }
-      if (is_win) {
+      if (is_win && !is_syzyasan) {
         cflags = [ "/arch:AVX2" ]
       }
       visibility = [ ":skia_opts" ]
diff --git a/skia/ext/SkOpts_hsw_stub.cc b/skia/ext/SkOpts_hsw_stub.cc
new file mode 100644
index 0000000..70573c85
--- /dev/null
+++ b/skia/ext/SkOpts_hsw_stub.cc
@@ -0,0 +1,13 @@
+// Copyright 2016 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 is SkOpts_hsw.cpp, stubbed out to do nothing. This is used by the
+// SyzyAsan builds because the Syzygy instrumentation pipeline doesn't support
+// the AVX2 and F16C instructions.
+
+namespace SkOpts {
+    void Init_hsw();
+    void Init_hsw() {}
+}
+
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 3ff58b2..ab95d59 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -212,11 +212,14 @@
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/webkit-margin-collapse-siblings.html [ Skip ]
 
 #### fast/block/float
-#### Passed: 48
-#### Skipped: 149
+#### Passed: 45
+#### Skipped: 152
 crbug.com/635619 virtual/layout_ng/fast/block/float/001.html [ Skip ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/002.html [ Skip ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/003.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/004.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/005.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/006.html [ Skip ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/007.html [ Skip ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/008.html [ Skip ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/009.html [ Skip ]
@@ -1448,8 +1451,8 @@
 crbug.com/487344 [ Mac10.10 Mac10.11 Retina ] virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
 crbug.com/638621 [ Win ] http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
 crbug.com/638621 [ Win ] virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
-crbug.com/646644 [ Mac10.9 ] http/tests/media/video-buffered-range-contains-currentTime.html [ Timeout ]
-crbug.com/646644 [ Mac10.9 ] virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime.html [ Timeout ]
+crbug.com/646644 [ Mac10.9 ] http/tests/media/video-buffered-range-contains-currentTime.html [ Failure Timeout ]
+crbug.com/646644 [ Mac10.9 ] virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure Timeout ]
 
 crbug.com/637930 http/tests/media/video-buffered.html [ Pass Failure ]
 crbug.com/637930 virtual/mojo-loading/http/tests/media/video-buffered.html [ Pass Failure ]
@@ -1628,6 +1631,7 @@
 crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/workers/upload-onprogress-event.html [ Failure ]
 crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/upload-onloadend-event-after-abort.html [ Timeout ]
 crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-sync.html [ Pass Timeout ]
+crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-sync.html [ Pass Timeout ]
 
 crbug.com/669357 virtual/mojo-loading/http/tests/inspector/network/network-fetch.html [ Failure ]
 crbug.com/669357 virtual/mojo-loading/http/tests/inspector-protocol/network-data-length.html [ Failure ]
@@ -1766,8 +1770,6 @@
 crbug.com/664782 images/huge-image-viewport-scale.html [ NeedsRebaseline ]
 crbug.com/664782 virtual/gpu-rasterization/images/huge-image-viewport-scale.html [ NeedsRebaseline ]
 
-crbug.com/661497 inspector/console/console-log-side-effects.html [ NeedsRebaseline ]
-
 crbug.com/475556 virtual/stable/webexposed/global-interface-listing.html [ NeedsRebaseline ]
 
 # [css-ui] Imported tests from W3C suite.
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-drawImage-no-context.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-drawImage-no-context.html
new file mode 100644
index 0000000..e44e9b3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-drawImage-no-context.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+test(function() {
+    var offscreenCanvas = new OffscreenCanvas(100, 50);
+    var ctx = offscreenCanvas.getContext('2d');
+    ctx.fillStyle = "#0f0";
+    ctx.fillRect(0, 0, 100, 50);
+    // The default globalCompositeOperation is source-over, that that will
+    // draw nothing in the next drawImage call. So we have to change it to copy
+    // so that it will actually draw transparent black in the next drawImage
+    // call.
+    ctx.globalCompositeOperation = 'copy';
+    
+    var offscreenCanvas2 = new OffscreenCanvas(100, 50);
+    ctx.drawImage(offscreenCanvas2, 0, 0);
+
+    var clr = ctx.getImageData(50, 25, 1, 1).data;
+    assert_array_equals(clr, [0, 0, 0, 0]);
+}, 'Use OffscreenCanvas without a context as ImageSource should draw transparent black');
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
index b0f0bf1..c2dd0ba 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
@@ -689,16 +689,18 @@
         var disabled = textEditor.hasLineClass(lineNumber, "cm-breakpoint-disabled");
         var conditional = textEditor.hasLineClass(lineNumber, "cm-breakpoint-conditional")
         InspectorTest.addResult("breakpoint at " + lineNumber + (disabled ? " disabled" : "") + (conditional ? " conditional" : ""));
-    }
-    var bookmarks = textEditor.bookmarks(textEditor.fullRange(), Sources.JavaScriptSourceFrame.BreakpointDecoration._bookmarkSymbol);
-    bookmarks = bookmarks.filter(bookmark => !!bookmark.position());
-    bookmarks.sort((bookmark1, bookmark2) => bookmark1.position().startColumn - bookmark2.position().startColumn);
-    for (var bookmark of bookmarks) {
-        var position = bookmark.position();
-        var element = bookmark[Sources.JavaScriptSourceFrame.BreakpointDecoration._elementSymbolForTest];
-        var disabled = element.classList.contains("cm-inline-disabled");
-        var conditional = element.classList.contains("cm-inline-conditional");
-        InspectorTest.addResult("  inline breakpoint at (" + position.startLine + ", " + position.startColumn + ")" + (disabled ? " disabled" : "") + (conditional ? " conditional" : ""));
+
+        var range = new Common.TextRange(lineNumber, 0, lineNumber, textEditor.line(lineNumber).length);
+        var bookmarks = textEditor.bookmarks(range, Sources.JavaScriptSourceFrame.BreakpointDecoration._bookmarkSymbol);
+        bookmarks = bookmarks.filter(bookmark => !!bookmark.position());
+        bookmarks.sort((bookmark1, bookmark2) => bookmark1.position().startColumn - bookmark2.position().startColumn);
+        for (var bookmark of bookmarks) {
+            var position = bookmark.position();
+            var element = bookmark[Sources.JavaScriptSourceFrame.BreakpointDecoration._elementSymbolForTest];
+            var disabled = element.classList.contains("cm-inline-disabled");
+            var conditional = element.classList.contains("cm-inline-conditional");
+            InspectorTest.addResult("  inline breakpoint at (" + position.startLine + ", " + position.startColumn + ")" + (disabled ? " disabled" : "") + (conditional ? " conditional" : ""));
+        }
     }
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-log-side-effects-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-log-side-effects-expected.txt
index da0f2bf8..1699ad06 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-log-side-effects-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-log-side-effects-expected.txt
@@ -6,8 +6,8 @@
 CONSOLE MESSAGE: line 22: NaN
 CONSOLE MESSAGE: line 23: -Infinity
 CONSOLE MESSAGE: line 24: 0
-CONSOLE MESSAGE: line 25: 42.000000
-CONSOLE MESSAGE: line 26: -0.000000
+CONSOLE MESSAGE: line 25: 42.0000
+CONSOLE MESSAGE: line 26: -4.24200e-11
 CONSOLE MESSAGE: line 27: true
 CONSOLE MESSAGE: line 28: foo
 CONSOLE MESSAGE: line 29: [object Object]
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt
index 307bda99..6070515 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt
@@ -28,3 +28,19 @@
   inline breakpoint at (3, 56)
 Click by second breakpoint
 
+Running: toggleBreakpointInAnotherLineWontRemoveExisting
+Setting breakpoint in line 4
+breakpoint at 4
+  inline breakpoint at (4, 9)
+  inline breakpoint at (4, 28) disabled
+  inline breakpoint at (4, 36) disabled
+Setting breakpoint in line 3
+breakpoint at 3
+  inline breakpoint at (3, 49)
+  inline breakpoint at (3, 56) disabled
+breakpoint at 4
+  inline breakpoint at (4, 9)
+  inline breakpoint at (4, 28) disabled
+  inline breakpoint at (4, 36) disabled
+Click by first inline breakpoints
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations.html
index 93329e48..92a7ce8 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations.html
@@ -101,6 +101,35 @@
                 waitAndDumpDecorations(javaScriptSourceFrame).then(() => next());
                 InspectorTest.clickJavaScriptSourceFrameBreakpoint(javaScriptSourceFrame, 3, 1);
             }
+        },
+
+        function toggleBreakpointInAnotherLineWontRemoveExisting(next) {
+            var javaScriptSourceFrame;
+            InspectorTest.showScriptSource("foo.js", addBreakpoint);
+
+            function addBreakpoint(sourceFrame)
+            {
+                javaScriptSourceFrame = sourceFrame;
+                InspectorTest.prepareSourceFrameForBreakpointTest(sourceFrame);
+                InspectorTest.addResult("Setting breakpoint in line 4");
+                InspectorTest.toggleBreakpoint(sourceFrame, 4, false);
+                waitAndDumpDecorations(javaScriptSourceFrame).then(toggleBreakpointInAnotherLine);
+            }
+
+            function toggleBreakpointInAnotherLine()
+            {
+                InspectorTest.addResult("Setting breakpoint in line 3");
+                waitAndDumpDecorations(javaScriptSourceFrame).then(removeBreakpoints);
+                InspectorTest.toggleBreakpoint(javaScriptSourceFrame, 3, false);
+            }
+
+            function removeBreakpoints()
+            {
+                InspectorTest.addResult("Click by first inline breakpoints");
+                waitAndDumpDecorations(javaScriptSourceFrame).then(() => next());
+                InspectorTest.clickJavaScriptSourceFrameBreakpoint(javaScriptSourceFrame, 3, 0);
+                InspectorTest.clickJavaScriptSourceFrameBreakpoint(javaScriptSourceFrame, 4, 0);
+            }
         }
     ]);
 };
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel-expected.png
new file mode 100644
index 0000000..c7498429
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel-expected.txt
new file mode 100644
index 0000000..653cc61
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel-expected.txt
@@ -0,0 +1,7 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x8
+  LayoutBlockFlow {HTML} at (0,0) size 800x8
+    LayoutBlockFlow {BODY} at (8,8) size 784x0
+layer at (699,101) size 101x100
+  LayoutBlockFlow (positioned) {DIV} at (699.41,100.59) size 100.59x100 [bgcolor=#FFFFFF]
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel.html b/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel.html
new file mode 100644
index 0000000..0fbd037a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/rotated-subpixel.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<div id="target" style="
+  position: absolute;
+  top: 100.6px;
+  right: 0;
+  height: 100px;
+  width: 100.6px;
+  transform: rotate(90deg);
+  transform-origin: 100% 0;
+  background-color: red">
+</div>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+runAfterLayoutAndPaint(function() {
+  target.style.backgroundColor = "white";
+}, true);
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset-expected.html
new file mode 100644
index 0000000..94ebe26
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset-expected.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<frameset cols="25%,*,25%">
+  <frame>
+  <frame>
+  <frame>
+</frameset>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset-expected.txt
new file mode 100644
index 0000000..4b7110b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset-expected.txt
@@ -0,0 +1,329 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [600, 250],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutFrameSet FRAMESET",
+          "rect": [0, 0, 600, 500],
+          "reason": "border box change"
+        },
+        {
+          "object": "LayoutView #document",
+          "rect": [0, 250, 600, 250],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [153, 0, 294, 500],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [453, 0, 147, 500],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [0, 0, 147, 500],
+          "reason": "forced by layout"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutView #document",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutFrameSet FRAMESET",
+      "reason": "border box change"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll"
+    },
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll"
+    },
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [400, 250],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutFrameSet FRAMESET",
+          "rect": [0, 0, 600, 250],
+          "reason": "border box change"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [153, 0, 294, 250],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutView #document",
+          "rect": [400, 0, 200, 250],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [103, 0, 194, 250],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [453, 0, 147, 250],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [0, 0, 147, 250],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [303, 0, 97, 250],
+          "reason": "forced by layout"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutView #document",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutFrameSet FRAMESET",
+      "reason": "border box change"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "location change"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "location change"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [400, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutFrameSet FRAMESET",
+          "rect": [0, 0, 400, 600],
+          "reason": "border box change"
+        },
+        {
+          "object": "LayoutView #document",
+          "rect": [0, 250, 400, 350],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [103, 0, 194, 600],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [303, 0, 97, 600],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [0, 0, 97, 600],
+          "reason": "forced by layout"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutView #document",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutFrameSet FRAMESET",
+      "reason": "border box change"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutFrameSet FRAMESET",
+          "rect": [0, 0, 800, 600],
+          "reason": "border box change"
+        },
+        {
+          "object": "LayoutView #document",
+          "rect": [400, 0, 400, 600],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [203, 0, 394, 600],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [603, 0, 197, 600],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [0, 0, 197, 600],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [103, 0, 194, 600],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutFrame FRAME",
+          "rect": [303, 0, 97, 600],
+          "reason": "forced by layout"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutView #document",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutFrameSet FRAMESET",
+      "reason": "border box change"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutFrame FRAME",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "location change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset.html b/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset.html
new file mode 100644
index 0000000..19c3cf11
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/window-resize-frameset.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<script src="resources/window-resize-repaint.js"></script>
+<frameset cols="25%,*,25%">
+  <frame> 
+  <frame>
+  <frame>
+</frameset>
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/animation/computed-style-during-delay-expected.txt b/third_party/WebKit/LayoutTests/platform/android/compositing/animation/computed-style-during-delay-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/compositing/animation/computed-style-during-delay-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/adjacent-html-context-element-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/adjacent-html-context-element-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/adjacent-html-context-element-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/article-element-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/article-element-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/article-element-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/body-offset-properties-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/body-offset-properties-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/body-offset-properties-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/crash-style-first-letter-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/crash-style-first-letter-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/crash-style-first-letter-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/details-element-render-inline-crash-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/details-element-render-inline-crash-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/details-element-render-inline-crash-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/empty-fragment-id-goto-top-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/empty-fragment-id-goto-top-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/empty-fragment-id-goto-top-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/font-face-empty-should-not-crash-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/font-face-empty-should-not-crash-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/font-face-empty-should-not-crash-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/process-end-tag-for-inbody-crash-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/process-end-tag-for-inbody-crash-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/process-end-tag-for-inbody-crash-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/tabindex-removal-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/tabindex-removal-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/tabindex-removal-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/html/xhtml-serialize-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/html/xhtml-serialize-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/html/xhtml-serialize-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/inline/fixed-pos-moves-with-abspos-parent-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/inline/fixed-pos-moves-with-abspos-parent-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/inline/fixed-pos-moves-with-abspos-parent-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/inline/inline-body-crash-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/inline/inline-body-crash-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/inline/inline-body-crash-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/inline/inline-body-with-scrollbar-crash-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/inline/inline-body-with-scrollbar-crash-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/inline/inline-body-with-scrollbar-crash-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/inline/skipped-whitespace-boundingBox-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/inline/skipped-whitespace-boundingBox-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/inline/skipped-whitespace-boundingBox-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/inline/skipped-whitespace-client-rect-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/inline/skipped-whitespace-client-rect-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/inline/skipped-whitespace-client-rect-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/images/link-body-content-imageDimensionChanged-crash-expected.txt b/third_party/WebKit/LayoutTests/platform/android/images/link-body-content-imageDimensionChanged-crash-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/images/link-body-content-imageDimensionChanged-crash-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/android/images/paletted-png-with-color-profile-expected.txt b/third_party/WebKit/LayoutTests/platform/android/images/paletted-png-with-color-profile-expected.txt
deleted file mode 100644
index 231fddb2..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/images/paletted-png-with-color-profile-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
index 29c47d1..0e9a774 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
@@ -29,12 +29,12 @@
         },
         {
           "object": "LayoutSVGRect rect id='rect'",
-          "rect": [354, 127, 105, 102],
+          "rect": [354, 127, 105, 103],
           "reason": "full"
         },
         {
           "object": "LayoutSVGRect rect id='rect'",
-          "rect": [111, 84, 101, 102],
+          "rect": [110, 84, 103, 102],
           "reason": "full"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt
index 8df5a1d..33ee647e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt
@@ -30,6 +30,11 @@
           "object": "LayoutText #text",
           "rect": [300, 302, 80, 176],
           "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [151, 87, 1, 1],
+          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png
deleted file mode 100644
index f08dc03a..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png
index 7ee03bc..10c17fb 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
index f4df5d1..689c7ec8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
@@ -29,12 +29,12 @@
         },
         {
           "object": "LayoutSVGRect rect id='rect'",
-          "rect": [354, 125, 105, 102],
+          "rect": [354, 125, 105, 103],
           "reason": "full"
         },
         {
           "object": "LayoutSVGRect rect id='rect'",
-          "rect": [111, 82, 101, 102],
+          "rect": [110, 82, 103, 102],
           "reason": "full"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt
index b15fac01..04c2773 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt
@@ -30,6 +30,11 @@
           "object": "LayoutText #text",
           "rect": [300, 301, 80, 161],
           "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [147, 85, 1, 1],
+          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png
index 7eb8223..7bddf329d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
index 78fb01b3..8dc60cb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
@@ -29,12 +29,12 @@
         },
         {
           "object": "LayoutSVGRect rect id='rect'",
-          "rect": [354, 125, 105, 102],
+          "rect": [354, 125, 105, 103],
           "reason": "full"
         },
         {
           "object": "LayoutSVGRect rect id='rect'",
-          "rect": [111, 82, 101, 102],
+          "rect": [110, 82, 103, 102],
           "reason": "full"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt
index 1b971517..564b65f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt
@@ -30,6 +30,11 @@
           "object": "LayoutText #text",
           "rect": [300, 301, 80, 160],
           "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [147, 85, 1, 1],
+          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
index 0a55618..ffe1fb198 100644
--- a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
@@ -26,10 +26,10 @@
 
 InterpolationValue SVGLengthInterpolationType::convertSVGLength(
     const SVGLength& length) {
-  const CSSPrimitiveValue* primitiveValue = length.asCSSPrimitiveValue();
+  const CSSPrimitiveValue& primitiveValue = length.asCSSPrimitiveValue();
 
   CSSLengthArray lengthArray;
-  primitiveValue->accumulateLengthArray(lengthArray);
+  primitiveValue.accumulateLengthArray(lengthArray);
 
   std::unique_ptr<InterpolableList> listOfValues =
       InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index 2f0ec93..0fdb26c 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -1294,6 +1294,12 @@
     m_frame->selection().invalidateCaretRect();
 }
 
+void FrameView::setNeedsPaintPropertyUpdate() {
+  m_needsPaintPropertyUpdate = true;
+  if (LayoutObject* owner = frame().ownerLayoutObject())
+    owner->setNeedsPaintPropertyUpdate();
+}
+
 IntRect FrameView::computeVisibleArea() {
   // Return our clipping bounds in the root frame.
   IntRect us(frameRect());
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h
index 34ae469..2078add 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.h
+++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -727,11 +727,18 @@
 
   // Paint properties (e.g., m_preTranslation, etc.) are built from the
   // FrameView's state (e.g., x(), y(), etc.) as well as inherited context.
-  // When these inputs change, setNeedsPaintPropertyUpdate will cause a property
-  // tree update during the next document lifecycle update.
-  // TODO(pdr): Add additional granularity such as the ability to signal that
-  // only a local paint property update is needed.
-  void setNeedsPaintPropertyUpdate() { m_needsPaintPropertyUpdate = true; }
+  // When these inputs change, setNeedsPaintPropertyUpdate will cause a paint
+  // property tree update during the next document lifecycle update.
+  // setNeedsPaintPropertyUpdate also sets the owning layout tree as needing a
+  // paint property update.
+  void setNeedsPaintPropertyUpdate();
+#if DCHECK_IS_ON()
+  // Similar to setNeedsPaintPropertyUpdate() but does not set the owning layout
+  // tree as needing a paint property update.
+  void setOnlyThisNeedsPaintPropertyUpdateForTesting() {
+    m_needsPaintPropertyUpdate = true;
+  }
+#endif
   void clearNeedsPaintPropertyUpdate() {
     DCHECK_EQ(lifecycle().state(), DocumentLifecycle::InPrePaint);
     m_needsPaintPropertyUpdate = false;
diff --git a/third_party/WebKit/Source/core/input/GestureManager.cpp b/third_party/WebKit/Source/core/input/GestureManager.cpp
index 530aa23..0069478 100644
--- a/third_party/WebKit/Source/core/input/GestureManager.cpp
+++ b/third_party/WebKit/Source/core/input/GestureManager.cpp
@@ -375,6 +375,17 @@
       PlatformMouseEvent::FromTouch, WTF::monotonicallyIncreasingTime(),
       WebPointerProperties::PointerType::Mouse);
 
+  if (!m_suppressMouseEventsFromGestures && m_frame->view()) {
+    HitTestRequest request(HitTestRequest::Active);
+    LayoutPoint documentPoint =
+        m_frame->view()->rootFrameToContents(targetedEvent.event().position());
+    MouseEventWithHitTestResults mev =
+        m_frame->document()->performMouseEventHitTest(request, documentPoint,
+                                                      mouseEvent);
+    m_mouseEventManager->handleMouseFocus(
+        mev.hitTestResult(),
+        InputDeviceCapabilities::firesTouchEventsSourceCapabilities());
+  }
   return m_frame->eventHandler().sendContextMenuEvent(mouseEvent);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index 50baae8..8dac83d2 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -316,8 +316,6 @@
     "ng/ng_length_utils.cc",
     "ng/ng_length_utils.h",
     "ng/ng_macros.h",
-    "ng/ng_physical_constraint_space.cc",
-    "ng/ng_physical_constraint_space.h",
     "ng/ng_physical_fragment.cc",
     "ng/ng_physical_fragment.h",
     "ng/ng_physical_fragment_base.cc",
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 604fadd..b5d59c0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2313,9 +2313,7 @@
     // for painted elements within the transform since we don't know the desired
     // subpixel accumulation at this point, and the transform may include a
     // scale.
-    FloatRect floatRect =
-        rect.isEmpty() ? FloatRect(rect) : FloatRect(enclosingIntRect(rect));
-    rect = LayoutRect(layer()->transform()->mapRect(floatRect));
+    rect = LayoutRect(layer()->transform()->mapRect(enclosingIntRect(rect)));
   }
   LayoutPoint topLeft = rect.location();
   if (container->isBox()) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutFrameSet.h b/third_party/WebKit/Source/core/layout/LayoutFrameSet.h
index 3250cbb6..5751f4c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFrameSet.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFrameSet.h
@@ -139,6 +139,10 @@
   void startResizing(GridAxis&, int position);
   void continueResizing(GridAxis&, int position);
 
+  bool paintedOutputOfObjectHasNoEffectRegardlessOfSize() const override {
+    return false;
+  }
+
   LayoutObjectChildList m_children;
 
   GridAxis m_rows;
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 2049367..26ebeb2a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -2735,9 +2735,6 @@
 void LayoutObject::setNeedsPaintPropertyUpdate() {
   m_bitfields.setNeedsPaintPropertyUpdate(true);
 
-  // Mark all ancestors as having a descendant needing paint property updates.
-  // |paintInvalidationParent()| is used to ensure we continue marking across
-  // frame boundaries.
   LayoutObject* ancestor = paintInvalidationParent();
   while (ancestor && !ancestor->descendantNeedsPaintPropertyUpdate()) {
     ancestor->m_bitfields.setDescendantNeedsPaintPropertyUpdate(true);
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index bd0ba94..7e1b0e0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -1737,10 +1737,16 @@
   // tree update during the next document lifecycle update.
   //
   // In addition to tracking if an object needs its own paint properties
-  // updated, |descendantNeedsPaintPropertyUpdate| is used to track if any
-  // descendant needs an update too. This bit is up the tree, crossing frames,
-  // when calling |setNeedsPaintPropertyUpdate|.
+  // updated, setNeedsPaintPropertyUpdate marks all ancestors as having a
+  // descendant needing a paint property update too.
   void setNeedsPaintPropertyUpdate();
+#if DCHECK_IS_ON()
+  // Same as setNeedsPaintPropertyUpdate() but does not mark ancestors as
+  // having a descendant needing a paint property update.
+  void setOnlyThisNeedsPaintPropertyUpdateForTesting() {
+    m_bitfields.setNeedsPaintPropertyUpdate(true);
+  }
+#endif
   bool needsPaintPropertyUpdate() const {
     return m_bitfields.needsPaintPropertyUpdate();
   }
diff --git a/third_party/WebKit/Source/core/layout/README.md b/third_party/WebKit/Source/core/layout/README.md
index 4cdf2f0b..0100895cc 100644
--- a/third_party/WebKit/Source/core/layout/README.md
+++ b/third_party/WebKit/Source/core/layout/README.md
@@ -212,7 +212,7 @@
 
 Values are generally transformed into flipped block-flow coordinates via a set
 of methods on the involved layout objects. See in particular
-`flipForWritingMode()`, `flipForWritingModeForChild()`, and `topLeftLocation()`.
+`flipForWritingMode()`, `flipForWritingModeForChild()`.
 
 `InlineBox::flipForWritingMode()` variants flip the input value within the
 inline box's containing block.
@@ -225,9 +225,21 @@
 and width. This is useful for a common pattern wherein we build up a point
 location starting with the current location of the (child) box.
 
-`LayoutBox::topLeftLocation()` performs flipping as needed. If the containing
-block is not passed to the method, looking it up requires walking up the layout
-tree, which can be expensive.
+For `LayoutBox` and `InlineBox` classes and subclasses:
+
+* `physicalLocation()` returns the physical location of a box or inline in the
+containing block. `(0,0)` is the top-left corner of the containing
+block. Flipping is performed on the values as needed. For `LayoutBox`, if the
+containing block is not passed to `physicalLocation()`, looking it up requires
+walking up the layout tree, which can be
+expensive. `InlineBox::physicalLocation()` is expensive only if the `InlineBox`
+is in flipped block-flow writing mode.
+* `location()` returns the location of a box or inline in the "physical
+coordinates with flipped block-flow direction" coordinate space. `(0,0)` is the
+top-left corner of the containing block for `writing-mode` in normal blocks
+direction (`horizontal-tb` and `vertical-lr`), and is the top-right corner of
+the containing block for `writing-mode` in flipped block-flow direction
+(`vertical-rl`).
 
 Note there are two primary similar, but slightly different, methods regarding
 finding the containing block for an element:
@@ -237,7 +249,7 @@
 * `LayoutObject::containingBlock()` which returns the enclosing non-anonymous
 block for an element. If the containing block is a relatively positioned inline,
 it returns that inline's enclosing non-anonymous block. This is the one used by
-`topLeftLocation()`.
+`physicalLocation()`.
 
 There are other containing block methods in `LayoutObject` for special purposes
 such as fixed position, absolute position, and paint invalidation.  Code will
diff --git a/third_party/WebKit/Source/core/layout/line/InlineBox.h b/third_party/WebKit/Source/core/layout/line/InlineBox.h
index 54b2c9c..95b6c6a 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineBox.h
+++ b/third_party/WebKit/Source/core/layout/line/InlineBox.h
@@ -220,7 +220,7 @@
 
   // x() is the location of the box in the containing block's "physical
   // coordinates with flipped block-flow direction".
-  // See../README.md#Coordinate-Spaces for the definition.
+  // See ../README.md#Coordinate-Spaces for the definition.
   void setX(LayoutUnit x) { m_location.setX(x); }
   LayoutUnit x() const { return m_location.x(); }
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils_test.cc
index d2905ff..9411339 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils_test.cc
@@ -26,18 +26,19 @@
     style_->setBoxSizing(EBoxSizing::BoxSizingBorderBox);
     container_size_ = NGLogicalSize(LayoutUnit(200), LayoutUnit(300));
     NGConstraintSpaceBuilder builder(kHorizontalTopBottom);
-    ltr_space_ = new NGConstraintSpace(
-        kHorizontalTopBottom, LTR,
-        builder.SetAvailableSize(container_size_).ToConstraintSpace());
-    rtl_space_ = new NGConstraintSpace(
-        kHorizontalTopBottom, RTL,
-        builder.SetAvailableSize(container_size_).ToConstraintSpace());
-    vertical_lr_space_ = new NGConstraintSpace(
-        kVerticalLeftRight, LTR,
-        builder.SetAvailableSize(container_size_).ToConstraintSpace());
-    vertical_rl_space_ = new NGConstraintSpace(
-        kVerticalLeftRight, LTR,
-        builder.SetAvailableSize(container_size_).ToConstraintSpace());
+    builder.SetAvailableSize(container_size_);
+    ltr_space_ = builder.SetWritingMode(kHorizontalTopBottom)
+                     .SetTextDirection(LTR)
+                     .ToConstraintSpace();
+    rtl_space_ = builder.SetWritingMode(kHorizontalTopBottom)
+                     .SetTextDirection(RTL)
+                     .ToConstraintSpace();
+    vertical_lr_space_ = builder.SetWritingMode(kVerticalLeftRight)
+                             .SetTextDirection(LTR)
+                             .ToConstraintSpace();
+    vertical_rl_space_ = builder.SetWritingMode(kVerticalLeftRight)
+                             .SetTextDirection(LTR)
+                             .ToConstraintSpace();
   }
 
   void SetHorizontalStyle(LayoutUnit left,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index 224f9bc..bcf798e 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -29,8 +29,8 @@
 void AdjustToClearance(const NGConstraintSpace& space,
                        const ComputedStyle& style,
                        LayoutUnit* content_size) {
-  const NGExclusion* right_exclusion = space.LastRightFloatExclusion();
-  const NGExclusion* left_exclusion = space.LastLeftFloatExclusion();
+  const NGExclusion* right_exclusion = space.Exclusions()->last_right_float;
+  const NGExclusion* left_exclusion = space.Exclusions()->last_left_float;
 
   // Calculates Left/Right block end offset from left/right float exclusions or
   // use the default content offset position.
@@ -218,8 +218,7 @@
       if (adjusted_block_size != NGSizeIndefinite)
         adjusted_block_size -= border_and_padding_.BlockSum();
 
-      space_builder_ =
-          new NGConstraintSpaceBuilder(constraint_space_->WritingMode());
+      space_builder_ = new NGConstraintSpaceBuilder(constraint_space_);
       if (Style().specifiesColumns()) {
         space_builder_->SetFragmentationType(kFragmentColumn);
         adjusted_inline_size =
@@ -429,19 +428,11 @@
   space_builder_->SetIsNewFormattingContext(
       IsNewFormattingContextForInFlowBlockLevelChild(ConstraintSpace(),
                                                      CurrentChildStyle()));
-  NGConstraintSpace* child_space = new NGConstraintSpace(
-      constraint_space_->WritingMode(), constraint_space_->Direction(),
-      space_builder_->ToConstraintSpace());
+  NGConstraintSpace* child_space = space_builder_->ToConstraintSpace();
 
   // TODO(layout-ng): Set offset through the space builder.
   child_space->SetOffset(
       NGLogicalOffset(border_and_padding_.inline_start, content_size_));
-
-  // TODO(layout-ng): avoid copying here. A child and parent constraint spaces
-  // should share the same backing space.
-  for (const auto& exclusion : constraint_space_->Exclusions()) {
-    child_space->AddExclusion(*exclusion.get());
-  }
   return child_space;
 }
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
index 3940810..7ba9e05 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -20,11 +20,11 @@
 NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode,
                                             TextDirection direction,
                                             NGLogicalSize size) {
-  NGConstraintSpaceBuilder builder(writing_mode);
-  builder.SetAvailableSize(size).SetPercentageResolutionSize(size);
-
-  return new NGConstraintSpace(writing_mode, direction,
-                               builder.ToConstraintSpace());
+  return NGConstraintSpaceBuilder(writing_mode)
+      .SetAvailableSize(size)
+      .SetPercentageResolutionSize(size)
+      .SetTextDirection(direction)
+      .ToConstraintSpace();
 }
 
 class NGBlockLayoutAlgorithmTest : public ::testing::Test {
@@ -167,14 +167,14 @@
 
   div1->SetFirstChild(div2);
 
-  NGLogicalSize size(LayoutUnit(100), NGSizeIndefinite);
-  NGConstraintSpaceBuilder builder(kHorizontalTopBottom);
-  builder.SetAvailableSize(size)
-      .SetPercentageResolutionSize(size)
-      .SetIsNewFormattingContext(true);
-  auto* space = new NGConstraintSpace(kHorizontalTopBottom, LTR,
-                                      builder.ToConstraintSpace());
-
+  auto* space =
+      NGConstraintSpaceBuilder(kHorizontalTopBottom)
+          .SetAvailableSize(NGLogicalSize(LayoutUnit(100), NGSizeIndefinite))
+          .SetPercentageResolutionSize(
+              NGLogicalSize(LayoutUnit(100), NGSizeIndefinite))
+          .SetTextDirection(LTR)
+          .SetIsNewFormattingContext(true)
+          .ToConstraintSpace();
   NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
 
   EXPECT_TRUE(frag->MarginStrut().IsEmpty());
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
index 3a652003..91753db 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -100,9 +100,11 @@
     // TODO(layoutng): Use builder.ToConstraintSpace.ToLogicalConstraintSpace
     // once
     // that's available.
-    NGConstraintSpace* constraint_space = new NGConstraintSpace(
-        FromPlatformWritingMode(Style()->getWritingMode()),
-        Style()->direction(), builder.ToConstraintSpace());
+    NGConstraintSpace* constraint_space =
+        NGConstraintSpaceBuilder(
+            FromPlatformWritingMode(Style()->getWritingMode()))
+            .SetTextDirection(Style()->direction())
+            .ToConstraintSpace();
 
     minmax_algorithm_ = new NGBlockLayoutAlgorithm(
         Style(), toNGBlockNode(FirstChild()), constraint_space);
@@ -130,14 +132,13 @@
   sizes->min_content = fragment->InlineOverflow();
 
   // Now, redo with infinite space for max_content
-  NGConstraintSpaceBuilder builder(
-      FromPlatformWritingMode(Style()->getWritingMode()));
-  builder.SetAvailableSize(NGLogicalSize(LayoutUnit::max(), LayoutUnit()));
-  builder.SetPercentageResolutionSize(
-      NGLogicalSize(LayoutUnit(), LayoutUnit()));
   NGConstraintSpace* constraint_space =
-      new NGConstraintSpace(FromPlatformWritingMode(Style()->getWritingMode()),
-                            Style()->direction(), builder.ToConstraintSpace());
+      NGConstraintSpaceBuilder(
+          FromPlatformWritingMode(Style()->getWritingMode()))
+          .SetTextDirection(Style()->direction())
+          .SetAvailableSize({LayoutUnit::max(), LayoutUnit()})
+          .SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()})
+          .ToConstraintSpace();
 
   minmax_algorithm_ = new NGBlockLayoutAlgorithm(
       Style(), toNGBlockNode(FirstChild()), constraint_space);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
index 79a201be..a415147 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
@@ -13,12 +13,31 @@
 
 namespace blink {
 
-NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode,
-                                     TextDirection direction,
-                                     NGPhysicalConstraintSpace* physical_space)
-    : physical_space_(physical_space),
+NGConstraintSpace::NGConstraintSpace(
+    NGWritingMode writing_mode,
+    TextDirection direction,
+    NGLogicalSize available_size,
+    NGLogicalSize percentage_resolution_size,
+    bool is_fixed_size_inline,
+    bool is_fixed_size_block,
+    bool is_inline_direction_triggers_scrollbar,
+    bool is_block_direction_triggers_scrollbar,
+    NGFragmentationType block_direction_fragmentation_type,
+    bool is_new_fc,
+    const std::shared_ptr<NGExclusions>& exclusions_)
+    : available_size_(available_size),
+      percentage_resolution_size_(percentage_resolution_size),
+      is_fixed_size_inline_(is_fixed_size_inline),
+      is_fixed_size_block_(is_fixed_size_block),
+      is_inline_direction_triggers_scrollbar_(
+          is_inline_direction_triggers_scrollbar),
+      is_block_direction_triggers_scrollbar_(
+          is_block_direction_triggers_scrollbar),
+      block_direction_fragmentation_type_(block_direction_fragmentation_type),
+      is_new_fc_(is_new_fc),
       writing_mode_(writing_mode),
-      direction_(direction) {}
+      direction_(direction),
+      exclusions_(exclusions_) {}
 
 NGConstraintSpace* NGConstraintSpace::CreateFromLayoutObject(
     const LayoutBox& box) {
@@ -50,85 +69,28 @@
   bool is_new_fc =
       box.isLayoutBlock() && toLayoutBlock(box).createsNewFormattingContext();
 
-  NGConstraintSpaceBuilder builder(
-      FromPlatformWritingMode(box.styleRef().getWritingMode()));
-  builder
-      .SetAvailableSize(
-          NGLogicalSize(available_logical_width, available_logical_height))
-      .SetPercentageResolutionSize(
-          NGLogicalSize(available_logical_width, available_logical_height))
+  NGLogicalSize size = {available_logical_width, available_logical_height};
+  auto writing_mode = FromPlatformWritingMode(box.styleRef().getWritingMode());
+  return NGConstraintSpaceBuilder(writing_mode)
+      .SetAvailableSize(size)
+      .SetPercentageResolutionSize(size)
       .SetIsInlineDirectionTriggersScrollbar(
           box.styleRef().overflowInlineDirection() == OverflowAuto)
       .SetIsBlockDirectionTriggersScrollbar(
           box.styleRef().overflowBlockDirection() == OverflowAuto)
       .SetIsFixedSizeInline(fixed_inline)
       .SetIsFixedSizeBlock(fixed_block)
-      .SetIsNewFormattingContext(is_new_fc);
-
-  return new NGConstraintSpace(
-      FromPlatformWritingMode(box.styleRef().getWritingMode()),
-      box.styleRef().direction(), builder.ToConstraintSpace());
+      .SetIsNewFormattingContext(is_new_fc)
+      .SetTextDirection(box.styleRef().direction())
+      .ToConstraintSpace();
 }
 
-void NGConstraintSpace::AddExclusion(const NGExclusion& exclusion) const {
-  WRITING_MODE_IGNORED(
-      "Exclusions are stored directly in physical constraint space.");
-  MutablePhysicalSpace()->AddExclusion(exclusion);
-}
-
-const NGExclusion* NGConstraintSpace::LastLeftFloatExclusion() const {
-  WRITING_MODE_IGNORED(
-      "Exclusions are stored directly in physical constraint space.");
-  return PhysicalSpace()->LastLeftFloatExclusion();
-}
-
-const NGExclusion* NGConstraintSpace::LastRightFloatExclusion() const {
-  WRITING_MODE_IGNORED(
-      "Exclusions are stored directly in physical constraint space.");
-  return PhysicalSpace()->LastRightFloatExclusion();
-}
-
-NGLogicalSize NGConstraintSpace::PercentageResolutionSize() const {
-  return physical_space_->percentage_resolution_size_.ConvertToLogical(
-      static_cast<NGWritingMode>(writing_mode_));
-}
-
-NGLogicalSize NGConstraintSpace::AvailableSize() const {
-  return physical_space_->available_size_.ConvertToLogical(
-      static_cast<NGWritingMode>(writing_mode_));
-}
-
-bool NGConstraintSpace::IsNewFormattingContext() const {
-  return physical_space_->is_new_fc_;
-}
-
-bool NGConstraintSpace::InlineTriggersScrollbar() const {
-  return writing_mode_ == kHorizontalTopBottom
-             ? physical_space_->width_direction_triggers_scrollbar_
-             : physical_space_->height_direction_triggers_scrollbar_;
-}
-
-bool NGConstraintSpace::BlockTriggersScrollbar() const {
-  return writing_mode_ == kHorizontalTopBottom
-             ? physical_space_->height_direction_triggers_scrollbar_
-             : physical_space_->width_direction_triggers_scrollbar_;
-}
-
-bool NGConstraintSpace::FixedInlineSize() const {
-  return writing_mode_ == kHorizontalTopBottom ? physical_space_->fixed_width_
-                                               : physical_space_->fixed_height_;
-}
-
-bool NGConstraintSpace::FixedBlockSize() const {
-  return writing_mode_ == kHorizontalTopBottom ? physical_space_->fixed_height_
-                                               : physical_space_->fixed_width_;
+void NGConstraintSpace::AddExclusion(const NGExclusion& exclusion) {
+  exclusions_->Add(exclusion);
 }
 
 NGFragmentationType NGConstraintSpace::BlockFragmentationType() const {
-  return static_cast<NGFragmentationType>(
-      writing_mode_ == kHorizontalTopBottom
-          ? physical_space_->height_direction_fragmentation_type_
-          : physical_space_->width_direction_fragmentation_type_);
+  return static_cast<NGFragmentationType>(block_direction_fragmentation_type_);
 }
 
 void NGConstraintSpace::Subtract(const NGFragment*) {
@@ -144,8 +106,10 @@
 
 NGConstraintSpace* NGConstraintSpace::ChildSpace(
     const ComputedStyle* style) const {
-  return new NGConstraintSpace(FromPlatformWritingMode(style->getWritingMode()),
-                               style->direction(), MutablePhysicalSpace());
+  return NGConstraintSpaceBuilder(this)
+      .SetWritingMode(FromPlatformWritingMode(style->getWritingMode()))
+      .SetTextDirection(style->direction())
+      .ToConstraintSpace();
 }
 
 String NGConstraintSpace::ToString() const {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
index 7124e1a..56e0daaf 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
@@ -7,7 +7,7 @@
 
 #include "core/CoreExport.h"
 #include "core/layout/ng/ng_macros.h"
-#include "core/layout/ng/ng_physical_constraint_space.h"
+#include "core/layout/ng/ng_units.h"
 #include "core/layout/ng/ng_writing_mode.h"
 #include "platform/heap/Handle.h"
 #include "wtf/text/WTFString.h"
@@ -20,39 +20,32 @@
 class NGFragment;
 class NGLayoutOpportunityIterator;
 
-// The NGConstraintSpace represents a set of constraints and available space
-// which a layout algorithm may produce a NGFragment within. It is a view on
-// top of a NGPhysicalConstraintSpace and provides accessor methods in the
-// logical coordinate system defined by the writing mode given.
-class CORE_EXPORT NGConstraintSpace final
-    : public GarbageCollected<NGConstraintSpace> {
- public:
-  // Constructs a constraint space based on an existing backing
-  // NGPhysicalConstraintSpace. Sets this constraint space's size to the
-  // physical constraint space's available size, converted to logical
-  // coordinates.
-  NGConstraintSpace(NGWritingMode, TextDirection, NGPhysicalConstraintSpace*);
+// TODO(glebl@): unused, delete.
+enum NGExclusionType {
+  kNGClearNone = 0,
+  kNGClearFloatLeft = 1,
+  kNGClearFloatRight = 2,
+  kNGClearFragment = 4
+};
 
+enum NGFragmentationType {
+  kFragmentNone,
+  kFragmentPage,
+  kFragmentColumn,
+  kFragmentRegion
+};
+
+// The NGConstraintSpace represents a set of constraints and available space
+// which a layout algorithm may produce a NGFragment within.
+class CORE_EXPORT NGConstraintSpace final
+    : public GarbageCollectedFinalized<NGConstraintSpace> {
+ public:
   // This should live on NGBlockNode or another layout bridge and probably take
-  // a root
-  // NGConstraintSpace or a NGPhysicalConstraintSpace.
+  // a root NGConstraintSpace.
   static NGConstraintSpace* CreateFromLayoutObject(const LayoutBox&);
 
-  // Mutable Getters.
-  // TODO(layout-dev): remove const constraint from MutablePhysicalSpace method
-  NGPhysicalConstraintSpace* MutablePhysicalSpace() const {
-    return physical_space_;
-  }
-
-  // Read-only Getters.
-  const NGPhysicalConstraintSpace* PhysicalSpace() const {
-    return physical_space_;
-  }
-
-  const Vector<std::unique_ptr<const NGExclusion>>& Exclusions() const {
-    WRITING_MODE_IGNORED(
-        "Exclusions are stored directly in physical constraint space.");
-    return PhysicalSpace()->Exclusions();
+  const std::shared_ptr<NGExclusions>& Exclusions() const {
+    return exclusions_;
   }
 
   TextDirection Direction() const {
@@ -63,40 +56,46 @@
     return static_cast<NGWritingMode>(writing_mode_);
   }
 
-  // Adds the exclusion in the physical constraint space.
-  void AddExclusion(const NGExclusion& exclusion) const;
-  const NGExclusion* LastLeftFloatExclusion() const;
-  const NGExclusion* LastRightFloatExclusion() const;
+  void AddExclusion(const NGExclusion& exclusion);
 
   // The size to use for percentage resolution.
   // See: https://drafts.csswg.org/css-sizing/#percentage-sizing
-  NGLogicalSize PercentageResolutionSize() const;
+  NGLogicalSize PercentageResolutionSize() const {
+    return percentage_resolution_size_;
+  }
 
   // The available space size.
   // See: https://drafts.csswg.org/css-sizing/#available
-  NGLogicalSize AvailableSize() const;
+  NGLogicalSize AvailableSize() const { return available_size_; }
 
   // Offset relative to the root constraint space.
   NGLogicalOffset Offset() const { return offset_; }
+  // TODO(layout-ng): Set offset via NGConstraintSpacebuilder.
   void SetOffset(const NGLogicalOffset& offset) { offset_ = offset; }
 
   // Whether the current constraint space is for the newly established
   // Formatting Context.
-  bool IsNewFormattingContext() const;
+  bool IsNewFormattingContext() const { return is_new_fc_; }
 
   // Whether exceeding the AvailableSize() triggers the presence of a scrollbar
   // for the indicated direction.
   // If exceeded the current layout should be aborted and invoked again with a
   // constraint space modified to reserve space for a scrollbar.
-  bool InlineTriggersScrollbar() const;
-  bool BlockTriggersScrollbar() const;
+  bool IsInlineDirectionTriggersScrollbar() const {
+    return is_inline_direction_triggers_scrollbar_;
+  }
+
+  bool IsBlockDirectionTriggersScrollbar() const {
+    return is_block_direction_triggers_scrollbar_;
+  }
 
   // Some layout modes “stretch” their children to a fixed size (e.g. flex,
   // grid). These flags represented whether a layout needs to produce a
   // fragment that satisfies a fixed constraint in the inline and block
   // direction respectively.
-  bool FixedInlineSize() const;
-  bool FixedBlockSize() const;
+  bool IsFixedSizeInline() const { return is_fixed_size_inline_; }
+
+  bool IsFixedSizeBlock() const { return is_fixed_size_block_; }
 
   // If specified a layout should produce a Fragment which fragments at the
   // blockSize if possible.
@@ -111,17 +110,46 @@
       unsigned clear = kNGClearNone,
       bool for_inline_or_bfc = false);
 
-  DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(physical_space_); }
+  DEFINE_INLINE_VIRTUAL_TRACE() {}
 
   NGConstraintSpace* ChildSpace(const ComputedStyle* style) const;
-
   String ToString() const;
 
  private:
-  Member<NGPhysicalConstraintSpace> physical_space_;
+  friend class NGConstraintSpaceBuilder;
+  // Default constructor.
+  NGConstraintSpace(NGWritingMode,
+                    TextDirection,
+                    NGLogicalSize available_size,
+                    NGLogicalSize percentage_resolution_size,
+                    bool is_fixed_size_inline,
+                    bool is_fixed_size_block,
+                    bool is_inline_direction_triggers_scrollbar,
+                    bool is_block_direction_triggers_scrollbar,
+                    NGFragmentationType block_direction_fragmentation_type,
+                    bool is_new_fc,
+                    const std::shared_ptr<NGExclusions>& exclusions_);
+
+  NGLogicalSize available_size_;
+  NGLogicalSize percentage_resolution_size_;
+
+  unsigned is_fixed_size_inline_ : 1;
+  unsigned is_fixed_size_block_ : 1;
+
+  unsigned is_inline_direction_triggers_scrollbar_ : 1;
+  unsigned is_block_direction_triggers_scrollbar_ : 1;
+
+  unsigned block_direction_fragmentation_type_ : 2;
+
+  // Whether the current constraint space is for the newly established
+  // formatting Context
+  unsigned is_new_fc_ : 1;
+
   NGLogicalOffset offset_;
   unsigned writing_mode_ : 3;
   unsigned direction_ : 1;
+
+  const std::shared_ptr<NGExclusions> exclusions_;
 };
 
 inline std::ostream& operator<<(std::ostream& stream,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
index f4981db4f..921f53f2 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
@@ -6,14 +6,32 @@
 
 namespace blink {
 
-NGConstraintSpaceBuilder::NGConstraintSpaceBuilder(NGWritingMode writing_mode)
-    : writing_mode_(writing_mode),
+NGConstraintSpaceBuilder::NGConstraintSpaceBuilder(
+    const NGConstraintSpace* parent_space)
+    : available_size_(parent_space->AvailableSize()),
+      percentage_resolution_size_(parent_space->PercentageResolutionSize()),
+      writing_mode_(parent_space->WritingMode()),
+      parent_writing_mode_(writing_mode_),
       is_fixed_size_inline_(false),
       is_fixed_size_block_(false),
       is_inline_direction_triggers_scrollbar_(false),
       is_block_direction_triggers_scrollbar_(false),
-      fragmentation_type_(NGFragmentationType::kFragmentNone),
-      is_new_fc_(false) {}
+      fragmentation_type_(kFragmentNone),
+      is_new_fc_(parent_space->IsNewFormattingContext()),
+      text_direction_(parent_space->Direction()),
+      exclusions_(parent_space->Exclusions()) {}
+
+NGConstraintSpaceBuilder::NGConstraintSpaceBuilder(NGWritingMode writing_mode)
+    : writing_mode_(writing_mode),
+      parent_writing_mode_(writing_mode_),
+      is_fixed_size_inline_(false),
+      is_fixed_size_block_(false),
+      is_inline_direction_triggers_scrollbar_(false),
+      is_block_direction_triggers_scrollbar_(false),
+      fragmentation_type_(kFragmentNone),
+      is_new_fc_(false),
+      text_direction_(TextDirection::LTR),
+      exclusions_(new NGExclusions()) {}
 
 NGConstraintSpaceBuilder& NGConstraintSpaceBuilder::SetAvailableSize(
     NGLogicalSize available_size) {
@@ -27,6 +45,12 @@
   return *this;
 }
 
+NGConstraintSpaceBuilder& NGConstraintSpaceBuilder::SetTextDirection(
+    TextDirection text_direction) {
+  text_direction_ = text_direction;
+  return *this;
+}
+
 NGConstraintSpaceBuilder& NGConstraintSpaceBuilder::SetIsFixedSizeInline(
     bool is_fixed_size_inline) {
   is_fixed_size_inline_ = is_fixed_size_inline;
@@ -67,27 +91,47 @@
   return *this;
 }
 
-NGPhysicalConstraintSpace* NGConstraintSpaceBuilder::ToConstraintSpace() {
-  NGPhysicalSize available_size = available_size_.ConvertToPhysical(
-      static_cast<NGWritingMode>(writing_mode_));
-  NGPhysicalSize percentage_resolution_size =
-      percentage_resolution_size_.ConvertToPhysical(
-          static_cast<NGWritingMode>(writing_mode_));
+NGConstraintSpaceBuilder& NGConstraintSpaceBuilder::SetWritingMode(
+    NGWritingMode writing_mode) {
+  writing_mode_ = writing_mode;
+  return *this;
+}
 
-  if (writing_mode_ == kHorizontalTopBottom) {
-    return new NGPhysicalConstraintSpace(
-        available_size, percentage_resolution_size, is_fixed_size_inline_,
-        is_fixed_size_block_, is_inline_direction_triggers_scrollbar_,
-        is_block_direction_triggers_scrollbar_, kFragmentNone,
-        static_cast<NGFragmentationType>(fragmentation_type_), is_new_fc_);
-  } else {
-    return new NGPhysicalConstraintSpace(
-        available_size, percentage_resolution_size, is_fixed_size_block_,
-        is_fixed_size_inline_, is_block_direction_triggers_scrollbar_,
+NGConstraintSpace* NGConstraintSpaceBuilder::ToConstraintSpace() {
+  // Exclusions do not pass the formatting context boundary.
+  std::shared_ptr<NGExclusions> exclusions(
+      is_new_fc_ ? std::make_shared<NGExclusions>() : exclusions_);
+
+  // Whether the child and the containing block are parallel to each other.
+  // Example: vertical-rl and vertical-lr
+  bool is_in_parallel_flow = (parent_writing_mode_ == kHorizontalTopBottom) ==
+                             (writing_mode_ == kHorizontalTopBottom);
+
+  if (is_in_parallel_flow) {
+    return new NGConstraintSpace(
+        static_cast<NGWritingMode>(writing_mode_),
+        static_cast<TextDirection>(text_direction_),
+        {available_size_.inline_size, available_size_.block_size},
+        {percentage_resolution_size_.inline_size,
+         percentage_resolution_size_.block_size},
+        is_fixed_size_inline_, is_fixed_size_block_,
         is_inline_direction_triggers_scrollbar_,
-        static_cast<NGFragmentationType>(fragmentation_type_), kFragmentNone,
-        is_new_fc_);
+        is_block_direction_triggers_scrollbar_,
+        static_cast<NGFragmentationType>(fragmentation_type_), is_new_fc_,
+        exclusions);
   }
+
+  return new NGConstraintSpace(
+      static_cast<NGWritingMode>(writing_mode_),
+      static_cast<TextDirection>(text_direction_),
+      {available_size_.block_size, available_size_.inline_size},
+      {percentage_resolution_size_.block_size,
+       percentage_resolution_size_.inline_size},
+      is_fixed_size_block_, is_fixed_size_inline_,
+      is_block_direction_triggers_scrollbar_,
+      is_inline_direction_triggers_scrollbar_,
+      static_cast<NGFragmentationType>(fragmentation_type_), is_new_fc_,
+      exclusions);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h
index 3f37ac8..ccff60e 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.h
@@ -11,8 +11,10 @@
 namespace blink {
 
 class CORE_EXPORT NGConstraintSpaceBuilder final
-    : public GarbageCollected<NGConstraintSpaceBuilder> {
+    : public GarbageCollectedFinalized<NGConstraintSpaceBuilder> {
  public:
+  NGConstraintSpaceBuilder(const NGConstraintSpace* parent_space);
+
   NGConstraintSpaceBuilder(NGWritingMode writing_mode);
 
   NGConstraintSpaceBuilder& SetAvailableSize(NGLogicalSize available_size);
@@ -20,6 +22,8 @@
   NGConstraintSpaceBuilder& SetPercentageResolutionSize(
       NGLogicalSize percentage_resolution_size);
 
+  NGConstraintSpaceBuilder& SetTextDirection(TextDirection);
+
   NGConstraintSpaceBuilder& SetIsFixedSizeInline(bool is_fixed_size_inline);
   NGConstraintSpaceBuilder& SetIsFixedSizeBlock(bool is_fixed_size_block);
 
@@ -31,13 +35,15 @@
   NGConstraintSpaceBuilder& SetFragmentationType(NGFragmentationType);
   NGConstraintSpaceBuilder& SetIsNewFormattingContext(bool is_new_fc);
 
+  NGConstraintSpaceBuilder& SetWritingMode(NGWritingMode writing_mode);
+
   // Creates a new constraint space. This may be called multiple times, for
   // example the constraint space will be different for a child which:
   //  - Establishes a new formatting context.
   //  - Is within a fragmentation container and needs its fragmentation offset
   //    updated.
   //  - Has its size is determined by its parent layout (flex, abs-pos).
-  NGPhysicalConstraintSpace* ToConstraintSpace();
+  NGConstraintSpace* ToConstraintSpace();
 
   DEFINE_INLINE_TRACE() {}
 
@@ -45,16 +51,17 @@
   NGLogicalSize available_size_;
   NGLogicalSize percentage_resolution_size_;
 
-  // const bit fields.
-  const unsigned writing_mode_ : 2;
-
-  // mutable bit fields.
+  unsigned writing_mode_ : 2;
+  unsigned parent_writing_mode_ : 2;
   unsigned is_fixed_size_inline_ : 1;
   unsigned is_fixed_size_block_ : 1;
   unsigned is_inline_direction_triggers_scrollbar_ : 1;
   unsigned is_block_direction_triggers_scrollbar_ : 1;
   unsigned fragmentation_type_ : 2;
   unsigned is_new_fc_ : 1;
+  unsigned text_direction_ : 1;
+
+  std::shared_ptr<NGExclusions> exclusions_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc
index 278d14d..942d384a 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc
@@ -5,8 +5,8 @@
 #include "core/layout/ng/ng_constraint_space.h"
 
 #include "core/layout/ng/ng_constraint_space.h"
+#include "core/layout/ng/ng_constraint_space_builder.h"
 #include "core/layout/ng/ng_layout_opportunity_iterator.h"
-#include "core/layout/ng/ng_physical_constraint_space.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -15,50 +15,15 @@
 
 NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode,
                                             TextDirection direction,
-                                            NGPhysicalSize size) {
-  return new NGConstraintSpace(
-      writing_mode, direction,
-      new NGPhysicalConstraintSpace(
-          size, size, /* fixed_width */ true, /* fixed_height */ false,
-          /* width_direction_triggers_scrollbar */ true,
-          /* height_direction_triggers_scrollbar */ false, kFragmentNone,
-          kFragmentColumn, /* is_new_fc */ false));
-}
-
-TEST(NGConstraintSpaceTest, WritingMode) {
-  NGPhysicalConstraintSpace* phy_space = new NGPhysicalConstraintSpace(
-      NGPhysicalSize(LayoutUnit(200), LayoutUnit(100)),
-      NGPhysicalSize(LayoutUnit(200), LayoutUnit(100)), /* fixed_width */ true,
-      /* fixed_height */ false, /* width_direction_triggers_scrollbar */ true,
-      /* height_direction_triggers_scrollbar */ false, kFragmentNone,
-      kFragmentColumn, /* is_new_fc */ false);
-
-  NGConstraintSpace* horz_space =
-      new NGConstraintSpace(kHorizontalTopBottom, LTR, phy_space);
-
-  NGConstraintSpace* vert_space =
-      new NGConstraintSpace(kVerticalRightLeft, LTR, phy_space);
-
-  EXPECT_EQ(LayoutUnit(200), horz_space->AvailableSize().inline_size);
-  EXPECT_EQ(LayoutUnit(200), vert_space->AvailableSize().block_size);
-
-  EXPECT_EQ(LayoutUnit(100), horz_space->AvailableSize().block_size);
-  EXPECT_EQ(LayoutUnit(100), vert_space->AvailableSize().inline_size);
-
-  EXPECT_TRUE(horz_space->InlineTriggersScrollbar());
-  EXPECT_TRUE(vert_space->BlockTriggersScrollbar());
-
-  EXPECT_FALSE(horz_space->BlockTriggersScrollbar());
-  EXPECT_FALSE(vert_space->InlineTriggersScrollbar());
-
-  EXPECT_TRUE(horz_space->FixedInlineSize());
-  EXPECT_TRUE(vert_space->FixedBlockSize());
-
-  EXPECT_FALSE(horz_space->FixedBlockSize());
-  EXPECT_FALSE(vert_space->FixedInlineSize());
-
-  EXPECT_EQ(kFragmentColumn, horz_space->BlockFragmentationType());
-  EXPECT_EQ(kFragmentNone, vert_space->BlockFragmentationType());
+                                            NGLogicalSize size) {
+  return NGConstraintSpaceBuilder(writing_mode)
+      .SetTextDirection(direction)
+      .SetAvailableSize(size)
+      .SetPercentageResolutionSize(size)
+      .SetIsFixedSizeInline(true)
+      .SetIsInlineDirectionTriggersScrollbar(true)
+      .SetFragmentationType(NGFragmentationType::kFragmentColumn)
+      .ToConstraintSpace();
 }
 
 static String OpportunityToString(const NGLayoutOpportunity& opportunity) {
@@ -66,26 +31,21 @@
 }
 
 TEST(NGConstraintSpaceTest, LayoutOpportunitiesNoExclusions) {
-  NGPhysicalSize physical_size;
-  physical_size.width = LayoutUnit(600);
-  physical_size.height = LayoutUnit(400);
-
-  auto* space =
-      ConstructConstraintSpace(kHorizontalTopBottom, LTR, physical_size);
+  NGLogicalSize size;
+  size.inline_size = LayoutUnit(600);
+  size.block_size = LayoutUnit(400);
+  auto* space = ConstructConstraintSpace(kHorizontalTopBottom, LTR, size);
   auto* iterator = space->LayoutOpportunities();
-
   EXPECT_EQ("0,0 600x400", OpportunityToString(iterator->Next()));
   EXPECT_EQ("(empty)", OpportunityToString(iterator->Next()));
 }
 
 TEST(NGConstraintSpaceTest, LayoutOpportunitiesTopRightExclusion) {
-  NGPhysicalSize physical_size;
-  physical_size.width = LayoutUnit(600);
-  physical_size.height = LayoutUnit(400);
-
+  NGLogicalSize size;
+  size.inline_size = LayoutUnit(600);
+  size.block_size = LayoutUnit(400);
   // Create a space with a 100x100 exclusion in the top right corner.
-  auto* space =
-      ConstructConstraintSpace(kHorizontalTopBottom, LTR, physical_size);
+  auto* space = ConstructConstraintSpace(kHorizontalTopBottom, LTR, size);
   NGExclusion exclusion;
   exclusion.rect.size = {/* inline_size */ LayoutUnit(100),
                          /* block_size */ LayoutUnit(100)};
@@ -93,40 +53,31 @@
                            /* block_offset */ LayoutUnit(0)};
   space->AddExclusion(exclusion);
   auto* iterator = space->LayoutOpportunities();
-
   // First opportunity should be to the left of the exclusion.
   EXPECT_EQ("0,0 500x400", OpportunityToString(iterator->Next()));
-
   // Second opportunity should be below the exclusion.
   EXPECT_EQ("0,100 600x300", OpportunityToString(iterator->Next()));
-
   // There should be no third opportunity.
   EXPECT_EQ("(empty)", OpportunityToString(iterator->Next()));
 }
 
 TEST(NGConstraintSpaceTest, LayoutOpportunitiesTopLeftExclusion) {
-  NGPhysicalSize physical_size;
-  physical_size.width = LayoutUnit(600);
-  physical_size.height = LayoutUnit(400);
-
+  NGLogicalSize size;
+  size.inline_size = LayoutUnit(600);
+  size.block_size = LayoutUnit(400);
   // Create a space with a 100x100 exclusion in the top left corner.
-  auto* space =
-      ConstructConstraintSpace(kHorizontalTopBottom, LTR, physical_size);
+  auto* space = ConstructConstraintSpace(kHorizontalTopBottom, LTR, size);
   NGExclusion exclusion;
   exclusion.rect.size = {/* inline_size */ LayoutUnit(100),
                          /* block_size */ LayoutUnit(100)};
   exclusion.rect.offset = {/* inline_offset */ LayoutUnit(0),
                            /* block_offset */ LayoutUnit(0)};
   space->AddExclusion(exclusion);
-
   auto* iterator = space->LayoutOpportunities();
-
   // First opportunity should be to the right of the exclusion.
   EXPECT_EQ("100,0 500x400", OpportunityToString(iterator->Next()));
-
   // Second opportunity should be below the exclusion.
   EXPECT_EQ("0,100 600x300", OpportunityToString(iterator->Next()));
-
   // There should be no third opportunity.
   EXPECT_EQ("(empty)", OpportunityToString(iterator->Next()));
 }
@@ -155,12 +106,10 @@
 //   - 3rd Start Point: 550,0 50x400
 //   - 4th Start Point: 0,300 600x50; 0,300 500x100
 TEST(NGConstraintSpaceTest, LayoutOpportunitiesTwoInMiddle) {
-  NGPhysicalSize physical_size;
-  physical_size.width = LayoutUnit(600);
-  physical_size.height = LayoutUnit(400);
-
-  auto* space =
-      ConstructConstraintSpace(kHorizontalTopBottom, LTR, physical_size);
+  NGLogicalSize size;
+  size.inline_size = LayoutUnit(600);
+  size.block_size = LayoutUnit(400);
+  auto* space = ConstructConstraintSpace(kHorizontalTopBottom, LTR, size);
   // Add exclusions
   NGExclusion exclusion1;
   exclusion1.rect.size = {/* inline_size */ LayoutUnit(100),
@@ -174,24 +123,18 @@
   exclusion2.rect.offset = {/* inline_offset */ LayoutUnit(500),
                             /* block_offset */ LayoutUnit(350)};
   space->AddExclusion(exclusion2);
-
   auto* iterator = space->LayoutOpportunities();
-
   // 1st Start point
   EXPECT_EQ("0,0 600x200", OpportunityToString(iterator->Next()));
   EXPECT_EQ("0,0 150x400", OpportunityToString(iterator->Next()));
-
   // 2nd Start point
   EXPECT_EQ("250,0 350x350", OpportunityToString(iterator->Next()));
   EXPECT_EQ("250,0 250x400", OpportunityToString(iterator->Next()));
-
   // 3rd Start point
   EXPECT_EQ("550,0 50x400", OpportunityToString(iterator->Next()));
-
   // 4th Start point
   EXPECT_EQ("0,300 600x50", OpportunityToString(iterator->Next()));
   EXPECT_EQ("0,300 500x100", OpportunityToString(iterator->Next()));
-
   // Iterator is exhausted.
   EXPECT_EQ("(empty)", OpportunityToString(iterator->Next()));
 }
@@ -210,12 +153,10 @@
 //   All other opportunities that are located before the origin point should be
 //   filtered out.
 TEST(NGConstraintSpaceTest, LayoutOpportunitiesTwoInMiddleWithOriginAndLeader) {
-  NGPhysicalSize physical_size;
-  physical_size.width = LayoutUnit(600);
-  physical_size.height = LayoutUnit(400);
-
-  auto* space =
-      ConstructConstraintSpace(kHorizontalTopBottom, LTR, physical_size);
+  NGLogicalSize size;
+  size.inline_size = LayoutUnit(600);
+  size.block_size = LayoutUnit(400);
+  auto* space = ConstructConstraintSpace(kHorizontalTopBottom, LTR, size);
   // Add exclusions
   NGExclusion exclusion1;
   exclusion1.rect.size = {/* inline_size */ LayoutUnit(100),
@@ -229,27 +170,21 @@
   exclusion2.rect.offset = {/* inline_offset */ LayoutUnit(500),
                             /* block_offset */ LayoutUnit(350)};
   space->AddExclusion(exclusion2);
-
   const NGLogicalOffset origin_point = {LayoutUnit(0), LayoutUnit(200)};
   const NGLogicalOffset leader_point = {LayoutUnit(250), LayoutUnit(300)};
   auto* iterator =
       new NGLayoutOpportunityIterator(space, origin_point, leader_point);
-
   // 1st Start Point
   EXPECT_EQ("250,200 350x150", OpportunityToString(iterator->Next()));
   EXPECT_EQ("250,200 250x200", OpportunityToString(iterator->Next()));
-
   // 2nd Start Point
   EXPECT_EQ("550,200 50x200", OpportunityToString(iterator->Next()));
-
   // 3rd Start Point
   EXPECT_EQ("0,300 600x50", OpportunityToString(iterator->Next()));
   EXPECT_EQ("0,300 500x100", OpportunityToString(iterator->Next()));
-
   // Iterator is exhausted.
   EXPECT_EQ("(empty)", OpportunityToString(iterator->Next()));
 }
-
 // Verifies that Layout Opportunity iterator ignores the exclusion that is not
 // within constraint space.
 //
@@ -266,21 +201,17 @@
 //   Layout opportunity iterator generates only one opportunity that equals to
 //   available constraint space, i.e. 0,0 600x200
 TEST(NGConstraintSpaceTest, LayoutOpportunitiesWithOutOfBoundsExclusions) {
-  NGPhysicalSize physical_size;
-  physical_size.width = LayoutUnit(600);
-  physical_size.height = LayoutUnit(100);
-
-  auto* space =
-      ConstructConstraintSpace(kHorizontalTopBottom, LTR, physical_size);
+  NGLogicalSize size;
+  size.inline_size = LayoutUnit(600);
+  size.block_size = LayoutUnit(100);
+  auto* space = ConstructConstraintSpace(kHorizontalTopBottom, LTR, size);
   NGExclusion exclusion;
   exclusion.rect.size = {/* inline_size */ LayoutUnit(100),
                          /* block_size */ LayoutUnit(100)};
   exclusion.rect.offset = {/* inline_offset */ LayoutUnit(0),
                            /* block_offset */ LayoutUnit(150)};
   space->AddExclusion(exclusion);
-
   auto* iterator = space->LayoutOpportunities();
-
   EXPECT_EQ("0,0 600x100", OpportunityToString(iterator->Next()));
   EXPECT_EQ("(empty)", OpportunityToString(iterator->Next()));
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_base.h b/third_party/WebKit/Source/core/layout/ng/ng_fragment_base.h
index 140c323..f1f10cd 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_base.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_base.h
@@ -6,7 +6,6 @@
 #define NGFragmentBase_h
 
 #include "core/CoreExport.h"
-#include "core/layout/ng/ng_physical_constraint_space.h"
 #include "core/layout/ng/ng_physical_fragment_base.h"
 #include "core/layout/ng/ng_writing_mode.h"
 #include "core/layout/ng/ng_units.h"
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
index 429a9d3..647d1db 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
@@ -209,9 +209,10 @@
 
   // NOTE: We don't need to change the coordinate system here as we are an
   // inline.
-  NGConstraintSpace* child_constraint_space = new NGConstraintSpace(
-      constraint_space->WritingMode(), constraint_space->Direction(),
-      constraint_space->MutablePhysicalSpace());
+  NGConstraintSpace* child_constraint_space =
+      NGConstraintSpaceBuilder(constraint_space->WritingMode())
+          .SetTextDirection(constraint_space->Direction())
+          .ToConstraintSpace();
 
   if (!layout_algorithm_)
     // TODO(layout-dev): If an atomic inline run the appropriate algorithm.
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
index 71d1272..8d377ad 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
@@ -4,7 +4,6 @@
 
 #include "core/layout/ng/ng_layout_opportunity_iterator.h"
 
-#include "core/layout/ng/ng_physical_constraint_space.h"
 #include "core/layout/ng/ng_units.h"
 #include "wtf/NonCopyingSort.h"
 
@@ -255,8 +254,8 @@
   RunPreconditionChecks(*space, opt_origin_point, opt_leader_point);
 
   // TODO(chrome-layout-team): Combine exclusions that shadow each other.
-  auto& exclusions = constraint_space_->PhysicalSpace()->Exclusions();
-  DCHECK(std::is_sorted(exclusions.begin(), exclusions.end(),
+  auto& exclusions = constraint_space_->Exclusions();
+  DCHECK(std::is_sorted(exclusions->storage.begin(), exclusions->storage.end(),
                         &CompareNGExclusionsByTopAsc))
       << "Exclusions are expected to be sorted by TOP";
 
@@ -273,7 +272,7 @@
                     opportunities_);
   }
 
-  for (const auto& exclusion : exclusions) {
+  for (const auto& exclusion : exclusions->storage) {
     InsertExclusion(MutableOpportunityTreeRoot(), exclusion.get(),
                     opportunities_);
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc
index 4388d544..50b6417c 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc
@@ -176,27 +176,26 @@
 }
 
 LayoutUnit ComputeInlineSizeForFragment(
-    const NGConstraintSpace& constraint_space,
+    const NGConstraintSpace& space,
     const ComputedStyle& style,
     const WTF::Optional<MinAndMaxContentSizes>& min_and_max) {
-  if (constraint_space.FixedInlineSize())
-    return constraint_space.AvailableSize().inline_size;
+  if (space.IsFixedSizeInline())
+    return space.AvailableSize().inline_size;
 
-  LayoutUnit extent = ResolveInlineLength(constraint_space, style, min_and_max,
-                                          style.logicalWidth(),
-                                          LengthResolveType::kContentSize);
+  LayoutUnit extent =
+      ResolveInlineLength(space, style, min_and_max, style.logicalWidth(),
+                          LengthResolveType::kContentSize);
 
   Length max_length = style.logicalMaxWidth();
   if (!max_length.isMaxSizeNone()) {
-    LayoutUnit max =
-        ResolveInlineLength(constraint_space, style, min_and_max, max_length,
-                            LengthResolveType::kMaxSize);
+    LayoutUnit max = ResolveInlineLength(space, style, min_and_max, max_length,
+                                         LengthResolveType::kMaxSize);
     extent = std::min(extent, max);
   }
 
   LayoutUnit min =
-      ResolveInlineLength(constraint_space, style, min_and_max,
-                          style.logicalMinWidth(), LengthResolveType::kMinSize);
+      ResolveInlineLength(space, style, min_and_max, style.logicalMinWidth(),
+                          LengthResolveType::kMinSize);
   extent = std::max(extent, min);
   return extent;
 }
@@ -205,7 +204,7 @@
     const NGConstraintSpace& constraint_space,
     const ComputedStyle& style,
     LayoutUnit content_size) {
-  if (constraint_space.FixedBlockSize())
+  if (constraint_space.IsFixedSizeBlock())
     return constraint_space.AvailableSize().block_size;
 
   LayoutUnit extent =
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_length_utils_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_length_utils_test.cc
index 205f524..d4bfe695 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_length_utils_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_length_utils_test.cc
@@ -28,17 +28,14 @@
                                                      int block_size,
                                                      bool fixed_inline = false,
                                                      bool fixed_block = false) {
-    NGConstraintSpaceBuilder builder(kHorizontalTopBottom);
-    builder
+    return NGConstraintSpaceBuilder(kHorizontalTopBottom)
         .SetAvailableSize(
             NGLogicalSize(LayoutUnit(inline_size), LayoutUnit(block_size)))
         .SetPercentageResolutionSize(
             NGLogicalSize(LayoutUnit(inline_size), LayoutUnit(block_size)))
         .SetIsFixedSizeInline(fixed_inline)
-        .SetIsFixedSizeBlock(fixed_block);
-
-    return new NGConstraintSpace(kHorizontalTopBottom, LTR,
-                                 builder.ToConstraintSpace());
+        .SetIsFixedSizeBlock(fixed_block)
+        .ToConstraintSpace();
   }
 
   LayoutUnit ResolveInlineLength(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_constraint_space.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_constraint_space.cc
deleted file mode 100644
index 4d71ef91..0000000
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_constraint_space.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2016 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 "core/layout/ng/ng_physical_constraint_space.h"
-
-namespace blink {
-
-NGPhysicalConstraintSpace::NGPhysicalConstraintSpace(
-    NGPhysicalSize available_size,
-    NGPhysicalSize percentage_resolution_size,
-    bool fixed_width,
-    bool fixed_height,
-    bool width_direction_triggers_scrollbar,
-    bool height_direction_triggers_scrollbar,
-    NGFragmentationType width_direction_fragmentation_type,
-    NGFragmentationType height_direction_fragmentation_type,
-    bool is_new_fc)
-    : available_size_(available_size),
-      percentage_resolution_size_(percentage_resolution_size),
-      fixed_width_(fixed_width),
-      fixed_height_(fixed_height),
-      width_direction_triggers_scrollbar_(width_direction_triggers_scrollbar),
-      height_direction_triggers_scrollbar_(height_direction_triggers_scrollbar),
-      width_direction_fragmentation_type_(width_direction_fragmentation_type),
-      height_direction_fragmentation_type_(height_direction_fragmentation_type),
-      is_new_fc_(is_new_fc),
-      last_left_float_exclusion_(nullptr),
-      last_right_float_exclusion_(nullptr) {}
-
-void NGPhysicalConstraintSpace::AddExclusion(const NGExclusion& exclusion) {
-  NGExclusion* exclusion_ptr = new NGExclusion(exclusion);
-  exclusions_.append(WTF::wrapUnique(exclusion_ptr));
-  if (exclusion.type == NGExclusion::kFloatLeft) {
-    last_left_float_exclusion_ = exclusions_.rbegin()->get();
-  } else if (exclusion.type == NGExclusion::kFloatRight) {
-    last_right_float_exclusion_ = exclusions_.rbegin()->get();
-  }
-}
-
-const Vector<std::unique_ptr<const NGExclusion>>&
-NGPhysicalConstraintSpace::Exclusions(unsigned options) const {
-  // TODO(layout-ng): Filter based on options? Perhaps layout Opportunities
-  // should filter instead?
-  return exclusions_;
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_constraint_space.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_constraint_space.h
deleted file mode 100644
index b1b1994e..0000000
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_constraint_space.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2016 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 NGPhysicalConstraintSpace_h
-#define NGPhysicalConstraintSpace_h
-
-#include "core/CoreExport.h"
-#include "core/layout/ng/ng_units.h"
-#include "platform/heap/Handle.h"
-#include "wtf/Vector.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-
-// TODO(glebl@): unused, delete.
-enum NGExclusionType {
-  kNGClearNone = 0,
-  kNGClearFloatLeft = 1,
-  kNGClearFloatRight = 2,
-  kNGClearFragment = 4
-};
-
-enum NGFragmentationType {
-  kFragmentNone,
-  kFragmentPage,
-  kFragmentColumn,
-  kFragmentRegion
-};
-
-// The NGPhysicalConstraintSpace contains the underlying data for the
-// NGConstraintSpace. It is not meant to be used directly as all members are in
-// the physical coordinate space. Instead NGConstraintSpace should be used.
-class CORE_EXPORT NGPhysicalConstraintSpace final
-    : public GarbageCollectedFinalized<NGPhysicalConstraintSpace> {
- public:
-  NGPhysicalConstraintSpace(
-      NGPhysicalSize available_size,
-      NGPhysicalSize percentage_resolution_size,
-      bool fixed_width,
-      bool fixed_height,
-      bool width_direction_triggers_scrollbar,
-      bool height_direction_triggers_scrollbar,
-      NGFragmentationType width_direction_fragmentation_type,
-      NGFragmentationType height_direction_fragmentation_type,
-      bool is_new_fc);
-
-  void AddExclusion(const NGExclusion&);
-  const Vector<std::unique_ptr<const NGExclusion>>& Exclusions(
-      unsigned options = 0) const;
-
-  // Read only getters.
-  const NGExclusion* LastLeftFloatExclusion() const {
-    return last_left_float_exclusion_;
-  }
-
-  const NGExclusion* LastRightFloatExclusion() const {
-    return last_right_float_exclusion_;
-  }
-
-  DEFINE_INLINE_TRACE() {}
-
- private:
-  friend class NGConstraintSpace;
-
-  NGPhysicalSize available_size_;
-  NGPhysicalSize percentage_resolution_size_;
-
-  unsigned fixed_width_ : 1;
-  unsigned fixed_height_ : 1;
-  unsigned width_direction_triggers_scrollbar_ : 1;
-  unsigned height_direction_triggers_scrollbar_ : 1;
-  unsigned width_direction_fragmentation_type_ : 2;
-  unsigned height_direction_fragmentation_type_ : 2;
-
-  // Whether the current constraint space is for the newly established
-  // formatting Context
-  unsigned is_new_fc_ : 1;
-
-  // Last left/right float exclusions are used to enforce the top edge alignment
-  // rule for floats and for the support of CSS "clear" property.
-  const NGExclusion* last_left_float_exclusion_;   // Owned by exclusions_.
-  const NGExclusion* last_right_float_exclusion_;  // Owned by exclusions_.
-
-  Vector<std::unique_ptr<const NGExclusion>> exclusions_;
-};
-
-}  // namespace blink
-
-#endif  // NGPhysicalConstraintSpace_h
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.cc b/third_party/WebKit/Source/core/layout/ng/ng_units.cc
index 2e515a8c..b11d1ecc 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_units.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_units.cc
@@ -226,4 +226,30 @@
                   negative_margin_block_start, negative_margin_block_end);
 }
 
+NGExclusions::NGExclusions()
+    : last_left_float(nullptr), last_right_float(nullptr) {}
+
+NGExclusions::NGExclusions(const NGExclusions& other) {
+  for (const auto& exclusion : other.storage)
+    Add(*exclusion);
+}
+
+void NGExclusions::Add(const NGExclusion& exclusion) {
+  storage.append(makeUnique<NGExclusion>(exclusion));
+  if (exclusion.type == NGExclusion::kFloatLeft) {
+    last_left_float = storage.rbegin()->get();
+  } else if (exclusion.type == NGExclusion::kFloatRight) {
+    last_right_float = storage.rbegin()->get();
+  }
+}
+
+inline NGExclusions& NGExclusions::operator=(const NGExclusions& other) {
+  storage.clear();
+  last_left_float = nullptr;
+  last_right_float = nullptr;
+  for (const auto& exclusion : other.storage)
+    Add(*exclusion);
+  return *this;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.h b/third_party/WebKit/Source/core/layout/ng/ng_units.h
index 95151cc..965f2f3e 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_units.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_units.h
@@ -184,6 +184,25 @@
   Type type;
 };
 
+struct CORE_EXPORT NGExclusions {
+  // Default constructor.
+  NGExclusions();
+
+  // Copy constructor.
+  NGExclusions(const NGExclusions& other);
+
+  Vector<std::unique_ptr<const NGExclusion>> storage;
+
+  // Last left/right float exclusions are used to enforce the top edge alignment
+  // rule for floats and for the support of CSS "clear" property.
+  const NGExclusion* last_left_float;   // Owned by storage.
+  const NGExclusion* last_right_float;  // Owned by storage.
+
+  NGExclusions& operator=(const NGExclusions& other);
+
+  void Add(const NGExclusion& exclusion);
+};
+
 struct NGPixelSnappedPhysicalRect {
   int top;
   int left;
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
index 7509d86..9dc16fe 100644
--- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
+++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
@@ -93,7 +93,10 @@
     const FloatSize& size) const {
   if (!m_context) {
     *status = InvalidSourceImageStatus;
-    return nullptr;
+    sk_sp<SkSurface> surface =
+        SkSurface::MakeRasterN32Premul(m_size.width(), m_size.height());
+    return surface ? StaticBitmapImage::create(surface->makeImageSnapshot())
+                   : nullptr;
   }
   if (!size.width() || !size.height()) {
     *status = ZeroSizeCanvasSourceImageStatus;
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
index f9558e30..389dbf58 100644
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
@@ -158,6 +158,10 @@
       m_box.mustInvalidateBackgroundOrBorderPaintOnHeightChange())
     return PaintInvalidationBorderBoxChange;
 
+  // Needs to repaint frame boundaries.
+  if (m_box.isFrameSet())
+    return PaintInvalidationBorderBoxChange;
+
   return PaintInvalidationIncremental;
 }
 
diff --git a/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h b/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
index fb3358b..d0f9b2aa 100644
--- a/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
+++ b/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
@@ -22,15 +22,19 @@
 
 class FindFrameViewPropertiesNeedingUpdateScope {
  public:
-  FindFrameViewPropertiesNeedingUpdateScope(FrameView* frameView)
+  FindFrameViewPropertiesNeedingUpdateScope(
+      FrameView* frameView,
+      PaintPropertyTreeBuilderContext& context)
       : m_frameView(frameView),
-        m_neededPaintPropertyUpdate(frameView->needsPaintPropertyUpdate()) {
-    // No need to check when already marked as needing an update.
-    if (m_neededPaintPropertyUpdate)
+        m_neededPaintPropertyUpdate(frameView->needsPaintPropertyUpdate()),
+        m_neededForcedSubtreeUpdate(context.forceSubtreeUpdate) {
+    // No need to check if an update was already needed.
+    if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
       return;
 
     // Mark the properties as needing an update to ensure they are rebuilt.
-    m_frameView->setNeedsPaintPropertyUpdate();
+    m_frameView->setOnlyThisNeedsPaintPropertyUpdateForTesting();
+
     if (auto* preTranslation = m_frameView->preTranslation())
       m_preTranslation = preTranslation->clone();
     if (auto* contentClip = m_frameView->contentClip())
@@ -42,8 +46,8 @@
   }
 
   ~FindFrameViewPropertiesNeedingUpdateScope() {
-    // No need to check when already marked as needing an update.
-    if (m_neededPaintPropertyUpdate)
+    // No need to check if an update was already needed.
+    if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
       return;
 
     // If paint properties are not marked as needing an update but still change,
@@ -52,6 +56,7 @@
     DCHECK_PTR_VAL_EQ(m_contentClip, m_frameView->contentClip());
     DCHECK_PTR_VAL_EQ(m_scrollTranslation, m_frameView->scrollTranslation());
     DCHECK_PTR_VAL_EQ(m_scroll, m_frameView->scroll());
+
     // Restore original clean bit.
     m_frameView->clearNeedsPaintPropertyUpdate();
   }
@@ -59,6 +64,7 @@
  private:
   Persistent<FrameView> m_frameView;
   bool m_neededPaintPropertyUpdate;
+  bool m_neededForcedSubtreeUpdate;
   RefPtr<TransformPaintPropertyNode> m_preTranslation;
   RefPtr<ClipPaintPropertyNode> m_contentClip;
   RefPtr<TransformPaintPropertyNode> m_scrollTranslation;
@@ -67,22 +73,27 @@
 
 class FindObjectPropertiesNeedingUpdateScope {
  public:
-  FindObjectPropertiesNeedingUpdateScope(const LayoutObject& object)
+  FindObjectPropertiesNeedingUpdateScope(
+      const LayoutObject& object,
+      PaintPropertyTreeBuilderContext& context)
       : m_object(object),
-        m_neededPaintPropertyUpdate(object.needsPaintPropertyUpdate()) {
-    // No need to check when already marked as needing an update.
-    if (m_neededPaintPropertyUpdate)
+        m_neededPaintPropertyUpdate(object.needsPaintPropertyUpdate()),
+        m_neededForcedSubtreeUpdate(context.forceSubtreeUpdate) {
+    // No need to check if an update was already needed.
+    if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
       return;
 
     // Mark the properties as needing an update to ensure they are rebuilt.
-    const_cast<LayoutObject&>(m_object).setNeedsPaintPropertyUpdate();
+    const_cast<LayoutObject&>(m_object)
+        .setOnlyThisNeedsPaintPropertyUpdateForTesting();
+
     if (const auto* properties = m_object.paintProperties())
       m_properties = properties->clone();
   }
 
   ~FindObjectPropertiesNeedingUpdateScope() {
-    // No need to check when already marked as needing an update.
-    if (m_neededPaintPropertyUpdate)
+    // No need to check if an update was already needed.
+    if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
       return;
 
     // If paint properties are not marked as needing an update but still change,
@@ -135,6 +146,7 @@
  private:
   const LayoutObject& m_object;
   bool m_neededPaintPropertyUpdate;
+  bool m_neededForcedSubtreeUpdate;
   std::unique_ptr<const ObjectPaintProperties> m_properties;
 };
 
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
index 20e95490..ba75401 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
@@ -142,6 +142,7 @@
               paintOffset, PropertyTreeState(transform, clip, effect, scroll)));
     }
   }
+  void clearLocalBorderBoxProperties() { m_localBorderBoxProperties = nullptr; }
 
   // This is the complete set of property nodes and paint offset that can be
   // used to paint the contents of this object. It is similar to
@@ -150,75 +151,98 @@
   // invalidation.
   ObjectPaintProperties::PropertyTreeStateWithOffset contentsProperties() const;
 
-  void clearPaintOffsetTranslation() { m_paintOffsetTranslation = nullptr; }
-  void clearTransform() { m_transform = nullptr; }
-  void clearEffect() { m_effect = nullptr; }
-  void clearCssClip() { m_cssClip = nullptr; }
-  void clearCssClipFixedPosition() { m_cssClipFixedPosition = nullptr; }
-  void clearInnerBorderRadiusClip() { m_innerBorderRadiusClip = nullptr; }
-  void clearOverflowClip() { m_overflowClip = nullptr; }
-  void clearLocalBorderBoxProperties() { m_localBorderBoxProperties = nullptr; }
-  void clearPerspective() { m_perspective = nullptr; }
-  void clearSvgLocalToBorderBoxTransform() {
-    m_svgLocalToBorderBoxTransform = nullptr;
+  // True if an existing property was deleted, false otherwise.
+  bool clearPaintOffsetTranslation() { return clear(m_paintOffsetTranslation); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearTransform() { return clear(m_transform); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearEffect() { return clear(m_effect); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearCssClip() { return clear(m_cssClip); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearCssClipFixedPosition() { return clear(m_cssClipFixedPosition); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearInnerBorderRadiusClip() { return clear(m_innerBorderRadiusClip); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearOverflowClip() { return clear(m_overflowClip); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearPerspective() { return clear(m_perspective); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearSvgLocalToBorderBoxTransform() {
+    return clear(m_svgLocalToBorderBoxTransform);
   }
-  void clearScrollTranslation() { m_scrollTranslation = nullptr; }
-  void clearScrollbarPaintOffset() { m_scrollbarPaintOffset = nullptr; }
-  void clearScroll() { m_scroll = nullptr; }
+  // True if an existing property was deleted, false otherwise.
+  bool clearScrollTranslation() { return clear(m_scrollTranslation); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearScrollbarPaintOffset() { return clear(m_scrollbarPaintOffset); }
+  // True if an existing property was deleted, false otherwise.
+  bool clearScroll() { return clear(m_scroll); }
 
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updatePaintOffsetTranslation(Args&&... args) {
-    updateProperty(m_paintOffsetTranslation, std::forward<Args>(args)...);
+  bool updatePaintOffsetTranslation(Args&&... args) {
+    return update(m_paintOffsetTranslation, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateTransform(Args&&... args) {
-    updateProperty(m_transform, std::forward<Args>(args)...);
+  bool updateTransform(Args&&... args) {
+    return update(m_transform, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updatePerspective(Args&&... args) {
-    updateProperty(m_perspective, std::forward<Args>(args)...);
+  bool updatePerspective(Args&&... args) {
+    return update(m_perspective, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateSvgLocalToBorderBoxTransform(Args&&... args) {
+  bool updateSvgLocalToBorderBoxTransform(Args&&... args) {
     DCHECK(!scrollTranslation()) << "SVG elements cannot scroll so there "
                                     "should never be both a scroll translation "
                                     "and an SVG local to border box transform.";
-    updateProperty(m_svgLocalToBorderBoxTransform, std::forward<Args>(args)...);
+    return update(m_svgLocalToBorderBoxTransform, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateScrollTranslation(Args&&... args) {
+  bool updateScrollTranslation(Args&&... args) {
     DCHECK(!svgLocalToBorderBoxTransform())
         << "SVG elements cannot scroll so there should never be both a scroll "
            "translation and an SVG local to border box transform.";
-    updateProperty(m_scrollTranslation, std::forward<Args>(args)...);
+    return update(m_scrollTranslation, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateScrollbarPaintOffset(Args&&... args) {
-    updateProperty(m_scrollbarPaintOffset, std::forward<Args>(args)...);
+  bool updateScrollbarPaintOffset(Args&&... args) {
+    return update(m_scrollbarPaintOffset, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateScroll(Args&&... args) {
-    updateProperty(m_scroll, std::forward<Args>(args)...);
+  bool updateScroll(Args&&... args) {
+    return update(m_scroll, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateEffect(Args&&... args) {
-    updateProperty(m_effect, std::forward<Args>(args)...);
+  bool updateEffect(Args&&... args) {
+    return update(m_effect, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateCssClip(Args&&... args) {
-    updateProperty(m_cssClip, std::forward<Args>(args)...);
+  bool updateCssClip(Args&&... args) {
+    return update(m_cssClip, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateCssClipFixedPosition(Args&&... args) {
-    updateProperty(m_cssClipFixedPosition, std::forward<Args>(args)...);
+  bool updateCssClipFixedPosition(Args&&... args) {
+    return update(m_cssClipFixedPosition, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateInnerBorderRadiusClip(Args&&... args) {
-    updateProperty(m_innerBorderRadiusClip, std::forward<Args>(args)...);
+  bool updateInnerBorderRadiusClip(Args&&... args) {
+    return update(m_innerBorderRadiusClip, std::forward<Args>(args)...);
   }
+  // True if a new property was created, false if an existing one was updated.
   template <typename... Args>
-  void updateOverflowClip(Args&&... args) {
-    updateProperty(m_overflowClip, std::forward<Args>(args)...);
+  bool updateOverflowClip(Args&&... args) {
+    return update(m_overflowClip, std::forward<Args>(args)...);
   }
 
 #if DCHECK_IS_ON()
@@ -266,12 +290,25 @@
  private:
   ObjectPaintProperties() {}
 
+  // True if an existing property was deleted, false otherwise.
+  template <typename PaintPropertyNode>
+  bool clear(RefPtr<PaintPropertyNode>& field) {
+    if (field) {
+      field = nullptr;
+      return true;
+    }
+    return false;
+  }
+
+  // True if a new property was created, false if an existing one was updated.
   template <typename PaintPropertyNode, typename... Args>
-  void updateProperty(RefPtr<PaintPropertyNode>& field, Args&&... args) {
-    if (field)
+  bool update(RefPtr<PaintPropertyNode>& field, Args&&... args) {
+    if (field) {
       field->update(std::forward<Args>(args)...);
-    else
-      field = PaintPropertyNode::create(std::forward<Args>(args)...);
+      return false;
+    }
+    field = PaintPropertyNode::create(std::forward<Args>(args)...);
+    return true;
   }
 
   RefPtr<TransformPaintPropertyNode> m_paintOffsetTranslation;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
index 8ed7a2e8..f3c2d82 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
@@ -437,6 +437,7 @@
   LayoutRect source(LayoutRect::infiniteIntRect());
   bool success = false;
   const auto* properties = m_layer.layoutObject()->paintProperties();
+  DCHECK(properties && properties->localBorderBoxProperties());
   PropertyTreeState propertyTreeState =
       properties->localBorderBoxProperties()->propertyTreeState;
 
@@ -445,6 +446,7 @@
 
   const auto* ancestorProperties =
       context.rootLayer->layoutObject()->paintProperties();
+  DCHECK(ancestorProperties && ancestorProperties->localBorderBoxProperties());
   PropertyTreeState destinationPropertyTreeState =
       ancestorProperties->localBorderBoxProperties()->propertyTreeState;
   if (!context.rootLayer->clipper().shouldRespectOverflowClip(context)) {
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 0c1b1d68..70ca561 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -34,21 +34,23 @@
   return context;
 }
 
-void updateFrameViewPreTranslation(
-    FrameView& frameView,
-    PassRefPtr<const TransformPaintPropertyNode> parent,
-    const TransformationMatrix& matrix,
-    const FloatPoint3D& origin) {
+// True if a new property was created, false if an existing one was updated.
+bool updatePreTranslation(FrameView& frameView,
+                          PassRefPtr<const TransformPaintPropertyNode> parent,
+                          const TransformationMatrix& matrix,
+                          const FloatPoint3D& origin) {
   DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled());
   if (auto* existingPreTranslation = frameView.preTranslation()) {
     existingPreTranslation->update(std::move(parent), matrix, origin);
-  } else {
-    frameView.setPreTranslation(
-        TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
+    return false;
   }
+  frameView.setPreTranslation(
+      TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
+  return true;
 }
 
-void updateFrameViewContentClip(
+// True if a new property was created, false if an existing one was updated.
+bool updateContentClip(
     FrameView& frameView,
     PassRefPtr<const ClipPaintPropertyNode> parent,
     PassRefPtr<const TransformPaintPropertyNode> localTransformSpace,
@@ -57,13 +59,15 @@
   if (auto* existingContentClip = frameView.contentClip()) {
     existingContentClip->update(std::move(parent),
                                 std::move(localTransformSpace), clipRect);
-  } else {
-    frameView.setContentClip(ClipPaintPropertyNode::create(
-        std::move(parent), std::move(localTransformSpace), clipRect));
+    return false;
   }
+  frameView.setContentClip(ClipPaintPropertyNode::create(
+      std::move(parent), std::move(localTransformSpace), clipRect));
+  return true;
 }
 
-void updateFrameViewScrollTranslation(
+// True if a new property was created, false if an existing one was updated.
+bool updateScrollTranslation(
     FrameView& frameView,
     PassRefPtr<const TransformPaintPropertyNode> parent,
     const TransformationMatrix& matrix,
@@ -71,32 +75,34 @@
   DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled());
   if (auto* existingScrollTranslation = frameView.scrollTranslation()) {
     existingScrollTranslation->update(std::move(parent), matrix, origin);
-  } else {
-    frameView.setScrollTranslation(
-        TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
+    return false;
   }
+  frameView.setScrollTranslation(
+      TransformPaintPropertyNode::create(std::move(parent), matrix, origin));
+  return true;
 }
 
-void updateFrameViewScroll(
-    FrameView& frameView,
-    PassRefPtr<const ScrollPaintPropertyNode> parent,
-    PassRefPtr<const TransformPaintPropertyNode> scrollOffset,
-    const IntSize& clip,
-    const IntSize& bounds,
-    bool userScrollableHorizontal,
-    bool userScrollableVertical,
-    MainThreadScrollingReasons mainThreadScrollingReasons) {
+// True if a new property was created, false if an existing one was updated.
+bool updateScroll(FrameView& frameView,
+                  PassRefPtr<const ScrollPaintPropertyNode> parent,
+                  PassRefPtr<const TransformPaintPropertyNode> scrollOffset,
+                  const IntSize& clip,
+                  const IntSize& bounds,
+                  bool userScrollableHorizontal,
+                  bool userScrollableVertical,
+                  MainThreadScrollingReasons mainThreadScrollingReasons) {
   DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled());
   if (auto* existingScroll = frameView.scroll()) {
     existingScroll->update(std::move(parent), std::move(scrollOffset), clip,
                            bounds, userScrollableHorizontal,
                            userScrollableVertical, mainThreadScrollingReasons);
-  } else {
-    frameView.setScroll(ScrollPaintPropertyNode::create(
-        std::move(parent), std::move(scrollOffset), clip, bounds,
-        userScrollableHorizontal, userScrollableVertical,
-        mainThreadScrollingReasons));
+    return false;
   }
+  frameView.setScroll(ScrollPaintPropertyNode::create(
+      std::move(parent), std::move(scrollOffset), clip, bounds,
+      userScrollableHorizontal, userScrollableVertical,
+      mainThreadScrollingReasons));
+  return true;
 }
 
 void PaintPropertyTreeBuilder::updateProperties(
@@ -117,27 +123,28 @@
   }
 
 #if DCHECK_IS_ON()
-  FindFrameViewPropertiesNeedingUpdateScope checkNeedsUpdateScope(&frameView);
+  FindFrameViewPropertiesNeedingUpdateScope checkScope(&frameView, context);
 #endif
 
-  if (frameView.needsPaintPropertyUpdate()) {
+  if (frameView.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     TransformationMatrix frameTranslate;
     frameTranslate.translate(frameView.x() + context.current.paintOffset.x(),
                              frameView.y() + context.current.paintOffset.y());
-    updateFrameViewPreTranslation(frameView, context.current.transform,
-                                  frameTranslate, FloatPoint3D());
+    context.forceSubtreeUpdate |= updatePreTranslation(
+        frameView, context.current.transform, frameTranslate, FloatPoint3D());
 
     FloatRoundedRect contentClip(
         IntRect(IntPoint(), frameView.visibleContentSize()));
-    updateFrameViewContentClip(frameView, context.current.clip,
-                               frameView.preTranslation(), contentClip);
+    context.forceSubtreeUpdate |=
+        updateContentClip(frameView, context.current.clip,
+                          frameView.preTranslation(), contentClip);
 
     ScrollOffset scrollOffset = frameView.scrollOffset();
     if (frameView.isScrollable() || !scrollOffset.isZero()) {
       TransformationMatrix frameScroll;
       frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
-      updateFrameViewScrollTranslation(frameView, frameView.preTranslation(),
-                                       frameScroll, FloatPoint3D());
+      context.forceSubtreeUpdate |= updateScrollTranslation(
+          frameView, frameView.preTranslation(), frameScroll, FloatPoint3D());
 
       IntSize scrollClip = frameView.visibleContentSize();
       IntSize scrollBounds = frameView.contentsSize();
@@ -153,14 +160,19 @@
         reasons |=
             MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
       }
-      updateFrameViewScroll(frameView, context.current.scroll,
-                            frameView.scrollTranslation(), scrollClip,
-                            scrollBounds, userScrollableHorizontal,
-                            userScrollableVertical, reasons);
+      context.forceSubtreeUpdate |= updateScroll(
+          frameView, context.current.scroll, frameView.scrollTranslation(),
+          scrollClip, scrollBounds, userScrollableHorizontal,
+          userScrollableVertical, reasons);
     } else {
-      // Ensure pre-existing properties are cleared when there is no scrolling.
-      frameView.setScrollTranslation(nullptr);
-      frameView.setScroll(nullptr);
+      if (frameView.scrollTranslation() || frameView.scroll()) {
+        // Ensure pre-existing properties are cleared if there is no scrolling.
+        frameView.setScrollTranslation(nullptr);
+        frameView.setScroll(nullptr);
+
+        // Rebuild all descendant properties because a property was removed.
+        context.forceSubtreeUpdate = true;
+      }
     }
   }
 
@@ -222,19 +234,18 @@
   LayoutPoint fractionalPaintOffset =
       LayoutPoint(context.current.paintOffset - roundedPaintOffset);
 
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     if (usesPaintOffsetTranslation) {
-      object.getMutableForPainting()
-          .ensurePaintProperties()
-          .updatePaintOffsetTranslation(
-              context.current.transform,
-              TransformationMatrix().translate(roundedPaintOffset.x(),
-                                               roundedPaintOffset.y()),
-              FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
-              context.current.renderingContextID);
+      auto& properties = object.getMutableForPainting().ensurePaintProperties();
+      context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation(
+          context.current.transform,
+          TransformationMatrix().translate(roundedPaintOffset.x(),
+                                           roundedPaintOffset.y()),
+          FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
+          context.current.renderingContextID);
     } else {
       if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearPaintOffsetTranslation();
+        context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation();
     }
   }
 
@@ -272,7 +283,7 @@
   DCHECK(object.isSVGForeignObject() ||
          context.current.paintOffset == LayoutPoint());
 
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     AffineTransform transform = object.localToSVGParentTransform();
     // TODO(pdr): Check for the presence of a transform instead of the value.
     // Checking for an identity matrix will cause the property tree structure
@@ -280,12 +291,13 @@
     // identity matrix.
     if (!transform.isIdentity()) {
       // The origin is included in the local transform, so leave origin empty.
-      object.getMutableForPainting().ensurePaintProperties().updateTransform(
+      auto& properties = object.getMutableForPainting().ensurePaintProperties();
+      context.forceSubtreeUpdate |= properties.updateTransform(
           context.current.transform, TransformationMatrix(transform),
           FloatPoint3D());
     } else {
       if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearTransform();
+        context.forceSubtreeUpdate |= properties->clearTransform();
     }
   }
 
@@ -304,7 +316,7 @@
     return;
   }
 
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     const ComputedStyle& style = object.styleRef();
     if (object.isBox() && (style.hasTransform() || style.preserves3D())) {
       TransformationMatrix matrix;
@@ -322,13 +334,14 @@
       if (style.preserves3D() && !renderingContextID)
         renderingContextID = PtrHash<const LayoutObject>::hash(&object);
 
-      object.getMutableForPainting().ensurePaintProperties().updateTransform(
+      auto& properties = object.getMutableForPainting().ensurePaintProperties();
+      context.forceSubtreeUpdate |= properties.updateTransform(
           context.current.transform, matrix,
           transformOrigin(toLayoutBox(object)),
           context.current.shouldFlattenInheritedTransform, renderingContextID);
     } else {
       if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearTransform();
+        context.forceSubtreeUpdate |= properties->clearTransform();
     }
   }
 
@@ -352,16 +365,16 @@
   const ComputedStyle& style = object.styleRef();
 
   if (!style.isStackingContext()) {
-    if (object.needsPaintPropertyUpdate()) {
+    if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
       if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearEffect();
+        context.forceSubtreeUpdate |= properties->clearEffect();
     }
     return;
   }
 
   // TODO(trchen): Can't omit effect node if we have 3D children.
   // TODO(trchen): Can't omit effect node if we have blending children.
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     bool effectNodeNeeded = false;
 
     float opacity = style.opacity();
@@ -405,12 +418,13 @@
     }
 
     if (effectNodeNeeded) {
-      object.getMutableForPainting().ensurePaintProperties().updateEffect(
+      auto& properties = object.getMutableForPainting().ensurePaintProperties();
+      context.forceSubtreeUpdate |= properties.updateEffect(
           context.currentEffect, context.current.transform, outputClip,
           std::move(filter), opacity);
     } else {
       if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearEffect();
+        context.forceSubtreeUpdate |= properties->clearEffect();
     }
   }
 
@@ -431,7 +445,7 @@
 void PaintPropertyTreeBuilder::updateCssClip(
     const LayoutObject& object,
     PaintPropertyTreeBuilderContext& context) {
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     if (object.hasClip()) {
       // Create clip node for descendants that are not fixed position.
       // We don't have to setup context.absolutePosition.clip here because this
@@ -440,12 +454,13 @@
       DCHECK(object.canContainAbsolutePositionObjects());
       LayoutRect clipRect =
           toLayoutBox(object).clipRect(context.current.paintOffset);
-      object.getMutableForPainting().ensurePaintProperties().updateCssClip(
+      auto& properties = object.getMutableForPainting().ensurePaintProperties();
+      context.forceSubtreeUpdate |= properties.updateCssClip(
           context.current.clip, context.current.transform,
           FloatRoundedRect(FloatRect(clipRect)));
     } else {
       if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearCssClip();
+        context.forceSubtreeUpdate |= properties->clearCssClip();
     }
   }
 
@@ -457,7 +472,7 @@
 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(
     const LayoutObject& object,
     PaintPropertyTreeBuilderContext& context) {
-  if (!object.needsPaintPropertyUpdate())
+  if (!object.needsPaintPropertyUpdate() && !context.forceSubtreeUpdate)
     return;
 
   // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since
@@ -476,8 +491,8 @@
 // TODO(trchen): Remove this once we bake the paint offset into frameRect.
 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(
     const LayoutObject& object,
-    const PaintPropertyTreeBuilderContext& context) {
-  if (!object.needsPaintPropertyUpdate())
+    PaintPropertyTreeBuilderContext& context) {
+  if (!object.needsPaintPropertyUpdate() && !context.forceSubtreeUpdate)
     return;
 
   bool needsScrollbarPaintOffset = false;
@@ -487,10 +502,10 @@
       if (area->horizontalScrollbar() || area->verticalScrollbar()) {
         auto paintOffset = TransformationMatrix().translate(
             roundedPaintOffset.x(), roundedPaintOffset.y());
-        object.getMutableForPainting()
-            .ensurePaintProperties()
-            .updateScrollbarPaintOffset(context.current.transform, paintOffset,
-                                        FloatPoint3D());
+        auto& properties =
+            object.getMutableForPainting().ensurePaintProperties();
+        context.forceSubtreeUpdate |= properties.updateScrollbarPaintOffset(
+            context.current.transform, paintOffset, FloatPoint3D());
         needsScrollbarPaintOffset = true;
       }
     }
@@ -498,7 +513,7 @@
 
   auto* properties = object.getMutableForPainting().paintProperties();
   if (!needsScrollbarPaintOffset && properties)
-    properties->clearScrollbarPaintOffset();
+    context.forceSubtreeUpdate |= properties->clearScrollbarPaintOffset();
 }
 
 void PaintPropertyTreeBuilder::updateOverflowClip(
@@ -507,7 +522,7 @@
   if (!object.isBox())
     return;
 
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     const LayoutBox& box = toLayoutBox(object);
     // The <input> elements can't have contents thus CSS overflow property
     // doesn't apply.  However for layout purposes we do generate child layout
@@ -524,29 +539,27 @@
           box.overflowClipRect(context.current.paintOffset)));
     } else {
       if (auto* properties = object.getMutableForPainting().paintProperties()) {
-        properties->clearInnerBorderRadiusClip();
-        properties->clearOverflowClip();
+        context.forceSubtreeUpdate |= properties->clearInnerBorderRadiusClip();
+        context.forceSubtreeUpdate |= properties->clearOverflowClip();
       }
       return;
     }
 
+    auto& properties = object.getMutableForPainting().ensurePaintProperties();
     const auto* currentClip = context.current.clip;
     if (box.styleRef().hasBorderRadius()) {
       auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
           LayoutRect(context.current.paintOffset, box.size()));
-      object.getMutableForPainting()
-          .ensurePaintProperties()
-          .updateInnerBorderRadiusClip(context.current.clip,
-                                       context.current.transform, innerBorder);
-      currentClip = object.paintProperties()->innerBorderRadiusClip();
-    } else if (auto* properties =
-                   object.getMutableForPainting().paintProperties()) {
-      properties->clearInnerBorderRadiusClip();
+      context.forceSubtreeUpdate |= properties.updateInnerBorderRadiusClip(
+          context.current.clip, context.current.transform, innerBorder);
+      currentClip = properties.innerBorderRadiusClip();
+    } else {
+      context.forceSubtreeUpdate |= properties.clearInnerBorderRadiusClip();
     }
 
-    object.getMutableForPainting().ensurePaintProperties().updateOverflowClip(
-        currentClip, context.current.transform,
-        FloatRoundedRect(FloatRect(clipRect)));
+    context.forceSubtreeUpdate |=
+        properties.updateOverflowClip(currentClip, context.current.transform,
+                                      FloatRoundedRect(FloatRect(clipRect)));
   }
 
   const auto* properties = object.paintProperties();
@@ -565,7 +578,7 @@
 void PaintPropertyTreeBuilder::updatePerspective(
     const LayoutObject& object,
     PaintPropertyTreeBuilderContext& context) {
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     const ComputedStyle& style = object.styleRef();
     if (object.isBox() && style.hasPerspective()) {
       // The perspective node must not flatten (else nothing will get
@@ -575,13 +588,14 @@
           TransformationMatrix().applyPerspective(style.perspective());
       FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) +
                             toLayoutSize(context.current.paintOffset);
-      object.getMutableForPainting().ensurePaintProperties().updatePerspective(
+      auto& properties = object.getMutableForPainting().ensurePaintProperties();
+      context.forceSubtreeUpdate |= properties.updatePerspective(
           context.current.transform, matrix, origin,
           context.current.shouldFlattenInheritedTransform,
           context.current.renderingContextID);
     } else {
       if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearPerspective();
+        context.forceSubtreeUpdate |= properties->clearPerspective();
     }
   }
 
@@ -598,18 +612,20 @@
   if (!object.isSVGRoot())
     return;
 
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     AffineTransform transformToBorderBox =
         SVGRootPainter(toLayoutSVGRoot(object))
             .transformToPixelSnappedBorderBox(context.current.paintOffset);
     if (!transformToBorderBox.isIdentity()) {
-      object.getMutableForPainting()
-          .ensurePaintProperties()
-          .updateSvgLocalToBorderBoxTransform(
+      auto& properties = object.getMutableForPainting().ensurePaintProperties();
+      context.forceSubtreeUpdate |=
+          properties.updateSvgLocalToBorderBoxTransform(
               context.current.transform, transformToBorderBox, FloatPoint3D());
     } else {
-      if (auto* properties = object.getMutableForPainting().paintProperties())
-        properties->clearSvgLocalToBorderBoxTransform();
+      if (auto* properties = object.getMutableForPainting().paintProperties()) {
+        context.forceSubtreeUpdate |=
+            properties->clearSvgLocalToBorderBoxTransform();
+      }
     }
   }
 
@@ -627,20 +643,20 @@
 void PaintPropertyTreeBuilder::updateScrollAndScrollTranslation(
     const LayoutObject& object,
     PaintPropertyTreeBuilderContext& context) {
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     if (object.hasOverflowClip()) {
       const LayoutBox& box = toLayoutBox(object);
       const PaintLayerScrollableArea* scrollableArea = box.getScrollableArea();
       IntSize scrollOffset = box.scrolledContentOffset();
       if (!scrollOffset.isZero() || scrollableArea->scrollsOverflow()) {
+        auto& properties =
+            object.getMutableForPainting().ensurePaintProperties();
         TransformationMatrix matrix = TransformationMatrix().translate(
             -scrollOffset.width(), -scrollOffset.height());
-        object.getMutableForPainting()
-            .ensurePaintProperties()
-            .updateScrollTranslation(
-                context.current.transform, matrix, FloatPoint3D(),
-                context.current.shouldFlattenInheritedTransform,
-                context.current.renderingContextID);
+        context.forceSubtreeUpdate |= properties.updateScrollTranslation(
+            context.current.transform, matrix, FloatPoint3D(),
+            context.current.shouldFlattenInheritedTransform,
+            context.current.renderingContextID);
 
         IntSize scrollClip = scrollableArea->visibleContentRect().size();
         IntSize scrollBounds = scrollableArea->contentsSize();
@@ -662,9 +678,8 @@
           reasons |=
               MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
         }
-        object.getMutableForPainting().ensurePaintProperties().updateScroll(
-            context.current.scroll,
-            object.paintProperties()->scrollTranslation(), scrollClip,
+        context.forceSubtreeUpdate |= properties.updateScroll(
+            context.current.scroll, properties.scrollTranslation(), scrollClip,
             scrollBounds, userScrollableHorizontal, userScrollableVertical,
             reasons);
       } else {
@@ -672,8 +687,8 @@
         // scrolling.
         auto* properties = object.getMutableForPainting().paintProperties();
         if (properties) {
-          properties->clearScrollTranslation();
-          properties->clearScroll();
+          context.forceSubtreeUpdate |= properties->clearScrollTranslation();
+          context.forceSubtreeUpdate |= properties->clearScroll();
         }
       }
     }
@@ -722,13 +737,13 @@
     if (context.fixedPosition.clip == cssClip->parent()) {
       context.fixedPosition.clip = cssClip;
     } else {
-      if (object.needsPaintPropertyUpdate()) {
-        object.getMutableForPainting()
-            .ensurePaintProperties()
-            .updateCssClipFixedPosition(context.fixedPosition.clip,
-                                        const_cast<TransformPaintPropertyNode*>(
+      if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
+        auto& properties =
+            object.getMutableForPainting().ensurePaintProperties();
+        context.forceSubtreeUpdate |= properties.updateCssClipFixedPosition(
+            context.fixedPosition.clip, const_cast<TransformPaintPropertyNode*>(
                                             cssClip->localTransformSpace()),
-                                        cssClip->clipRect());
+            cssClip->clipRect());
       }
       const auto* properties = object.paintProperties();
       if (properties && properties->cssClipFixedPosition())
@@ -737,9 +752,9 @@
     }
   }
 
-  if (object.needsPaintPropertyUpdate()) {
+  if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
     if (auto* properties = object.getMutableForPainting().paintProperties())
-      properties->clearCssClipFixedPosition();
+      context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition();
   }
 }
 
@@ -866,7 +881,7 @@
     return;
 
 #if DCHECK_IS_ON()
-  FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object);
+  FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
 #endif
 
   deriveBorderBoxFromContainerContext(object, context);
@@ -886,7 +901,7 @@
     return;
 
 #if DCHECK_IS_ON()
-  FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object);
+  FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
 #endif
 
   updateOverflowClip(object, context);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
index b6925cf..e1f5e391 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
@@ -77,6 +77,11 @@
   const ClipPaintPropertyNode* inputClipOfCurrentEffect = nullptr;
 
   bool isUnderMultiColumnSpanner = false;
+
+  // True if a change has forced all properties in a subtree to be updated. This
+  // can be set due to paint offset changes or when the structure of the
+  // property tree changes (i.e., a node is added or removed).
+  bool forceSubtreeUpdate = false;
 };
 
 // Creates paint property tree nodes for special things in the layout tree.
@@ -113,9 +118,8 @@
                             PaintPropertyTreeBuilderContext&);
   static void updateLocalBorderBoxContext(const LayoutObject&,
                                           PaintPropertyTreeBuilderContext&);
-  static void updateScrollbarPaintOffset(
-      const LayoutObject&,
-      const PaintPropertyTreeBuilderContext&);
+  static void updateScrollbarPaintOffset(const LayoutObject&,
+                                         PaintPropertyTreeBuilderContext&);
   static void updateOverflowClip(const LayoutObject&,
                                  PaintPropertyTreeBuilderContext&);
   static void updatePerspective(const LayoutObject&,
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 6ab437c8..2af3d7f 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "core/html/HTMLIFrameElement.h"
 #include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutTreeAsText.h"
 #include "core/layout/api/LayoutViewItem.h"
@@ -2929,6 +2930,16 @@
   EXPECT_FALSE(divWithTransform->descendantNeedsPaintPropertyUpdate());
   EXPECT_FALSE(childLayoutView->descendantNeedsPaintPropertyUpdate());
   EXPECT_FALSE(innerDivWithTransform->descendantNeedsPaintPropertyUpdate());
+
+  // A child frame marked as needing a paint property update should not be
+  // skipped if the owning layout tree does not need an update.
+  FrameView* childFrameView = childDocument().view();
+  childFrameView->setNeedsPaintPropertyUpdate();
+  EXPECT_TRUE(document().layoutView()->descendantNeedsPaintPropertyUpdate());
+  frameView->updateAllLifecyclePhases();
+  EXPECT_FALSE(document().layoutView()->descendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(frameView->needsPaintPropertyUpdate());
+  EXPECT_FALSE(childFrameView->needsPaintPropertyUpdate());
 }
 
 TEST_P(PaintPropertyTreeBuilderTest, UpdatingFrameViewContentClip) {
@@ -2945,4 +2956,77 @@
   EXPECT_EQ(FloatRoundedRect(0, 0, 5, 5), frameContentClip()->clipRect());
 }
 
+TEST_P(PaintPropertyTreeBuilderTest, BuildingStopsAtThrottledFrames) {
+  setBodyInnerHTML(
+      "<style>body { margin: 0; }</style>"
+      "<div id='transform' style='transform: translate3d(4px, 5px, 6px);'>"
+      "</div>"
+      "<iframe id='iframe' sandbox></iframe>");
+  setChildFrameHTML(
+      "<style>body { margin: 0; }</style>"
+      "<div id='iframeTransform'"
+      "  style='transform: translate3d(4px, 5px, 6px);'/>");
+
+  // Move the child frame offscreen so it becomes available for throttling.
+  auto* iframe = toHTMLIFrameElement(document().getElementById("iframe"));
+  iframe->setAttribute(HTMLNames::styleAttr, "transform: translateY(5555px)");
+  document().view()->updateAllLifecyclePhases();
+  // Ensure intersection observer notifications get delivered.
+  testing::runPendingTasks();
+  EXPECT_FALSE(document().view()->isHiddenForThrottling());
+  EXPECT_TRUE(childDocument().view()->isHiddenForThrottling());
+
+  auto* transform = document().getElementById("transform")->layoutObject();
+  auto* iframeLayoutView = childDocument().layoutView();
+  auto* iframeTransform =
+      childDocument().getElementById("iframeTransform")->layoutObject();
+
+  // Invalidate properties in the iframe and ensure ancestors are marked.
+  iframeTransform->setNeedsPaintPropertyUpdate();
+  EXPECT_FALSE(document().layoutView()->needsPaintPropertyUpdate());
+  EXPECT_TRUE(document().layoutView()->descendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(transform->needsPaintPropertyUpdate());
+  EXPECT_FALSE(transform->descendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(iframeLayoutView->needsPaintPropertyUpdate());
+  EXPECT_TRUE(iframeLayoutView->descendantNeedsPaintPropertyUpdate());
+  EXPECT_TRUE(iframeTransform->needsPaintPropertyUpdate());
+  EXPECT_FALSE(iframeTransform->descendantNeedsPaintPropertyUpdate());
+
+  transform->setNeedsPaintPropertyUpdate();
+  EXPECT_TRUE(transform->needsPaintPropertyUpdate());
+  EXPECT_FALSE(transform->descendantNeedsPaintPropertyUpdate());
+
+  {
+    DocumentLifecycle::AllowThrottlingScope throttlingScope(
+        document().lifecycle());
+    EXPECT_FALSE(document().view()->shouldThrottleRendering());
+    EXPECT_TRUE(childDocument().view()->shouldThrottleRendering());
+
+    // A lifecycle update should update all properties except those with
+    // actively throttled descendants.
+    document().view()->updateAllLifecyclePhases();
+    EXPECT_FALSE(document().layoutView()->needsPaintPropertyUpdate());
+    EXPECT_TRUE(document().layoutView()->descendantNeedsPaintPropertyUpdate());
+    EXPECT_FALSE(transform->needsPaintPropertyUpdate());
+    EXPECT_FALSE(transform->descendantNeedsPaintPropertyUpdate());
+    EXPECT_FALSE(iframeLayoutView->needsPaintPropertyUpdate());
+    EXPECT_TRUE(iframeLayoutView->descendantNeedsPaintPropertyUpdate());
+    EXPECT_TRUE(iframeTransform->needsPaintPropertyUpdate());
+    EXPECT_FALSE(iframeTransform->descendantNeedsPaintPropertyUpdate());
+  }
+
+  EXPECT_FALSE(document().view()->shouldThrottleRendering());
+  EXPECT_FALSE(childDocument().view()->shouldThrottleRendering());
+  // Once unthrottled, a lifecycel update should update all properties.
+  document().view()->updateAllLifecyclePhases();
+  EXPECT_FALSE(document().layoutView()->needsPaintPropertyUpdate());
+  EXPECT_FALSE(document().layoutView()->descendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(transform->needsPaintPropertyUpdate());
+  EXPECT_FALSE(transform->descendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(iframeLayoutView->needsPaintPropertyUpdate());
+  EXPECT_FALSE(iframeLayoutView->descendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(iframeTransform->needsPaintPropertyUpdate());
+  EXPECT_FALSE(iframeTransform->descendantNeedsPaintPropertyUpdate());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
index f7764be6..265fd62 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -20,7 +20,6 @@
         paintInvalidatorContext(treeBuilderContext,
                                 parentContext.paintInvalidatorContext) {}
 
-  bool needToUpdatePaintPropertySubtree = false;
   PaintPropertyTreeBuilderContext treeBuilderContext;
   PaintInvalidatorContext paintInvalidatorContext;
 };
@@ -36,75 +35,65 @@
   m_paintInvalidator.processPendingDelayedPaintInvalidations();
 }
 
-void PrePaintTreeWalk::walk(FrameView& frameView,
+bool PrePaintTreeWalk::walk(FrameView& frameView,
                             const PrePaintTreeWalkContext& context) {
-  if (frameView.shouldThrottleRendering())
-    return;
+  if (frameView.shouldThrottleRendering()) {
+    // The walk was interrupted by throttled rendering so this subtree was not
+    // fully updated.
+    return false;
+  }
 
   PrePaintTreeWalkContext localContext(context);
-
-  // Check whether we need to update the paint property trees.
-  if (!localContext.needToUpdatePaintPropertySubtree) {
-    if (context.paintInvalidatorContext.forcedSubtreeInvalidationFlags) {
-      // forcedSubtreeInvalidationFlags will be true if locations have changed
-      // which will affect paint properties (e.g., PaintOffset).
-      localContext.needToUpdatePaintPropertySubtree = true;
-    } else if (frameView.needsPaintPropertyUpdate()) {
-      localContext.needToUpdatePaintPropertySubtree = true;
-    }
-  }
-  // Paint properties can depend on their ancestor properties so ensure the
-  // entire subtree is rebuilt on any changes.
-  // TODO(pdr): Add additional granularity to the needs update approach such as
-  // the ability to do local updates that don't change the subtree.
-  if (localContext.needToUpdatePaintPropertySubtree)
-    frameView.setNeedsPaintPropertyUpdate();
-
   m_propertyTreeBuilder.updateProperties(frameView,
                                          localContext.treeBuilderContext);
-
   m_paintInvalidator.invalidatePaintIfNeeded(
       frameView, localContext.paintInvalidatorContext);
 
-  if (LayoutView* layoutView = frameView.layoutView())
-    walk(*layoutView, localContext);
-
+  LayoutView* view = frameView.layoutView();
+  bool descendantsFullyUpdated = view ? walk(*view, localContext) : true;
+  if (descendantsFullyUpdated) {
 #if DCHECK_IS_ON()
-  frameView.layoutView()->assertSubtreeClearedPaintInvalidationFlags();
+    frameView.layoutView()->assertSubtreeClearedPaintInvalidationFlags();
 #endif
-
-  frameView.clearNeedsPaintPropertyUpdate();
+    // If descendants were not fully updated, do not clear flags. During the
+    // next PrePaintTreeWalk, these flags will be used again.
+    frameView.clearNeedsPaintPropertyUpdate();
+  }
+  return descendantsFullyUpdated;
 }
 
-void PrePaintTreeWalk::walk(const LayoutObject& object,
+bool PrePaintTreeWalk::walk(const LayoutObject& object,
                             const PrePaintTreeWalkContext& context) {
-  PrePaintTreeWalkContext localContext(context);
-
-  // Check whether we need to update the paint property trees.
-  if (!localContext.needToUpdatePaintPropertySubtree) {
-    if (context.paintInvalidatorContext.forcedSubtreeInvalidationFlags) {
-      // forcedSubtreeInvalidationFlags will be true if locations have changed
-      // which will affect paint properties (e.g., PaintOffset).
-      localContext.needToUpdatePaintPropertySubtree = true;
-    } else if (object.needsPaintPropertyUpdate()) {
-      localContext.needToUpdatePaintPropertySubtree = true;
-    } else if (object.mayNeedPaintInvalidation()) {
-      // mayNeedpaintInvalidation will be true when locations change which will
-      // affect paint properties (e.g., PaintOffset).
-      localContext.needToUpdatePaintPropertySubtree = true;
-    } else if (object.shouldDoFullPaintInvalidation()) {
-      // shouldDoFullPaintInvalidation will be true when locations or overflow
-      // changes which will affect paint properties (e.g., PaintOffset, scroll).
-      localContext.needToUpdatePaintPropertySubtree = true;
-    }
+  // Early out from the treewalk if possible.
+  if (!object.needsPaintPropertyUpdate() &&
+      !object.descendantNeedsPaintPropertyUpdate() &&
+      !context.treeBuilderContext.forceSubtreeUpdate &&
+      !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags &&
+      !object
+           .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) {
+    // Even though the subtree was not walked, we know that a walk will not
+    // change anything and can return true as if the subtree was fully updated.
+    return true;
   }
 
-  // Paint properties can depend on their ancestor properties so ensure the
-  // entire subtree is rebuilt on any changes.
-  // TODO(pdr): Add additional granularity to the needs update approach such as
-  // the ability to do local updates that don't change the subtree.
-  if (localContext.needToUpdatePaintPropertySubtree)
+  PrePaintTreeWalkContext localContext(context);
+
+  // TODO(pdr): These should be removable once paint offset changes mark an
+  // object as needing a paint property update. Below, we temporarily re-use
+  // paint invalidation flags to detect paint offset changes.
+  if (localContext.paintInvalidatorContext.forcedSubtreeInvalidationFlags) {
+    // forcedSubtreeInvalidationFlags will be true if locations have changed
+    // which will affect paint properties (e.g., PaintOffset).
+    localContext.treeBuilderContext.forceSubtreeUpdate = true;
+  } else if (object.shouldDoFullPaintInvalidation()) {
+    // shouldDoFullPaintInvalidation will be true when locations or overflow
+    // changes which will affect paint properties (e.g., PaintOffset, scroll).
     object.getMutableForPainting().setNeedsPaintPropertyUpdate();
+  } else if (object.mayNeedPaintInvalidation()) {
+    // mayNeedpaintInvalidation will be true when locations change which will
+    // affect paint properties (e.g., PaintOffset).
+    object.getMutableForPainting().setNeedsPaintPropertyUpdate();
+  }
 
   // TODO(pdr): Ensure multi column works with incremental property tree
   // construction.
@@ -114,13 +103,18 @@
     // positioned descendants if their containers are between the multi-column
     // container and the spanner. See PaintPropertyTreeBuilder for details.
     localContext.treeBuilderContext.isUnderMultiColumnSpanner = true;
-    walk(*toLayoutMultiColumnSpannerPlaceholder(object)
-              .layoutObjectInFlowThread(),
-         localContext);
-    object.getMutableForPainting().clearPaintInvalidationFlags();
-    object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
-    object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
-    return;
+    bool descendantsFullyUpdated =
+        walk(*toLayoutMultiColumnSpannerPlaceholder(object)
+                  .layoutObjectInFlowThread(),
+             localContext);
+    if (descendantsFullyUpdated) {
+      // If descendants were not fully updated, do not clear flags. During the
+      // next PrePaintTreeWalk, these flags will be used again.
+      object.getMutableForPainting().clearPaintInvalidationFlags();
+      object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
+      object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
+    }
+    return descendantsFullyUpdated;
   }
 
   m_propertyTreeBuilder.updatePropertiesForSelf(
@@ -130,12 +124,15 @@
   m_propertyTreeBuilder.updatePropertiesForChildren(
       object, localContext.treeBuilderContext);
 
+  bool descendantsFullyUpdated = true;
   for (const LayoutObject* child = object.slowFirstChild(); child;
        child = child->nextSibling()) {
     // Column spanners are walked through their placeholders. See above.
     if (child->isColumnSpanAll())
       continue;
-    walk(*child, localContext);
+    bool childFullyUpdated = walk(*child, localContext);
+    if (!childFullyUpdated)
+      descendantsFullyUpdated = false;
   }
 
   if (object.isLayoutPart()) {
@@ -147,14 +144,21 @@
           widget->frameRect().location();
       localContext.treeBuilderContext.current.paintOffset =
           roundedIntPoint(localContext.treeBuilderContext.current.paintOffset);
-      walk(*toFrameView(widget), localContext);
+      bool frameFullyUpdated = walk(*toFrameView(widget), localContext);
+      if (!frameFullyUpdated)
+        descendantsFullyUpdated = false;
     }
     // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
   }
 
-  object.getMutableForPainting().clearPaintInvalidationFlags();
-  object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
-  object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
+  if (descendantsFullyUpdated) {
+    // If descendants were not updated, do not clear flags. During the next
+    // PrePaintTreeWalk, these flags will be used again.
+    object.getMutableForPainting().clearPaintInvalidationFlags();
+    object.getMutableForPainting().clearNeedsPaintPropertyUpdate();
+    object.getMutableForPainting().clearDescendantNeedsPaintPropertyUpdate();
+  }
+  return descendantsFullyUpdated;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h
index d0c7300..603fad7e 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h
@@ -22,8 +22,11 @@
   void walk(FrameView& rootFrame);
 
  private:
-  void walk(FrameView&, const PrePaintTreeWalkContext&);
-  void walk(const LayoutObject&, const PrePaintTreeWalkContext&);
+  // Throttled rendering (see: FrameView::shouldThrottleRendering()) can prevent
+  // updating a subtree. We return true if the subtree was fully walked/updated,
+  // and false if the walk was interrupted by throttling.
+  bool walk(FrameView&, const PrePaintTreeWalkContext&);
+  bool walk(const LayoutObject&, const PrePaintTreeWalkContext&);
 
   PaintPropertyTreeBuilder m_propertyTreeBuilder;
   PaintInvalidator m_paintInvalidator;
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedEnumerationBase.cpp b/third_party/WebKit/Source/core/svg/SVGAnimatedEnumerationBase.cpp
index ca9ab5d..ce358537 100644
--- a/third_party/WebKit/Source/core/svg/SVGAnimatedEnumerationBase.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGAnimatedEnumerationBase.cpp
@@ -52,13 +52,7 @@
     return;
   }
 
-  baseValue()->setValue(value);
-
-  m_baseValueUpdated = true;
-
-  ASSERT(this->attributeName() != QualifiedName::null());
-  contextElement()->invalidateSVGAttributes();
-  contextElement()->svgAttributeBaseValChanged(this->attributeName());
+  SVGAnimatedProperty<SVGEnumerationBase>::setBaseVal(value, exceptionState);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedLength.h b/third_party/WebKit/Source/core/svg/SVGAnimatedLength.h
index 35db400..5dd38ee 100644
--- a/third_party/WebKit/Source/core/svg/SVGAnimatedLength.h
+++ b/third_party/WebKit/Source/core/svg/SVGAnimatedLength.h
@@ -54,6 +54,10 @@
   void setDefaultValueAsString(const String&);
   SVGParsingError setBaseValueAsString(const String&) override;
 
+  const CSSValue* cssValue() const {
+    return &currentValue()->asCSSPrimitiveValue();
+  }
+
   DECLARE_VIRTUAL_TRACE_WRAPPERS();
 
  protected:
diff --git a/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp b/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp
index 5ab3a9a..42bd6a8 100644
--- a/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp
@@ -82,18 +82,19 @@
     const AtomicString& value,
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
-  if (property == m_cx)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyCx, m_cx->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_cy)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyCy, m_cy->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_r)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyR, m_r->currentValue()->asCSSPrimitiveValue());
-  else
+  if (property == m_cx) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyCx,
+                                            m_cx->cssValue());
+  } else if (property == m_cy) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyCy,
+                                            m_cy->cssValue());
+  } else if (property == m_r) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyR,
+                                            m_r->cssValue());
+  } else {
     SVGGeometryElement::collectStyleForPresentationAttribute(name, value,
                                                              style);
+  }
 }
 
 void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName) {
diff --git a/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp b/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp
index c2161df..7421058 100644
--- a/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp
@@ -95,21 +95,22 @@
     const AtomicString& value,
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
-  if (property == m_cx)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyCx, m_cx->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_cy)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyCy, m_cy->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_rx)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyRx, m_rx->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_ry)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyRy, m_ry->currentValue()->asCSSPrimitiveValue());
-  else
+  if (property == m_cx) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyCx,
+                                            m_cx->cssValue());
+  } else if (property == m_cy) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyCy,
+                                            m_cy->cssValue());
+  } else if (property == m_rx) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyRx,
+                                            m_rx->cssValue());
+  } else if (property == m_ry) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyRy,
+                                            m_ry->cssValue());
+  } else {
     SVGGeometryElement::collectStyleForPresentationAttribute(name, value,
                                                              style);
+  }
 }
 
 void SVGEllipseElement::svgAttributeChanged(const QualifiedName& attrName) {
diff --git a/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp b/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp
index d5966e2..daf86ff 100644
--- a/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp
@@ -70,23 +70,22 @@
     const AtomicString& value,
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
-  if (property == m_width)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyWidth,
-        m_width->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_height)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyHeight,
-        m_height->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_x)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyX, m_x->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_y)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyY, m_y->currentValue()->asCSSPrimitiveValue());
-  else
+  if (property == m_width) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth,
+                                            m_width->cssValue());
+  } else if (property == m_height) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight,
+                                            m_height->cssValue());
+  } else if (property == m_x) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyX,
+                                            m_x->cssValue());
+  } else if (property == m_y) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyY,
+                                            m_y->cssValue());
+  } else {
     SVGGraphicsElement::collectStyleForPresentationAttribute(name, value,
                                                              style);
+  }
 }
 
 void SVGForeignObjectElement::svgAttributeChanged(
diff --git a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
index 0e1b5c8..4dc7f4e 100644
--- a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
@@ -90,23 +90,22 @@
     const AtomicString& value,
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
-  if (property == m_width)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyWidth,
-        m_width->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_height)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyHeight,
-        m_height->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_x)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyX, m_x->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_y)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyY, m_y->currentValue()->asCSSPrimitiveValue());
-  else
+  if (property == m_width) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth,
+                                            m_width->cssValue());
+  } else if (property == m_height) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight,
+                                            m_height->cssValue());
+  } else if (property == m_x) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyX,
+                                            m_x->cssValue());
+  } else if (property == m_y) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyY,
+                                            m_y->cssValue());
+  } else {
     SVGGraphicsElement::collectStyleForPresentationAttribute(name, value,
                                                              style);
+  }
 }
 
 void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName) {
diff --git a/third_party/WebKit/Source/core/svg/SVGLength.cpp b/third_party/WebKit/Source/core/svg/SVGLength.cpp
index 0a2b699..91b9d28 100644
--- a/third_party/WebKit/Source/core/svg/SVGLength.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGLength.cpp
@@ -67,7 +67,7 @@
 
 float SVGLength::value(const SVGLengthContext& context) const {
   if (isCalculated())
-    return context.resolveValue(*asCSSPrimitiveValue(), unitMode());
+    return context.resolveValue(asCSSPrimitiveValue(), unitMode());
 
   return context.convertValueToUserUnits(m_value->getFloatValue(), unitMode(),
                                          m_value->typeWithCalcResolved());
diff --git a/third_party/WebKit/Source/core/svg/SVGLength.h b/third_party/WebKit/Source/core/svg/SVGLength.h
index 1d6db09..6b04d8d 100644
--- a/third_party/WebKit/Source/core/svg/SVGLength.h
+++ b/third_party/WebKit/Source/core/svg/SVGLength.h
@@ -66,7 +66,7 @@
     m_value = CSSPrimitiveValue::create(value, m_value->typeWithCalcResolved());
   }
 
-  const CSSPrimitiveValue* asCSSPrimitiveValue() const { return m_value.get(); }
+  const CSSPrimitiveValue& asCSSPrimitiveValue() const { return *m_value; }
 
   // Resolves LengthTypePercentage into a normalized floating point number (full
   // value is 1.0).
diff --git a/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp b/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp
index 95b071a..eadc802 100644
--- a/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp
@@ -93,22 +93,21 @@
     const AtomicString& value,
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
-  if (property == m_x)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyX, m_x->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_y)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyY, m_y->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_width)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyWidth,
-        m_width->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_height)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyHeight,
-        m_height->currentValue()->asCSSPrimitiveValue());
-  else
+  if (property == m_x) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyX,
+                                            m_x->cssValue());
+  } else if (property == m_y) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyY,
+                                            m_y->cssValue());
+  } else if (property == m_width) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth,
+                                            m_width->cssValue());
+  } else if (property == m_height) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight,
+                                            m_height->cssValue());
+  } else {
     SVGElement::collectStyleForPresentationAttribute(name, value, style);
+  }
 }
 
 void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) {
diff --git a/third_party/WebKit/Source/core/svg/SVGRectElement.cpp b/third_party/WebKit/Source/core/svg/SVGRectElement.cpp
index c7e08f7..4320bcb 100644
--- a/third_party/WebKit/Source/core/svg/SVGRectElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGRectElement.cpp
@@ -121,29 +121,28 @@
     const AtomicString& value,
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
-  if (property == m_x)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyX, m_x->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_y)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyY, m_y->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_width)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyWidth,
-        m_width->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_height)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyHeight,
-        m_height->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_rx)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyRx, m_rx->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_ry)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyRy, m_ry->currentValue()->asCSSPrimitiveValue());
-  else
+  if (property == m_x) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyX,
+                                            m_x->cssValue());
+  } else if (property == m_y) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyY,
+                                            m_y->cssValue());
+  } else if (property == m_width) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth,
+                                            m_width->cssValue());
+  } else if (property == m_height) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight,
+                                            m_height->cssValue());
+  } else if (property == m_rx) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyRx,
+                                            m_rx->cssValue());
+  } else if (property == m_ry) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyRy,
+                                            m_ry->cssValue());
+  } else {
     SVGGeometryElement::collectStyleForPresentationAttribute(name, value,
                                                              style);
+  }
 }
 
 void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName) {
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
index a08056b..181fd7b 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -238,21 +238,20 @@
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
   if (property == m_x) {
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyX, m_x->currentValue()->asCSSPrimitiveValue());
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyX,
+                                            m_x->cssValue());
   } else if (property == m_y) {
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyY, m_y->currentValue()->asCSSPrimitiveValue());
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyY,
+                                            m_y->cssValue());
   } else if (isOutermostSVGSVGElement() &&
              (property == m_width || property == m_height)) {
-    if (property == m_width)
-      addPropertyToPresentationAttributeStyle(
-          style, CSSPropertyWidth,
-          m_width->currentValue()->asCSSPrimitiveValue());
-    else if (property == m_height)
-      addPropertyToPresentationAttributeStyle(
-          style, CSSPropertyHeight,
-          m_height->currentValue()->asCSSPrimitiveValue());
+    if (property == m_width) {
+      addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth,
+                                              m_width->cssValue());
+    } else if (property == m_height) {
+      addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight,
+                                              m_height->cssValue());
+    }
   } else {
     SVGGraphicsElement::collectStyleForPresentationAttribute(name, value,
                                                              style);
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
index 72bd3e79..6922049 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -180,15 +180,16 @@
     const AtomicString& value,
     MutableStylePropertySet* style) {
   SVGAnimatedPropertyBase* property = propertyFromAttribute(name);
-  if (property == m_x)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyX, m_x->currentValue()->asCSSPrimitiveValue());
-  else if (property == m_y)
-    addPropertyToPresentationAttributeStyle(
-        style, CSSPropertyY, m_y->currentValue()->asCSSPrimitiveValue());
-  else
+  if (property == m_x) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyX,
+                                            m_x->cssValue());
+  } else if (property == m_y) {
+    addPropertyToPresentationAttributeStyle(style, CSSPropertyY,
+                                            m_y->cssValue());
+  } else {
     SVGGraphicsElement::collectStyleForPresentationAttribute(name, value,
                                                              style);
+  }
 }
 
 bool SVGUseElement::isStructurallyExternal() const {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index 59fbbc2..30c887d 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -2885,7 +2885,7 @@
 
     var prefixResults = [];
     var anywhereResults = [];
-    this._cssCompletions.forEach(filterCompletions);
+    this._cssCompletions.forEach(filterCompletions.bind(this));
     var results = prefixResults.concat(anywhereResults);
 
     if (!this._isEditingName && !results.length && query.length > 1 && '!important'.startsWith(lowerQuery))
@@ -2899,13 +2899,16 @@
 
     /**
      * @param {string} completion
+     * @this {Elements.StylesSidebarPane.CSSPropertyPrompt}
      */
     function filterCompletions(completion) {
       var index = completion.indexOf(lowerQuery);
-      if (index === 0)
-        prefixResults.push({title: completion, priority: SDK.cssMetadata().propertyUsageWeight(completion)});
-      else if (index > -1)
+      if (index === 0) {
+        var priority = this._isEditingName ? SDK.cssMetadata().propertyUsageWeight(completion) : 1;
+        prefixResults.push({title: completion, priority: priority});
+      } else if (index > -1) {
         anywhereResults.push({title: completion});
+      }
     }
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
index 628f2ab..5d716f8a 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -794,7 +794,7 @@
             new Set(decorations.map(decoration => decoration.bookmark).filter(bookmark => !!bookmark));
         var lineEnd = this._textEditor.line(lineNumber).length;
         var bookmarks = this._textEditor.bookmarks(
-            new Common.TextRange(lineNumber, 0, lineEnd, 0),
+            new Common.TextRange(lineNumber, 0, lineNumber, lineEnd),
             Sources.JavaScriptSourceFrame.BreakpointDecoration.bookmarkSymbol);
         for (var bookmark of bookmarks) {
           if (!actualBookmarks.has(bookmark))
diff --git a/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js
index 29533c3..ae224e5 100644
--- a/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js
+++ b/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -141,7 +141,8 @@
     this._shouldClearHistory = true;
     this._lineSeparator = '\n';
 
-    this._fixWordMovement = new TextEditor.CodeMirrorTextEditor.FixWordMovement(this._codeMirror);
+    TextEditor.CodeMirrorTextEditor._fixWordMovement(this._codeMirror);
+
     this._selectNextOccurrenceController =
         new TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController(this, this._codeMirror);
 
@@ -155,7 +156,6 @@
 
     /** @type {!Multimap<number, !TextEditor.CodeMirrorTextEditor.Decoration>} */
     this._decorations = new Multimap();
-    this._nestedUpdatesCounter = 0;
 
     this.element.addEventListener('focus', this._handleElementFocus.bind(this), false);
     this.element.addEventListener('keydown', this._handleKeyDown.bind(this), true);
@@ -314,6 +314,53 @@
   }
 
   /**
+   * @param {!CodeMirror} codeMirror
+   */
+  static _fixWordMovement(codeMirror) {
+    function moveLeft(shift, codeMirror) {
+      codeMirror.setExtending(shift);
+      var cursor = codeMirror.getCursor('head');
+      codeMirror.execCommand('goGroupLeft');
+      var newCursor = codeMirror.getCursor('head');
+      if (newCursor.ch === 0 && newCursor.line !== 0) {
+        codeMirror.setExtending(false);
+        return;
+      }
+
+      var skippedText = codeMirror.getRange(newCursor, cursor, '#');
+      if (/^\s+$/.test(skippedText))
+        codeMirror.execCommand('goGroupLeft');
+      codeMirror.setExtending(false);
+    }
+
+    function moveRight(shift, codeMirror) {
+      codeMirror.setExtending(shift);
+      var cursor = codeMirror.getCursor('head');
+      codeMirror.execCommand('goGroupRight');
+      var newCursor = codeMirror.getCursor('head');
+      if (newCursor.ch === 0 && newCursor.line !== 0) {
+        codeMirror.setExtending(false);
+        return;
+      }
+
+      var skippedText = codeMirror.getRange(cursor, newCursor, '#');
+      if (/^\s+$/.test(skippedText))
+        codeMirror.execCommand('goGroupRight');
+      codeMirror.setExtending(false);
+    }
+
+    var modifierKey = Host.isMac() ? 'Alt' : 'Ctrl';
+    var leftKey = modifierKey + '-Left';
+    var rightKey = modifierKey + '-Right';
+    var keyMap = {};
+    keyMap[leftKey] = moveLeft.bind(null, false);
+    keyMap[rightKey] = moveRight.bind(null, false);
+    keyMap['Shift-' + leftKey] = moveLeft.bind(null, true);
+    keyMap['Shift-' + rightKey] = moveRight.bind(null, true);
+    codeMirror.addKeyMap(keyMap);
+  }
+
+  /**
    * @protected
    * @return {!CodeMirror}
    */
@@ -1323,58 +1370,6 @@
 /**
  * @unrestricted
  */
-TextEditor.CodeMirrorTextEditor.FixWordMovement = class {
-  /**
-   * @param {!CodeMirror} codeMirror
-   */
-  constructor(codeMirror) {
-    function moveLeft(shift, codeMirror) {
-      codeMirror.setExtending(shift);
-      var cursor = codeMirror.getCursor('head');
-      codeMirror.execCommand('goGroupLeft');
-      var newCursor = codeMirror.getCursor('head');
-      if (newCursor.ch === 0 && newCursor.line !== 0) {
-        codeMirror.setExtending(false);
-        return;
-      }
-
-      var skippedText = codeMirror.getRange(newCursor, cursor, '#');
-      if (/^\s+$/.test(skippedText))
-        codeMirror.execCommand('goGroupLeft');
-      codeMirror.setExtending(false);
-    }
-
-    function moveRight(shift, codeMirror) {
-      codeMirror.setExtending(shift);
-      var cursor = codeMirror.getCursor('head');
-      codeMirror.execCommand('goGroupRight');
-      var newCursor = codeMirror.getCursor('head');
-      if (newCursor.ch === 0 && newCursor.line !== 0) {
-        codeMirror.setExtending(false);
-        return;
-      }
-
-      var skippedText = codeMirror.getRange(cursor, newCursor, '#');
-      if (/^\s+$/.test(skippedText))
-        codeMirror.execCommand('goGroupRight');
-      codeMirror.setExtending(false);
-    }
-
-    var modifierKey = Host.isMac() ? 'Alt' : 'Ctrl';
-    var leftKey = modifierKey + '-Left';
-    var rightKey = modifierKey + '-Right';
-    var keyMap = {};
-    keyMap[leftKey] = moveLeft.bind(null, false);
-    keyMap[rightKey] = moveRight.bind(null, false);
-    keyMap['Shift-' + leftKey] = moveLeft.bind(null, true);
-    keyMap['Shift-' + rightKey] = moveRight.bind(null, true);
-    codeMirror.addKeyMap(keyMap);
-  }
-};
-
-/**
- * @unrestricted
- */
 TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
   /**
    * @param {!TextEditor.CodeMirrorTextEditor} textEditor
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp
index 64819e62..0042689 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp
+++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp
@@ -14,11 +14,30 @@
 #include "platform/network/ResourceRequest.h"
 #include "platform/weborigin/KURL.h"
 #include "public/platform/WebURLRequest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
+#include "public/platform/modules/notifications/WebNotificationConstants.h"
+#include "skia/ext/image_operations.h"
 #include "wtf/CurrentTime.h"
 #include "wtf/Threading.h"
 #include <memory>
 
+#define NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, type_name, value, max) \
+  case NotificationImageLoader::Type::type_name: {                            \
+    DEFINE_THREAD_SAFE_STATIC_LOCAL(                                          \
+        CustomCountHistogram, metric##type_name##Histogram,                   \
+        new CustomCountHistogram("Notifications." #metric "." #type_name,     \
+                                 1 /* min */, max, 50 /* buckets */));        \
+    metric##type_name##Histogram.count(value);                                \
+    break;                                                                    \
+  }
+
+#define NOTIFICATION_HISTOGRAM_COUNTS(metric, type, value, max)            \
+  switch (type) {                                                          \
+    NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Image, value, max)      \
+    NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Icon, value, max)       \
+    NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Badge, value, max)      \
+    NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, ActionIcon, value, max) \
+  }
+
 namespace {
 
 // 99.9% of all images were fetched successfully in 90 seconds.
@@ -28,11 +47,53 @@
 
 namespace blink {
 
-NotificationImageLoader::NotificationImageLoader()
-    : m_stopped(false), m_startTime(0.0) {}
+NotificationImageLoader::NotificationImageLoader(Type type)
+    : m_type(type), m_stopped(false), m_startTime(0.0) {}
 
 NotificationImageLoader::~NotificationImageLoader() {}
 
+// static
+SkBitmap NotificationImageLoader::scaleDownIfNeeded(const SkBitmap& image,
+                                                    Type type) {
+  int maxWidthPx = 0, maxHeightPx = 0;
+  switch (type) {
+    case Type::Image:
+      maxWidthPx = kWebNotificationMaxImageWidthPx;
+      maxHeightPx = kWebNotificationMaxImageHeightPx;
+      break;
+    case Type::Icon:
+      maxWidthPx = kWebNotificationMaxIconSizePx;
+      maxHeightPx = kWebNotificationMaxIconSizePx;
+      break;
+    case Type::Badge:
+      maxWidthPx = kWebNotificationMaxBadgeSizePx;
+      maxHeightPx = kWebNotificationMaxBadgeSizePx;
+      break;
+    case Type::ActionIcon:
+      maxWidthPx = kWebNotificationMaxActionIconSizePx;
+      maxHeightPx = kWebNotificationMaxActionIconSizePx;
+      break;
+  }
+  DCHECK_GT(maxWidthPx, 0);
+  DCHECK_GT(maxHeightPx, 0);
+  // TODO(peter): Explore doing the scaling on a background thread.
+  if (image.width() > maxWidthPx || image.height() > maxHeightPx) {
+    double scale = std::min(static_cast<double>(maxWidthPx) / image.width(),
+                            static_cast<double>(maxHeightPx) / image.height());
+    double startTime = monotonicallyIncreasingTimeMS();
+    // TODO(peter): Try using RESIZE_BETTER for large images.
+    SkBitmap scaledImage =
+        skia::ImageOperations::Resize(image, skia::ImageOperations::RESIZE_BEST,
+                                      std::lround(scale * image.width()),
+                                      std::lround(scale * image.height()));
+    NOTIFICATION_HISTOGRAM_COUNTS(LoadScaleDownTime, type,
+                                  monotonicallyIncreasingTimeMS() - startTime,
+                                  1000 * 10 /* 10 seconds max */);
+    return scaledImage;
+  }
+  return image;
+}
+
 void NotificationImageLoader::start(
     ExecutionContext* executionContext,
     const KURL& url,
@@ -89,19 +150,13 @@
   if (m_stopped)
     return;
 
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      CustomCountHistogram, finishedTimeHistogram,
-      new CustomCountHistogram("Notifications.Icon.LoadFinishTime", 1,
-                               1000 * 60 * 60 /* 1 hour max */,
-                               50 /* buckets */));
-  finishedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime);
+  NOTIFICATION_HISTOGRAM_COUNTS(LoadFinishTime, m_type,
+                                monotonicallyIncreasingTimeMS() - m_startTime,
+                                1000 * 60 * 60 /* 1 hour max */);
 
   if (m_data) {
-    DEFINE_THREAD_SAFE_STATIC_LOCAL(
-        CustomCountHistogram, fileSizeHistogram,
-        new CustomCountHistogram("Notifications.Icon.FileSize", 1,
-                                 10000000 /* ~10mb max */, 50 /* buckets */));
-    fileSizeHistogram.count(m_data->size());
+    NOTIFICATION_HISTOGRAM_COUNTS(LoadFileSize, m_type, m_data->size(),
+                                  10000000 /* ~10mb max */);
 
     std::unique_ptr<ImageDecoder> decoder = ImageDecoder::create(
         m_data, true /* dataComplete */, ImageDecoder::AlphaPremultiplied,
@@ -120,12 +175,9 @@
 }
 
 void NotificationImageLoader::didFail(const ResourceError& error) {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      CustomCountHistogram, failedTimeHistogram,
-      new CustomCountHistogram("Notifications.Icon.LoadFailTime", 1,
-                               1000 * 60 * 60 /* 1 hour max */,
-                               50 /* buckets */));
-  failedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime);
+  NOTIFICATION_HISTOGRAM_COUNTS(LoadFailTime, m_type,
+                                monotonicallyIncreasingTimeMS() - m_startTime,
+                                1000 * 60 * 60 /* 1 hour max */);
 
   runCallbackWithEmptyBitmap();
 }
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h
index ea0cc3d..46e6be4 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h
+++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h
@@ -10,12 +10,11 @@
 #include "modules/ModulesExport.h"
 #include "platform/SharedBuffer.h"
 #include "platform/heap/Handle.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "wtf/Functional.h"
 #include "wtf/RefPtr.h"
 #include <memory>
 
-class SkBitmap;
-
 namespace blink {
 
 class ExecutionContext;
@@ -28,13 +27,20 @@
     : public GarbageCollectedFinalized<NotificationImageLoader>,
       public ThreadableLoaderClient {
  public:
+  // Type names are used in UMAs, so do not rename.
+  enum class Type { Image, Icon, Badge, ActionIcon };
+
   // The bitmap may be empty if the request failed or the image data could not
   // be decoded.
   using ImageCallback = Function<void(const SkBitmap&)>;
 
-  NotificationImageLoader();
+  explicit NotificationImageLoader(Type);
   ~NotificationImageLoader() override;
 
+  // Scales down |image| according to its type and returns result. If it is
+  // already small enough, |image| is returned unchanged.
+  static SkBitmap scaleDownIfNeeded(const SkBitmap& image, Type);
+
   // Asynchronously downloads an image from the given url, decodes the loaded
   // data, and passes the bitmap to the callback. Times out if the load takes
   // too long and ImageCallback is invoked with an empty bitmap.
@@ -56,6 +62,7 @@
  private:
   void runCallbackWithEmptyBitmap();
 
+  Type m_type;
   bool m_stopped;
   double m_startTime;
   RefPtr<SharedBuffer> m_data;
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp b/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp
index bcb59f4..8b31a76 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp
+++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp
@@ -7,6 +7,7 @@
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/MemoryCache.h"
 #include "core/testing/DummyPageHolder.h"
+#include "platform/testing/HistogramTester.h"
 #include "platform/testing/TestingPlatformSupport.h"
 #include "platform/testing/URLTestHelpers.h"
 #include "public/platform/Platform.h"
@@ -35,7 +36,9 @@
  public:
   NotificationImageLoaderTest()
       : m_page(DummyPageHolder::create()),
-        m_loader(new NotificationImageLoader()) {}
+        // Use an arbitrary type, since it only affects which UMA bucket we use.
+        m_loader(
+            new NotificationImageLoader(NotificationImageLoader::Type::Icon)) {}
 
   ~NotificationImageLoaderTest() override {
     m_loader->stop();
@@ -70,6 +73,9 @@
   ExecutionContext* context() const { return &m_page->document(); }
   LoadState loaded() const { return m_loaded; }
 
+ protected:
+  HistogramTester m_histogramTester;
+
  private:
   std::unique_ptr<DummyPageHolder> m_page;
   Persistent<NotificationImageLoader> m_loader;
@@ -79,8 +85,15 @@
 TEST_F(NotificationImageLoaderTest, SuccessTest) {
   KURL url = registerMockedURL(kIcon500x500);
   loadImage(url);
+  m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 0);
+  m_histogramTester.expectTotalCount("Notifications.LoadFileSize.Icon", 0);
+  m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 0);
   Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests();
   EXPECT_EQ(LoadState::kLoadSuccessful, loaded());
+  m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 1);
+  m_histogramTester.expectUniqueSample("Notifications.LoadFileSize.Icon", 7439,
+                                       1);
+  m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 0);
 }
 
 TEST_F(NotificationImageLoaderTest, TimeoutTest) {
@@ -94,12 +107,20 @@
   // result in a timeout.
   testingPlatform.runForPeriodSeconds(kImageFetchTimeoutInMs / 1000 - 1);
   EXPECT_EQ(LoadState::kNotLoaded, loaded());
+  m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 0);
+  m_histogramTester.expectTotalCount("Notifications.LoadFileSize.Icon", 0);
+  m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 0);
 
   // Now advance time until a timeout should be expected.
   testingPlatform.runForPeriodSeconds(2);
 
   // If the loader times out, it calls the callback and returns an empty bitmap.
   EXPECT_EQ(LoadState::kLoadFailed, loaded());
+  m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 0);
+  m_histogramTester.expectTotalCount("Notifications.LoadFileSize.Icon", 0);
+  // Should log a non-zero failure time.
+  m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 1);
+  m_histogramTester.expectBucketCount("Notifications.LoadFailTime.Icon", 0, 0);
 }
 
 }  // namspace
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
index 7c4a01cd..fb717c2 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
+++ b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
@@ -6,47 +6,14 @@
 
 #include "platform/Histogram.h"
 #include "platform/weborigin/KURL.h"
-#include "public/platform/modules/notifications/WebNotificationConstants.h"
 #include "public/platform/modules/notifications/WebNotificationData.h"
 #include "public/platform/modules/notifications/WebNotificationResources.h"
-#include "skia/ext/image_operations.h"
-#include "third_party/skia/include/core/SkBitmap.h"
 #include "wtf/CurrentTime.h"
 #include "wtf/Threading.h"
 #include <cmath>
 
 namespace blink {
 
-namespace {
-
-// Scales down |image| to fit within |maxWidthPx|x|maxHeightPx| if it is larger
-// and returns the result. Otherwise does nothing and returns |image| unchanged.
-// TODO(mvanouwerkerk): Explore doing the scaling on a background thread.
-SkBitmap scaleDownIfNeeded(const SkBitmap& image,
-                           int maxWidthPx,
-                           int maxHeightPx) {
-  if (image.width() > maxWidthPx || image.height() > maxHeightPx) {
-    double scale = std::min(static_cast<double>(maxWidthPx) / image.width(),
-                            static_cast<double>(maxHeightPx) / image.height());
-    DEFINE_THREAD_SAFE_STATIC_LOCAL(
-        CustomCountHistogram, scaleTimeHistogram,
-        new CustomCountHistogram("Notifications.Icon.ScaleDownTime", 1,
-                                 1000 * 10 /* 10 seconds max */,
-                                 50 /* buckets */));
-    double startTime = monotonicallyIncreasingTimeMS();
-    // TODO(peter): Try using RESIZE_BETTER for large images.
-    SkBitmap scaledImage =
-        skia::ImageOperations::Resize(image, skia::ImageOperations::RESIZE_BEST,
-                                      std::lround(scale * image.width()),
-                                      std::lround(scale * image.height()));
-    scaleTimeHistogram.count(monotonicallyIncreasingTimeMS() - startTime);
-    return scaledImage;
-  }
-  return image;
-}
-
-}  // namespace
-
 NotificationResourcesLoader::NotificationResourcesLoader(
     std::unique_ptr<CompletionCallback> completionCallback)
     : m_started(false),
@@ -69,19 +36,23 @@
 
   // TODO(johnme): ensure image is not loaded when it will not be used.
   // TODO(mvanouwerkerk): ensure no badge is loaded when it will not be used.
-  loadImage(executionContext, notificationData.image,
+  loadImage(executionContext, NotificationImageLoader::Type::Image,
+            notificationData.image,
             WTF::bind(&NotificationResourcesLoader::didLoadImage,
                       wrapWeakPersistent(this)));
-  loadImage(executionContext, notificationData.icon,
+  loadImage(executionContext, NotificationImageLoader::Type::Icon,
+            notificationData.icon,
             WTF::bind(&NotificationResourcesLoader::didLoadIcon,
                       wrapWeakPersistent(this)));
-  loadImage(executionContext, notificationData.badge,
+  loadImage(executionContext, NotificationImageLoader::Type::Badge,
+            notificationData.badge,
             WTF::bind(&NotificationResourcesLoader::didLoadBadge,
                       wrapWeakPersistent(this)));
 
   m_actionIcons.resize(numActions);
   for (size_t i = 0; i < numActions; i++)
-    loadImage(executionContext, notificationData.actions[i].icon,
+    loadImage(executionContext, NotificationImageLoader::Type::ActionIcon,
+              notificationData.actions[i].icon,
               WTF::bind(&NotificationResourcesLoader::didLoadActionIcon,
                         wrapWeakPersistent(this), i));
 }
@@ -108,6 +79,7 @@
 
 void NotificationResourcesLoader::loadImage(
     ExecutionContext* executionContext,
+    NotificationImageLoader::Type type,
     const KURL& url,
     std::unique_ptr<NotificationImageLoader::ImageCallback> imageCallback) {
   if (url.isNull() || url.isEmpty() || !url.isValid()) {
@@ -115,26 +87,26 @@
     return;
   }
 
-  NotificationImageLoader* imageLoader = new NotificationImageLoader();
+  NotificationImageLoader* imageLoader = new NotificationImageLoader(type);
   m_imageLoaders.append(imageLoader);
   imageLoader->start(executionContext, url, std::move(imageCallback));
 }
 
 void NotificationResourcesLoader::didLoadImage(const SkBitmap& image) {
-  m_image = scaleDownIfNeeded(image, kWebNotificationMaxImageWidthPx,
-                              kWebNotificationMaxImageHeightPx);
+  m_image = NotificationImageLoader::scaleDownIfNeeded(
+      image, NotificationImageLoader::Type::Image);
   didFinishRequest();
 }
 
 void NotificationResourcesLoader::didLoadIcon(const SkBitmap& image) {
-  m_icon = scaleDownIfNeeded(image, kWebNotificationMaxIconSizePx,
-                             kWebNotificationMaxIconSizePx);
+  m_icon = NotificationImageLoader::scaleDownIfNeeded(
+      image, NotificationImageLoader::Type::Icon);
   didFinishRequest();
 }
 
 void NotificationResourcesLoader::didLoadBadge(const SkBitmap& image) {
-  m_badge = scaleDownIfNeeded(image, kWebNotificationMaxBadgeSizePx,
-                              kWebNotificationMaxBadgeSizePx);
+  m_badge = NotificationImageLoader::scaleDownIfNeeded(
+      image, NotificationImageLoader::Type::Badge);
   didFinishRequest();
 }
 
@@ -142,9 +114,8 @@
                                                     const SkBitmap& image) {
   DCHECK_LT(actionIndex, m_actionIcons.size());
 
-  m_actionIcons[actionIndex] =
-      scaleDownIfNeeded(image, kWebNotificationMaxActionIconSizePx,
-                        kWebNotificationMaxActionIconSizePx);
+  m_actionIcons[actionIndex] = NotificationImageLoader::scaleDownIfNeeded(
+      image, NotificationImageLoader::Type::ActionIcon);
   didFinishRequest();
 }
 
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h
index 8f11042..4ab17e9 100644
--- a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h
+++ b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h
@@ -56,6 +56,7 @@
 
  private:
   void loadImage(ExecutionContext*,
+                 NotificationImageLoader::Type,
                  const KURL&,
                  std::unique_ptr<NotificationImageLoader::ImageCallback>);
   void didLoadImage(const SkBitmap& image);
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
index e6515a2e..657e91f0 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -460,8 +460,9 @@
     Fullscreen::requestFullscreen(*canvas, Fullscreen::UnprefixedRequest);
 
     // Check to see if the canvas is still the current fullscreen
-    // element once every 5 seconds.
-    m_fullscreenCheckTimer.startRepeating(5.0, BLINK_FROM_HERE);
+    // element once every 2 seconds.
+    m_fullscreenCheckTimer.startRepeating(2.0, BLINK_FROM_HERE);
+    m_reenteredFullscreen = false;
   }
 
   if (doc) {
@@ -653,18 +654,38 @@
 }
 
 void VRDisplay::onFullscreenCheck(TimerBase*) {
+  if (!m_isPresenting) {
+    m_fullscreenCheckTimer.stop();
+    return;
+  }
   // TODO: This is a temporary measure to track if fullscreen mode has been
   // exited by the UA. If so we need to end VR presentation. Soon we won't
   // depend on the Fullscreen API to fake VR presentation, so this will
   // become unnessecary. Until that point, though, this seems preferable to
   // adding a bunch of notification plumbing to Fullscreen.
   if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) {
-    m_isPresenting = false;
-    OnPresentChange();
-    m_fullscreenCheckTimer.stop();
-    if (!m_display)
+    // TODO(mthiesse): Due to asynchronous resizing, we might get kicked out of
+    // fullscreen when changing display parameters upon entering WebVR. So one
+    // time only, we reenter fullscreen after having left it; otherwise we exit
+    // presentation.
+    if (m_reenteredFullscreen) {
+      m_isPresenting = false;
+      OnPresentChange();
+      m_fullscreenCheckTimer.stop();
+      if (m_display)
+        m_display->ExitPresent();
       return;
-    m_display->ExitPresent();
+    }
+    m_reenteredFullscreen = true;
+    auto canvas = m_layer.source();
+    Document* doc = m_navigatorVR->document();
+    std::unique_ptr<UserGestureIndicator> gestureIndicator;
+    if (doc) {
+      gestureIndicator =
+          wrapUnique(new UserGestureIndicator(DocumentUserGestureToken::create(
+              doc, UserGestureToken::Status::PossiblyExistingGesture)));
+    }
+    Fullscreen::requestFullscreen(*canvas, Fullscreen::UnprefixedRequest);
   }
 }
 
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.h b/third_party/WebKit/Source/modules/vr/VRDisplay.h
index d96e666..ba79dd0 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.h
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.h
@@ -148,6 +148,7 @@
   bool m_animationCallbackRequested;
   bool m_inAnimationFrame;
   bool m_displayBlurred;
+  bool m_reenteredFullscreen;
 
   device::mojom::blink::VRDisplayPtr m_display;
 
diff --git a/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp b/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp
index 2cbd0f5..a0cac20 100644
--- a/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp
+++ b/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp
@@ -21,15 +21,12 @@
 class NGInlineLayoutTest : public SimTest {
  public:
   NGConstraintSpace* constraintSpaceForElement(LayoutNGBlockFlow* blockFlow) {
-    NGConstraintSpaceBuilder builder(
-        FromPlatformWritingMode(blockFlow->style()->getWritingMode()));
-    builder.SetAvailableSize(NGLogicalSize(LayoutUnit(), LayoutUnit()));
-    builder.SetPercentageResolutionSize(
-        NGLogicalSize(LayoutUnit(), LayoutUnit()));
-    NGConstraintSpace* constraintSpace = new NGConstraintSpace(
-        FromPlatformWritingMode(blockFlow->style()->getWritingMode()),
-        blockFlow->style()->direction(), builder.ToConstraintSpace());
-    return constraintSpace;
+    return NGConstraintSpaceBuilder(
+               FromPlatformWritingMode(blockFlow->style()->getWritingMode()))
+        .SetAvailableSize(NGLogicalSize(LayoutUnit(), LayoutUnit()))
+        .SetPercentageResolutionSize(NGLogicalSize(LayoutUnit(), LayoutUnit()))
+        .SetTextDirection(blockFlow->style()->direction())
+        .ToConstraintSpace();
   }
 };
 
diff --git a/third_party/webrtc_overrides/init_webrtc.cc b/third_party/webrtc_overrides/init_webrtc.cc
index 42a5df2..f51455ec 100644
--- a/third_party/webrtc_overrides/init_webrtc.cc
+++ b/third_party/webrtc_overrides/init_webrtc.cc
@@ -51,6 +51,13 @@
           base::HistogramBase::kUmaTargetedHistogramFlag));
 }
 
+Histogram* HistogramFactoryGetCountsLinear(
+    const std::string& name, int min, int max, int bucket_count) {
+  return reinterpret_cast<Histogram*>(
+      base::LinearHistogram::FactoryGet(name, min, max, bucket_count,
+          base::HistogramBase::kUmaTargetedHistogramFlag));
+}
+
 Histogram* HistogramFactoryGetEnumeration(
     const std::string& name, int boundary) {
   return reinterpret_cast<Histogram*>(
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc
index 09f62db..6e50428 100644
--- a/tools/gn/xcode_writer.cc
+++ b/tools/gn/xcode_writer.cc
@@ -31,6 +31,16 @@
 
 namespace {
 
+struct SafeEnvironmentVariableInfo {
+  const char* name;
+  bool capture_at_generation;
+};
+
+SafeEnvironmentVariableInfo kSafeEnvironmentVariables[] = {
+    {"HOME", true}, {"LANG", true},    {"PATH", true},
+    {"USER", true}, {"TMPDIR", false},
+};
+
 XcodeWriter::TargetOsType GetTargetOs(const Args& args) {
   const Value* target_os_value = args.GetArgOverride(variables::kTargetOs);
   if (target_os_value) {
@@ -43,13 +53,31 @@
 }
 
 std::string GetBuildScript(const std::string& target_name,
-                           const std::string& build_path,
-                           const std::string& ninja_extra_args) {
+                           const std::string& ninja_extra_args,
+                           base::Environment* environment) {
   std::stringstream script;
   script << "echo note: \"Compile and copy " << target_name << " via ninja\"\n"
          << "exec ";
-  if (!build_path.empty())
-    script << "env PATH=\"" << build_path << "\" ";
+
+  // Launch ninja with a sanitized environment (Xcode sets many environment
+  // variable overridding settings, including the SDK, thus breaking hermetic
+  // build).
+  script << "env -i ";
+  for (size_t i = 0; i < arraysize(kSafeEnvironmentVariables); ++i) {
+    const auto& variable = kSafeEnvironmentVariables[i];
+    script << variable.name << "=\"";
+
+    std::string value;
+    if (variable.capture_at_generation)
+      environment->GetVar(variable.name, &value);
+
+    if (!value.empty())
+      script << value;
+    else
+      script << "$" << variable.name;
+    script << "\" ";
+  }
+
   script << "ninja -C .";
   if (!ninja_extra_args.empty())
     script << " " << ninja_extra_args;
@@ -253,10 +281,9 @@
 
   std::string build_path;
   std::unique_ptr<base::Environment> env(base::Environment::Create());
-  env->GetVar("PATH", &build_path);
 
   main_project->AddAggregateTarget(
-      "All", GetBuildScript(root_target, build_path, ninja_extra_args));
+      "All", GetBuildScript(root_target, ninja_extra_args, env.get()));
 
   for (const Target* target : targets) {
     switch (target->output_type()) {
@@ -269,8 +296,8 @@
             target->output_name().empty() ? target->label().name()
                                           : target->output_name(),
             "com.apple.product-type.tool",
-            GetBuildScript(target->label().name(), build_path,
-                           ninja_extra_args));
+            GetBuildScript(target->label().name(), ninja_extra_args,
+                           env.get()));
         break;
 
       case Target::CREATE_BUNDLE:
@@ -284,8 +311,8 @@
                            .value(),
                        build_settings->build_dir()),
             target->bundle_data().product_type(),
-            GetBuildScript(target->label().name(), build_path,
-                           ninja_extra_args));
+            GetBuildScript(target->label().name(), ninja_extra_args,
+                           env.get()));
         break;
 
       default:
diff --git a/tools/json_schema_compiler/test/features_generation_unittest.cc b/tools/json_schema_compiler/test/features_generation_unittest.cc
index 3b7e8e1..79f76387 100644
--- a/tools/json_schema_compiler/test/features_generation_unittest.cc
+++ b/tools/json_schema_compiler/test/features_generation_unittest.cc
@@ -287,12 +287,12 @@
     comparator.CompareFeature(feature);
   }
   {
-    Feature* feature = GetAPIFeature("complex_alias");
+    Feature* feature = provider.GetFeature("complex_alias");
     ASSERT_EQ("", feature->alias());
     ASSERT_EQ("complex_alias_source", feature->source());
   }
   {
-    Feature* feature = GetAPIFeature("complex_alias_source");
+    Feature* feature = provider.GetFeature("complex_alias_source");
     ASSERT_EQ("complex_alias", feature->alias());
     ASSERT_EQ("", feature->source());
   }
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 41da607..ae162cf 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -39352,11 +39352,17 @@
 </histogram>
 
 <histogram name="Notifications.Icon.FileSize" units="bytes">
+  <obsolete>
+    Deprecated Nov 2016 in favor of Notifications.LoadFileSize.*
+  </obsolete>
   <owner>peter@chromium.org</owner>
   <summary>The number of bytes loaded for a Web Notification icon.</summary>
 </histogram>
 
 <histogram name="Notifications.Icon.LoadFailTime" units="ms">
+  <obsolete>
+    Deprecated Nov 2016 in favor of Notifications.LoadFailTime.*
+  </obsolete>
   <owner>peter@chromium.org</owner>
   <summary>
     The number of milliseconds it took to fail loading an icon for a Web
@@ -39365,6 +39371,9 @@
 </histogram>
 
 <histogram name="Notifications.Icon.LoadFinishTime" units="ms">
+  <obsolete>
+    Deprecated Nov 2016 in favor of Notifications.LoadFinishTime.*
+  </obsolete>
   <owner>peter@chromium.org</owner>
   <summary>
     The number of milliseconds it took to finish successfully loading an icon
@@ -39373,6 +39382,9 @@
 </histogram>
 
 <histogram name="Notifications.Icon.ScaleDownTime" units="ms">
+  <obsolete>
+    Deprecated Nov 2016 in favor of Notifications.LoadScaleDownTime.*
+  </obsolete>
   <owner>peter@chromium.org</owner>
   <summary>
     The number of milliseconds it took to scale down an icon for a Web
@@ -39380,6 +39392,45 @@
   </summary>
 </histogram>
 
+<histogram name="Notifications.LoadFailTime" units="ms">
+<!-- Name completed by histogram_suffixes name="NotificationImageTypes" -->
+
+  <owner>johnme@chromium.org</owner>
+  <summary>
+    The number of milliseconds it took to fail loading an icon/image for a Web
+    Notification.
+  </summary>
+</histogram>
+
+<histogram name="Notifications.LoadFileSize" units="bytes">
+<!-- Name completed by histogram_suffixes name="NotificationImageTypes" -->
+
+  <owner>johnme@chromium.org</owner>
+  <summary>
+    The number of bytes loaded for a Web Notification icon/image.
+  </summary>
+</histogram>
+
+<histogram name="Notifications.LoadFinishTime" units="ms">
+<!-- Name completed by histogram_suffixes name="NotificationImageTypes" -->
+
+  <owner>johnme@chromium.org</owner>
+  <summary>
+    The number of milliseconds it took to finish successfully loading an
+    icon/image for a Web Notification.
+  </summary>
+</histogram>
+
+<histogram name="Notifications.LoadScaleDownTime" units="ms">
+<!-- Name completed by histogram_suffixes name="NotificationImageTypes" -->
+
+  <owner>johnme@chromium.org</owner>
+  <summary>
+    The number of milliseconds it took to scale down an icon/image for a Web
+    Notification.
+  </summary>
+</histogram>
+
 <histogram name="Notifications.PerNotificationActions"
     enum="NotificationActionType">
   <owner>dewittj@chromium.org</owner>
@@ -110757,6 +110808,17 @@
   <affected-histogram name="Notifications.Display"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="NotificationImageTypes" separator=".">
+  <suffix name="ActionIcon"/>
+  <suffix name="Badge"/>
+  <suffix name="Icon"/>
+  <suffix name="Image"/>
+  <affected-histogram name="Notifications.LoadFailTime"/>
+  <affected-histogram name="Notifications.LoadFileSize"/>
+  <affected-histogram name="Notifications.LoadFinishTime"/>
+  <affected-histogram name="Notifications.LoadScaleDownTime"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="NQE.Accuracy.Metric.Accuracy.DiffPositiveOrNegative"
     separator=".">
   <suffix name="Negative"
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index a437a98f..f9f6e448 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -17,7 +17,8 @@
 #include "ui/android/context_provider_factory.h"
 #include "ui/android/view_android.h"
 #include "ui/android/window_android_compositor.h"
-#include "ui/gfx/android/device_display_info.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
 #include "ui/gfx/geometry/dip_util.h"
 
 namespace ui {
@@ -214,8 +215,10 @@
 void DelegatedFrameHostAndroid::UpdateContainerSizeinDIP(
     const gfx::Size& size_in_dip) {
   container_size_in_dip_ = size_in_dip;
-  background_layer_->SetBounds(gfx::ConvertSizeToPixel(
-      gfx::DeviceDisplayInfo().GetDIPScale(), container_size_in_dip_));
+  float device_scale_factor = display::Screen::GetScreen()
+      ->GetDisplayNearestWindow(view_).device_scale_factor();
+  background_layer_->SetBounds(
+      gfx::ConvertSizeToPixel(device_scale_factor, container_size_in_dip_));
   UpdateBackgroundLayer();
 }
 
@@ -256,7 +259,8 @@
   bool background_is_drawable = false;
 
   if (current_frame_) {
-    float device_scale_factor = gfx::DeviceDisplayInfo().GetDIPScale();
+    float device_scale_factor = display::Screen::GetScreen()
+        ->GetDisplayNearestWindow(view_).device_scale_factor();
     gfx::Size content_size_in_dip = gfx::ConvertSizeToDIP(
         device_scale_factor, current_frame_->surface_size);
     background_is_drawable =
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
index dd0ed40a..fc60dd20 100644
--- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
+++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
@@ -91,7 +91,7 @@
     protected HashMap<Integer, String> mIntentErrors;
 
     // We track all animations over content and provide a drawing placeholder for them.
-    private HashSet<Animator> mAnimationsOverContent = new HashSet<Animator>();
+    private HashSet<Animator> mAnimationsOverContent = new HashSet<>();
     private View mAnimationPlaceholderView;
 
     private ViewGroup mKeyboardAccessoryView;
@@ -116,7 +116,7 @@
         public void keyboardVisibilityChanged(boolean isShowing);
     }
     private LinkedList<KeyboardVisibilityListener> mKeyboardVisibilityListeners =
-            new LinkedList<KeyboardVisibilityListener>();
+            new LinkedList<>();
 
     private final VSyncMonitor.Listener mVSyncListener = new VSyncMonitor.Listener() {
         @Override
@@ -166,18 +166,26 @@
     /**
      * @param context The application context.
      */
-    @SuppressLint("UseSparseArrays")
     public WindowAndroid(Context context) {
+        this(context, DisplayAndroid.getNonMultiDisplay(context));
+    }
+
+    /**
+     * @param context The application context.
+     * @param display
+     */
+    @SuppressLint("UseSparseArrays")
+    protected WindowAndroid(Context context, DisplayAndroid display) {
         mApplicationContext = context.getApplicationContext();
         // context does not have the same lifetime guarantees as an application context so we can't
         // hold a strong reference to it.
-        mContextRef = new WeakReference<Context>(context);
-        mOutstandingIntents = new SparseArray<IntentCallback>();
-        mIntentErrors = new HashMap<Integer, String>();
+        mContextRef = new WeakReference<>(context);
+        mOutstandingIntents = new SparseArray<>();
+        mIntentErrors = new HashMap<>();
         mVSyncMonitor = new VSyncMonitor(context, mVSyncListener);
         mAccessibilityManager = (AccessibilityManager) mApplicationContext.getSystemService(
                 Context.ACCESSIBILITY_SERVICE);
-        mDisplayAndroid = DisplayAndroid.getNonMultiDisplay(context);
+        mDisplayAndroid = display;
     }
 
     @CalledByNative
@@ -411,7 +419,7 @@
      *         this is in the context of a WebView that was not created using an Activity).
      */
     public WeakReference<Activity> getActivity() {
-        return new WeakReference<Activity>(null);
+        return new WeakReference<>(null);
     }
 
     /**
@@ -614,7 +622,7 @@
 
         // Clone the list in case a listener tries to remove itself during the callback.
         LinkedList<KeyboardVisibilityListener> listeners =
-                new LinkedList<KeyboardVisibilityListener>(mKeyboardVisibilityListeners);
+                new LinkedList<>(mKeyboardVisibilityListeners);
         for (KeyboardVisibilityListener listener : listeners) {
             listener.keyboardVisibilityChanged(isShowing);
         }
@@ -663,7 +671,7 @@
      */
     public WeakReference<Context> getContext() {
         // Return a new WeakReference to prevent clients from releasing our internal WeakReference.
-        return new WeakReference<Context>(mContextRef.get());
+        return new WeakReference<>(mContextRef.get());
     }
 
     /**
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn
index 12ba33e..37af5ba 100644
--- a/ui/display/BUILD.gn
+++ b/ui/display/BUILD.gn
@@ -7,23 +7,6 @@
 
 component("display") {
   sources = [
-    "chromeos/apply_content_protection_task.cc",
-    "chromeos/apply_content_protection_task.h",
-    "chromeos/configure_displays_task.cc",
-    "chromeos/configure_displays_task.h",
-    "chromeos/display_configurator.cc",
-    "chromeos/display_configurator.h",
-    "chromeos/display_layout_manager.h",
-    "chromeos/display_snapshot_virtual.cc",
-    "chromeos/display_snapshot_virtual.h",
-    "chromeos/display_util.cc",
-    "chromeos/display_util.h",
-    "chromeos/query_content_protection_task.cc",
-    "chromeos/query_content_protection_task.h",
-    "chromeos/touchscreen_util.cc",
-    "chromeos/touchscreen_util.h",
-    "chromeos/update_display_configuration_task.cc",
-    "chromeos/update_display_configuration_task.h",
     "display.cc",
     "display.h",
     "display_change_notifier.cc",
@@ -31,6 +14,10 @@
     "display_export.h",
     "display_finder.cc",
     "display_finder.h",
+    "display_layout.cc",
+    "display_layout.h",
+    "display_layout_builder.cc",
+    "display_layout_builder.h",
     "display_list.cc",
     "display_list.h",
     "display_observer.cc",
@@ -43,18 +30,6 @@
     "fake_display_snapshot.h",
     "ios/screen_ios.mm",
     "mac/screen_mac.mm",
-    "manager/display_layout.cc",
-    "manager/display_layout.h",
-    "manager/display_layout_builder.cc",
-    "manager/display_layout_builder.h",
-    "manager/display_layout_store.cc",
-    "manager/display_layout_store.h",
-    "manager/display_manager.cc",
-    "manager/display_manager.h",
-    "manager/display_manager_utilities.cc",
-    "manager/display_manager_utilities.h",
-    "manager/managed_display_info.cc",
-    "manager/managed_display_info.h",
     "screen.cc",
     "screen.h",
     "screen_aura.cc",
@@ -83,39 +58,10 @@
     "//base",
     "//third_party/re2",
     "//ui/display/util",
-    "//ui/events/devices",
     "//ui/gfx",
     "//ui/gfx/geometry",
   ]
 
-  if (is_chromeos && use_x11) {
-    sources += [
-      "chromeos/x11/display_mode_x11.cc",
-      "chromeos/x11/display_mode_x11.h",
-      "chromeos/x11/display_snapshot_x11.cc",
-      "chromeos/x11/display_snapshot_x11.h",
-      "chromeos/x11/display_util_x11.cc",
-      "chromeos/x11/display_util_x11.h",
-      "chromeos/x11/native_display_delegate_x11.cc",
-      "chromeos/x11/native_display_delegate_x11.h",
-      "chromeos/x11/native_display_event_dispatcher_x11.cc",
-      "chromeos/x11/native_display_event_dispatcher_x11.h",
-    ]
-
-    configs += [
-      "//build/config/linux:x11",
-      "//build/config/linux:xext",
-      "//build/config/linux:xi",
-      "//build/config/linux:xrandr",
-    ]
-
-    deps += [ "//ui/events/platform" ]
-  }
-
-  if (use_x11) {
-    deps += [ "//ui/gfx/x" ]
-  }
-
   if (!use_aura) {
     sources -= [ "screen_aura.cc" ]
   }
@@ -138,7 +84,7 @@
   defines = [ "DISPLAY_IMPLEMENTATION" ]
 
   public_deps = [
-    ":display",
+    "//ui/display/manager",
   ]
 
   deps = [
@@ -151,14 +97,14 @@
 static_library("test_support") {
   testonly = true
   sources = [
-    "chromeos/test/action_logger.cc",
-    "chromeos/test/action_logger.h",
-    "chromeos/test/action_logger_util.cc",
-    "chromeos/test/action_logger_util.h",
-    "chromeos/test/test_display_layout_manager.cc",
-    "chromeos/test/test_display_layout_manager.h",
-    "chromeos/test/test_native_display_delegate.cc",
-    "chromeos/test/test_native_display_delegate.h",
+    "manager/chromeos/test/action_logger.cc",
+    "manager/chromeos/test/action_logger.h",
+    "manager/chromeos/test/action_logger_util.cc",
+    "manager/chromeos/test/action_logger_util.h",
+    "manager/chromeos/test/test_display_layout_manager.cc",
+    "manager/chromeos/test/test_display_layout_manager.h",
+    "manager/chromeos/test/test_native_display_delegate.cc",
+    "manager/chromeos/test/test_native_display_delegate.h",
     "test/display_matchers.cc",
     "test/display_matchers.h",
     "test/display_test_util.h",
@@ -170,6 +116,7 @@
 
   public_deps = [
     ":display",
+    "//ui/display/manager",
   ]
   deps = [
     "//base",
@@ -184,16 +131,16 @@
 # This test covers all testable components in display.
 test("display_unittests") {
   sources = [
-    "chromeos/apply_content_protection_task_unittest.cc",
-    "chromeos/configure_displays_task_unittest.cc",
-    "chromeos/display_configurator_unittest.cc",
-    "chromeos/query_content_protection_task_unittest.cc",
-    "chromeos/touchscreen_util_unittest.cc",
-    "chromeos/update_display_configuration_task_unittest.cc",
     "display_change_notifier_unittest.cc",
     "display_list_unittest.cc",
     "display_unittest.cc",
     "fake_display_snapshot_unittests.cc",
+    "manager/chromeos/apply_content_protection_task_unittest.cc",
+    "manager/chromeos/configure_displays_task_unittest.cc",
+    "manager/chromeos/display_configurator_unittest.cc",
+    "manager/chromeos/query_content_protection_task_unittest.cc",
+    "manager/chromeos/touchscreen_util_unittest.cc",
+    "manager/chromeos/update_display_configuration_task_unittest.cc",
     "manager/display_layout_builder_unittest.cc",
     "manager/display_layout_unittest.cc",
     "manager/display_manager_utilities_unittest.cc",
@@ -214,6 +161,7 @@
     "//base/test:test_support",
     "//testing/gmock",
     "//testing/gtest",
+    "//ui/display/manager",
     "//ui/display/types",
     "//ui/display/util",
     "//ui/events/devices",
@@ -229,8 +177,8 @@
 
   if (is_chromeos && use_x11) {
     sources += [
-      "chromeos/x11/display_util_x11_unittest.cc",
-      "chromeos/x11/native_display_event_dispatcher_x11_unittest.cc",
+      "manager/chromeos/x11/display_util_x11_unittest.cc",
+      "manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc",
     ]
   }
 }
diff --git a/ui/display/chromeos/x11/display_mode_x11.cc b/ui/display/chromeos/x11/display_mode_x11.cc
deleted file mode 100644
index 7fc327c..0000000
--- a/ui/display/chromeos/x11/display_mode_x11.cc
+++ /dev/null
@@ -1,27 +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/ptr_util.h"
-
-#include "ui/display/chromeos/x11/display_mode_x11.h"
-
-namespace ui {
-
-DisplayModeX11::DisplayModeX11(const gfx::Size& size,
-                               bool interlaced,
-                               float refresh_rate,
-                               RRMode mode_id)
-    : DisplayMode(size, interlaced, refresh_rate),
-      mode_id_(mode_id) {}
-
-DisplayModeX11::~DisplayModeX11() {}
-
-std::unique_ptr<DisplayMode> DisplayModeX11::Clone() const {
-  return base::WrapUnique(new DisplayModeX11(size(),
-                                             is_interlaced(),
-                                             refresh_rate(),
-                                             mode_id()));
-}
-
-}  // namespace ui
diff --git a/ui/display/chromeos/x11/display_util_x11.h b/ui/display/chromeos/x11/display_util_x11.h
deleted file mode 100644
index 1bc2369e..0000000
--- a/ui/display/chromeos/x11/display_util_x11.h
+++ /dev/null
@@ -1,25 +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 UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_X11_H_
-#define UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_X11_H_
-
-#include <string>
-
-#include "ui/display/display_export.h"
-#include "ui/display/types/display_constants.h"
-
-typedef unsigned long XID;
-typedef XID RROutput;
-
-namespace ui {
-
-// Returns the DisplayConnectionType by matching known type prefixes to |name|.
-// Returns DISPLAY_TYPE_UNKNOWN if no valid match.
-DISPLAY_EXPORT DisplayConnectionType
-    GetDisplayConnectionTypeFromName(const std::string& name);
-
-}  // namespace ui
-
-#endif  // UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_X11_H_
diff --git a/ui/display/manager/display_layout.cc b/ui/display/display_layout.cc
similarity index 95%
rename from ui/display/manager/display_layout.cc
rename to ui/display/display_layout.cc
index bfee319..bf20ae4b 100644
--- a/ui/display/manager/display_layout.cc
+++ b/ui/display/display_layout.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 "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 
 #include <algorithm>
 #include <set>
@@ -16,7 +16,7 @@
 #include "ui/gfx/geometry/insets.h"
 
 namespace display {
-namespace  {
+namespace {
 
 // DisplayPlacement Positions
 const char kTop[] = "top";
@@ -191,8 +191,7 @@
     parents.erase(parent_id);
     for (const DisplayPlacement& placement : placement_list) {
       if (placement.parent_display_id == parent_id) {
-        if (ApplyDisplayPlacement(placement,
-                                  display_list,
+        if (ApplyDisplayPlacement(placement, display_list,
                                   minimum_offset_overlap) &&
             updated_ids) {
           updated_ids->push_back(placement.display_id);
@@ -331,18 +330,14 @@
     if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT)
       offset = parent_bounds.width() - offset - target_bounds.width();
 
-    offset = std::min(
-        offset, parent_bounds.width() - minimum_offset_overlap);
-    offset = std::max(
-        offset, -target_bounds.width() + minimum_offset_overlap);
+    offset = std::min(offset, parent_bounds.width() - minimum_offset_overlap);
+    offset = std::max(offset, -target_bounds.width() + minimum_offset_overlap);
   } else {
     if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT)
       offset = parent_bounds.height() - offset - target_bounds.height();
 
-    offset = std::min(
-        offset, parent_bounds.height() - minimum_offset_overlap);
-    offset = std::max(
-        offset, -target_bounds.height() + minimum_offset_overlap);
+    offset = std::min(offset, parent_bounds.height() - minimum_offset_overlap);
+    offset = std::max(offset, -target_bounds.height() + minimum_offset_overlap);
   }
   switch (position) {
     case DisplayPlacement::TOP:
diff --git a/ui/display/manager/display_layout.h b/ui/display/display_layout.h
similarity index 96%
rename from ui/display/manager/display_layout.h
rename to ui/display/display_layout.h
index 5e7db09..e9f85f7 100644
--- a/ui/display/manager/display_layout.h
+++ b/ui/display/display_layout.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 UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_H_
-#define UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_H_
+#ifndef UI_DISPLAY_DISPLAY_LAYOUT_H_
+#define UI_DISPLAY_DISPLAY_LAYOUT_H_
 
 #include <stdint.h>
 
@@ -130,4 +130,4 @@
 
 }  // namespace display
 
-#endif  // UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_H_
+#endif  // UI_DISPLAY_DISPLAY_LAYOUT_H_
diff --git a/ui/display/manager/display_layout_builder.cc b/ui/display/display_layout_builder.cc
similarity index 97%
rename from ui/display/manager/display_layout_builder.cc
rename to ui/display/display_layout_builder.cc
index b6da680..43527ed 100644
--- a/ui/display/manager/display_layout_builder.cc
+++ b/ui/display/display_layout_builder.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 "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout_builder.h"
 
 #include <algorithm>
 
diff --git a/ui/display/manager/display_layout_builder.h b/ui/display/display_layout_builder.h
similarity index 84%
rename from ui/display/manager/display_layout_builder.h
rename to ui/display/display_layout_builder.h
index b93683e..ecd685a 100644
--- a/ui/display/manager/display_layout_builder.h
+++ b/ui/display/display_layout_builder.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_BUILDER_H_
-#define UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_BUILDER_H_
+#ifndef UI_DISPLAY_DISPLAY_LAYOUT_BUILDER_H_
+#define UI_DISPLAY_DISPLAY_LAYOUT_BUILDER_H_
 
 #include <memory>
 
 #include "base/macros.h"
 #include "ui/display/display_export.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 
 namespace display {
 
@@ -39,8 +39,7 @@
                                             int offset);
 
   // Adds a display placement.
-  DisplayLayoutBuilder& AddDisplayPlacement(
-      const DisplayPlacement& placement);
+  DisplayLayoutBuilder& AddDisplayPlacement(const DisplayPlacement& placement);
 
   // Sets the display placement for the secondary display.
   DisplayLayoutBuilder& SetSecondaryPlacement(
@@ -59,4 +58,4 @@
 
 }  // namespace display
 
-#endif  // UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_BUILDER_H_
+#endif  // UI_DISPLAY_DISPLAY_LAYOUT_BUILDER_H_
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn
new file mode 100644
index 0000000..6cd1163
--- /dev/null
+++ b/ui/display/manager/BUILD.gn
@@ -0,0 +1,77 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ui.gni")
+
+component("manager") {
+  sources = [
+    "chromeos/apply_content_protection_task.cc",
+    "chromeos/apply_content_protection_task.h",
+    "chromeos/configure_displays_task.cc",
+    "chromeos/configure_displays_task.h",
+    "chromeos/display_configurator.cc",
+    "chromeos/display_configurator.h",
+    "chromeos/display_layout_manager.h",
+    "chromeos/display_snapshot_virtual.cc",
+    "chromeos/display_snapshot_virtual.h",
+    "chromeos/display_util.cc",
+    "chromeos/display_util.h",
+    "chromeos/query_content_protection_task.cc",
+    "chromeos/query_content_protection_task.h",
+    "chromeos/touchscreen_util.cc",
+    "chromeos/touchscreen_util.h",
+    "chromeos/update_display_configuration_task.cc",
+    "chromeos/update_display_configuration_task.h",
+    "display_layout_store.cc",
+    "display_layout_store.h",
+    "display_manager.cc",
+    "display_manager.h",
+    "display_manager_export.h",
+    "display_manager_utilities.cc",
+    "display_manager_utilities.h",
+    "managed_display_info.cc",
+    "managed_display_info.h",
+  ]
+
+  public_deps = [
+    "//ui/display",
+  ]
+
+  deps = [
+    "//base",
+    "//ui/base",
+    "//ui/display/util",
+    "//ui/events/devices",
+  ]
+
+  defines = [ "DISPLAY_MANAGER_IMPLEMENTATION" ]
+
+  if (use_x11) {
+    deps += [ "//ui/gfx/x" ]
+  }
+
+  if (is_chromeos && use_x11) {
+    sources += [
+      "chromeos/x11/display_mode_x11.cc",
+      "chromeos/x11/display_mode_x11.h",
+      "chromeos/x11/display_snapshot_x11.cc",
+      "chromeos/x11/display_snapshot_x11.h",
+      "chromeos/x11/display_util_x11.cc",
+      "chromeos/x11/display_util_x11.h",
+      "chromeos/x11/native_display_delegate_x11.cc",
+      "chromeos/x11/native_display_delegate_x11.h",
+      "chromeos/x11/native_display_event_dispatcher_x11.cc",
+      "chromeos/x11/native_display_event_dispatcher_x11.h",
+    ]
+
+    configs += [
+      "//build/config/linux:x11",
+      "//build/config/linux:xext",
+      "//build/config/linux:xi",
+      "//build/config/linux:xrandr",
+    ]
+
+    deps += [ "//ui/events/platform" ]
+  }
+}
diff --git a/ui/display/chromeos/DEPS b/ui/display/manager/DEPS
similarity index 100%
rename from ui/display/chromeos/DEPS
rename to ui/display/manager/DEPS
diff --git a/ui/display/chromeos/apply_content_protection_task.cc b/ui/display/manager/chromeos/apply_content_protection_task.cc
similarity index 95%
rename from ui/display/chromeos/apply_content_protection_task.cc
rename to ui/display/manager/chromeos/apply_content_protection_task.cc
index 43214709..eda1907 100644
--- a/ui/display/chromeos/apply_content_protection_task.cc
+++ b/ui/display/manager/chromeos/apply_content_protection_task.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/apply_content_protection_task.h"
+#include "ui/display/manager/chromeos/apply_content_protection_task.h"
 
-#include "ui/display/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/native_display_delegate.h"
 
@@ -53,11 +53,9 @@
       callback_(callback),
       query_status_(true),
       pending_requests_(0),
-      weak_ptr_factory_(this) {
-}
+      weak_ptr_factory_(this) {}
 
-ApplyContentProtectionTask::~ApplyContentProtectionTask() {
-}
+ApplyContentProtectionTask::~ApplyContentProtectionTask() {}
 
 void ApplyContentProtectionTask::Run() {
   std::vector<DisplaySnapshot*> hdcp_capable_displays;
diff --git a/ui/display/chromeos/apply_content_protection_task.h b/ui/display/manager/chromeos/apply_content_protection_task.h
similarity index 88%
rename from ui/display/chromeos/apply_content_protection_task.h
rename to ui/display/manager/chromeos/apply_content_protection_task.h
index 9d3df15..a533628 100644
--- a/ui/display/chromeos/apply_content_protection_task.h
+++ b/ui/display/manager/chromeos/apply_content_protection_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 UI_DISPLAY_CHROMEOS_APPLY_CONTENT_PROTECTION_TASK_H_
-#define UI_DISPLAY_CHROMEOS_APPLY_CONTENT_PROTECTION_TASK_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_APPLY_CONTENT_PROTECTION_TASK_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_APPLY_CONTENT_PROTECTION_TASK_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -13,7 +13,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace ui {
 
@@ -33,7 +33,7 @@
 //
 // Note, in steps 1a and 2a, if no HDCP capable displays are found or if errors
 // are reported, the task finishes early and skips to step 3.
-class DISPLAY_EXPORT ApplyContentProtectionTask {
+class DISPLAY_MANAGER_EXPORT ApplyContentProtectionTask {
  public:
   typedef base::Callback<void(bool)> ResponseCallback;
 
@@ -85,4 +85,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_APPLY_CONTENT_PROTECTION_TASK_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_APPLY_CONTENT_PROTECTION_TASK_H_
diff --git a/ui/display/chromeos/apply_content_protection_task_unittest.cc b/ui/display/manager/chromeos/apply_content_protection_task_unittest.cc
similarity index 91%
rename from ui/display/chromeos/apply_content_protection_task_unittest.cc
rename to ui/display/manager/chromeos/apply_content_protection_task_unittest.cc
index 595db28d..90d47dc 100644
--- a/ui/display/chromeos/apply_content_protection_task_unittest.cc
+++ b/ui/display/manager/chromeos/apply_content_protection_task_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/apply_content_protection_task.h"
+#include "ui/display/manager/chromeos/apply_content_protection_task.h"
 
 #include <stdint.h>
 #include <utility>
@@ -10,11 +10,11 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/display_layout_manager.h"
-#include "ui/display/chromeos/test/action_logger_util.h"
-#include "ui/display/chromeos/test/test_display_layout_manager.h"
-#include "ui/display/chromeos/test/test_native_display_delegate.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/test_display_layout_manager.h"
+#include "ui/display/manager/chromeos/test/test_native_display_delegate.h"
 
 namespace ui {
 namespace test {
@@ -92,7 +92,8 @@
   EXPECT_EQ(SUCCESS, response_);
   EXPECT_EQ(
       JoinActions(GetSetHDCPStateAction(*layout_manager.GetDisplayStates()[0],
-                                        HDCP_STATE_DESIRED).c_str(),
+                                        HDCP_STATE_DESIRED)
+                      .c_str(),
                   NULL),
       log_.GetActionsAndClear());
 }
@@ -152,7 +153,8 @@
   EXPECT_EQ(ERROR, response_);
   EXPECT_EQ(
       JoinActions(GetSetHDCPStateAction(*layout_manager.GetDisplayStates()[0],
-                                        HDCP_STATE_DESIRED).c_str(),
+                                        HDCP_STATE_DESIRED)
+                      .c_str(),
                   NULL),
       log_.GetActionsAndClear());
 }
diff --git a/ui/display/chromeos/configure_displays_task.cc b/ui/display/manager/chromeos/configure_displays_task.cc
similarity index 94%
rename from ui/display/chromeos/configure_displays_task.cc
rename to ui/display/manager/chromeos/configure_displays_task.cc
index 81e2f25d..24657b41 100644
--- a/ui/display/chromeos/configure_displays_task.cc
+++ b/ui/display/manager/chromeos/configure_displays_task.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/configure_displays_task.h"
+#include "ui/display/manager/chromeos/configure_displays_task.h"
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
-#include "ui/display/chromeos/display_util.h"
+#include "ui/display/manager/chromeos/display_util.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/native_display_delegate.h"
 
@@ -40,8 +40,7 @@
 DisplayConfigureRequest::DisplayConfigureRequest(DisplaySnapshot* display,
                                                  const DisplayMode* mode,
                                                  const gfx::Point& origin)
-    : display(display), mode(mode), origin(origin) {
-}
+    : display(display), mode(mode), origin(origin) {}
 
 ConfigureDisplaysTask::ConfigureDisplaysTask(
     NativeDisplayDelegate* delegate,
@@ -58,8 +57,7 @@
     pending_request_indexes_.push(i);
 }
 
-ConfigureDisplaysTask::~ConfigureDisplaysTask() {
-}
+ConfigureDisplaysTask::~ConfigureDisplaysTask() {}
 
 void ConfigureDisplaysTask::Run() {
   // Synchronous configurators will recursively call Run(). In that case just
diff --git a/ui/display/chromeos/configure_displays_task.h b/ui/display/manager/chromeos/configure_displays_task.h
similarity index 86%
rename from ui/display/chromeos/configure_displays_task.h
rename to ui/display/manager/chromeos/configure_displays_task.h
index 6a734c61..bc71454 100644
--- a/ui/display/chromeos/configure_displays_task.h
+++ b/ui/display/manager/chromeos/configure_displays_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 UI_DISPLAY_CHROMEOS_CONFIGURATION_TASK_H_
-#define UI_DISPLAY_CHROMEOS_CONFIGURATION_TASK_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_CONFIGURE_DISPLAYS_TASK_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_CONFIGURE_DISPLAYS_TASK_H_
 
 #include <stddef.h>
 
@@ -13,7 +13,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/gfx/geometry/point.h"
 
 namespace ui {
@@ -22,7 +22,7 @@
 class DisplaySnapshot;
 class NativeDisplayDelegate;
 
-struct DISPLAY_EXPORT DisplayConfigureRequest {
+struct DISPLAY_MANAGER_EXPORT DisplayConfigureRequest {
   DisplayConfigureRequest(DisplaySnapshot* display,
                           const DisplayMode* mode,
                           const gfx::Point& origin);
@@ -33,7 +33,7 @@
 };
 
 // Applies the display configuration asynchronously.
-class DISPLAY_EXPORT ConfigureDisplaysTask {
+class DISPLAY_MANAGER_EXPORT ConfigureDisplaysTask {
  public:
   enum Status {
     // At least one of the displays failed to apply any mode it supports.
@@ -88,4 +88,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_CONFIGURATION_TASK_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_CONFIGURE_DISPLAYS_TASK_H_
diff --git a/ui/display/chromeos/configure_displays_task_unittest.cc b/ui/display/manager/chromeos/configure_displays_task_unittest.cc
similarity index 97%
rename from ui/display/chromeos/configure_displays_task_unittest.cc
rename to ui/display/manager/chromeos/configure_displays_task_unittest.cc
index 347d8a2..0104d798 100644
--- a/ui/display/chromeos/configure_displays_task_unittest.cc
+++ b/ui/display/manager/chromeos/configure_displays_task_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/configure_displays_task.h"
-#include "ui/display/chromeos/test/action_logger_util.h"
-#include "ui/display/chromeos/test/test_native_display_delegate.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/configure_displays_task.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/test_native_display_delegate.h"
 
 namespace ui {
 namespace test {
diff --git a/ui/display/chromeos/display_configurator.cc b/ui/display/manager/chromeos/display_configurator.cc
similarity index 97%
rename from ui/display/chromeos/display_configurator.cc
rename to ui/display/manager/chromeos/display_configurator.cc
index 7ac7702..8258d23 100644
--- a/ui/display/chromeos/display_configurator.cc
+++ b/ui/display/manager/chromeos/display_configurator.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 "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 #include <stddef.h>
 #include <utility>
@@ -13,13 +13,13 @@
 #include "base/macros.h"
 #include "base/sys_info.h"
 #include "base/time/time.h"
-#include "ui/display/chromeos/apply_content_protection_task.h"
-#include "ui/display/chromeos/display_layout_manager.h"
-#include "ui/display/chromeos/display_snapshot_virtual.h"
-#include "ui/display/chromeos/display_util.h"
-#include "ui/display/chromeos/update_display_configuration_task.h"
 #include "ui/display/display.h"
 #include "ui/display/display_switches.h"
+#include "ui/display/manager/chromeos/apply_content_protection_task.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/display_snapshot_virtual.h"
+#include "ui/display/manager/chromeos/display_util.h"
+#include "ui/display/manager/chromeos/update_display_configuration_task.h"
 #include "ui/display/types/display_mode.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/native_display_delegate.h"
@@ -44,15 +44,14 @@
   const DisplayMode* mirror_mode = nullptr;
 };
 
-void DoNothing(bool status) {
-}
+void DoNothing(bool status) {}
 
 }  // namespace
 
 const int DisplayConfigurator::kSetDisplayPowerNoFlags = 0;
 const int DisplayConfigurator::kSetDisplayPowerForceProbe = 1 << 0;
-const int
-DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay = 1 << 1;
+const int DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay =
+    1 << 1;
 
 bool DisplayConfigurator::TestApi::TriggerConfigureTimeout() {
   if (configurator_->configure_timer_.IsRunning()) {
@@ -126,11 +125,9 @@
 
 DisplayConfigurator::DisplayLayoutManagerImpl::DisplayLayoutManagerImpl(
     DisplayConfigurator* configurator)
-    : configurator_(configurator) {
-}
+    : configurator_(configurator) {}
 
-DisplayConfigurator::DisplayLayoutManagerImpl::~DisplayLayoutManagerImpl() {
-}
+DisplayConfigurator::DisplayLayoutManagerImpl::~DisplayLayoutManagerImpl() {}
 
 DisplayConfigurator::SoftwareMirroringController*
 DisplayConfigurator::DisplayLayoutManagerImpl::GetSoftwareMirroringController()
@@ -413,7 +410,7 @@
             *internal_display->display, external_mode.get());
         internal_display->display->add_mode(external_mode.get());
         internal_display->mirror_mode =
-          internal_display->display->modes().back().get();
+            internal_display->display->modes().back().get();
         external_display->mirror_mode = external_mode.get();
         return true;  // Mirror mode created.
       }
@@ -483,8 +480,7 @@
       display_control_changing_(false),
       displays_suspended_(false),
       layout_manager_(new DisplayLayoutManagerImpl(this)),
-      weak_ptr_factory_(this) {
-}
+      weak_ptr_factory_(this) {}
 
 DisplayConfigurator::~DisplayConfigurator() {
   if (native_display_delegate_)
@@ -596,7 +592,8 @@
 }
 
 void DisplayConfigurator::SendRelinquishDisplayControl(
-    const DisplayControlCallback& callback, bool success) {
+    const DisplayControlCallback& callback,
+    bool success) {
   if (success) {
     // Set the flag early such that an incoming configuration event won't start
     // while we're releasing control of the displays.
@@ -1032,9 +1029,9 @@
 
   configuration_task_.reset(new UpdateDisplayConfigurationTask(
       native_display_delegate_.get(), layout_manager_.get(),
-      requested_display_state_, pending_power_state_, pending_power_flags_,
-      0, force_configure_, base::Bind(&DisplayConfigurator::OnConfigured,
-                                      weak_ptr_factory_.GetWeakPtr())));
+      requested_display_state_, pending_power_state_, pending_power_flags_, 0,
+      force_configure_, base::Bind(&DisplayConfigurator::OnConfigured,
+                                   weak_ptr_factory_.GetWeakPtr())));
   configuration_task_->set_virtual_display_snapshots(
       virtual_display_snapshots_.get());
 
diff --git a/ui/display/chromeos/display_configurator.h b/ui/display/manager/chromeos/display_configurator.h
similarity index 96%
rename from ui/display/chromeos/display_configurator.h
rename to ui/display/manager/chromeos/display_configurator.h
index 64ac535..cce56b0 100644
--- a/ui/display/chromeos/display_configurator.h
+++ b/ui/display/manager/chromeos/display_configurator.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 UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_
-#define UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_CONFIGURATOR_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_CONFIGURATOR_H_
 
 #include <stdint.h>
 
@@ -20,9 +20,9 @@
 #include "base/observer_list.h"
 #include "base/timer/timer.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
-#include "ui/display/chromeos/display_snapshot_virtual.h"
-#include "ui/display/chromeos/query_content_protection_task.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/chromeos/display_snapshot_virtual.h"
+#include "ui/display/manager/chromeos/query_content_protection_task.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/display/types/native_display_observer.h"
 #include "ui/display/util/display_util.h"
@@ -41,7 +41,8 @@
 class UpdateDisplayConfigurationTask;
 
 // This class interacts directly with the system display configurator.
-class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver {
+class DISPLAY_MANAGER_EXPORT DisplayConfigurator
+    : public NativeDisplayObserver {
  public:
   typedef uint64_t ContentProtectionClientId;
   static const ContentProtectionClientId kInvalidClientId = 0;
@@ -81,8 +82,7 @@
     // just-applied configuration. Note that the X server is no longer grabbed
     // when this method is called, so the actual configuration could've changed
     // already.
-    virtual void OnDisplayModeChanged(
-        const DisplayStateList& displays) {}
+    virtual void OnDisplayModeChanged(const DisplayStateList& displays) {}
 
     // Called after a display mode change attempt failed. |displays| contains
     // displays that are detected when failed.
@@ -93,8 +93,7 @@
 
     // Called after the power state has been changed. |power_state| contains
     // the just-applied power state.
-    virtual void OnPowerStateChanged(
-        chromeos::DisplayPowerState power_state) {}
+    virtual void OnPowerStateChanged(chromeos::DisplayPowerState power_state) {}
   };
 
   // Interface for classes that make decisions about which display state
@@ -490,4 +489,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_CONFIGURATOR_H_
diff --git a/ui/display/chromeos/display_configurator_unittest.cc b/ui/display/manager/chromeos/display_configurator_unittest.cc
similarity index 99%
rename from ui/display/chromeos/display_configurator_unittest.cc
rename to ui/display/manager/chromeos/display_configurator_unittest.cc
index 6169253..bf2379e7 100644
--- a/ui/display/chromeos/display_configurator_unittest.cc
+++ b/ui/display/manager/chromeos/display_configurator_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -13,9 +13,9 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/test/action_logger_util.h"
-#include "ui/display/chromeos/test/test_native_display_delegate.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/test_native_display_delegate.h"
 #include "ui/display/util/display_util.h"
 
 namespace ui {
@@ -1740,14 +1740,13 @@
       base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated,
                  base::Unretained(this)));
   EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult());
-  EXPECT_EQ(
-      JoinActions(
-          kGrab,
-          GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
-              .c_str(),
-          GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
-          kUngrab, kRelinquishDisplayControl, nullptr),
-      log_->GetActionsAndClear());
+  EXPECT_EQ(JoinActions(
+                kGrab, GetFramebufferAction(small_mode_.size(),
+                                            outputs_[0].get(), nullptr)
+                           .c_str(),
+                GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+                kUngrab, kRelinquishDisplayControl, nullptr),
+            log_->GetActionsAndClear());
   configurator_.TakeControl(
       base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated,
                  base::Unretained(this)));
diff --git a/ui/display/chromeos/display_layout_manager.h b/ui/display/manager/chromeos/display_layout_manager.h
similarity index 86%
rename from ui/display/chromeos/display_layout_manager.h
rename to ui/display/manager/chromeos/display_layout_manager.h
index 068f118..f99bb65 100644
--- a/ui/display/chromeos/display_layout_manager.h
+++ b/ui/display/manager/chromeos/display_layout_manager.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_DISPLAY_LAYOUT_MANAGER_H_
-#define UI_DISPLAY_CHROMEOS_DISPLAY_LAYOUT_MANAGER_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_LAYOUT_MANAGER_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_LAYOUT_MANAGER_H_
 
 #include <vector>
 
 #include "third_party/cros_system_api/dbus/service_constants.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #include "ui/display/types/display_constants.h"
 
 namespace ui {
@@ -48,4 +48,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_DISPLAY_LAYOUT_MANAGER_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_LAYOUT_MANAGER_H_
diff --git a/ui/display/chromeos/display_snapshot_virtual.cc b/ui/display/manager/chromeos/display_snapshot_virtual.cc
similarity index 96%
rename from ui/display/chromeos/display_snapshot_virtual.cc
rename to ui/display/manager/chromeos/display_snapshot_virtual.cc
index 88d44c47..fa371f2 100644
--- a/ui/display/chromeos/display_snapshot_virtual.cc
+++ b/ui/display/manager/chromeos/display_snapshot_virtual.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 "ui/display/chromeos/display_snapshot_virtual.h"
+#include "ui/display/manager/chromeos/display_snapshot_virtual.h"
 
 #include <inttypes.h>
 
diff --git a/ui/display/chromeos/display_snapshot_virtual.h b/ui/display/manager/chromeos/display_snapshot_virtual.h
similarity index 73%
rename from ui/display/chromeos/display_snapshot_virtual.h
rename to ui/display/manager/chromeos/display_snapshot_virtual.h
index 9db8180..4f9d042 100644
--- a/ui/display/chromeos/display_snapshot_virtual.h
+++ b/ui/display/manager/chromeos/display_snapshot_virtual.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_DISPLAY_SNAPSHOT_VIRTUAL_H_
-#define UI_DISPLAY_CHROMEOS_DISPLAY_SNAPSHOT_VIRTUAL_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_SNAPSHOT_VIRTUAL_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_SNAPSHOT_VIRTUAL_H_
 
 #include <stdint.h>
 
 #include <memory>
 
 #include "base/macros.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/display_mode.h"
 #include "ui/display/types/display_snapshot.h"
 
@@ -18,7 +18,7 @@
 
 // This class represents a virtual display to be enabled on demand. The display
 // is constructed for the desired pixel resolution.
-class DISPLAY_EXPORT DisplaySnapshotVirtual : public DisplaySnapshot {
+class DISPLAY_MANAGER_EXPORT DisplaySnapshotVirtual : public DisplaySnapshot {
  public:
   // |display_id| is the numerical identifier for the virtual display,
   // |display_size| is the pixel dimensions for the display.
@@ -35,4 +35,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_DISPLAY_SNAPSHOT_VIRTUAL_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_SNAPSHOT_VIRTUAL_H_
diff --git a/ui/display/chromeos/display_util.cc b/ui/display/manager/chromeos/display_util.cc
similarity index 97%
rename from ui/display/chromeos/display_util.cc
rename to ui/display/manager/chromeos/display_util.cc
index 359165f..d90171249 100644
--- a/ui/display/chromeos/display_util.cc
+++ b/ui/display/manager/chromeos/display_util.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 "ui/display/chromeos/display_util.h"
+#include "ui/display/manager/chromeos/display_util.h"
 
 #include <stddef.h>
 
diff --git a/ui/display/chromeos/display_util.h b/ui/display/manager/chromeos/display_util.h
similarity index 83%
rename from ui/display/chromeos/display_util.h
rename to ui/display/manager/chromeos/display_util.h
index dc09698..ff42a574 100644
--- a/ui/display/chromeos/display_util.h
+++ b/ui/display/manager/chromeos/display_util.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_H_
-#define UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_UTIL_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_UTIL_H_
 
 #include <string>
 #include <vector>
 
 #include "third_party/cros_system_api/dbus/service_constants.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/display_constants.h"
 
 namespace ui {
@@ -25,7 +25,7 @@
 // Returns the number of displays in |displays| that should be turned on, per
 // |state|.  If |display_power| is non-NULL, it is updated to contain the
 // on/off state of each corresponding entry in |displays|.
-int DISPLAY_EXPORT
+int DISPLAY_MANAGER_EXPORT
 GetDisplayPower(const std::vector<DisplaySnapshot*>& displays,
                 chromeos::DisplayPowerState state,
                 std::vector<bool>* display_power);
@@ -37,4 +37,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_DISPLAY_UTIL_H_
diff --git a/ui/display/chromeos/query_content_protection_task.cc b/ui/display/manager/chromeos/query_content_protection_task.cc
similarity index 91%
rename from ui/display/chromeos/query_content_protection_task.cc
rename to ui/display/manager/chromeos/query_content_protection_task.cc
index c35e5c1..f26469dd 100644
--- a/ui/display/chromeos/query_content_protection_task.cc
+++ b/ui/display/manager/chromeos/query_content_protection_task.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/query_content_protection_task.h"
+#include "ui/display/manager/chromeos/query_content_protection_task.h"
 
-#include "ui/display/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/native_display_delegate.h"
 
@@ -20,11 +20,9 @@
       display_id_(display_id),
       callback_(callback),
       pending_requests_(0),
-      weak_ptr_factory_(this) {
-}
+      weak_ptr_factory_(this) {}
 
-QueryContentProtectionTask::~QueryContentProtectionTask() {
-}
+QueryContentProtectionTask::~QueryContentProtectionTask() {}
 
 void QueryContentProtectionTask::Run() {
   std::vector<DisplaySnapshot*> hdcp_capable_displays;
diff --git a/ui/display/chromeos/query_content_protection_task.h b/ui/display/manager/chromeos/query_content_protection_task.h
similarity index 83%
rename from ui/display/chromeos/query_content_protection_task.h
rename to ui/display/manager/chromeos/query_content_protection_task.h
index 525d8579..0d4b0b1 100644
--- a/ui/display/chromeos/query_content_protection_task.h
+++ b/ui/display/manager/chromeos/query_content_protection_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 UI_DISPLAY_CHROMEOS_QUERY_CONTENT_PROTECTION_TASK_H_
-#define UI_DISPLAY_CHROMEOS_QUERY_CONTENT_PROTECTION_TASK_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_QUERY_CONTENT_PROTECTION_TASK_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_QUERY_CONTENT_PROTECTION_TASK_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/display_constants.h"
 
 namespace ui {
@@ -19,7 +19,7 @@
 class DisplayLayoutManager;
 class NativeDisplayDelegate;
 
-class DISPLAY_EXPORT QueryContentProtectionTask {
+class DISPLAY_MANAGER_EXPORT QueryContentProtectionTask {
  public:
   struct Response {
     bool success = false;
@@ -65,4 +65,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_QUERY_CONTENT_PROTECTION_TASK_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_QUERY_CONTENT_PROTECTION_TASK_H_
diff --git a/ui/display/chromeos/query_content_protection_task_unittest.cc b/ui/display/manager/chromeos/query_content_protection_task_unittest.cc
similarity index 94%
rename from ui/display/chromeos/query_content_protection_task_unittest.cc
rename to ui/display/manager/chromeos/query_content_protection_task_unittest.cc
index 287b679..87aeb5c1 100644
--- a/ui/display/chromeos/query_content_protection_task_unittest.cc
+++ b/ui/display/manager/chromeos/query_content_protection_task_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/query_content_protection_task.h"
+#include "ui/display/manager/chromeos/query_content_protection_task.h"
 
 #include <stdint.h>
 #include <utility>
@@ -10,11 +10,11 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/display_layout_manager.h"
-#include "ui/display/chromeos/test/action_logger_util.h"
-#include "ui/display/chromeos/test/test_display_layout_manager.h"
-#include "ui/display/chromeos/test/test_native_display_delegate.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/test_display_layout_manager.h"
+#include "ui/display/manager/chromeos/test/test_native_display_delegate.h"
 
 namespace ui {
 namespace test {
diff --git a/ui/display/chromeos/test/action_logger.cc b/ui/display/manager/chromeos/test/action_logger.cc
similarity index 79%
rename from ui/display/chromeos/test/action_logger.cc
rename to ui/display/manager/chromeos/test/action_logger.cc
index 2afcb489..106f563c 100644
--- a/ui/display/chromeos/test/action_logger.cc
+++ b/ui/display/manager/chromeos/test/action_logger.cc
@@ -2,16 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/test/action_logger.h"
+#include "ui/display/manager/chromeos/test/action_logger.h"
 
 namespace ui {
 namespace test {
 
-ActionLogger::ActionLogger() {
-}
+ActionLogger::ActionLogger() {}
 
-ActionLogger::~ActionLogger() {
-}
+ActionLogger::~ActionLogger() {}
 
 void ActionLogger::AppendAction(const std::string& action) {
   if (!actions_.empty())
diff --git a/ui/display/chromeos/test/action_logger.h b/ui/display/manager/chromeos/test/action_logger.h
similarity index 79%
rename from ui/display/chromeos/test/action_logger.h
rename to ui/display/manager/chromeos/test/action_logger.h
index 92028fc..bf960743 100644
--- a/ui/display/chromeos/test/action_logger.h
+++ b/ui/display/manager/chromeos/test/action_logger.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 UI_DISPLAY_CHROMEOS_TEST_ACTION_LOGGER_H_
-#define UI_DISPLAY_CHROMEOS_TEST_ACTION_LOGGER_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_TEST_ACTION_LOGGER_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_TEST_ACTION_LOGGER_H_
 
 #include <string>
 
@@ -33,4 +33,4 @@
 }  // namespace test
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_TEST_ACTION_LOGGER_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_TEST_ACTION_LOGGER_H_
diff --git a/ui/display/chromeos/test/action_logger_util.cc b/ui/display/manager/chromeos/test/action_logger_util.cc
similarity index 97%
rename from ui/display/chromeos/test/action_logger_util.cc
rename to ui/display/manager/chromeos/test/action_logger_util.cc
index ebd9ef84..a620841 100644
--- a/ui/display/chromeos/test/action_logger_util.cc
+++ b/ui/display/manager/chromeos/test/action_logger_util.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 "ui/display/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
 
 #include <stddef.h>
 
diff --git a/ui/display/chromeos/test/action_logger_util.h b/ui/display/manager/chromeos/test/action_logger_util.h
similarity index 93%
rename from ui/display/chromeos/test/action_logger_util.h
rename to ui/display/manager/chromeos/test/action_logger_util.h
index 06be848..e1a287d 100644
--- a/ui/display/chromeos/test/action_logger_util.h
+++ b/ui/display/manager/chromeos/test/action_logger_util.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 UI_DISPLAY_CHROMEOS_TEST_ACTION_LOGGER_UTIL_H_
-#define UI_DISPLAY_CHROMEOS_TEST_ACTION_LOGGER_UTIL_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_TEST_ACTION_LOGGER_UTIL_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_TEST_ACTION_LOGGER_UTIL_H_
 
 #include <stdint.h>
 
@@ -82,4 +82,4 @@
 }  // namespace test
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_TEST_ACTION_LOGGER_UTIL_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_TEST_ACTION_LOGGER_UTIL_H_
diff --git a/ui/display/chromeos/test/test_display_layout_manager.cc b/ui/display/manager/chromeos/test/test_display_layout_manager.cc
similarity index 91%
rename from ui/display/chromeos/test/test_display_layout_manager.cc
rename to ui/display/manager/chromeos/test/test_display_layout_manager.cc
index 6c7e5127..8fed084 100644
--- a/ui/display/chromeos/test/test_display_layout_manager.cc
+++ b/ui/display/manager/chromeos/test/test_display_layout_manager.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 "ui/display/chromeos/test/test_display_layout_manager.h"
+#include "ui/display/manager/chromeos/test/test_display_layout_manager.h"
 
 #include <utility>
 
@@ -14,11 +14,9 @@
 TestDisplayLayoutManager::TestDisplayLayoutManager(
     ScopedVector<DisplaySnapshot> displays,
     MultipleDisplayState display_state)
-    : displays_(std::move(displays)), display_state_(display_state) {
-}
+    : displays_(std::move(displays)), display_state_(display_state) {}
 
-TestDisplayLayoutManager::~TestDisplayLayoutManager() {
-}
+TestDisplayLayoutManager::~TestDisplayLayoutManager() {}
 
 DisplayConfigurator::StateController*
 TestDisplayLayoutManager::GetStateController() const {
diff --git a/ui/display/chromeos/test/test_display_layout_manager.h b/ui/display/manager/chromeos/test/test_display_layout_manager.h
similarity index 80%
rename from ui/display/chromeos/test/test_display_layout_manager.h
rename to ui/display/manager/chromeos/test/test_display_layout_manager.h
index 44b97f7..30e8707d 100644
--- a/ui/display/chromeos/test/test_display_layout_manager.h
+++ b/ui/display/manager/chromeos/test/test_display_layout_manager.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_TEST_TEST_DISPLAY_LAYOUT_MANAGER_H_
-#define UI_DISPLAY_CHROMEOS_TEST_TEST_DISPLAY_LAYOUT_MANAGER_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_TEST_TEST_DISPLAY_LAYOUT_MANAGER_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_TEST_TEST_DISPLAY_LAYOUT_MANAGER_H_
 
 #include "base/macros.h"
 #include "base/memory/scoped_vector.h"
-#include "ui/display/chromeos/display_configurator.h"
-#include "ui/display/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
 
 namespace ui {
 namespace test {
@@ -43,4 +43,4 @@
 }  // namespace test
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_TEST_TEST_DISPLAY_LAYOUT_MANAGER_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_TEST_TEST_DISPLAY_LAYOUT_MANAGER_H_
diff --git a/ui/display/chromeos/test/test_native_display_delegate.cc b/ui/display/manager/chromeos/test/test_native_display_delegate.cc
similarity index 94%
rename from ui/display/chromeos/test/test_native_display_delegate.cc
rename to ui/display/manager/chromeos/test/test_native_display_delegate.cc
index 23a9e01..060dec2 100644
--- a/ui/display/chromeos/test/test_native_display_delegate.cc
+++ b/ui/display/manager/chromeos/test/test_native_display_delegate.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/test/test_native_display_delegate.h"
+#include "ui/display/manager/chromeos/test/test_native_display_delegate.h"
 
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "ui/display/chromeos/test/action_logger.h"
+#include "ui/display/manager/chromeos/test/action_logger.h"
 #include "ui/display/types/display_mode.h"
 
 namespace ui {
@@ -20,11 +20,9 @@
       set_hdcp_expectation_(true),
       hdcp_state_(HDCP_STATE_UNDESIRED),
       run_async_(false),
-      log_(log) {
-}
+      log_(log) {}
 
-TestNativeDisplayDelegate::~TestNativeDisplayDelegate() {
-}
+TestNativeDisplayDelegate::~TestNativeDisplayDelegate() {}
 
 void TestNativeDisplayDelegate::Initialize() {
   log_->AppendAction(kInitXRandR);
@@ -146,12 +144,10 @@
   return true;
 }
 
-void TestNativeDisplayDelegate::AddObserver(NativeDisplayObserver* observer) {
-}
+void TestNativeDisplayDelegate::AddObserver(NativeDisplayObserver* observer) {}
 
 void TestNativeDisplayDelegate::RemoveObserver(
-    NativeDisplayObserver* observer) {
-}
+    NativeDisplayObserver* observer) {}
 
 display::FakeDisplayController*
 TestNativeDisplayDelegate::GetFakeDisplayController() {
diff --git a/ui/display/chromeos/test/test_native_display_delegate.h b/ui/display/manager/chromeos/test/test_native_display_delegate.h
similarity index 91%
rename from ui/display/chromeos/test/test_native_display_delegate.h
rename to ui/display/manager/chromeos/test/test_native_display_delegate.h
index bad8ab2..1b875f6 100644
--- a/ui/display/chromeos/test/test_native_display_delegate.h
+++ b/ui/display/manager/chromeos/test/test_native_display_delegate.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_TEST_TEST_NATIVE_DISPLAY_DELEGATE_H_
-#define UI_DISPLAY_CHROMEOS_TEST_TEST_NATIVE_DISPLAY_DELEGATE_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_TEST_TEST_NATIVE_DISPLAY_DELEGATE_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_TEST_TEST_NATIVE_DISPLAY_DELEGATE_H_
 
 #include <stdint.h>
 
 #include <vector>
 
 #include "base/macros.h"
-#include "ui/display/chromeos/test/action_logger.h"
-#include "ui/display/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/action_logger.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
 #include "ui/display/types/native_display_delegate.h"
 
 namespace ui {
@@ -117,4 +117,4 @@
 }  // namespace test
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_TEST_TEST_NATIVE_DISPLAY_DELEGATE_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_TEST_TEST_NATIVE_DISPLAY_DELEGATE_H_
diff --git a/ui/display/chromeos/touchscreen_util.cc b/ui/display/manager/chromeos/touchscreen_util.cc
similarity index 99%
rename from ui/display/chromeos/touchscreen_util.cc
rename to ui/display/manager/chromeos/touchscreen_util.cc
index 78327d64..31dbf2f6 100644
--- a/ui/display/chromeos/touchscreen_util.cc
+++ b/ui/display/manager/chromeos/touchscreen_util.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 "ui/display/chromeos/touchscreen_util.h"
+#include "ui/display/manager/chromeos/touchscreen_util.h"
 
 #include <set>
 
diff --git a/ui/display/chromeos/touchscreen_util.h b/ui/display/manager/chromeos/touchscreen_util.h
similarity index 68%
rename from ui/display/chromeos/touchscreen_util.h
rename to ui/display/manager/chromeos/touchscreen_util.h
index 2edb410..0328c131 100644
--- a/ui/display/chromeos/touchscreen_util.h
+++ b/ui/display/manager/chromeos/touchscreen_util.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_TOUCHSCREEN_UTIL_H_
-#define UI_DISPLAY_CHROMEOS_TOUCHSCREEN_UTIL_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_TOUCHSCREEN_UTIL_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_TOUCHSCREEN_UTIL_H_
 
 #include <vector>
 
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/events/devices/touchscreen_device.h"
 
@@ -15,10 +15,10 @@
 
 // Given a list of displays and a list of touchscreens, associate them. The
 // information in |displays| will be updated to reflect the mapping.
-DISPLAY_EXPORT void AssociateTouchscreens(
+DISPLAY_MANAGER_EXPORT void AssociateTouchscreens(
     std::vector<display::ManagedDisplayInfo>* displays,
     const std::vector<ui::TouchscreenDevice>& touchscreens);
 
 }  // namespace display
 
-#endif  // UI_DISPLAY_CHROMEOS_TOUCHSCREEN_UTIL_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_TOUCHSCREEN_UTIL_H_
diff --git a/ui/display/chromeos/touchscreen_util_unittest.cc b/ui/display/manager/chromeos/touchscreen_util_unittest.cc
similarity index 99%
rename from ui/display/chromeos/touchscreen_util_unittest.cc
rename to ui/display/manager/chromeos/touchscreen_util_unittest.cc
index c7f0195..2cbe023 100644
--- a/ui/display/chromeos/touchscreen_util_unittest.cc
+++ b/ui/display/manager/chromeos/touchscreen_util_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/touchscreen_util.h"
+#include "ui/display/manager/chromeos/touchscreen_util.h"
 
 #include <memory>
 #include <string>
diff --git a/ui/display/chromeos/update_display_configuration_task.cc b/ui/display/manager/chromeos/update_display_configuration_task.cc
similarity index 96%
rename from ui/display/chromeos/update_display_configuration_task.cc
rename to ui/display/manager/chromeos/update_display_configuration_task.cc
index db8dffb..3993db5a 100644
--- a/ui/display/chromeos/update_display_configuration_task.cc
+++ b/ui/display/manager/chromeos/update_display_configuration_task.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/update_display_configuration_task.h"
+#include "ui/display/manager/chromeos/update_display_configuration_task.h"
 
-#include "ui/display/chromeos/configure_displays_task.h"
-#include "ui/display/chromeos/display_layout_manager.h"
-#include "ui/display/chromeos/display_util.h"
+#include "ui/display/manager/chromeos/configure_displays_task.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/display_util.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/native_display_delegate.h"
 
diff --git a/ui/display/chromeos/update_display_configuration_task.h b/ui/display/manager/chromeos/update_display_configuration_task.h
similarity index 87%
rename from ui/display/chromeos/update_display_configuration_task.h
rename to ui/display/manager/chromeos/update_display_configuration_task.h
index e92faf5d..3244543 100644
--- a/ui/display/chromeos/update_display_configuration_task.h
+++ b/ui/display/manager/chromeos/update_display_configuration_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 UI_DISPLAY_CHROMEOS_UPDATE_DISPLAY_CONFIGURATION_TASK_H_
-#define UI_DISPLAY_CHROMEOS_UPDATE_DISPLAY_CONFIGURATION_TASK_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_UPDATE_DISPLAY_CONFIGURATION_TASK_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_UPDATE_DISPLAY_CONFIGURATION_TASK_H_
 
 #include <stdint.h>
 
@@ -11,22 +11,23 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/display/chromeos/configure_displays_task.h"
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/configure_displays_task.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 
 namespace ui {
 
 class DisplaySnapshot;
 class NativeDisplayDelegate;
 
-class DISPLAY_EXPORT UpdateDisplayConfigurationTask {
+class DISPLAY_MANAGER_EXPORT UpdateDisplayConfigurationTask {
  public:
   typedef base::Callback<void(
       bool /* success */,
       const std::vector<DisplaySnapshot*>& /* displays */,
       const gfx::Size& /* framebuffer_size */,
       MultipleDisplayState /* new_display_state */,
-      chromeos::DisplayPowerState /* new_power_state */)> ResponseCallback;
+      chromeos::DisplayPowerState /* new_power_state */)>
+      ResponseCallback;
 
   UpdateDisplayConfigurationTask(NativeDisplayDelegate* delegate,
                                  DisplayLayoutManager* layout_manager,
@@ -115,4 +116,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_UPDATE_DISPLAY_CONFIGURATION_TASK_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_UPDATE_DISPLAY_CONFIGURATION_TASK_H_
diff --git a/ui/display/chromeos/update_display_configuration_task_unittest.cc b/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
similarity index 97%
rename from ui/display/chromeos/update_display_configuration_task_unittest.cc
rename to ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
index 9ec1043..5fb7dd14 100644
--- a/ui/display/chromeos/update_display_configuration_task_unittest.cc
+++ b/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/update_display_configuration_task.h"
+#include "ui/display/manager/chromeos/update_display_configuration_task.h"
 
 #include <stddef.h>
 
@@ -14,10 +14,10 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/display_layout_manager.h"
-#include "ui/display/chromeos/test/action_logger_util.h"
-#include "ui/display/chromeos/test/test_native_display_delegate.h"
 #include "ui/display/fake_display_snapshot.h"
+#include "ui/display/manager/chromeos/display_layout_manager.h"
+#include "ui/display/manager/chromeos/test/action_logger_util.h"
+#include "ui/display/manager/chromeos/test/test_native_display_delegate.h"
 
 namespace ui {
 namespace test {
@@ -444,7 +444,7 @@
   EXPECT_TRUE(configuration_status_);
   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, display_state_);
   EXPECT_TRUE(layout_manager_.GetSoftwareMirroringController()
-              ->SoftwareMirroringEnabled());
+                  ->SoftwareMirroringEnabled());
   EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_.GetActionsAndClear());
 }
 
@@ -478,7 +478,7 @@
   EXPECT_TRUE(configuration_status_);
   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, display_state_);
   EXPECT_TRUE(layout_manager_.GetSoftwareMirroringController()
-              ->SoftwareMirroringEnabled());
+                  ->SoftwareMirroringEnabled());
   EXPECT_EQ(
       JoinActions(
           kGrab, GetFramebufferAction(gfx::Size(big_mode_.size().width(),
diff --git a/ui/display/chromeos/x11/DEPS b/ui/display/manager/chromeos/x11/DEPS
similarity index 100%
rename from ui/display/chromeos/x11/DEPS
rename to ui/display/manager/chromeos/x11/DEPS
diff --git a/ui/display/manager/chromeos/x11/display_mode_x11.cc b/ui/display/manager/chromeos/x11/display_mode_x11.cc
new file mode 100644
index 0000000..a84f92b
--- /dev/null
+++ b/ui/display/manager/chromeos/x11/display_mode_x11.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/ptr_util.h"
+
+#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
+
+namespace ui {
+
+DisplayModeX11::DisplayModeX11(const gfx::Size& size,
+                               bool interlaced,
+                               float refresh_rate,
+                               RRMode mode_id)
+    : DisplayMode(size, interlaced, refresh_rate), mode_id_(mode_id) {}
+
+DisplayModeX11::~DisplayModeX11() {}
+
+std::unique_ptr<DisplayMode> DisplayModeX11::Clone() const {
+  return base::WrapUnique(
+      new DisplayModeX11(size(), is_interlaced(), refresh_rate(), mode_id()));
+}
+
+}  // namespace ui
diff --git a/ui/display/chromeos/x11/display_mode_x11.h b/ui/display/manager/chromeos/x11/display_mode_x11.h
similarity index 70%
rename from ui/display/chromeos/x11/display_mode_x11.h
rename to ui/display/manager/chromeos/x11/display_mode_x11.h
index 737fcc4..eb9ba6a 100644
--- a/ui/display/chromeos/x11/display_mode_x11.h
+++ b/ui/display/manager/chromeos/x11/display_mode_x11.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_X11_DISPLAY_MODE_X11_H_
-#define UI_DISPLAY_CHROMEOS_X11_DISPLAY_MODE_X11_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_MODE_X11_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_MODE_X11_H_
 
 #include "base/macros.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/display_mode.h"
 
 // Forward declare from Xlib and Xrandr.
@@ -15,7 +15,7 @@
 
 namespace ui {
 
-class DISPLAY_EXPORT DisplayModeX11 : public DisplayMode {
+class DISPLAY_MANAGER_EXPORT DisplayModeX11 : public DisplayMode {
  public:
   DisplayModeX11(const gfx::Size& size,
                  bool interlaced,
@@ -34,4 +34,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_X11_DISPLAY_MODE_X11_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_MODE_X11_H_
diff --git a/ui/display/chromeos/x11/display_snapshot_x11.cc b/ui/display/manager/chromeos/x11/display_snapshot_x11.cc
similarity index 93%
rename from ui/display/chromeos/x11/display_snapshot_x11.cc
rename to ui/display/manager/chromeos/x11/display_snapshot_x11.cc
index 7e6b4e1..938d3ba 100644
--- a/ui/display/chromeos/x11/display_snapshot_x11.cc
+++ b/ui/display/manager/chromeos/x11/display_snapshot_x11.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/x11/display_snapshot_x11.h"
+#include "ui/display/manager/chromeos/x11/display_snapshot_x11.h"
 
 #include "base/strings/stringprintf.h"
-#include "ui/display/chromeos/x11/display_mode_x11.h"
+#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
 
 namespace ui {
 
diff --git a/ui/display/chromeos/x11/display_snapshot_x11.h b/ui/display/manager/chromeos/x11/display_snapshot_x11.h
similarity index 83%
rename from ui/display/chromeos/x11/display_snapshot_x11.h
rename to ui/display/manager/chromeos/x11/display_snapshot_x11.h
index 37814850..80f3574 100644
--- a/ui/display/chromeos/x11/display_snapshot_x11.h
+++ b/ui/display/manager/chromeos/x11/display_snapshot_x11.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
-#define UI_DISPLAY_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
 
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/display_snapshot.h"
 
 // Forward declare from Xlib and Xrandr.
@@ -18,7 +18,7 @@
 
 namespace ui {
 
-class DISPLAY_EXPORT DisplaySnapshotX11 : public DisplaySnapshot {
+class DISPLAY_MANAGER_EXPORT DisplaySnapshotX11 : public DisplaySnapshot {
  public:
   DisplaySnapshotX11(int64_t display_id,
                      const gfx::Point& origin,
@@ -59,4 +59,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
diff --git a/ui/display/chromeos/x11/display_util_x11.cc b/ui/display/manager/chromeos/x11/display_util_x11.cc
similarity index 94%
rename from ui/display/chromeos/x11/display_util_x11.cc
rename to ui/display/manager/chromeos/x11/display_util_x11.cc
index b328655..348be37a 100644
--- a/ui/display/chromeos/x11/display_util_x11.cc
+++ b/ui/display/manager/chromeos/x11/display_util_x11.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 "ui/display/chromeos/x11/display_util_x11.h"
+#include "ui/display/manager/chromeos/x11/display_util_x11.h"
 
 #include "base/macros.h"
 #include "base/strings/string_util.h"
diff --git a/ui/display/manager/chromeos/x11/display_util_x11.h b/ui/display/manager/chromeos/x11/display_util_x11.h
new file mode 100644
index 0000000..c32b1650
--- /dev/null
+++ b/ui/display/manager/chromeos/x11/display_util_x11.h
@@ -0,0 +1,25 @@
+// 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 UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_UTIL_X11_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_UTIL_X11_H_
+
+#include <string>
+
+#include "ui/display/manager/display_manager_export.h"
+#include "ui/display/types/display_constants.h"
+
+typedef unsigned long XID;
+typedef XID RROutput;
+
+namespace ui {
+
+// Returns the DisplayConnectionType by matching known type prefixes to |name|.
+// Returns DISPLAY_TYPE_UNKNOWN if no valid match.
+DISPLAY_MANAGER_EXPORT DisplayConnectionType
+GetDisplayConnectionTypeFromName(const std::string& name);
+
+}  // namespace ui
+
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_UTIL_X11_H_
diff --git a/ui/display/chromeos/x11/display_util_x11_unittest.cc b/ui/display/manager/chromeos/x11/display_util_x11_unittest.cc
similarity index 97%
rename from ui/display/chromeos/x11/display_util_x11_unittest.cc
rename to ui/display/manager/chromeos/x11/display_util_x11_unittest.cc
index c5a990e..6d65b5f 100644
--- a/ui/display/chromeos/x11/display_util_x11_unittest.cc
+++ b/ui/display/manager/chromeos/x11/display_util_x11_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/x11/display_util_x11.h"
+#include "ui/display/manager/chromeos/x11/display_util_x11.h"
 
 #include <memory>
 
diff --git a/ui/display/chromeos/x11/native_display_delegate_x11.cc b/ui/display/manager/chromeos/x11/native_display_delegate_x11.cc
similarity index 97%
rename from ui/display/chromeos/x11/native_display_delegate_x11.cc
rename to ui/display/manager/chromeos/x11/native_display_delegate_x11.cc
index 3cbfe69..5a0b4f5 100644
--- a/ui/display/chromeos/x11/native_display_delegate_x11.cc
+++ b/ui/display/manager/chromeos/x11/native_display_delegate_x11.cc
@@ -2,23 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/x11/native_display_delegate_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_delegate_x11.h"
 
 #include <X11/Xatom.h>
 #include <X11/Xlib.h>
 #include <X11/extensions/dpms.h>
-#include <X11/extensions/Xrandr.h>
 #include <X11/extensions/XInput2.h>
+#include <X11/extensions/Xrandr.h>
 
 #include <utility>
 
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "ui/display/chromeos/x11/display_mode_x11.h"
-#include "ui/display/chromeos/x11/display_snapshot_x11.h"
-#include "ui/display/chromeos/x11/display_util_x11.h"
-#include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
+#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
+#include "ui/display/manager/chromeos/x11/display_snapshot_x11.h"
+#include "ui/display/manager/chromeos/x11/display_util_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h"
 #include "ui/display/types/native_display_observer.h"
 #include "ui/display/util/x11/edid_parser_x11.h"
 #include "ui/events/platform/platform_event_source.h"
@@ -156,7 +156,9 @@
   NOTIMPLEMENTED();
 }
 
-void NativeDisplayDelegateX11::SyncWithServer() { XSync(display_, 0); }
+void NativeDisplayDelegateX11::SyncWithServer() {
+  XSync(display_, 0);
+}
 
 void NativeDisplayDelegateX11::SetBackgroundColor(uint32_t color_argb) {
   background_color_argb_ = color_argb;
@@ -591,7 +593,6 @@
   return false;
 }
 
-
 std::vector<ColorCalibrationProfile>
 NativeDisplayDelegateX11::GetAvailableColorCalibrationProfiles(
     const DisplaySnapshot& output) {
@@ -612,8 +613,7 @@
     return false;
 
   int gamma_ramp_size = XRRGetCrtcGammaSize(display_, x11_output.crtc());
-  XRRSetCrtcGamma(display_,
-                  x11_output.crtc(),
+  XRRSetCrtcGamma(display_, x11_output.crtc(),
                   ResampleGammaRamp(gamma_ramp, gamma_ramp_size));
   XRRFreeGamma(gamma_ramp);
   return true;
diff --git a/ui/display/chromeos/x11/native_display_delegate_x11.h b/ui/display/manager/chromeos/x11/native_display_delegate_x11.h
similarity index 92%
rename from ui/display/chromeos/x11/native_display_delegate_x11.h
rename to ui/display/manager/chromeos/x11/native_display_delegate_x11.h
index c7cbdd21..fb3536eb 100644
--- a/ui/display/chromeos/x11/native_display_delegate_x11.h
+++ b/ui/display/manager/chromeos/x11/native_display_delegate_x11.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 UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
-#define UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
 
 #include <stdint.h>
 
@@ -17,7 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_vector.h"
 #include "base/observer_list.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/native_display_delegate.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/size.h"
@@ -47,7 +47,8 @@
 class DisplaySnapshotX11;
 class NativeDisplayEventDispatcherX11;
 
-class DISPLAY_EXPORT NativeDisplayDelegateX11 : public NativeDisplayDelegate {
+class DISPLAY_MANAGER_EXPORT NativeDisplayDelegateX11
+    : public NativeDisplayDelegate {
  public:
   // Helper class that allows NativeDisplayEventDispatcherX11 and
   // NativeDisplayDelegateX11::PlatformEventObserverX11 to interact with this
@@ -138,9 +139,8 @@
 
   // Creates the gamma ramp for |new_profile|, or NULL if it doesn't exist.
   // The caller should take the ownership.
-  XRRCrtcGamma* CreateGammaRampForProfile(
-      const DisplaySnapshotX11& x11_output,
-      ColorCalibrationProfile new_profile);
+  XRRCrtcGamma* CreateGammaRampForProfile(const DisplaySnapshotX11& x11_output,
+                                          ColorCalibrationProfile new_profile);
 
   void DrawBackground();
 
@@ -177,4 +177,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
diff --git a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.cc b/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.cc
similarity index 95%
rename from ui/display/chromeos/x11/native_display_event_dispatcher_x11.cc
rename to ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.cc
index 8b46c4c..70d0550a 100644
--- a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.cc
+++ b/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h"
 
 #include <X11/extensions/Xrandr.h>
 #include <utility>
 
 #include "base/time/default_tick_clock.h"
-#include "ui/display/chromeos/x11/display_mode_x11.h"
-#include "ui/display/chromeos/x11/display_snapshot_x11.h"
+#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
+#include "ui/display/manager/chromeos/x11/display_snapshot_x11.h"
 #include "ui/events/platform/platform_event_source.h"
 
 namespace ui {
diff --git a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.h b/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h
similarity index 80%
rename from ui/display/chromeos/x11/native_display_event_dispatcher_x11.h
rename to ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h
index 399063e..511c422 100644
--- a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.h
+++ b/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
-#define UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
+#ifndef UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
+#define UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
 
 #include <stdint.h>
 
 #include "base/macros.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
-#include "ui/display/chromeos/x11/native_display_delegate_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_delegate_x11.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
 
 namespace ui {
@@ -19,7 +19,7 @@
 // correspond to output add/remove events. Note that Output add/remove events
 // are sent in response to our own reconfiguration operations so spurious events
 // are common. Spurious events will have no effect.
-class DISPLAY_EXPORT NativeDisplayEventDispatcherX11
+class DISPLAY_MANAGER_EXPORT NativeDisplayEventDispatcherX11
     : public ui::PlatformEventDispatcher {
  public:
   NativeDisplayEventDispatcherX11(
@@ -52,4 +52,4 @@
 
 }  // namespace ui
 
-#endif  // UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
+#endif  // UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
diff --git a/ui/display/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc b/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
similarity index 89%
rename from ui/display/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
rename to ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
index 5dda0a6..76e7ac2 100644
--- a/ui/display/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
+++ b/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
@@ -11,10 +11,10 @@
 #include "base/macros.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/chromeos/x11/display_mode_x11.h"
-#include "ui/display/chromeos/x11/display_snapshot_x11.h"
-#include "ui/display/chromeos/x11/native_display_delegate_x11.h"
-#include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
+#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
+#include "ui/display/manager/chromeos/x11/display_snapshot_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_delegate_x11.h"
+#include "ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h"
 
 namespace ui {
 
@@ -24,9 +24,7 @@
                                  DisplayConnectionType type,
                                  RROutput output,
                                  RRCrtc crtc) {
-  static const DisplayModeX11 kDefaultDisplayMode(gfx::Size(1, 1),
-                                                  false,
-                                                  60.0f,
+  static const DisplayModeX11 kDefaultDisplayMode(gfx::Size(1, 1), false, 60.0f,
                                                   20);
   std::vector<std::unique_ptr<const DisplayMode>> modes;
   const DisplayMode* mode;
@@ -35,36 +33,19 @@
   mode = modes.front().get();
 
   DisplaySnapshotX11* snapshot = new DisplaySnapshotX11(
-      id,
-      gfx::Point(0, 0),
-      gfx::Size(0, 0),
-      type,
-      false,
-      false,
-      std::string(),
-      std::move(modes),
-      std::vector<uint8_t>(),
-      mode,
-      NULL,
-      output,
-      crtc,
-      0);
+      id, gfx::Point(0, 0), gfx::Size(0, 0), type, false, false, std::string(),
+      std::move(modes), std::vector<uint8_t>(), mode, NULL, output, crtc, 0);
 
   return snapshot;
 }
 
 DisplaySnapshotX11* CreateExternalOutput(RROutput output, RRCrtc crtc) {
   return CreateOutput(static_cast<int64_t>(output),
-                      DISPLAY_CONNECTION_TYPE_UNKNOWN,
-                      output,
-                      crtc);
+                      DISPLAY_CONNECTION_TYPE_UNKNOWN, output, crtc);
 }
 
 DisplaySnapshotX11* CreateInternalOutput(RROutput output, RRCrtc crtc) {
-  return CreateOutput(0,
-                      DISPLAY_CONNECTION_TYPE_INTERNAL,
-                      output,
-                      crtc);
+  return CreateOutput(0, DISPLAY_CONNECTION_TYPE_INTERNAL, output, crtc);
 }
 
 class TestHelperDelegate : public NativeDisplayDelegateX11::HelperDelegate {
@@ -266,8 +247,7 @@
   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
 }
 
-TEST_F(NativeDisplayEventDispatcherX11Test,
-       ForceUpdateAfterCacheExpiration) {
+TEST_F(NativeDisplayEventDispatcherX11Test, ForceUpdateAfterCacheExpiration) {
   // +1 to compenstate a possible rounding error.
   const int kHalfOfExpirationMs =
       NativeDisplayEventDispatcherX11::kUseCacheAfterStartupMs / 2 + 1;
@@ -283,8 +263,8 @@
   DispatchOutputChangeEvent(2, 11, 20, true);
   EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
 
-  test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
-      kHalfOfExpirationMs));
+  test_tick_clock_->Advance(
+      base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
 
   // Duplicated event will still be ignored.
   DispatchOutputChangeEvent(2, 11, 20, true);
@@ -302,8 +282,8 @@
   EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
 
   // Advancing time further should not change the behavior.
-  test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
-      kHalfOfExpirationMs));
+  test_tick_clock_->Advance(
+      base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
   DispatchOutputChangeEvent(2, 11, 20, true);
   EXPECT_EQ(3, helper_delegate_->num_calls_notify_observers());
 
@@ -313,8 +293,7 @@
   EXPECT_EQ(4, helper_delegate_->num_calls_notify_observers());
 }
 
-TEST_F(NativeDisplayEventDispatcherX11Test,
-       UpdateMissingExternalDisplayId) {
+TEST_F(NativeDisplayEventDispatcherX11Test, UpdateMissingExternalDisplayId) {
   ScopedVector<DisplaySnapshot> outputs;
   outputs.push_back(CreateInternalOutput(1, 10));
   helper_delegate_->set_cached_outputs(outputs.get());
diff --git a/ui/display/manager/display_layout_builder_unittest.cc b/ui/display/manager/display_layout_builder_unittest.cc
index f632679..dca48d6e9 100644
--- a/ui/display/manager/display_layout_builder_unittest.cc
+++ b/ui/display/manager/display_layout_builder_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout_builder.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ui/display/manager/display_layout_store.h b/ui/display/manager/display_layout_store.h
index 53db0c6c..d7e5167 100644
--- a/ui/display/manager/display_layout_store.h
+++ b/ui/display/manager/display_layout_store.h
@@ -12,12 +12,12 @@
 
 #include "base/macros.h"
 #include "ui/display/display.h"
-#include "ui/display/display_export.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/manager/display_manager_export.h"
 
 namespace display {
 
-class DISPLAY_EXPORT DisplayLayoutStore {
+class DISPLAY_MANAGER_EXPORT DisplayLayoutStore {
  public:
   DisplayLayoutStore();
   ~DisplayLayoutStore();
diff --git a/ui/display/manager/display_layout_unittest.cc b/ui/display/manager/display_layout_unittest.cc
index 3dac1149..bc940f0 100644
--- a/ui/display/manager/display_layout_unittest.cc
+++ b/ui/display/manager/display_layout_unittest.cc
@@ -8,8 +8,8 @@
 #include <vector>
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/manager/display_layout.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/display_layout_builder.h"
 
 namespace display {
 
diff --git a/ui/display/manager/display_manager.h b/ui/display/manager/display_manager.h
index 2e1e9048..f573f4d1 100644
--- a/ui/display/manager/display_manager.h
+++ b/ui/display/manager/display_manager.h
@@ -19,14 +19,14 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "ui/display/display.h"
-#include "ui/display/display_export.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/display_observer.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/display/types/display_constants.h"
 
 #if defined(OS_CHROMEOS)
-#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/manager/chromeos/display_configurator.h"
 #endif
 
 namespace gfx {
@@ -47,13 +47,13 @@
 
 // DisplayManager maintains the current display configurations,
 // and notifies observers when configuration changes.
-class DISPLAY_EXPORT DisplayManager
+class DISPLAY_MANAGER_EXPORT DisplayManager
 #if defined(OS_CHROMEOS)
     : public ui::DisplayConfigurator::SoftwareMirroringController
 #endif
 {
  public:
-  class DISPLAY_EXPORT Delegate {
+  class DISPLAY_MANAGER_EXPORT Delegate {
    public:
     virtual ~Delegate() {}
 
diff --git a/ui/display/manager/display_manager_export.h b/ui/display/manager/display_manager_export.h
new file mode 100644
index 0000000..4277cfa
--- /dev/null
+++ b/ui/display/manager/display_manager_export.h
@@ -0,0 +1,29 @@
+// Copyright 2016 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_DISPLAY_MANAGER_DISPLAY_MANAGER_EXPORT_H_
+#define UI_DISPLAY_MANAGER_DISPLAY_MANAGER_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(DISPLAY_MANAGER_IMPLEMENTATION)
+#define DISPLAY_MANAGER_EXPORT __declspec(dllexport)
+#else
+#define DISPLAY_MANAGER_EXPORT __declspec(dllimport)
+#endif
+
+#else  // !defined(WIN32)
+#if defined(DISPLAY_MANAGER_IMPLEMENTATION)
+#define DISPLAY_MANAGER_EXPORT __attribute__((visibility("default")))
+#else
+#define DISPLAY_MANAGER_EXPORT
+#endif
+#endif
+
+#else  // !defined(COMPONENT_BUILD)
+#define DISPLAY_MANAGER_EXPORT
+#endif
+
+#endif  // UI_DISPLAY_MANAGER_DISPLAY_MANAGER_EXPORT_H_
diff --git a/ui/display/manager/display_manager_utilities.h b/ui/display/manager/display_manager_utilities.h
index 3c826c7..ca004055 100644
--- a/ui/display/manager/display_manager_utilities.h
+++ b/ui/display/manager/display_manager_utilities.h
@@ -8,8 +8,8 @@
 #include <set>
 
 #include "ui/display/display.h"
-#include "ui/display/display_export.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/manager/managed_display_info.h"
 
 namespace gfx {
@@ -24,32 +24,31 @@
 
 // Creates the display mode list for internal display
 // based on |native_mode|.
-DISPLAY_EXPORT ManagedDisplayInfo::ManagedDisplayModeList
+DISPLAY_MANAGER_EXPORT ManagedDisplayInfo::ManagedDisplayModeList
 CreateInternalManagedDisplayModeList(
     const scoped_refptr<ManagedDisplayMode>& native_mode);
 
 // Creates the display mode list for unified display
 // based on |native_mode| and |scales|.
-DISPLAY_EXPORT ManagedDisplayInfo::ManagedDisplayModeList
+DISPLAY_MANAGER_EXPORT ManagedDisplayInfo::ManagedDisplayModeList
 CreateUnifiedManagedDisplayModeList(
     const scoped_refptr<ManagedDisplayMode>& native_mode,
     const std::set<std::pair<float, float>>& dsf_scale_list);
 
 // Gets the display mode for |resolution|. Returns false if no display
 // mode matches the resolution, or the display is an internal display.
-DISPLAY_EXPORT scoped_refptr<ManagedDisplayMode> GetDisplayModeForResolution(
-    const ManagedDisplayInfo& info,
-    const gfx::Size& resolution);
+DISPLAY_MANAGER_EXPORT scoped_refptr<ManagedDisplayMode>
+GetDisplayModeForResolution(const ManagedDisplayInfo& info,
+                            const gfx::Size& resolution);
 
 // Gets the display mode for the next valid UI scale. Returns false
 // if the display is not an internal display.
-DISPLAY_EXPORT scoped_refptr<ManagedDisplayMode> GetDisplayModeForNextUIScale(
-    const ManagedDisplayInfo& info,
-    bool up);
+DISPLAY_MANAGER_EXPORT scoped_refptr<ManagedDisplayMode>
+GetDisplayModeForNextUIScale(const ManagedDisplayInfo& info, bool up);
 
 // Gets the display mode for the next valid resolution. Returns false
 // if the display is an internal display.
-DISPLAY_EXPORT scoped_refptr<ManagedDisplayMode>
+DISPLAY_MANAGER_EXPORT scoped_refptr<ManagedDisplayMode>
 GetDisplayModeForNextResolution(const ManagedDisplayInfo& info, bool up);
 
 // Tests if the |info| has display mode that matches |ui_scale|.
@@ -57,19 +56,20 @@
 
 // Computes the bounds that defines the bounds between two displays.
 // Returns false if two displays do not intersect.
-DISPLAY_EXPORT bool ComputeBoundary(const Display& primary_display,
-                                    const Display& secondary_display,
-                                    gfx::Rect* primary_edge_in_screen,
-                                    gfx::Rect* secondary_edge_in_screen);
+DISPLAY_MANAGER_EXPORT bool ComputeBoundary(
+    const Display& primary_display,
+    const Display& secondary_display,
+    gfx::Rect* primary_edge_in_screen,
+    gfx::Rect* secondary_edge_in_screen);
 
 // Returns the index in the displays whose bounds contains |point_in_screen|.
 // Returns -1 if no such display exist.
-DISPLAY_EXPORT int FindDisplayIndexContainingPoint(
+DISPLAY_MANAGER_EXPORT int FindDisplayIndexContainingPoint(
     const std::vector<Display>& displays,
     const gfx::Point& point_in_screen);
 
 // Sorts id list using |CompareDisplayIds| below.
-DISPLAY_EXPORT void SortDisplayIdList(DisplayIdList* list);
+DISPLAY_MANAGER_EXPORT void SortDisplayIdList(DisplayIdList* list);
 
 // Default id generator.
 class DefaultDisplayIdGenerator {
@@ -92,14 +92,15 @@
 }
 
 // Creates sorted DisplayIdList.
-DISPLAY_EXPORT DisplayIdList CreateDisplayIdList(const Displays& list);
+DISPLAY_MANAGER_EXPORT DisplayIdList CreateDisplayIdList(const Displays& list);
 
-DISPLAY_EXPORT std::string DisplayIdListToString(const DisplayIdList& list);
+DISPLAY_MANAGER_EXPORT std::string DisplayIdListToString(
+    const DisplayIdList& list);
 
 // Returns true if one of following conditions is met.
 // 1) id1 is internal.
 // 2) output index of id1 < output index of id2 and id2 isn't internal.
-DISPLAY_EXPORT bool CompareDisplayIds(int64_t id1, int64_t id2);
+DISPLAY_MANAGER_EXPORT bool CompareDisplayIds(int64_t id1, int64_t id2);
 
 }  // namespace display
 
diff --git a/ui/display/manager/managed_display_info.h b/ui/display/manager/managed_display_info.h
index 1fb48a879..57c259b 100644
--- a/ui/display/manager/managed_display_info.h
+++ b/ui/display/manager/managed_display_info.h
@@ -15,7 +15,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "ui/display/display.h"
-#include "ui/display/display_export.h"
+#include "ui/display/manager/display_manager_export.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
@@ -24,7 +24,7 @@
 
 // A struct that represents all the data required for touch calibration for the
 // display.
-struct DISPLAY_EXPORT TouchCalibrationData {
+struct DISPLAY_MANAGER_EXPORT TouchCalibrationData {
   // CalibrationPointPair.first -> display point
   // CalibrationPointPair.second -> touch point
   using CalibrationPointPair = std::pair<gfx::Point, gfx::Point>;
@@ -43,7 +43,7 @@
 };
 
 // A class that represents the display's mode info.
-class DISPLAY_EXPORT ManagedDisplayMode
+class DISPLAY_MANAGER_EXPORT ManagedDisplayMode
     : public base::RefCounted<ManagedDisplayMode> {
  public:
   ManagedDisplayMode();
@@ -98,7 +98,7 @@
 // ManagedDisplayInfo contains metadata for each display. This is used to create
 // |Display| as well as to maintain extra infomation to manage displays in ash
 // environment. This class is intentionally made copiable.
-class DISPLAY_EXPORT ManagedDisplayInfo {
+class DISPLAY_MANAGER_EXPORT ManagedDisplayInfo {
  public:
   using ManagedDisplayModeList = std::vector<scoped_refptr<ManagedDisplayMode>>;
 
@@ -393,7 +393,7 @@
 
 // Resets the synthesized display id for testing. This
 // is necessary to avoid overflowing the output index.
-void DISPLAY_EXPORT ResetDisplayIdForTest();
+void DISPLAY_MANAGER_EXPORT ResetDisplayIdForTest();
 
 }  // namespace display
 
diff --git a/ui/display/test/display_manager_test_api.cc b/ui/display/test/display_manager_test_api.cc
index 31f8323f..f0997b4e 100644
--- a/ui/display/test/display_manager_test_api.cc
+++ b/ui/display/test/display_manager_test_api.cc
@@ -9,7 +9,7 @@
 
 #include "base/strings/string_split.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/display_manager_utilities.h"
 #include "ui/display/manager/managed_display_info.h"
diff --git a/ui/display/test/display_manager_test_api.h b/ui/display/test/display_manager_test_api.h
index 95fe502e..ee5793b6 100644
--- a/ui/display/test/display_manager_test_api.h
+++ b/ui/display/test/display_manager_test_api.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "ui/display/display.h"
 #include "ui/display/display_export.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/types/display_constants.h"
 
 namespace gfx {
diff --git a/ui/display/win/scaling_util.h b/ui/display/win/scaling_util.h
index 615396a2..18b475f 100644
--- a/ui/display/win/scaling_util.h
+++ b/ui/display/win/scaling_util.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 
 #include "ui/display/display_export.h"
-#include "ui/display/manager/display_layout.h"
+#include "ui/display/display_layout.h"
 #include "ui/display/win/display_info.h"
 
 namespace gfx {
diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc
index ee5e8b0..dbbe685 100644
--- a/ui/display/win/screen_win.cc
+++ b/ui/display/win/screen_win.cc
@@ -14,8 +14,8 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/win/win_util.h"
 #include "ui/display/display.h"
-#include "ui/display/manager/display_layout.h"
-#include "ui/display/manager/display_layout_builder.h"
+#include "ui/display/display_layout.h"
+#include "ui/display/display_layout_builder.h"
 #include "ui/display/win/display_info.h"
 #include "ui/display/win/dpi.h"
 #include "ui/display/win/scaling_util.h"
diff --git a/ui/snapshot/snapshot_android.cc b/ui/snapshot/snapshot_android.cc
index e16cdd73..557a325 100644
--- a/ui/snapshot/snapshot_android.cc
+++ b/ui/snapshot/snapshot_android.cc
@@ -43,7 +43,7 @@
       cc::CopyOutputRequest::CreateBitmapRequest(callback);
 
   const display::Display& display =
-      display::Screen::GetScreen()->GetPrimaryDisplay();
+      display::Screen::GetScreen()->GetDisplayNearestWindow(window);
   float device_scale_factor = display.device_scale_factor();
   gfx::Rect source_rect_in_pixel =
       gfx::ScaleToEnclosingRect(source_rect, device_scale_factor);
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc
index dcf7f58..29197e63 100644
--- a/ui/views/mus/desktop_window_tree_host_mus.cc
+++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -135,8 +135,6 @@
          ui::SHOW_STATE_DOCKED;
 }
 
-// TODO(erg): In addition to being called on system events, this also needs to
-// be called after window size changed.
 void DesktopWindowTreeHostMus::SendClientAreaToServer() {
   NonClientView* non_client_view =
       native_widget_delegate_->AsWidget()->non_client_view();
@@ -177,6 +175,9 @@
 
 void DesktopWindowTreeHostMus::Init(aura::Window* content_window,
                                     const Widget::InitParams& params) {
+  // Needed so we don't render over the non-client area the window manager
+  // renders to.
+  content_window->layer()->SetFillsBoundsOpaquely(false);
   if (!params.bounds.IsEmpty())
     SetBoundsInDIP(params.bounds);
 }
@@ -540,6 +541,11 @@
   window()->SetProperty(aura::client::kResizeBehaviorKey, behavior);
 }
 
+bool DesktopWindowTreeHostMus::ShouldUpdateWindowTransparency() const {
+  // Needed so the window manager can render the client decorations.
+  return false;
+}
+
 void DesktopWindowTreeHostMus::OnWindowManagerFrameValuesChanged() {
   NonClientView* non_client_view =
       native_widget_delegate_->AsWidget()->non_client_view();
@@ -579,7 +585,12 @@
       size.SetToMin(max_size_in_pixels);
     final_bounds_in_pixels.set_size(size);
   }
+  const gfx::Rect old_bounds_in_pixels = GetBoundsInPixels();
   WindowTreeHostMus::SetBoundsInPixels(final_bounds_in_pixels);
+  if (old_bounds_in_pixels.size() != final_bounds_in_pixels.size()) {
+    SendClientAreaToServer();
+    SendHitTestMaskToServer();
+  }
 }
 
 void DesktopWindowTreeHostMus::OnWindowInitialized(aura::Window* window) {}
diff --git a/ui/views/mus/desktop_window_tree_host_mus.h b/ui/views/mus/desktop_window_tree_host_mus.h
index 2d6343e8..eb0e6930 100644
--- a/ui/views/mus/desktop_window_tree_host_mus.h
+++ b/ui/views/mus/desktop_window_tree_host_mus.h
@@ -101,6 +101,7 @@
   bool IsAnimatingClosed() const override;
   bool IsTranslucentWindowOpacitySupported() const override;
   void SizeConstraintsChanged() override;
+  bool ShouldUpdateWindowTransparency() const override;
 
   // MusClientObserver:
   void OnWindowManagerFrameValuesChanged() override;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index da8f9fb..91698f4 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -1185,6 +1185,9 @@
 // DesktopNativeWidgetAura, private:
 
 void DesktopNativeWidgetAura::UpdateWindowTransparency() {
+  if (!desktop_window_tree_host_->ShouldUpdateWindowTransparency())
+    return;
+
   content_window_->SetTransparent(
       desktop_window_tree_host_->ShouldWindowContentsBeTransparent());
   // Regardless of transparency or not, this root content window will always
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host.h b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index b09f9660..e8bfb9d 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -158,6 +158,10 @@
 
   // Called when the window's size constraints change.
   virtual void SizeConstraintsChanged() = 0;
+
+  // Returns true if the transparency of the DesktopNativeWidgetAura's
+  // |content_window_| should change.
+  virtual bool ShouldUpdateWindowTransparency() const = 0;
 };
 
 }  // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 6cb9469e..8f030fb 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -484,6 +484,10 @@
   message_handler_->SizeConstraintsChanged();
 }
 
+bool DesktopWindowTreeHostWin::ShouldUpdateWindowTransparency() const {
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHostWin, WindowTreeHost implementation:
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 61b5ab9..8935db5 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -104,6 +104,7 @@
   bool IsAnimatingClosed() const override;
   bool IsTranslucentWindowOpacitySupported() const override;
   void SizeConstraintsChanged() override;
+  bool ShouldUpdateWindowTransparency() const override;
 
   // Overridden from aura::WindowTreeHost:
   ui::EventSource* GetEventSource() override;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 15ebd9c..d4a5387 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -1167,6 +1167,10 @@
   UpdateMinAndMaxSize();
 }
 
+bool DesktopWindowTreeHostX11::ShouldUpdateWindowTransparency() const {
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHostX11, aura::WindowTreeHost implementation:
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index 53cacea7..fc227c35 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -152,6 +152,7 @@
   bool IsAnimatingClosed() const override;
   bool IsTranslucentWindowOpacitySupported() const override;
   void SizeConstraintsChanged() override;
+  bool ShouldUpdateWindowTransparency() const override;
 
   // Overridden from aura::WindowTreeHost:
   gfx::Transform GetRootTransform() const override;