diff --git a/DEPS b/DEPS
index 29a42c9..e285c416 100644
--- a/DEPS
+++ b/DEPS
@@ -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': 'b8227824c221733e8636c42c3aee8ccff9efd719',
+  'pdfium_revision': 'e4b035b722ad69d4a4357c54cd3c9f1f8574b067',
   # 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.
diff --git a/cc/surfaces/BUILD.gn b/cc/surfaces/BUILD.gn
index a326729..a01b819 100644
--- a/cc/surfaces/BUILD.gn
+++ b/cc/surfaces/BUILD.gn
@@ -45,6 +45,8 @@
     "display_client.h",
     "display_scheduler.cc",
     "display_scheduler.h",
+    "framesink_manager.cc",
+    "framesink_manager.h",
     "local_surface_id_allocator.cc",
     "local_surface_id_allocator.h",
     "pending_frame_observer.h",
diff --git a/cc/surfaces/framesink_manager.cc b/cc/surfaces/framesink_manager.cc
new file mode 100644
index 0000000..d8fad7e
--- /dev/null
+++ b/cc/surfaces/framesink_manager.cc
@@ -0,0 +1,231 @@
+// 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 "cc/surfaces/framesink_manager.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/logging.h"
+#include "cc/surfaces/surface_factory_client.h"
+
+#if DCHECK_IS_ON()
+#include <sstream>
+#endif
+
+namespace cc {
+
+FrameSinkManager::FrameSinkSourceMapping::FrameSinkSourceMapping()
+    : source(nullptr) {}
+
+FrameSinkManager::FrameSinkSourceMapping::FrameSinkSourceMapping(
+    const FrameSinkSourceMapping& other) = default;
+
+FrameSinkManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() {
+}
+
+FrameSinkManager::FrameSinkManager() {}
+
+FrameSinkManager::~FrameSinkManager() {
+  // All surface factory clients should be unregistered prior to SurfaceManager
+  // destruction.
+  DCHECK_EQ(clients_.size(), 0u);
+  DCHECK_EQ(registered_sources_.size(), 0u);
+}
+
+void FrameSinkManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) {
+  bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second;
+  DCHECK(inserted);
+}
+
+void FrameSinkManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) {
+  valid_frame_sink_ids_.erase(frame_sink_id);
+}
+
+void FrameSinkManager::RegisterSurfaceFactoryClient(
+    const FrameSinkId& frame_sink_id,
+    SurfaceFactoryClient* client) {
+  DCHECK(client);
+  DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u);
+
+  clients_[frame_sink_id] = client;
+
+  auto it = frame_sink_source_map_.find(frame_sink_id);
+  if (it != frame_sink_source_map_.end()) {
+    if (it->second.source)
+      client->SetBeginFrameSource(it->second.source);
+  }
+}
+
+void FrameSinkManager::UnregisterSurfaceFactoryClient(
+    const FrameSinkId& frame_sink_id) {
+  DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u);
+  auto client_iter = clients_.find(frame_sink_id);
+  DCHECK(client_iter != clients_.end());
+
+  auto source_iter = frame_sink_source_map_.find(frame_sink_id);
+  if (source_iter != frame_sink_source_map_.end()) {
+    if (source_iter->second.source)
+      client_iter->second->SetBeginFrameSource(nullptr);
+    if (!source_iter->second.has_children())
+      frame_sink_source_map_.erase(source_iter);
+  }
+  clients_.erase(client_iter);
+}
+
+void FrameSinkManager::RegisterBeginFrameSource(
+    BeginFrameSource* source,
+    const FrameSinkId& frame_sink_id) {
+  DCHECK(source);
+  DCHECK_EQ(registered_sources_.count(source), 0u);
+  DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u);
+
+  registered_sources_[source] = frame_sink_id;
+  RecursivelyAttachBeginFrameSource(frame_sink_id, source);
+}
+
+void FrameSinkManager::UnregisterBeginFrameSource(BeginFrameSource* source) {
+  DCHECK(source);
+  DCHECK_EQ(registered_sources_.count(source), 1u);
+
+  FrameSinkId frame_sink_id = registered_sources_[source];
+  registered_sources_.erase(source);
+
+  if (frame_sink_source_map_.count(frame_sink_id) == 0u)
+    return;
+
+  // TODO(enne): these walks could be done in one step.
+  // Remove this begin frame source from its subtree.
+  RecursivelyDetachBeginFrameSource(frame_sink_id, source);
+  // Then flush every remaining registered source to fix any sources that
+  // became null because of the previous step but that have an alternative.
+  for (auto source_iter : registered_sources_)
+    RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first);
+}
+
+void FrameSinkManager::RecursivelyAttachBeginFrameSource(
+    const FrameSinkId& frame_sink_id,
+    BeginFrameSource* source) {
+  FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id];
+  if (!mapping.source) {
+    mapping.source = source;
+    auto client_iter = clients_.find(frame_sink_id);
+    if (client_iter != clients_.end())
+      client_iter->second->SetBeginFrameSource(source);
+  }
+  for (size_t i = 0; i < mapping.children.size(); ++i)
+    RecursivelyAttachBeginFrameSource(mapping.children[i], source);
+}
+
+void FrameSinkManager::RecursivelyDetachBeginFrameSource(
+    const FrameSinkId& frame_sink_id,
+    BeginFrameSource* source) {
+  auto iter = frame_sink_source_map_.find(frame_sink_id);
+  if (iter == frame_sink_source_map_.end())
+    return;
+  if (iter->second.source == source) {
+    iter->second.source = nullptr;
+    auto client_iter = clients_.find(frame_sink_id);
+    if (client_iter != clients_.end())
+      client_iter->second->SetBeginFrameSource(nullptr);
+  }
+
+  if (!iter->second.has_children() && !clients_.count(frame_sink_id)) {
+    frame_sink_source_map_.erase(iter);
+    return;
+  }
+
+  std::vector<FrameSinkId>& children = iter->second.children;
+  for (size_t i = 0; i < children.size(); ++i) {
+    RecursivelyDetachBeginFrameSource(children[i], source);
+  }
+}
+
+bool FrameSinkManager::ChildContains(
+    const FrameSinkId& child_frame_sink_id,
+    const FrameSinkId& search_frame_sink_id) const {
+  auto iter = frame_sink_source_map_.find(child_frame_sink_id);
+  if (iter == frame_sink_source_map_.end())
+    return false;
+
+  const std::vector<FrameSinkId>& children = iter->second.children;
+  for (size_t i = 0; i < children.size(); ++i) {
+    if (children[i] == search_frame_sink_id)
+      return true;
+    if (ChildContains(children[i], search_frame_sink_id))
+      return true;
+  }
+  return false;
+}
+
+void FrameSinkManager::RegisterFrameSinkHierarchy(
+    const FrameSinkId& parent_frame_sink_id,
+    const FrameSinkId& child_frame_sink_id) {
+  // If it's possible to reach the parent through the child's descendant chain,
+  // then this will create an infinite loop.  Might as well just crash here.
+  CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id));
+
+  std::vector<FrameSinkId>& children =
+      frame_sink_source_map_[parent_frame_sink_id].children;
+  for (size_t i = 0; i < children.size(); ++i)
+    DCHECK(children[i] != child_frame_sink_id);
+  children.push_back(child_frame_sink_id);
+
+  // If the parent has no source, then attaching it to this child will
+  // not change any downstream sources.
+  BeginFrameSource* parent_source =
+      frame_sink_source_map_[parent_frame_sink_id].source;
+  if (!parent_source)
+    return;
+
+  DCHECK_EQ(registered_sources_.count(parent_source), 1u);
+  RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source);
+}
+
+void FrameSinkManager::UnregisterFrameSinkHierarchy(
+    const FrameSinkId& parent_frame_sink_id,
+    const FrameSinkId& child_frame_sink_id) {
+  // Deliberately do not check validity of either parent or child FrameSinkId
+  // here.  They were valid during the registration, so were valid at some
+  // point in time.  This makes it possible to invalidate parent and child
+  // FrameSinkIds independently of each other and not have an ordering
+  // dependency  of unregistering the hierarchy first before either of them.
+  DCHECK_EQ(frame_sink_source_map_.count(parent_frame_sink_id), 1u);
+
+  auto iter = frame_sink_source_map_.find(parent_frame_sink_id);
+
+  std::vector<FrameSinkId>& children = iter->second.children;
+  bool found_child = false;
+  for (size_t i = 0; i < children.size(); ++i) {
+    if (children[i] == child_frame_sink_id) {
+      found_child = true;
+      children[i] = children.back();
+      children.resize(children.size() - 1);
+      break;
+    }
+  }
+  DCHECK(found_child);
+
+  // The SurfaceFactoryClient and hierarchy can be registered/unregistered
+  // in either order, so empty frame_sink_source_map entries need to be
+  // checked when removing either clients or relationships.
+  if (!iter->second.has_children() && !clients_.count(parent_frame_sink_id) &&
+      !iter->second.source) {
+    frame_sink_source_map_.erase(iter);
+    return;
+  }
+
+  // If the parent does not have a begin frame source, then disconnecting it
+  // will not change any of its children.
+  BeginFrameSource* parent_source = iter->second.source;
+  if (!parent_source)
+    return;
+
+  // TODO(enne): these walks could be done in one step.
+  RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source);
+  for (auto source_iter : registered_sources_)
+    RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first);
+}
+
+}  // namespace cc
diff --git a/cc/surfaces/framesink_manager.h b/cc/surfaces/framesink_manager.h
new file mode 100644
index 0000000..087126c
--- /dev/null
+++ b/cc/surfaces/framesink_manager.h
@@ -0,0 +1,122 @@
+// 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 CC_SURFACES_FRAMESINK_MANAGER_H_
+#define CC_SURFACES_FRAMESINK_MANAGER_H_
+
+#include <stdint.h>
+
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "cc/surfaces/frame_sink_id.h"
+#include "cc/surfaces/surfaces_export.h"
+
+namespace cc {
+class BeginFrameSource;
+class SurfaceFactoryClient;
+
+namespace test {
+class CompositorFrameSinkSupportTest;
+}
+
+class CC_SURFACES_EXPORT FrameSinkManager {
+ public:
+  FrameSinkManager();
+  ~FrameSinkManager();
+
+  void RegisterFrameSinkId(const FrameSinkId& frame_sink_id);
+
+  // Invalidate a frame_sink_id that might still have associated sequences,
+  // possibly because a renderer process has crashed.
+  void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id);
+
+  // SurfaceFactoryClient, hierarchy, and BeginFrameSource can be registered
+  // and unregistered in any order with respect to each other.
+  //
+  // This happens in practice, e.g. the relationship to between ui::Compositor /
+  // DelegatedFrameHost is known before ui::Compositor has a surface/client).
+  // However, DelegatedFrameHost can register itself as a client before its
+  // relationship with the ui::Compositor is known.
+
+  // Associates a SurfaceFactoryClient with the  frame_sink_id it  uses.
+  // SurfaceFactoryClient and framesink allocators have a 1:1 mapping.
+  // Caller guarantees the client is alive between register/unregister.
+  void RegisterSurfaceFactoryClient(const FrameSinkId& frame_sink_id,
+                                    SurfaceFactoryClient* client);
+  void UnregisterSurfaceFactoryClient(const FrameSinkId& frame_sink_id);
+
+  // Associates a |source| with a particular framesink.  That framesink and
+  // any children of that framesink with valid clients can potentially use
+  // that |source|.
+  void RegisterBeginFrameSource(BeginFrameSource* source,
+                                const FrameSinkId& frame_sink_id);
+  void UnregisterBeginFrameSource(BeginFrameSource* source);
+
+  // Register a relationship between two framesinks.  This relationship means
+  // that surfaces from the child framesik will be displayed in the parent.
+  // Children are allowed to use any begin frame source that their parent can
+  // use.
+  void RegisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id,
+                                  const FrameSinkId& child_frame_sink_id);
+  void UnregisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id,
+                                    const FrameSinkId& child_frame_sink_id);
+
+  // Export list of valid frame_sink_ids for SatisfyDestructionDeps in surface
+  // may be removed later when References replace Sequences
+  std::unordered_set<FrameSinkId, FrameSinkIdHash>* GetValidFrameSinkIds(){
+    return &valid_frame_sink_ids_;
+  }
+
+ private:
+  friend class test::CompositorFrameSinkSupportTest;
+
+  void RecursivelyAttachBeginFrameSource(const FrameSinkId& frame_sink_id,
+                                         BeginFrameSource* source);
+  void RecursivelyDetachBeginFrameSource(const FrameSinkId& frame_sink_id,
+                                         BeginFrameSource* source);
+
+  // Returns true if |child framesink| is or has |search_frame_sink_id| as a
+  // child.
+  bool ChildContains(const FrameSinkId& child_frame_sink_id,
+                     const FrameSinkId& search_frame_sink_id) const;
+
+  // Set of valid framesink Ids. When a framesink Id  is removed from
+  // this set, any remaining (surface) sequences with that framesink are
+  // considered satisfied.
+  std::unordered_set<FrameSinkId, FrameSinkIdHash> valid_frame_sink_ids_;
+
+  // Begin frame source routing. Both BeginFrameSource and SurfaceFactoryClient
+  // pointers guaranteed alive by callers until unregistered.
+  struct FrameSinkSourceMapping {
+    FrameSinkSourceMapping();
+    FrameSinkSourceMapping(const FrameSinkSourceMapping& other);
+    ~FrameSinkSourceMapping();
+    bool has_children() const { return !children.empty(); }
+    // The currently assigned begin frame source for this client.
+    BeginFrameSource* source;
+    // This represents a dag of parent -> children mapping.
+    std::vector<FrameSinkId> children;
+  };
+
+  std::unordered_map<FrameSinkId, SurfaceFactoryClient*, FrameSinkIdHash>
+      clients_;
+
+  std::unordered_map<FrameSinkId, FrameSinkSourceMapping, FrameSinkIdHash>
+      frame_sink_source_map_;
+
+  // Set of which sources are registered to which frmesinks.  Any child
+  // that is implicitly using this framesink must be reachable by the
+  // parent in the dag.
+  std::unordered_map<BeginFrameSource*, FrameSinkId> registered_sources_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameSinkManager);
+};
+
+}  // namespace cc
+
+#endif  // CC_SURFACES_FRAMESINK_MANAGER_H_
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index 64a180f..f6ecbb8 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -23,15 +23,6 @@
 
 namespace cc {
 
-SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping()
-    : source(nullptr) {}
-
-SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping(
-    const FrameSinkSourceMapping& other) = default;
-
-SurfaceManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() {
-}
-
 SurfaceManager::SurfaceManager(LifetimeType lifetime_type)
     : lifetime_type_(lifetime_type),
       root_surface_id_(FrameSinkId(0u, 0u),
@@ -59,11 +50,6 @@
     UnregisterSurface((*it)->surface_id());
   }
   surfaces_to_destroy_.clear();
-
-  // All surface factory clients should be unregistered prior to SurfaceManager
-  // destruction.
-  DCHECK_EQ(clients_.size(), 0u);
-  DCHECK_EQ(registered_sources_.size(), 0u);
 }
 
 #if DCHECK_IS_ON()
@@ -163,12 +149,11 @@
 }
 
 void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) {
-  bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second;
-  DCHECK(inserted);
+  framesink_manager_.RegisterFrameSinkId(frame_sink_id);
 }
 
 void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) {
-  valid_frame_sink_ids_.erase(frame_sink_id);
+  framesink_manager_.InvalidateFrameSinkId(frame_sink_id);
 
   if (using_surface_references()) {
     // Remove any temporary references owned by |frame_sink_id|.
@@ -304,7 +289,7 @@
     const SurfaceId& surface_id = map_entry.first;
     Surface* surface = map_entry.second;
     surface->SatisfyDestructionDependencies(&satisfied_sequences_,
-                                            &valid_frame_sink_ids_);
+                                  framesink_manager_.GetValidFrameSinkIds());
 
     if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) {
       live_surfaces_set.insert(surface_id);
@@ -430,186 +415,36 @@
 void SurfaceManager::RegisterSurfaceFactoryClient(
     const FrameSinkId& frame_sink_id,
     SurfaceFactoryClient* client) {
-  DCHECK(client);
-  DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u);
-
-  clients_[frame_sink_id] = client;
-
-  auto it = frame_sink_source_map_.find(frame_sink_id);
-  if (it != frame_sink_source_map_.end()) {
-    if (it->second.source)
-      client->SetBeginFrameSource(it->second.source);
-  }
+  framesink_manager_.RegisterSurfaceFactoryClient(frame_sink_id, client);
 }
 
 void SurfaceManager::UnregisterSurfaceFactoryClient(
     const FrameSinkId& frame_sink_id) {
-  DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u);
-  auto client_iter = clients_.find(frame_sink_id);
-  DCHECK(client_iter != clients_.end());
-
-  auto source_iter = frame_sink_source_map_.find(frame_sink_id);
-  if (source_iter != frame_sink_source_map_.end()) {
-    if (source_iter->second.source)
-      client_iter->second->SetBeginFrameSource(nullptr);
-    if (!source_iter->second.has_children())
-      frame_sink_source_map_.erase(source_iter);
-  }
-  clients_.erase(client_iter);
+  framesink_manager_.UnregisterSurfaceFactoryClient(frame_sink_id);
 }
 
 void SurfaceManager::RegisterBeginFrameSource(
     BeginFrameSource* source,
     const FrameSinkId& frame_sink_id) {
-  DCHECK(source);
-  DCHECK_EQ(registered_sources_.count(source), 0u);
-  DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u);
-
-  registered_sources_[source] = frame_sink_id;
-  RecursivelyAttachBeginFrameSource(frame_sink_id, source);
+  framesink_manager_.RegisterBeginFrameSource(source, frame_sink_id);
 }
 
 void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) {
-  DCHECK(source);
-  DCHECK_EQ(registered_sources_.count(source), 1u);
-
-  FrameSinkId frame_sink_id = registered_sources_[source];
-  registered_sources_.erase(source);
-
-  if (frame_sink_source_map_.count(frame_sink_id) == 0u)
-    return;
-
-  // TODO(enne): these walks could be done in one step.
-  // Remove this begin frame source from its subtree.
-  RecursivelyDetachBeginFrameSource(frame_sink_id, source);
-  // Then flush every remaining registered source to fix any sources that
-  // became null because of the previous step but that have an alternative.
-  for (auto source_iter : registered_sources_)
-    RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first);
-}
-
-void SurfaceManager::RecursivelyAttachBeginFrameSource(
-    const FrameSinkId& frame_sink_id,
-    BeginFrameSource* source) {
-  FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id];
-  if (!mapping.source) {
-    mapping.source = source;
-    auto client_iter = clients_.find(frame_sink_id);
-    if (client_iter != clients_.end())
-      client_iter->second->SetBeginFrameSource(source);
-  }
-  for (size_t i = 0; i < mapping.children.size(); ++i)
-    RecursivelyAttachBeginFrameSource(mapping.children[i], source);
-}
-
-void SurfaceManager::RecursivelyDetachBeginFrameSource(
-    const FrameSinkId& frame_sink_id,
-    BeginFrameSource* source) {
-  auto iter = frame_sink_source_map_.find(frame_sink_id);
-  if (iter == frame_sink_source_map_.end())
-    return;
-  if (iter->second.source == source) {
-    iter->second.source = nullptr;
-    auto client_iter = clients_.find(frame_sink_id);
-    if (client_iter != clients_.end())
-      client_iter->second->SetBeginFrameSource(nullptr);
-  }
-
-  if (!iter->second.has_children() && !clients_.count(frame_sink_id)) {
-    frame_sink_source_map_.erase(iter);
-    return;
-  }
-
-  std::vector<FrameSinkId>& children = iter->second.children;
-  for (size_t i = 0; i < children.size(); ++i) {
-    RecursivelyDetachBeginFrameSource(children[i], source);
-  }
-}
-
-bool SurfaceManager::ChildContains(
-    const FrameSinkId& child_frame_sink_id,
-    const FrameSinkId& search_frame_sink_id) const {
-  auto iter = frame_sink_source_map_.find(child_frame_sink_id);
-  if (iter == frame_sink_source_map_.end())
-    return false;
-
-  const std::vector<FrameSinkId>& children = iter->second.children;
-  for (size_t i = 0; i < children.size(); ++i) {
-    if (children[i] == search_frame_sink_id)
-      return true;
-    if (ChildContains(children[i], search_frame_sink_id))
-      return true;
-  }
-  return false;
+  framesink_manager_.UnregisterBeginFrameSource(source);
 }
 
 void SurfaceManager::RegisterFrameSinkHierarchy(
     const FrameSinkId& parent_frame_sink_id,
     const FrameSinkId& child_frame_sink_id) {
-  // If it's possible to reach the parent through the child's descendant chain,
-  // then this will create an infinite loop.  Might as well just crash here.
-  CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id));
-
-  std::vector<FrameSinkId>& children =
-      frame_sink_source_map_[parent_frame_sink_id].children;
-  for (size_t i = 0; i < children.size(); ++i)
-    DCHECK(children[i] != child_frame_sink_id);
-  children.push_back(child_frame_sink_id);
-
-  // If the parent has no source, then attaching it to this child will
-  // not change any downstream sources.
-  BeginFrameSource* parent_source =
-      frame_sink_source_map_[parent_frame_sink_id].source;
-  if (!parent_source)
-    return;
-
-  DCHECK_EQ(registered_sources_.count(parent_source), 1u);
-  RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source);
+  framesink_manager_.RegisterFrameSinkHierarchy(parent_frame_sink_id,
+                                                child_frame_sink_id);
 }
 
 void SurfaceManager::UnregisterFrameSinkHierarchy(
     const FrameSinkId& parent_frame_sink_id,
     const FrameSinkId& child_frame_sink_id) {
-  // Deliberately do not check validity of either parent or child FrameSinkId
-  // here.  They were valid during the registration, so were valid at some
-  // point in time.  This makes it possible to invalidate parent and child
-  // FrameSinkIds independently of each other and not have an ordering
-  // dependency  of unregistering the hierarchy first before either of them.
-  DCHECK_EQ(frame_sink_source_map_.count(parent_frame_sink_id), 1u);
-
-  auto iter = frame_sink_source_map_.find(parent_frame_sink_id);
-
-  std::vector<FrameSinkId>& children = iter->second.children;
-  bool found_child = false;
-  for (size_t i = 0; i < children.size(); ++i) {
-    if (children[i] == child_frame_sink_id) {
-      found_child = true;
-      children[i] = children.back();
-      children.resize(children.size() - 1);
-      break;
-    }
-  }
-  DCHECK(found_child);
-
-  // The SurfaceFactoryClient and hierarchy can be registered/unregistered
-  // in either order, so empty frame_sink_source_map entries need to be
-  // checked when removing either clients or relationships.
-  if (!iter->second.has_children() && !clients_.count(parent_frame_sink_id) &&
-      !iter->second.source) {
-    frame_sink_source_map_.erase(iter);
-    return;
-  }
-
-  // If the parent does not have a begin frame source, then disconnecting it
-  // will not change any of its children.
-  BeginFrameSource* parent_source = iter->second.source;
-  if (!parent_source)
-    return;
-
-  // TODO(enne): these walks could be done in one step.
-  RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source);
-  for (auto source_iter : registered_sources_)
-    RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first);
+  framesink_manager_.UnregisterFrameSinkHierarchy(parent_frame_sink_id,
+                                                child_frame_sink_id);
 }
 
 Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) {
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h
index c0c8e76..53998ec5 100644
--- a/cc/surfaces/surface_manager.h
+++ b/cc/surfaces/surface_manager.h
@@ -19,6 +19,7 @@
 #include "base/observer_list.h"
 #include "base/threading/thread_checker.h"
 #include "cc/surfaces/frame_sink_id.h"
+#include "cc/surfaces/framesink_manager.h"
 #include "cc/surfaces/surface_dependency_tracker.h"
 #include "cc/surfaces/surface_id.h"
 #include "cc/surfaces/surface_observer.h"
@@ -175,16 +176,6 @@
 
   using SurfaceIdSet = std::unordered_set<SurfaceId, SurfaceIdHash>;
 
-  void RecursivelyAttachBeginFrameSource(const FrameSinkId& frame_sink_id,
-                                         BeginFrameSource* source);
-  void RecursivelyDetachBeginFrameSource(const FrameSinkId& frame_sink_id,
-                                         BeginFrameSource* source);
-
-  // Returns true if |child namespace| is or has |search_frame_sink_id| as a
-  // child.
-  bool ChildContains(const FrameSinkId& child_frame_sink_id,
-                     const FrameSinkId& search_frame_sink_id) const;
-
   // Garbage collects all destroyed surfaces that aren't live.
   void GarbageCollectSurfaces();
 
@@ -232,6 +223,8 @@
   // Use reference or sequence based lifetime management.
   LifetimeType lifetime_type_;
 
+  FrameSinkManager framesink_manager_;
+
   using SurfaceMap = std::unordered_map<SurfaceId, Surface*, SurfaceIdHash>;
   SurfaceMap surface_map_;
   base::ObserverList<SurfaceObserver> observer_list_;
@@ -246,30 +239,6 @@
   // waited on.
   std::unordered_set<SurfaceSequence, SurfaceSequenceHash> satisfied_sequences_;
 
-  // Set of valid surface ID namespaces. When a namespace is removed from
-  // this set, any remaining sequences with that namespace are considered
-  // satisfied.
-  std::unordered_set<FrameSinkId, FrameSinkIdHash> valid_frame_sink_ids_;
-
-  // Begin frame source routing. Both BeginFrameSource and SurfaceFactoryClient
-  // pointers guaranteed alive by callers until unregistered.
-  struct FrameSinkSourceMapping {
-    FrameSinkSourceMapping();
-    FrameSinkSourceMapping(const FrameSinkSourceMapping& other);
-    ~FrameSinkSourceMapping();
-    bool has_children() const { return !children.empty(); }
-    // The currently assigned begin frame source for this client.
-    BeginFrameSource* source;
-    // This represents a dag of parent -> children mapping.
-    std::vector<FrameSinkId> children;
-  };
-
-  std::unordered_map<FrameSinkId, SurfaceFactoryClient*, FrameSinkIdHash>
-      clients_;
-
-  std::unordered_map<FrameSinkId, FrameSinkSourceMapping, FrameSinkIdHash>
-      frame_sink_source_map_;
-
   // Tracks references from the child surface to parent surface. If there are
   // zero entries in the set for a SurfaceId then nothing is referencing the
   // surface and it can be garbage collected.
@@ -280,11 +249,6 @@
   std::unordered_map<SurfaceId, SurfaceIdSet, SurfaceIdHash>
       parent_to_child_refs_;
 
-  // Set of which sources are registered to which namespace.  Any child
-  // that is implicitly using this namespace must be reachable by the
-  // parent in the dag.
-  std::unordered_map<BeginFrameSource*, FrameSinkId> registered_sources_;
-
   // Root SurfaceId that references display root surfaces. There is no Surface
   // with this id, it's for bookkeeping purposes only.
   const SurfaceId root_surface_id_;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index b4d47f95..d02a67d 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -296,7 +296,7 @@
     "arc/notification/arc_boot_error_notification.h",
     "arc/optin/arc_optin_preference_handler.cc",
     "arc/optin/arc_optin_preference_handler.h",
-    "arc/optin/arc_optin_preference_handler_delegate.h",
+    "arc/optin/arc_optin_preference_handler_observer.h",
     "arc/optin/arc_terms_of_service_default_negotiator.cc",
     "arc/optin/arc_terms_of_service_default_negotiator.h",
     "arc/optin/arc_terms_of_service_negotiator.cc",
diff --git a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
index 5afa9d4e9..263e0ac3 100644
--- a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
+++ b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
@@ -39,6 +39,7 @@
     {
       'target_name': 'edit_dialog',
       'dependencies': [
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
         '<(EXTERNS_GYP):chrome_extensions',
diff --git a/chrome/browser/resources/md_bookmarks/edit_dialog.html b/chrome/browser/resources/md_bookmarks/edit_dialog.html
index 7361e15..0808848 100644
--- a/chrome/browser/resources/md_bookmarks/edit_dialog.html
+++ b/chrome/browser/resources/md_bookmarks/edit_dialog.html
@@ -2,6 +2,7 @@
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
 
diff --git a/chrome/browser/resources/md_bookmarks/edit_dialog.js b/chrome/browser/resources/md_bookmarks/edit_dialog.js
index c2a4873c..6f7bccdd 100644
--- a/chrome/browser/resources/md_bookmarks/edit_dialog.js
+++ b/chrome/browser/resources/md_bookmarks/edit_dialog.js
@@ -5,6 +5,10 @@
 Polymer({
   is: 'bookmarks-edit-dialog',
 
+  behaviors: [
+    Polymer.IronA11yKeysBehavior,
+  ],
+
   properties: {
     /** @private {BookmarkNode} */
     editItem_: Object,
@@ -19,6 +23,10 @@
     urlValue_: String,
   },
 
+  keyBindings: {
+    'enter': 'onSaveButtonTap_',
+  },
+
   /** @param {BookmarkNode} editItem */
   showEditDialog: function(editItem) {
     this.editItem_ = editItem;
@@ -43,7 +51,6 @@
 
   /** @private */
   onSaveButtonTap_: function() {
-    // TODO(tsergeant): Save changes when enter is pressed.
     // TODO(tsergeant): Verify values.
     var edit = {'title': this.titleValue_};
     if (!this.isFolder_)
diff --git a/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc b/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc
index a2d30433..bbe258d4 100644
--- a/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc
+++ b/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc
@@ -8,6 +8,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
+#include "chrome/browser/ui/views/harmony/layout_delegate.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/strings/grit/components_strings.h"
@@ -22,7 +23,6 @@
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_client_view.h"
 
@@ -74,9 +74,14 @@
       callback_(callback),
       open_as_window_checkbox_(nullptr),
       title_tf_(nullptr) {
+  LayoutDelegate* layout_delegate = LayoutDelegate::Get();
+  // Align the contents with the dialog buttons.
   views::BoxLayout* layout = new views::BoxLayout(
-      views::BoxLayout::kHorizontal, views::kButtonHEdgeMarginNew,
-      views::kButtonHEdgeMarginNew, views::kButtonHEdgeMarginNew);
+      views::BoxLayout::kHorizontal,
+      layout_delegate->GetMetric(LayoutDelegate::Metric::DIALOG_BUTTON_MARGIN),
+      layout_delegate->GetMetric(LayoutDelegate::Metric::PANEL_CONTENT_MARGIN),
+      layout_delegate->GetMetric(
+          LayoutDelegate::Metric::UNRELATED_CONTROL_HORIZONTAL_SPACING_LARGE));
   layout->set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
   SetLayoutManager(layout);
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
index 55705ccb9..38f05c54 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -50,7 +50,6 @@
 #include "ui/views/controls/separator.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/grid_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 
 using content::OpenURLParams;
@@ -60,25 +59,36 @@
 namespace {
 
 // Width of the bullet column in BulletedView.
-const int kBulletWidth = 20;
+constexpr int kBulletWidth = 20;
 
 // Size of extension icon in top left of dialog.
-const int kIconSize = 64;
+constexpr int kIconSize = 64;
 
 // The maximum height of the scroll view before it will show a scrollbar.
-const int kScrollViewMaxHeight = 250;
+constexpr int kScrollViewMaxHeight = 250;
 
 // Width of the left column of the dialog when the extension requests
 // permissions.
-const int kPermissionsLeftColumnWidth = 250;
+constexpr int kPermissionsLeftColumnWidth = 250;
 
 // Width of the left column of the dialog when the extension requests no
 // permissions.
-const int kNoPermissionsLeftColumnWidth = 200;
+constexpr int kNoPermissionsLeftColumnWidth = 200;
 
 // Width of the left column for external install prompts. The text is long in
 // this case, so make it wider than normal.
-const int kExternalInstallLeftColumnWidth = 350;
+constexpr int kExternalInstallLeftColumnWidth = 350;
+
+// Get the appropriate indentation for an item if its parent is using bullet
+// points. If the parent is using bullets for its items, then a padding of one
+// unit will make the child item (which has no bullet) look like a sibling of
+// its parent. Therefore increase the indentation by one more unit to show that
+// it is in fact a child item (with no missing bullet) and not a sibling.
+int GetLeftPaddingForBulletedItems(bool parent_bulleted) {
+  return LayoutDelegate::Get()->GetMetric(
+             LayoutDelegate::Metric::RELATED_CONTROL_HORIZONTAL_SPACING) *
+         (parent_bulleted ? 2 : 1);
+}
 
 void AddResourceIcon(const gfx::ImageSkia* skia_image, void* data) {
   views::View* parent = static_cast<views::View*>(data);
@@ -254,17 +264,20 @@
     layout->AddView(user_count);
   }
 
+  LayoutDelegate* layout_delegate = LayoutDelegate::Get();
+  const int vertical_padding = layout_delegate->GetMetric(
+      LayoutDelegate::Metric::RELATED_CONTROL_VERTICAL_SPACING);
   if (prompt_->ShouldShowPermissions()) {
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, vertical_padding);
     layout->StartRow(0, column_set_id);
     layout->AddView(new views::Separator(), 3, 1, views::GridLayout::FILL,
                     views::GridLayout::FILL);
   }
 
-  const int content_width = left_column_width +
-                            LayoutDelegate::Get()->GetMetric(
-                                LayoutDelegate::Metric::PANEL_CONTENT_MARGIN) +
-                            kIconSize;
+  const int content_width =
+      left_column_width +
+      layout_delegate->GetMetric(LayoutDelegate::Metric::PANEL_CONTENT_MARGIN) +
+      kIconSize;
 
   // Create the scrollable view which will contain the permissions and retained
   // files/devices. It will span the full content width.
@@ -281,7 +294,9 @@
       views::GridLayout::USE_PREF, content_width, content_width);
 
   // Pad to the very right of the dialog, so the scrollbar will be on the edge.
-  scrollable_column_set->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
+  const int button_margin =
+      layout_delegate->GetMetric(LayoutDelegate::Metric::DIALOG_BUTTON_MARGIN);
+  scrollable_column_set->AddPaddingColumn(0, button_margin);
 
   layout->StartRow(0, column_set_id);
   scroll_view_ = new views::ScrollView();
@@ -301,7 +316,7 @@
           scroll_layout, rb, column_set_id, content_width,
           ExtensionInstallPrompt::PermissionsType::WITHHELD_PERMISSIONS);
     } else {
-      scroll_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+      scroll_layout->AddPaddingRow(0, vertical_padding);
       scroll_layout->StartRow(0, column_set_id);
       views::Label* permission_label = new views::Label(
           l10n_util::GetStringUTF16(IDS_EXTENSION_NO_SPECIAL_PERMISSIONS));
@@ -313,7 +328,7 @@
   }
 
   if (prompt_->GetRetainedFileCount()) {
-    scroll_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+    scroll_layout->AddPaddingRow(0, vertical_padding);
 
     scroll_layout->StartRow(0, column_set_id);
     views::Label* retained_files_header =
@@ -334,7 +349,7 @@
   }
 
   if (prompt_->GetRetainedDeviceCount()) {
-    scroll_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+    scroll_layout->AddPaddingRow(0, vertical_padding);
 
     scroll_layout->StartRow(0, column_set_id);
     views::Label* retained_devices_header =
@@ -363,9 +378,8 @@
       0,
       std::min(kScrollViewMaxHeight, scrollable->GetPreferredSize().height()));
 
-  dialog_size_ = gfx::Size(
-      content_width + 2 * views::kButtonHEdgeMarginNew,
-      container_->GetPreferredSize().height());
+  dialog_size_ = gfx::Size(content_width + 2 * button_margin,
+                           container_->GetPreferredSize().height());
 
   std::string event_name = ExperienceSamplingEvent::kExtensionInstallDialog;
   event_name.append(
@@ -382,7 +396,9 @@
   if (prompt_->GetPermissionCount(perm_type) == 0)
     return false;
 
-  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+  const int vertical_padding = LayoutDelegate::Get()->GetMetric(
+      LayoutDelegate::Metric::RELATED_CONTROL_VERTICAL_SPACING);
+  layout->AddPaddingRow(0, vertical_padding);
 
   layout->StartRow(0, column_set_id);
   views::Label* permissions_header =
@@ -393,7 +409,7 @@
   layout->AddView(permissions_header);
 
   for (size_t i = 0; i < prompt_->GetPermissionCount(perm_type); ++i) {
-    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+    layout->AddPaddingRow(0, vertical_padding);
     layout->StartRow(0, column_set_id);
     views::Label* permission_label =
         new views::Label(prompt_->GetPermission(i, perm_type));
@@ -421,14 +437,20 @@
     int left_column_width,
     int column_set_id) {
   container_ = new views::View();
-  // This is basically views::GridLayout::CreatePanel, but without a top or
-  // right margin (we effectively get a top margin anyway from the empty dialog
-  // title, and we add an explicit padding column as a right margin below).
+  LayoutDelegate* layout_delegate = LayoutDelegate::Get();
+  const int horizontal_margin =
+      layout_delegate->GetMetric(LayoutDelegate::Metric::DIALOG_BUTTON_MARGIN);
+  const int bottom_margin =
+      layout_delegate->GetMetric(LayoutDelegate::Metric::PANEL_CONTENT_MARGIN);
+
+  // This is views::GridLayout::CreatePanel(), but without a top or right
+  // margin. The empty dialog title will then become the top margin, and a
+  // padding column will be manually added to handle a right margin. This is
+  // done so that the extension icon can be shown on the right of the dialog
+  // title, but on the same y-axis, and the scroll view used to contain other
+  // content can have its scrollbar aligned with the right edge of the dialog.
   views::GridLayout* layout = new views::GridLayout(container_);
-  layout->SetInsets(0, views::kButtonHEdgeMarginNew,
-                    LayoutDelegate::Get()->GetMetric(
-                        LayoutDelegate::Metric::PANEL_CONTENT_MARGIN),
-                    0);
+  layout->SetInsets(0, horizontal_margin, bottom_margin, 0);
   container_->SetLayoutManager(layout);
   AddChildView(container_);
 
@@ -439,14 +461,14 @@
                         0,  // no fixed width
                         left_column_width);
   column_set->AddPaddingColumn(
-      0, LayoutDelegate::Get()->GetMetric(
-             LayoutDelegate::Metric::PANEL_CONTENT_MARGIN));
+      0, layout_delegate->GetMetric(
+             LayoutDelegate::Metric::UNRELATED_CONTROL_HORIZONTAL_SPACING));
   column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING,
                         0,  // no resizing
                         views::GridLayout::USE_PREF,
                         0,  // no fixed width
                         kIconSize);
-  column_set->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
+  column_set->AddPaddingColumn(0, horizontal_margin);
 
   layout->StartRow(0, column_set_id);
   views::Label* title = new views::Label(prompt_->GetDialogTitle(),
@@ -587,25 +609,19 @@
       state_(0) {
   SetLayoutManager(layout_);
   views::ColumnSet* column_set = layout_->AddColumnSet(0);
-  // If the parent is using bullets for its items, then a padding of one unit
-  // will make the child item (which has no bullet) look like a sibling of its
-  // parent. Therefore increase the indentation by one more unit to show that it
-  // is in fact a child item (with no missing bullet) and not a sibling.
-  int padding =
-      views::kRelatedControlHorizontalSpacing * (parent_bulleted ? 2 : 1);
+  const int padding = GetLeftPaddingForBulletedItems(parent_bulleted);
   column_set->AddPaddingColumn(0, padding);
-  column_set->AddColumn(views::GridLayout::LEADING,
-                        views::GridLayout::LEADING,
-                        0,
-                        views::GridLayout::FIXED,
-                        horizontal_space - padding,
+  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
+                        0, views::GridLayout::FIXED, horizontal_space - padding,
                         0);
 }
 
 void ExpandableContainerView::DetailsView::AddDetail(
     const base::string16& detail) {
-  layout_->StartRowWithPadding(0, 0,
-                               0, views::kRelatedControlSmallVerticalSpacing);
+  layout_->StartRowWithPadding(
+      0, 0, 0,
+      LayoutDelegate::Get()->GetMetric(
+          LayoutDelegate::Metric::RELATED_CONTROL_VERTICAL_SPACING_SMALL));
   views::Label* detail_label =
       new views::Label(PrepareForDisplay(detail, false));
   detail_label->SetMultiLine(true);
@@ -654,8 +670,7 @@
     details_view_->AddDetail(details[i]);
 
   // Make sure the link width column is as wide as needed for both Show and
-  // Hide details, so that the arrow doesn't shift horizontally when we
-  // toggle.
+  // Hide details, so that the arrow doesn't shift horizontally when we toggle.
   views::Link* link = new views::Link(
       l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_DETAILS));
   int link_col_width = link->GetPreferredSize().width();
@@ -663,13 +678,9 @@
   link_col_width = std::max(link_col_width, link->GetPreferredSize().width());
 
   column_set = layout->AddColumnSet(++column_set_id);
-  // Padding to the left of the More Details column. If the parent is using
-  // bullets for its items, then a padding of one unit will make the child
-  // item (which has no bullet) look like a sibling of its parent. Therefore
-  // increase the indentation by one more unit to show that it is in fact a
-  // child item (with no missing bullet) and not a sibling.
-  column_set->AddPaddingColumn(
-      0, views::kRelatedControlHorizontalSpacing * (parent_bulleted ? 2 : 1));
+  // Padding to the left of the More Details column.
+  column_set->AddPaddingColumn(0,
+                               GetLeftPaddingForBulletedItems(parent_bulleted));
   // The More Details column.
   column_set->AddColumn(views::GridLayout::LEADING,
                         views::GridLayout::LEADING,
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
index 4f0c3180..74d2a599 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/sync/bubble_sync_promo_delegate.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/harmony/layout_delegate.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 #include "chrome/browser/ui/views/sync/bubble_sync_promo_view.h"
@@ -35,7 +36,6 @@
 #include "ui/views/controls/link.h"
 #include "ui/views/controls/link_listener.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 
 using extensions::Extension;
 
@@ -207,14 +207,19 @@
   //     or a link to configure the keybinding shortcut (if one exists).
   // Extra info can include a promo for signing into sync.
 
-  std::unique_ptr<views::BoxLayout> layout(
-      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
-                           views::kRelatedControlVerticalSpacing));
+  LayoutDelegate* layout_delegate = LayoutDelegate::Get();
+  std::unique_ptr<views::BoxLayout> layout(new views::BoxLayout(
+      views::BoxLayout::kVertical, 0, 0,
+      layout_delegate->GetMetric(
+          LayoutDelegate::Metric::RELATED_CONTROL_VERTICAL_SPACING)));
   layout->set_minimum_cross_axis_size(kRightColumnWidth);
   // Indent by the size of the icon.
   layout->set_inside_border_insets(gfx::Insets(
-      0, GetIconSize().width() + views::kUnrelatedControlHorizontalSpacing, 0,
-      0));
+      0,
+      GetIconSize().width() +
+          layout_delegate->GetMetric(
+              LayoutDelegate::Metric::UNRELATED_CONTROL_HORIZONTAL_SPACING),
+      0, 0));
   layout->set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
   SetLayoutManager(layout.release());
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
index 19a26fd..4a80cf6 100644
--- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
@@ -23,7 +23,6 @@
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
@@ -169,11 +168,13 @@
     : dialog_(dialog_view),
       triggered_by_extension_(triggered_by_extension),
       report_abuse_checkbox_(nullptr) {
+  LayoutDelegate* layout_delegate = LayoutDelegate::Get();
   SetLayoutManager(new views::BoxLayout(
-      views::BoxLayout::kHorizontal, views::kButtonHEdgeMarginNew,
-      LayoutDelegate::Get()->GetMetric(
-          LayoutDelegate::Metric::PANEL_CONTENT_MARGIN),
-      views::kRelatedControlHorizontalSpacing));
+      views::BoxLayout::kHorizontal,
+      layout_delegate->GetMetric(LayoutDelegate::Metric::DIALOG_BUTTON_MARGIN),
+      layout_delegate->GetMetric(LayoutDelegate::Metric::PANEL_CONTENT_MARGIN),
+      layout_delegate->GetMetric(
+          LayoutDelegate::Metric::RELATED_CONTROL_HORIZONTAL_SPACING)));
 
   icon_ = new views::ImageView();
   DCHECK_GE(image->width(), kIconSize);
@@ -212,7 +213,8 @@
 bool ExtensionUninstallDialogDelegateView::GetExtraViewPadding(int* padding) {
   // We want a little more padding between the "report abuse" checkbox and the
   // buttons.
-  *padding = views::kUnrelatedControlLargeHorizontalSpacing;
+  *padding = LayoutDelegate::Get()->GetMetric(
+      LayoutDelegate::Metric::UNRELATED_CONTROL_HORIZONTAL_SPACING_LARGE);
   return true;
 }
 
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
index 19ad08d..a41e059 100644
--- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
+++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -27,7 +27,6 @@
 #include "ui/views/controls/separator.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/grid_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_client_view.h"
@@ -112,6 +111,9 @@
                      0);
 
   // Message text.
+  LayoutDelegate* layout_delegate = LayoutDelegate::Get();
+  const int vertical_padding = layout_delegate->GetMetric(
+      LayoutDelegate::Metric::RELATED_CONTROL_VERTICAL_SPACING);
   views::Label* subtext = new views::Label(controller_->GetSubtext());
   subtext->SetMultiLine(true);
   subtext->SetHorizontalAlignment(gfx::ALIGN_LEFT);
@@ -120,16 +122,16 @@
       subtext, 1, 1,
       views::GridLayout::FILL, views::GridLayout::LEADING,
       dialog_content_width, subtext->GetHeightForWidth(dialog_content_width));
-  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+  layout->AddPaddingRow(0, vertical_padding);
 
   // Scrollable area for checkboxes.
+  const int small_vertical_padding = LayoutDelegate::Get()->GetMetric(
+      LayoutDelegate::Metric::RELATED_CONTROL_VERTICAL_SPACING_SMALL);
   ScrollableView* scroll_container = new ScrollableView();
   scroll_container->SetLayoutManager(new views::BoxLayout(
-      views::BoxLayout::kVertical, 0, 0,
-      views::kRelatedControlSmallVerticalSpacing));
+      views::BoxLayout::kVertical, 0, 0, small_vertical_padding));
   scroll_container->SetBorder(
-      views::CreateEmptyBorder(views::kRelatedControlVerticalSpacing, 0,
-                               views::kRelatedControlVerticalSpacing, 0));
+      views::CreateEmptyBorder(vertical_padding, 0, vertical_padding, 0));
 
   std::vector<base::string16> section_headers =
       controller_->GetSectionHeaders();
@@ -146,19 +148,17 @@
       header->SetMultiLine(true);
       header->SetHorizontalAlignment(gfx::ALIGN_LEFT);
       header->SetBorder(views::CreateEmptyBorder(
-          views::kRelatedControlVerticalSpacing,
-          LayoutDelegate::Get()->GetMetric(
+          vertical_padding,
+          layout_delegate->GetMetric(
               LayoutDelegate::Metric::PANEL_CONTENT_MARGIN),
-          views::kRelatedControlVerticalSpacing, 0));
+          vertical_padding, 0));
       scroll_container->AddChildView(header);
     }
 
     // Checkboxes.
     MediaGalleriesDialogController::Entries::const_iterator iter;
     for (iter = entries.begin(); iter != entries.end(); ++iter) {
-      int spacing = 0;
-      if (iter + 1 == entries.end())
-        spacing = views::kRelatedControlSmallVerticalSpacing;
+      int spacing = iter + 1 == entries.end() ? small_vertical_padding : 0;
       AddOrUpdateGallery(*iter, scroll_container, spacing);
     }
   }
@@ -170,8 +170,7 @@
   views::ScrollView* scroll_view =
       views::ScrollView::CreateScrollViewWithBorder();
   scroll_view->SetContents(scroll_container);
-  layout->StartRowWithPadding(1, column_set_id,
-                              0, views::kRelatedControlVerticalSpacing);
+  layout->StartRowWithPadding(1, column_set_id, 0, vertical_padding);
   layout->AddView(scroll_view, 1, 1,
                   views::GridLayout::FILL, views::GridLayout::FILL,
                   dialog_content_width, kScrollAreaHeight);
diff --git a/chrome/browser/ui/views/extensions/media_gallery_checkbox_view.cc b/chrome/browser/ui/views/extensions/media_gallery_checkbox_view.cc
index 9b2fb073..0f36191 100644
--- a/chrome/browser/ui/views/extensions/media_gallery_checkbox_view.cc
+++ b/chrome/browser/ui/views/extensions/media_gallery_checkbox_view.cc
@@ -14,7 +14,6 @@
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 
 namespace {
 
@@ -31,8 +30,9 @@
   DCHECK(button_listener != NULL);
   SetLayoutManager(
       new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
-  const int border_horiz_margin = LayoutDelegate::Get()->GetMetric(
-      LayoutDelegate::Metric::PANEL_CONTENT_MARGIN);
+  LayoutDelegate* layout_delegate = LayoutDelegate::Get();
+  const int border_horiz_margin =
+      layout_delegate->GetMetric(LayoutDelegate::Metric::PANEL_CONTENT_MARGIN);
   SetBorder(views::CreateEmptyBorder(
       0, border_horiz_margin, trailing_vertical_space, border_horiz_margin));
   if (menu_controller)
@@ -55,7 +55,10 @@
   secondary_text_->SetElideBehavior(gfx::ELIDE_HEAD);
   secondary_text_->SetTooltipText(tooltip_text);
   secondary_text_->SetBorder(views::CreateEmptyBorder(
-      0, views::kRelatedControlSmallHorizontalSpacing, 0, 0));
+      0,
+      layout_delegate->GetMetric(
+          LayoutDelegate::Metric::RELATED_CONTROL_HORIZONTAL_SPACING_SMALL),
+      0, 0));
 
   AddChildView(checkbox_);
   AddChildView(secondary_text_);
diff --git a/chrome/browser/ui/views/harmony/harmony_layout_delegate.cc b/chrome/browser/ui/views/harmony/harmony_layout_delegate.cc
index a64f6df..57f9099 100644
--- a/chrome/browser/ui/views/harmony/harmony_layout_delegate.cc
+++ b/chrome/browser/ui/views/harmony/harmony_layout_delegate.cc
@@ -40,8 +40,12 @@
       return kHarmonyLayoutUnit / 2;
     case Metric::RELATED_CONTROL_HORIZONTAL_SPACING:
       return kHarmonyLayoutUnit;
+    case Metric::RELATED_CONTROL_HORIZONTAL_SPACING_SMALL:
+      return kHarmonyLayoutUnit;
     case Metric::RELATED_CONTROL_VERTICAL_SPACING:
       return kHarmonyLayoutUnit / 2;
+    case Metric::RELATED_CONTROL_VERTICAL_SPACING_SMALL:
+      return kHarmonyLayoutUnit / 2;
     case Metric::RELATED_LABEL_HORIZONTAL_SPACING:
       return kHarmonyLayoutUnit;
     case Metric::SUBSECTION_HORIZONTAL_INDENT:
diff --git a/chrome/browser/ui/views/harmony/layout_delegate.cc b/chrome/browser/ui/views/harmony/layout_delegate.cc
index 9f5dad1..9967dcb 100644
--- a/chrome/browser/ui/views/harmony/layout_delegate.cc
+++ b/chrome/browser/ui/views/harmony/layout_delegate.cc
@@ -49,9 +49,13 @@
     case Metric::RELATED_CONTROL_HORIZONTAL_SPACING:
       return ChromeViewsDelegate::GetDefaultDistanceMetric(
           views::DistanceMetric::RELATED_CONTROL_HORIZONTAL);
+    case Metric::RELATED_CONTROL_HORIZONTAL_SPACING_SMALL:
+      return views::kRelatedControlSmallVerticalSpacing;
     case Metric::RELATED_CONTROL_VERTICAL_SPACING:
       return ChromeViewsDelegate::GetDefaultDistanceMetric(
           views::DistanceMetric::RELATED_CONTROL_VERTICAL);
+    case Metric::RELATED_CONTROL_VERTICAL_SPACING_SMALL:
+      return views::kRelatedControlSmallVerticalSpacing;
     case Metric::RELATED_LABEL_HORIZONTAL_SPACING:
       return views::kItemLabelSpacing;
     case Metric::SUBSECTION_HORIZONTAL_INDENT:
diff --git a/chrome/browser/ui/views/harmony/layout_delegate.h b/chrome/browser/ui/views/harmony/layout_delegate.h
index d7d6252..9cfbd56 100644
--- a/chrome/browser/ui/views/harmony/layout_delegate.h
+++ b/chrome/browser/ui/views/harmony/layout_delegate.h
@@ -40,8 +40,13 @@
     RELATED_BUTTON_HORIZONTAL_SPACING,
     // Horizontal spacing between other controls that are logically related.
     RELATED_CONTROL_HORIZONTAL_SPACING,
+    // Smaller horizontal spacing between other controls that are logically
+    // related.
+    RELATED_CONTROL_HORIZONTAL_SPACING_SMALL,
     // Vertical spacing between controls that are logically related.
     RELATED_CONTROL_VERTICAL_SPACING,
+    // Smaller vertical spacing between controls that are logically related.
+    RELATED_CONTROL_VERTICAL_SPACING_SMALL,
     // Horizontal spacing between an item such as an icon or checkbox and a
     // label related to it.
     RELATED_LABEL_HORIZONTAL_SPACING,
diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc
index 1f540add..53bd332d 100644
--- a/chrome/renderer/content_settings_observer.cc
+++ b/chrome/renderer/content_settings_observer.cc
@@ -213,7 +213,7 @@
   // Reload if we are the main frame.
   blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
   if (!frame->parent())
-    frame->reload(blink::WebFrameLoadType::ReloadMainResource);
+    frame->reload(blink::WebFrameLoadType::Reload);
 }
 
 void ContentSettingsObserver::OnInsecureContentRendererRequest(
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index b55941f..0c91b1c 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -314,7 +314,7 @@
 void NetErrorHelper::ReloadPage(bool bypass_cache) {
   render_frame()->GetWebFrame()->reload(
       bypass_cache ? blink::WebFrameLoadType::ReloadBypassingCache
-                   : blink::WebFrameLoadType::ReloadMainResource);
+                   : blink::WebFrameLoadType::Reload);
 }
 
 void NetErrorHelper::LoadPageFromCache(const GURL& page_url) {
diff --git a/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js b/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js
index 5bc4269..3eb9a2d 100644
--- a/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js
+++ b/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js
@@ -55,4 +55,12 @@
     assertEquals(undefined, lastUpdate.edit.url);
     assertEquals('Awesome websites', lastUpdate.edit.title);
   });
+
+  test('pressing enter saves and closes dialog', function() {
+    var item = createItem('1', {url: 'http://www.example.com'});
+    dialog.showEditDialog(item);
+
+    MockInteractions.pressEnter(dialog.$.url);
+    assertFalse(dialog.$.dialog.open);
+  });
 });
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index b585005d..86b774e33 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -32,6 +32,7 @@
     "intent_helper/activity_icon_loader.h",
     "intent_helper/arc_intent_helper_bridge.cc",
     "intent_helper/arc_intent_helper_bridge.h",
+    "intent_helper/arc_intent_helper_observer.h",
     "intent_helper/font_size_util.cc",
     "intent_helper/font_size_util.h",
     "intent_helper/intent_constants.cc",
diff --git a/components/arc/common/input.mojom b/components/arc/common/input.mojom
deleted file mode 100644
index 17ecc43..0000000
--- a/components/arc/common/input.mojom
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module arc.mojom;
-
-interface InputInstance {
-  // Registers a virtual input device on the container side.
-  // |name| is the device name, like "Chrome OS Keyboard".
-  // |device_type| is the device type, like "keyboard".
-  // The virtual device will be reading 'struct input_event's from |fd|.  The
-  // ownership of |fd| will be transferred to the receiver, so the sender must
-  // not close it.
-  RegisterInputDevice@0(string name,
-                        string device_type,
-                        handle fd);
-};
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 953d839..3460c75 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -718,7 +718,7 @@
   switch (navigation_type) {
     case FrameMsg_Navigate_Type::RELOAD:
     case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
-      return WebFrameLoadType::ReloadMainResource;
+      return WebFrameLoadType::Reload;
 
     case FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE:
       return WebFrameLoadType::ReloadBypassingCache;
@@ -2297,7 +2297,7 @@
 
 void RenderFrameImpl::OnReload(bool bypass_cache) {
   frame_->reload(bypass_cache ? WebFrameLoadType::ReloadBypassingCache
-                              : WebFrameLoadType::ReloadMainResource);
+                              : WebFrameLoadType::Reload);
 }
 
 void RenderFrameImpl::OnReloadLoFiImages() {
@@ -6452,7 +6452,6 @@
     const GURL base_url = params.base_url_for_data_url.is_empty() ?
         params.url : params.base_url_for_data_url;
     bool replace = load_type == WebFrameLoadType::ReloadBypassingCache ||
-                   load_type == WebFrameLoadType::ReloadMainResource ||
                    load_type == WebFrameLoadType::Reload;
 
     frame->loadData(
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
index 049f2df..139ed88 100644
--- a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -112,8 +112,9 @@
   TRACE_EVENT1("v8", "LocalWindowProxy::initialize", "isMainWindow",
                frame()->isMainFrame());
   SCOPED_BLINK_UMA_HISTOGRAM_TIMER(
-      frame()->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy"
-                             : "Blink.Binding.InitializeNonMainWindowProxy");
+      frame()->isMainFrame()
+          ? "Blink.Binding.InitializeMainLocalWindowProxy"
+          : "Blink.Binding.InitializeNonMainLocalWindowProxy");
 
   ScriptForbiddenScope::AllowUserAgentScript allowScript;
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
index b484ebeb..c60566d5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
@@ -69,8 +69,9 @@
   TRACE_EVENT1("v8", "RemoteWindowProxy::initialize", "isMainWindow",
                frame()->isMainFrame());
   SCOPED_BLINK_UMA_HISTOGRAM_TIMER(
-      frame()->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy"
-                             : "Blink.Binding.InitializeNonMainWindowProxy");
+      frame()->isMainFrame()
+          ? "Blink.Binding.InitializeMainRemoteWindowProxy"
+          : "Blink.Binding.InitializeNonMainRemoteWindowProxy");
 
   ScriptForbiddenScope::AllowUserAgentScript allowScript;
 
diff --git a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
index ccdbb47..5baf4c07 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
@@ -79,6 +79,8 @@
 
   {% endfor %}
  protected:
+  // Constructor and destructor are protected so that only the parent class ComputedStyle
+  // can instantiate this class.
   ALWAYS_INLINE ComputedStyleBase() :
   {% for field in fields %}
       {{field.name}}(static_cast<unsigned>({{field.default_value}})){{print_if(not loop.last, ',')}}
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 74aa3fb..b35fda0 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -1864,9 +1864,9 @@
     case CSSPropertyFontWeight:
       return CSSPropertyFontUtils::consumeFontWeight(m_range);
     case CSSPropertyCounterIncrement:
+      return consumeCounter(m_range, 1);
     case CSSPropertyCounterReset:
-      return consumeCounter(m_range,
-                            property == CSSPropertyCounterIncrement ? 1 : 0);
+      return consumeCounter(m_range, 0);
     case CSSPropertyMaxWidth:
     case CSSPropertyMaxHeight:
       return CSSPropertyLengthUtils::consumeMaxWidthOrHeight(
diff --git a/third_party/WebKit/Source/core/frame/BUILD.gn b/third_party/WebKit/Source/core/frame/BUILD.gn
index 2e49aeb..16ad882 100644
--- a/third_party/WebKit/Source/core/frame/BUILD.gn
+++ b/third_party/WebKit/Source/core/frame/BUILD.gn
@@ -38,6 +38,8 @@
     "FrameConsole.h",
     "FrameHost.cpp",
     "FrameHost.h",
+    "FrameLifecycle.cpp",
+    "FrameLifecycle.h",
     "FrameOwner.h",
     "FrameSerializer.cpp",
     "FrameSerializer.h",
diff --git a/third_party/WebKit/Source/core/frame/Frame.cpp b/third_party/WebKit/Source/core/frame/Frame.cpp
index a3d935d..23bd1e6 100644
--- a/third_party/WebKit/Source/core/frame/Frame.cpp
+++ b/third_party/WebKit/Source/core/frame/Frame.cpp
@@ -58,7 +58,8 @@
 
 Frame::~Frame() {
   InstanceCounters::decrementCounter(InstanceCounters::FrameCounter);
-  ASSERT(!m_owner);
+  DCHECK(!m_owner);
+  DCHECK_EQ(m_lifecycle.state(), FrameLifecycle::Detached);
 }
 
 DEFINE_TRACE(Frame) {
@@ -71,7 +72,10 @@
 }
 
 void Frame::detach(FrameDetachType type) {
-  ASSERT(m_client);
+  DCHECK(m_client);
+  // By the time this method is called, the subclasses should have already
+  // advanced to the Detaching state.
+  DCHECK_EQ(m_lifecycle.state(), FrameLifecycle::Detaching);
   m_client->setOpener(0);
   disconnectOwnerElement();
   // After this, we must no longer talk to the client since this clears
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h
index e84cdab..f60c6ca 100644
--- a/third_party/WebKit/Source/core/frame/Frame.h
+++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -30,6 +30,7 @@
 #define Frame_h
 
 #include "core/CoreExport.h"
+#include "core/frame/FrameLifecycle.h"
 #include "core/frame/FrameTypes.h"
 #include "core/loader/FrameLoaderTypes.h"
 #include "core/page/FrameTree.h"
@@ -149,7 +150,9 @@
   void setDocumentHasReceivedUserGesture();
   bool hasReceivedUserGesture() const { return m_hasReceivedUserGesture; }
 
-  bool isDetaching() const { return m_isDetaching; }
+  bool isAttached() const {
+    return m_lifecycle.state() == FrameLifecycle::Attached;
+  }
 
   // Tests whether the feature-policy controlled feature is enabled by policy in
   // the given frame.
@@ -165,13 +168,15 @@
   Member<DOMWindow> m_domWindow;
 
   bool m_hasReceivedUserGesture = false;
-  bool m_isDetaching = false;
+
+  FrameLifecycle m_lifecycle;
 
  private:
   bool canNavigateWithoutFramebusting(const Frame&, String& errorReason);
 
   Member<FrameClient> m_client;
   const Member<WindowProxyManager> m_windowProxyManager;
+  // TODO(sashab): Investigate if this can be represented with m_lifecycle.
   bool m_isLoading;
 };
 
diff --git a/third_party/WebKit/Source/core/frame/FrameLifecycle.cpp b/third_party/WebKit/Source/core/frame/FrameLifecycle.cpp
new file mode 100644
index 0000000..77b977e
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/FrameLifecycle.cpp
@@ -0,0 +1,29 @@
+// Copyright 2017 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/frame/FrameLifecycle.h"
+
+#include "wtf/Assertions.h"
+
+namespace blink {
+
+FrameLifecycle::FrameLifecycle() : m_state(Attached) {}
+
+void FrameLifecycle::advanceTo(State state) {
+  switch (state) {
+    case Attached:
+    case Detached:
+      // Normally, only allow state to move forward.
+      DCHECK_GT(state, m_state);
+      break;
+    case Detaching:
+      // We can go from Detaching to Detaching since the detach() method can be
+      // re-entered.
+      DCHECK_GE(state, m_state);
+      break;
+  }
+  m_state = state;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/FrameLifecycle.h b/third_party/WebKit/Source/core/frame/FrameLifecycle.h
new file mode 100644
index 0000000..e75b634
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/FrameLifecycle.h
@@ -0,0 +1,33 @@
+// Copyright 2017 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 FrameLifecycle_h
+#define FrameLifecycle_h
+
+#include "wtf/Noncopyable.h"
+
+namespace blink {
+
+class FrameLifecycle {
+  WTF_MAKE_NONCOPYABLE(FrameLifecycle);
+
+ public:
+  enum State {
+    Attached,
+    Detaching,
+    Detached,
+  };
+
+  FrameLifecycle();
+
+  State state() const { return m_state; }
+  void advanceTo(State);
+
+ private:
+  State m_state;
+};
+
+}  // namespace blink
+
+#endif  // FrameLifecycle_h
diff --git a/third_party/WebKit/Source/core/frame/History.cpp b/third_party/WebKit/Source/core/frame/History.cpp
index 59c101e..43f27ac 100644
--- a/third_party/WebKit/Source/core/frame/History.cpp
+++ b/third_party/WebKit/Source/core/frame/History.cpp
@@ -152,8 +152,7 @@
     // Otherwise, navigation happens on the root frame.
     // This behavior is designed in the following spec.
     // https://html.spec.whatwg.org/multipage/browsers.html#dom-history-go
-    frame()->reload(FrameLoadTypeReloadMainResource,
-                    ClientRedirectPolicy::ClientRedirect);
+    frame()->reload(FrameLoadTypeReload, ClientRedirectPolicy::ClientRedirect);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index 69f80ab7..995caa83 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -385,15 +385,15 @@
     request.setClientRedirect(clientRedirectPolicy);
     m_loader.load(request, loadType);
   } else {
-    DCHECK_EQ(FrameLoadTypeReloadMainResource, loadType);
+    DCHECK_EQ(FrameLoadTypeReload, loadType);
     m_navigationScheduler->scheduleReload();
   }
 }
 
 void LocalFrame::detach(FrameDetachType type) {
   // Note that detach() can be re-entered, so it's not possible to
-  // DCHECK(!m_isDetaching) here.
-  m_isDetaching = true;
+  // DCHECK(isAttached()) here.
+  m_lifecycle.advanceTo(FrameLifecycle::Detaching);
 
   if (isLocalRoot())
     m_performanceMonitor->shutdown();
@@ -452,6 +452,7 @@
   m_supplements.clear();
   m_frameScheduler.reset();
   WeakIdentifierMap<LocalFrame>::notifyObjectDestroyed(this);
+  m_lifecycle.advanceTo(FrameLifecycle::Detached);
 }
 
 bool LocalFrame::prepareForCommit() {
diff --git a/third_party/WebKit/Source/core/frame/Location.cpp b/third_party/WebKit/Source/core/frame/Location.cpp
index f67dc7b..7dca60cc 100644
--- a/third_party/WebKit/Source/core/frame/Location.cpp
+++ b/third_party/WebKit/Source/core/frame/Location.cpp
@@ -218,7 +218,7 @@
     return;
   if (document()->url().protocolIsJavaScript())
     return;
-  m_domWindow->frame()->reload(FrameLoadTypeReloadMainResource,
+  m_domWindow->frame()->reload(FrameLoadTypeReload,
                                ClientRedirectPolicy::ClientRedirect);
 }
 
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
index e8644352..76ec00e 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -81,7 +81,7 @@
 }
 
 void RemoteFrame::detach(FrameDetachType type) {
-  m_isDetaching = true;
+  m_lifecycle.advanceTo(FrameLifecycle::Detaching);
 
   PluginScriptForbiddenScope forbidPluginDestructorScripting;
   detachChildren();
@@ -104,6 +104,7 @@
   if (m_webLayer)
     setWebLayer(nullptr);
   Frame::detach(type);
+  m_lifecycle.advanceTo(FrameLifecycle::Detached);
 }
 
 bool RemoteFrame::prepareForCommit() {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
index 6c47a57..a9a27de 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -449,7 +449,7 @@
   m_reloading = true;
   m_inspectedFrames->root()->reload(optionalBypassCache.fromMaybe(false)
                                         ? FrameLoadTypeReloadBypassingCache
-                                        : FrameLoadTypeReloadMainResource,
+                                        : FrameLoadTypeReload,
                                     ClientRedirectPolicy::NotClientRedirect);
   return Response::OK();
 }
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp
index f52868e..b84d3ec 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -867,16 +867,6 @@
   m_frameView->frame().selection().commitAppearanceIfNeeded(*this);
 }
 
-LayoutObject* LayoutView::selectionStart() {
-  commitPendingSelection();
-  return m_selectionStart;
-}
-
-LayoutObject* LayoutView::selectionEnd() {
-  commitPendingSelection();
-  return m_selectionEnd;
-}
-
 void LayoutView::selectionStartEnd(int& startPos, int& endPos) {
   commitPendingSelection();
   startPos = m_selectionStartPos;
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.h b/third_party/WebKit/Source/core/layout/LayoutView.h
index fccdf4bd..3192c97e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.h
+++ b/third_party/WebKit/Source/core/layout/LayoutView.h
@@ -159,8 +159,6 @@
   void clearSelection();
   bool hasPendingSelection() const;
   void commitPendingSelection();
-  LayoutObject* selectionStart();
-  LayoutObject* selectionEnd();
   IntRect selectionBounds();
   void selectionStartEnd(int& startPos, int& endPos);
   void invalidatePaintForSelection();
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index 4aa9e4a6..6d117db 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -254,8 +254,6 @@
                  ? WebCachePolicy::ReturnCacheDataDontLoad
                  : WebCachePolicy::ReturnCacheDataElseLoad;
     case FrameLoadTypeReload:
-      return WebCachePolicy::ValidatingCacheData;
-    case FrameLoadTypeReloadMainResource:
       return resourceType == ResourceType::kIsMainResource
                  ? WebCachePolicy::ValidatingCacheData
                  : WebCachePolicy::UseProtocolCachePolicy;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
index 008bad6..0f7085a1 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -568,8 +568,8 @@
             fetchContext->resourceRequestCachePolicy(
                 postRequest, Resource::MainResource, FetchRequest::NoDefer));
 
-  // FrameLoadTypeReloadMainResource
-  document->loader()->setLoadType(FrameLoadTypeReloadMainResource);
+  // FrameLoadTypeReload
+  document->loader()->setLoadType(FrameLoadTypeReload);
   EXPECT_EQ(WebCachePolicy::ValidatingCacheData,
             fetchContext->resourceRequestCachePolicy(
                 request, Resource::MainResource, FetchRequest::NoDefer));
@@ -593,7 +593,7 @@
 
   // Child frame as part of reload
   document->loader()->setLoadType(FrameLoadTypeReload);
-  EXPECT_EQ(WebCachePolicy::ValidatingCacheData,
+  EXPECT_EQ(WebCachePolicy::UseProtocolCachePolicy,
             childFetchContext->resourceRequestCachePolicy(
                 request, Resource::MainResource, FetchRequest::NoDefer));
 
@@ -726,7 +726,7 @@
   EXPECT_EQ("on", resourceRequest.httpHeaderField("Save-Data"));
 
   settings->setDataSaverEnabled(false);
-  document->loader()->setLoadType(FrameLoadTypeReloadMainResource);
+  document->loader()->setLoadType(FrameLoadTypeReload);
   fetchContext->addAdditionalRequestHeaders(resourceRequest, FetchMainResource);
   EXPECT_EQ(String(), resourceRequest.httpHeaderField("Save-Data"));
 
@@ -735,7 +735,7 @@
   EXPECT_EQ("on", resourceRequest.httpHeaderField("Save-Data"));
 
   settings->setDataSaverEnabled(false);
-  document->loader()->setLoadType(FrameLoadTypeReloadMainResource);
+  document->loader()->setLoadType(FrameLoadTypeReload);
   fetchContext->addAdditionalRequestHeaders(resourceRequest, FetchMainResource);
   EXPECT_EQ(String(), resourceRequest.httpHeaderField("Save-Data"));
 }
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index f108a6c..597cb1b1 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -114,7 +114,6 @@
 
 bool isReloadLoadType(FrameLoadType type) {
   return type == FrameLoadTypeReload ||
-         type == FrameLoadTypeReloadMainResource ||
          type == FrameLoadTypeReloadBypassingCache;
 }
 
@@ -578,7 +577,7 @@
     return false;
 
   // Don't notify if the frame is being detached.
-  if (frame->isDetaching())
+  if (!frame->isAttached())
     return false;
 
   return true;
@@ -852,7 +851,7 @@
     if (request.resourceRequest().httpMethod() == HTTPNames::POST)
       return FrameLoadTypeStandard;
     if (!request.originDocument())
-      return FrameLoadTypeReloadMainResource;
+      return FrameLoadTypeReload;
     return FrameLoadTypeReplaceCurrentItem;
   }
 
diff --git a/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h b/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h
index 14eab13..3cafa56 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h
+++ b/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h
@@ -36,7 +36,6 @@
   FrameLoadTypeStandard,
   FrameLoadTypeBackForward,
   FrameLoadTypeReload,
-  FrameLoadTypeReloadMainResource,
   FrameLoadTypeReplaceCurrentItem,
   FrameLoadTypeInitialInChildFrame,
   FrameLoadTypeInitialHistoryLoad,
diff --git a/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp b/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
index f71c9d7..082c4a8b 100644
--- a/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
+++ b/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
@@ -271,7 +271,7 @@
     request.setClientRedirect(ClientRedirectPolicy::ClientRedirect);
     maybeLogScheduledNavigationClobber(ScheduledNavigationType::ScheduledReload,
                                        frame);
-    frame->loader().load(request, FrameLoadTypeReloadMainResource);
+    frame->loader().load(request, FrameLoadTypeReload);
   }
 
  private:
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp
index 0a37141..b3d6d6d 100644
--- a/third_party/WebKit/Source/core/page/Page.cpp
+++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -648,7 +648,10 @@
 void Page::willBeDestroyed() {
   Frame* mainFrame = m_mainFrame;
 
-  mainFrame->detach(FrameDetachType::Remove);
+  // TODO(sashab): Remove this check, the call to detach() here should always
+  // work.
+  if (mainFrame->isAttached())
+    mainFrame->detach(FrameDetachType::Remove);
 
   ASSERT(allPages().contains(this));
   allPages().erase(this);
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 04cfc281..62264b0 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -2625,9 +2625,9 @@
   if (!frame())
     return;
 
-  frame()->reload(bypassCache ? FrameLoadTypeReloadBypassingCache
-                              : FrameLoadTypeReloadMainResource,
-                  ClientRedirectPolicy::NotClientRedirect);
+  frame()->reload(
+      bypassCache ? FrameLoadTypeReloadBypassingCache : FrameLoadTypeReload,
+      ClientRedirectPolicy::NotClientRedirect);
 }
 
 Node* Internals::visibleSelectionAnchorNode() {
diff --git a/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp b/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp
index 04d0cda1..14793505 100644
--- a/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp
+++ b/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp
@@ -69,8 +69,7 @@
     return;
   Page::refreshPlugins();
   if (reload) {
-    frame()->reload(FrameLoadTypeReloadMainResource,
-                    ClientRedirectPolicy::ClientRedirect);
+    frame()->reload(FrameLoadTypeReload, ClientRedirectPolicy::ClientRedirect);
   }
 }
 
diff --git a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
index 3235300..a640b87 100644
--- a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
+++ b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
@@ -842,8 +842,6 @@
 STATIC_ASSERT_ENUM(WebFrameLoadType::Standard, FrameLoadTypeStandard);
 STATIC_ASSERT_ENUM(WebFrameLoadType::BackForward, FrameLoadTypeBackForward);
 STATIC_ASSERT_ENUM(WebFrameLoadType::Reload, FrameLoadTypeReload);
-STATIC_ASSERT_ENUM(WebFrameLoadType::ReloadMainResource,
-                   FrameLoadTypeReloadMainResource);
 STATIC_ASSERT_ENUM(WebFrameLoadType::ReplaceCurrentItem,
                    FrameLoadTypeReplaceCurrentItem);
 STATIC_ASSERT_ENUM(WebFrameLoadType::InitialInChildFrame,
diff --git a/third_party/WebKit/Source/web/WebFrame.cpp b/third_party/WebKit/Source/web/WebFrame.cpp
index 96c4787..372c36a 100644
--- a/third_party/WebKit/Source/web/WebFrame.cpp
+++ b/third_party/WebKit/Source/web/WebFrame.cpp
@@ -6,7 +6,6 @@
 
 #include "bindings/core/v8/WindowProxyManager.h"
 #include "core/HTMLNames.h"
-#include "core/frame/FrameHost.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/RemoteFrame.h"
@@ -30,7 +29,7 @@
 bool WebFrame::swap(WebFrame* frame) {
   using std::swap;
   Frame* oldFrame = toImplBase()->frame();
-  if (oldFrame->isDetaching())
+  if (!oldFrame->isAttached())
     return false;
 
   // Unload the current Document in this frame: this calls unload handlers,
@@ -68,7 +67,7 @@
   }
   m_openedFrameTracker->transferTo(frame);
 
-  FrameHost* host = oldFrame->host();
+  Page* page = oldFrame->page();
   AtomicString name = oldFrame->tree().name();
   FrameOwner* owner = oldFrame->owner();
 
@@ -105,7 +104,7 @@
                            TRACE_EVENT_SCOPE_THREAD, "frame", &localFrame);
     }
   } else {
-    toWebRemoteFrameImpl(frame)->initializeCoreFrame(host, owner, name);
+    toWebRemoteFrameImpl(frame)->initializeCoreFrame(*page, owner, name);
   }
 
   if (m_parent && oldFrame->hasReceivedUserGesture())
diff --git a/third_party/WebKit/Source/web/WebFrameImplBase.h b/third_party/WebKit/Source/web/WebFrameImplBase.h
index 9b5367c..8134801 100644
--- a/third_party/WebKit/Source/web/WebFrameImplBase.h
+++ b/third_party/WebKit/Source/web/WebFrameImplBase.h
@@ -12,8 +12,8 @@
 namespace blink {
 
 class Frame;
-class FrameHost;
 class FrameOwner;
+class Page;
 
 // WebFrameImplBase exists to avoid the diamond inheritance problem:
 // - The public interfaces WebLocalFrame/WebRemoteFrame extend WebFrame.
@@ -33,7 +33,7 @@
  public:
   virtual ~WebFrameImplBase();
 
-  virtual void initializeCoreFrame(FrameHost*,
+  virtual void initializeCoreFrame(Page&,
                                    FrameOwner*,
                                    const AtomicString& name) = 0;
   // TODO(dcheng): Rename this to coreFrame()? This probably also shouldn't be
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index ebda68aa..9ce0a57 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -118,7 +118,6 @@
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/serializers/Serialization.h"
 #include "core/editing/spellcheck/SpellChecker.h"
-#include "core/frame/FrameHost.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/PageScaleConstraintsSet.h"
@@ -1599,11 +1598,10 @@
   m_frame = frame;
 }
 
-void WebLocalFrameImpl::initializeCoreFrame(FrameHost* host,
+void WebLocalFrameImpl::initializeCoreFrame(Page& page,
                                             FrameOwner* owner,
                                             const AtomicString& name) {
-  setCoreFrame(LocalFrame::create(m_localFrameClientImpl.get(),
-                                  host ? &host->page() : nullptr, owner,
+  setCoreFrame(LocalFrame::create(m_localFrameClientImpl.get(), &page, owner,
                                   m_interfaceProvider, m_interfaceRegistry));
   frame()->tree().setName(name);
   // We must call init() after m_frame is assigned because it is referenced
@@ -1662,7 +1660,7 @@
   if (!webframeChild)
     return nullptr;
 
-  webframeChild->initializeCoreFrame(frame()->host(), ownerElement, name);
+  webframeChild->initializeCoreFrame(*frame()->page(), ownerElement, name);
   // Initializing the core frame may cause the new child to be detached, since
   // it may dispatch a load event in the parent.
   if (!webframeChild->parent())
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
index e296884f..a57a15a 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -314,7 +314,7 @@
                             WebString& clipHtml) override;
 
   // WebFrameImplBase methods:
-  void initializeCoreFrame(FrameHost*,
+  void initializeCoreFrame(Page&,
                            FrameOwner*,
                            const AtomicString& name) override;
   LocalFrame* frame() const override { return m_frame.get(); }
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
index 22ce4740..eb9f42c 100644
--- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
@@ -9,7 +9,6 @@
 #include "core/dom/Fullscreen.h"
 #include "core/dom/RemoteSecurityContext.h"
 #include "core/dom/SecurityContext.h"
-#include "core/frame/FrameHost.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/Settings.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
@@ -337,7 +336,7 @@
   // (one from the initial frame creation, and one from swapping it into the
   // remote process).  FrameLoader might need a special initialization function
   // for this case to avoid that duplicate navigation.
-  child->initializeCoreFrame(frame()->host(), owner, name);
+  child->initializeCoreFrame(*frame()->page(), owner, name);
   // Partially related with the above FIXME--the init() call may trigger JS
   // dispatch. However,
   // if the parent is remote, it should never be detached synchronously...
@@ -345,11 +344,10 @@
   return child;
 }
 
-void WebRemoteFrameImpl::initializeCoreFrame(FrameHost* host,
+void WebRemoteFrameImpl::initializeCoreFrame(Page& page,
                                              FrameOwner* owner,
                                              const AtomicString& name) {
-  setCoreFrame(RemoteFrame::create(m_frameClient.get(),
-                                   host ? &host->page() : nullptr, owner));
+  setCoreFrame(RemoteFrame::create(m_frameClient.get(), &page, owner));
   frame()->createView();
   m_frame->tree().setName(name);
 }
@@ -364,7 +362,7 @@
   appendChild(child);
   RemoteFrameOwner* owner = RemoteFrameOwner::create(
       static_cast<SandboxFlags>(sandboxFlags), WebFrameOwnerProperties());
-  child->initializeCoreFrame(frame()->host(), owner, name);
+  child->initializeCoreFrame(*frame()->page(), owner, name);
   return child;
 }
 
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
index 692f7fb..52cc9ce8 100644
--- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
@@ -17,7 +17,6 @@
 
 namespace blink {
 
-class FrameHost;
 class FrameOwner;
 class RemoteFrame;
 enum class WebFrameLoadType;
@@ -109,7 +108,7 @@
   WebFrameImplBase* toImplBase() { return this; }
 
   // WebFrameImplBase methods:
-  void initializeCoreFrame(FrameHost*,
+  void initializeCoreFrame(Page&,
                            FrameOwner*,
                            const AtomicString& name) override;
   RemoteFrame* frame() const override { return m_frame.get(); }
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index b2f5196..58d99bf 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -309,7 +309,7 @@
 }
 
 void WebViewImpl::setMainFrame(WebFrame* frame) {
-  frame->toImplBase()->initializeCoreFrame(&page()->frameHost(), 0, nullAtom);
+  frame->toImplBase()->initializeCoreFrame(*page(), 0, nullAtom);
 }
 
 void WebViewImpl::setCredentialManagerClient(
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
index 731b037a..e2e57a3 100644
--- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
+++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
@@ -126,7 +126,7 @@
 }
 
 void reloadFrame(WebFrame* frame) {
-  frame->reload(WebFrameLoadType::ReloadMainResource);
+  frame->reload(WebFrameLoadType::Reload);
   pumpPendingRequestsForFrameToLoad(frame);
 }
 
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index ba56e4a..b17d570 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -4159,7 +4159,7 @@
 
   // Reload the page and end up at the same url. State should be propagated.
   webViewHelper.webView()->mainFrame()->reloadWithOverrideURL(
-      toKURL(m_baseURL + firstURL), WebFrameLoadType::ReloadMainResource);
+      toKURL(m_baseURL + firstURL), WebFrameLoadType::Reload);
   FrameTestHelpers::pumpPendingRequestsForFrameToLoad(
       webViewHelper.webView()->mainFrame());
   EXPECT_EQ(previousOffset.width,
@@ -4170,7 +4170,7 @@
 
   // Reload the page using the cache. State should not be propagated.
   webViewHelper.webView()->mainFrame()->reloadWithOverrideURL(
-      toKURL(m_baseURL + secondURL), WebFrameLoadType::ReloadMainResource);
+      toKURL(m_baseURL + secondURL), WebFrameLoadType::Reload);
   FrameTestHelpers::pumpPendingRequestsForFrameToLoad(
       webViewHelper.webView()->mainFrame());
   EXPECT_EQ(0, webViewHelper.webView()->mainFrame()->getScrollOffset().width);
@@ -7172,22 +7172,19 @@
 class TestSameDocumentWebFrameClient
     : public FrameTestHelpers::TestWebFrameClient {
  public:
-  TestSameDocumentWebFrameClient()
-      : m_frameLoadTypeReloadMainResourceSeen(false) {}
+  TestSameDocumentWebFrameClient() : m_frameLoadTypeReloadSeen(false) {}
 
   virtual void willSendRequest(WebLocalFrame* frame, WebURLRequest&) {
     FrameLoader& frameLoader = toWebLocalFrameImpl(frame)->frame()->loader();
     if (frameLoader.provisionalDocumentLoader()->loadType() ==
-        FrameLoadTypeReloadMainResource)
-      m_frameLoadTypeReloadMainResourceSeen = true;
+        FrameLoadTypeReload)
+      m_frameLoadTypeReloadSeen = true;
   }
 
-  bool frameLoadTypeReloadMainResourceSeen() const {
-    return m_frameLoadTypeReloadMainResourceSeen;
-  }
+  bool frameLoadTypeReloadSeen() const { return m_frameLoadTypeReloadSeen; }
 
  private:
-  bool m_frameLoadTypeReloadMainResourceSeen;
+  bool m_frameLoadTypeReloadSeen;
 };
 
 TEST_P(ParameterizedWebFrameTest, NavigateToSame) {
@@ -7196,7 +7193,7 @@
   FrameTestHelpers::WebViewHelper webViewHelper;
   webViewHelper.initializeAndLoad(m_baseURL + "navigate_to_same.html", true,
                                   &client);
-  EXPECT_FALSE(client.frameLoadTypeReloadMainResourceSeen());
+  EXPECT_FALSE(client.frameLoadTypeReloadSeen());
 
   FrameLoadRequest frameRequest(
       0,
@@ -7209,7 +7206,7 @@
   FrameTestHelpers::pumpPendingRequestsForFrameToLoad(
       webViewHelper.webView()->mainFrame());
 
-  EXPECT_TRUE(client.frameLoadTypeReloadMainResourceSeen());
+  EXPECT_TRUE(client.frameLoadTypeReloadSeen());
 }
 
 class TestSameDocumentWithImageWebFrameClient
diff --git a/third_party/WebKit/public/web/WebFrameLoadType.h b/third_party/WebKit/public/web/WebFrameLoadType.h
index 06920f0..2e3fd24 100644
--- a/third_party/WebKit/public/web/WebFrameLoadType.h
+++ b/third_party/WebKit/public/web/WebFrameLoadType.h
@@ -18,9 +18,6 @@
 //   Uses cached entries even if the entries are stale. Used in history back and
 //   forward navigations.
 // Reload:
-//   Revalidates cached entries even if the entries are fresh. Used in usual
-//   reload.
-// ReloadMainResource:
 //   Revalidates a cached entry for the main resource if one exists, but follows
 //   protocols for other subresources. Blink internally uses this for the same
 //   page navigation. Also used in optimized reload for mobiles in a field
@@ -39,7 +36,6 @@
   Standard,
   BackForward,
   Reload,
-  ReloadMainResource,
   ReplaceCurrentItem,
   InitialInChildFrame,
   InitialHistoryLoad,
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e4300f4..b9111bb3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4562,15 +4562,58 @@
   <summary>Records whenever a Blimp tab toggles visibility.</summary>
 </histogram>
 
+<histogram name="Blink.Binding.InitializeMainLocalWindowProxy"
+    units="microseconds">
+  <owner>peria@chromium.org</owner>
+  <summary>
+    Time spent initializing LocalWindowProxy during a page loading in main
+    windows.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Binding.InitializeMainRemoteWindowProxy"
+    units="microseconds">
+  <owner>peria@chromium.org</owner>
+  <summary>
+    Time spent initializing RemoteWindowProxy during a page loading in main
+    frame of OOPIF.
+  </summary>
+</histogram>
+
 <histogram name="Blink.Binding.InitializeMainWindowProxy" units="microseconds">
+  <obsolete>
+    Deprecated as of 03/2017. This metric was split into two metrics depending
+    if it figures time for local window proxies or remote ones.
+  </obsolete>
   <owner>peria@chromium.org</owner>
   <summary>
     Time spent initializing WindowProxy during a page loading in main windows.
   </summary>
 </histogram>
 
+<histogram name="Blink.Binding.InitializeNonMainLocalWindowProxy"
+    units="microseconds">
+  <owner>peria@chromium.org</owner>
+  <summary>
+    Time spent initializing LocalWindowProxy during a page loading in non-main
+    windows, e.g. iframe.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Binding.InitializeNonMainRemoteWindowProxy"
+    units="microseconds">
+  <owner>peria@chromium.org</owner>
+  <summary>
+    Time spent initializing RemoteWindowProxy during a page loading in OOPIF.
+  </summary>
+</histogram>
+
 <histogram name="Blink.Binding.InitializeNonMainWindowProxy"
     units="microseconds">
+  <obsolete>
+    Deprecated as of 03/2017. This metric was split into two metrics depending
+    if it figures time for local window proxies or remote ones.
+  </obsolete>
   <owner>peria@chromium.org</owner>
   <summary>
     Time spent initializing WindowProxy during a page loading in non-main