Fix up cc::Layer scroll parent management

The previous code was trying to perform scroll parent pointer fixup during
LayerImpl destruction, which is problematic since ~LayerImpl() always runs
during tree synchronization and there is nothing to ensure that the scroll
parent's portion of the tree has be fully synchronized when a particular
scroll child is being destroyed.

Instead, this performs pointer fixup on the main thread and then just pushes
the values through to the LayerImpl tree without performing additional fixups.
So long as the main-thread (cc::Layer) tree stays structurally valid there's
no need for additional changes at layer destruction or tree manipulation time
on any LayerImpl trees.

BUG=347284

Review URL: https://codereview.chromium.org/182363002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254244 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/cc/trees/tree_synchronizer.cc b/cc/trees/tree_synchronizer.cc
index 1c1c7e1..6d52f35 100644
--- a/cc/trees/tree_synchronizer.cc
+++ b/cc/trees/tree_synchronizer.cc
@@ -4,6 +4,8 @@
 
 #include "cc/trees/tree_synchronizer.h"
 
+#include <set>
+
 #include "base/containers/hash_tables.h"
 #include "base/containers/scoped_ptr_hash_map.h"
 #include "base/debug/trace_event.h"
@@ -234,11 +236,64 @@
   *num_dependents_need_push_properties_for_parent += add_self_to_parent ? 1 : 0;
 }
 
+static void CheckScrollAndClipPointersRecursive(Layer* layer,
+                                                LayerImpl* layer_impl) {
+  DCHECK_EQ(!!layer, !!layer_impl);
+  if (!layer)
+    return;
+
+  DCHECK_EQ(!!layer->scroll_parent(), !!layer_impl->scroll_parent());
+  if (layer->scroll_parent())
+    DCHECK_EQ(layer->scroll_parent()->id(), layer_impl->scroll_parent()->id());
+
+  DCHECK_EQ(!!layer->clip_parent(), !!layer_impl->clip_parent());
+  if (layer->clip_parent())
+    DCHECK_EQ(layer->clip_parent()->id(), layer_impl->clip_parent()->id());
+
+  DCHECK_EQ(!!layer->scroll_children(), !!layer_impl->scroll_children());
+  if (layer->scroll_children()) {
+    for (std::set<Layer*>::iterator it = layer->scroll_children()->begin();
+         it != layer->scroll_children()->end();
+         ++it) {
+      DCHECK_EQ((*it)->scroll_parent(), layer);
+    }
+    for (std::set<LayerImpl*>::iterator it =
+             layer_impl->scroll_children()->begin();
+         it != layer_impl->scroll_children()->end();
+         ++it) {
+      DCHECK_EQ((*it)->scroll_parent(), layer_impl);
+    }
+  }
+
+  DCHECK_EQ(!!layer->clip_children(), !!layer_impl->clip_children());
+  if (layer->clip_children()) {
+    for (std::set<Layer*>::iterator it = layer->clip_children()->begin();
+         it != layer->clip_children()->end();
+         ++it) {
+      DCHECK_EQ((*it)->clip_parent(), layer);
+    }
+    for (std::set<LayerImpl*>::iterator it =
+             layer_impl->clip_children()->begin();
+         it != layer_impl->clip_children()->end();
+         ++it) {
+      DCHECK_EQ((*it)->clip_parent(), layer_impl);
+    }
+  }
+
+  for (size_t i = 0u; i < layer->children().size(); ++i) {
+    CheckScrollAndClipPointersRecursive(layer->child_at(i),
+                                        layer_impl->child_at(i));
+  }
+}
+
 void TreeSynchronizer::PushProperties(Layer* layer,
                                       LayerImpl* layer_impl) {
   size_t num_dependents_need_push_properties = 0;
   PushPropertiesInternal(
       layer, layer_impl, &num_dependents_need_push_properties);
+  if (DCHECK_IS_ON()) {
+    CheckScrollAndClipPointersRecursive(layer, layer_impl);
+  }
 }
 
 void TreeSynchronizer::PushProperties(LayerImpl* layer, LayerImpl* layer_impl) {