Reconcile TouchExplorationController and TouchAccessibilityEnabler

TouchExplorationController is an event rewriter. When it's on it rewrites
lots of touch events to enable touch-screen accessibility.

TouchAccessibilityEnabler is a simple event listener. It watches for two
fingers being held down and fires some events if so, which may trigger
enabling TouchExplorationController in some cases. Rather than needing
separate logic for rewritten events, TouchExplorationController just passes
events directly to TouchAccessibilityEnabler when it's running.

This leads to problems when TouchExplorationController is enabled or disabled,
because sometimes "release" events get dropped. This causes things to stop
working from time to time after using two fingers to toggle accessibility
more than once.

Fix this by making TouchExplorationController notify TouchAccessibilityEnabler
when it's enabled and disabled so that it can stop or start listening to
events, and reset its internal state.

Bug: 756667
Change-Id: I1aa5e4867999b545fd8d1128c288b6f3b3554262
Reviewed-on: https://chromium-review.googlesource.com/620007
Reviewed-by: Mitsuru Oshima <[email protected]>
Reviewed-by: James Cook <[email protected]>
Commit-Queue: Dominic Mazzoni <[email protected]>
Cr-Commit-Position: refs/heads/master@{#496406}
diff --git a/ui/chromeos/touch_accessibility_enabler_unittest.cc b/ui/chromeos/touch_accessibility_enabler_unittest.cc
index 6899000..71e5bfc 100644
--- a/ui/chromeos/touch_accessibility_enabler_unittest.cc
+++ b/ui/chromeos/touch_accessibility_enabler_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/time/time.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/window.h"
+#include "ui/chromeos/touch_exploration_controller.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/gestures/gesture_provider_aura.h"
@@ -96,6 +97,34 @@
 
 }  // namespace
 
+TEST_F(TouchAccessibilityEnablerTest, InteractsWithTouchExplorationController) {
+  // This test ensures that if TouchExplorationController starts and stops,
+  // TouchAccessibilityEnabler continues to work correctly. Because
+  // TouchExplorationController rewrites most touch events, it can screw up
+  // TouchAccessibilityEnabler if they don't explicitly coordinate.
+
+  std::unique_ptr<TouchExplorationController> controller(
+      new TouchExplorationController(root_window(), nullptr,
+                                     enabler_->GetWeakPtr()));
+
+  EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
+  generator_->set_current_location(gfx::Point(11, 12));
+  generator_->PressTouchId(1);
+
+  simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(500));
+
+  generator_->set_current_location(gfx::Point(22, 34));
+  generator_->PressTouchId(2);
+
+  EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting());
+
+  controller.reset();
+
+  generator_->ReleaseTouchId(1);
+  generator_->ReleaseTouchId(2);
+  EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
+}
+
 TEST_F(TouchAccessibilityEnablerTest, EntersOneFingerDownMode) {
   EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
   EXPECT_FALSE(enabler_->IsInOneFingerDownForTesting());