Fix flaky WebViewTest.SpatialNavigationJavascriptAPI.

Two reasons for flakiness were identified:

* Occasional lack of sync between the C++ and JS sides of the test.
Sometimes, the JS side emitted signals before the C++ code was ready to
listen to them, or the C++ side emitted keystrokes before listeners were
ready in JS code. Fixed with slight changes in the order of the test
code.

* When checking the spatial navigation status immediately after changing
it, the wrong state could be reported. When the system is under heavy
load, it could happen that the changed state is reported before the
change has been made effective in the render process. Fixed sending a
message to the guest render process with postMessage, which uses the
same IPC channel; when the message is answered we can be sure that the
SetSpatialNavigationEnabled operation is complete.

Bug: 884306
Change-Id: Iae227098cd36980357d8b747ddcb527df2317fa1
Reviewed-on: https://chromium-review.googlesource.com/c/1327204
Reviewed-by: Lucas Gadani <lfg@chromium.org>
Commit-Queue: Jacobo Aragunde Pérez <jaragunde@igalia.com>
Cr-Commit-Position: refs/heads/master@{#609241}
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 1c2a2df..5433724 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -1113,17 +1113,16 @@
 }
 
 // This test exercises the webview spatial navigation API
-// This test is disabled due to being flaky. http://crbug.com/884306
-IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_SpatialNavigationJavascriptAPI) {
+IN_PROC_BROWSER_TEST_F(WebViewTest, SpatialNavigationJavascriptAPI) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableSpatialNavigation);
 
-  LoadAndLaunchPlatformApp("web_view/spatial_navigation_state_api",
-                           "WebViewTest.LAUNCHED");
-
   ExtensionTestMessageListener next_step_listener("TEST_STEP_PASSED", false);
   next_step_listener.set_failure_message("TEST_STEP_FAILED");
 
+  LoadAndLaunchPlatformApp("web_view/spatial_navigation_state_api",
+                           "WebViewTest.LAUNCHED");
+
   // Check that spatial navigation is initialized in the beginning
   ASSERT_TRUE(next_step_listener.WaitUntilSatisfied());
   next_step_listener.Reset();
diff --git a/chrome/test/data/extensions/platform_apps/web_view/spatial_navigation_state_api/main.js b/chrome/test/data/extensions/platform_apps/web_view/spatial_navigation_state_api/main.js
index 4906a9d..23fdcff 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/spatial_navigation_state_api/main.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/spatial_navigation_state_api/main.js
@@ -14,7 +14,7 @@
 function secondCheck(e) {
   chrome.test.log('After RIGHT key is pressed once');
   if (e.message == 'focused:1') {
-    // setup next tests
+    // setup next test
     var webview = document.querySelector('webview');
     webview.removeEventListener('consolemessage', secondCheck);
     webview.addEventListener('consolemessage', thirdCheck);
@@ -28,24 +28,39 @@
 function thirdCheck(e) {
   chrome.test.log('After RIGHT key is pressed once more');
   if (e.message == 'focused:2') {
-    // setup next tests
+    chrome.test.sendMessage('TEST_STEP_PASSED');
+
+    // setup next test
     var webview = document.querySelector('webview');
     webview.removeEventListener('consolemessage', thirdCheck);
     webview.setSpatialNavigationEnabled(false);
-    webview.isSpatialNavigationEnabled(fourthCheck);
-    webview.addEventListener('consolemessage', fifthCheck);
 
-    chrome.test.sendMessage('TEST_STEP_PASSED');
+    // send message via the same IPC channel as setSpatialNavigationEnabled and
+    // wait for reply before checking the state with
+    // getSpatialNavigationEnabled. Required to make sure that the
+    // setSpatialNavigationEnabled call has reached the renderer process.
+    window.onmessage = onMessage;
+    webview.contentWindow.postMessage('{}', '*');
   } else {
     chrome.test.sendMessage('TEST_STEP_FAILED');
   }
 }
 
+var onMessage = function(e) {
+  chrome.test.log('Received message back from renderer');
+  var webview = document.querySelector('webview');
+  webview.isSpatialNavigationEnabled(fourthCheck);
+};
+
 function fourthCheck(spatialNavigationEnabled) {
   chrome.test.log('Spatial navigation disabled');
   if (spatialNavigationEnabled) {
     chrome.test.sendMessage('TEST_STEP_FAILED');
   } else {
+    // setup next test
+    var webview = document.querySelector('webview');
+    webview.addEventListener('consolemessage', fifthCheck);
+
     chrome.test.sendMessage('TEST_STEP_PASSED');
   }
 }
@@ -67,8 +82,8 @@
     webview.removeEventListener('loadstop', onLoadStop);
     chrome.test.sendMessage('WebViewTest.LAUNCHED');
 
-    webview.isSpatialNavigationEnabled(firstCheck);
     webview.focus();
+    webview.isSpatialNavigationEnabled(firstCheck);
   };
 
   webview.addEventListener('loadstop', onLoadStop);
@@ -90,6 +105,9 @@
             console.log('focused:'+ev.target.id);
           };
         });
+        window.onmessage = function(e) {
+          e.source.postMessage('{}', '*');
+        };
         </script>
     </body>
   `;