Bug 1459301 - 3. Fix and add onNewSession tests; r?snorp draft
authorJim Chen <nchen@mozilla.com>
Fri, 11 May 2018 14:59:49 -0400
changeset 794347 6367e92b8faa56e5018a0a47729c42ed6c811dbc
parent 794346 1147bfdba62ecd991c99c07e5ba78edd13a0c9a3
child 794350 d3e4e626d38ec45c837c98d8da631ed7aa5f5cbd
push id109648
push userbmo:nchen@mozilla.com
push dateFri, 11 May 2018 19:00:34 +0000
reviewerssnorp
bugs1459301
milestone62.0a1
Bug 1459301 - 3. Fix and add onNewSession tests; r?snorp Use RDP instead of synthesizeTap to fix the onNewSession tests. Also add some additional onNewSession tests, including setting / not-setting of the window opener. MozReview-Commit-ID: 7wAEdqiAi5j
mobile/android/geckoview/src/androidTest/assets/www/newSession.html
mobile/android/geckoview/src/androidTest/assets/www/newSession_child.html
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
mobile/android/modules/geckoview/GeckoViewNavigation.jsm
--- a/mobile/android/geckoview/src/androidTest/assets/www/newSession.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/newSession.html
@@ -1,20 +1,7 @@
 <html>
     <head><title>Hello, world!</title></head>
     <body>
-        <p id="message"></p>
-        <script>
-            const msg = document.getElementById("message");
-            msg.innerText = "Waiting for click...";
-            window.addEventListener("click", function() {
-                msg.innerText = "Opening window....";
-                try {
-                    const win = window.open("newSession_child.html");
-
-                    msg.innerText = "Opened window: " + win;
-                } catch (e) {
-                    msg.innerText = "Failed to open window: " + e;
-                }
-            });
-        </script>
+        <a id="targetBlankLink" target="_blank" href="newSession_child.html">target="_blank"</a>
+        <a id="noOpenerLink" target="_blank" rel="noopener" href="newSession_child.html">rel="noopener"</a>
     </body>
-</html>
\ No newline at end of file
+</html>
--- a/mobile/android/geckoview/src/androidTest/assets/www/newSession_child.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/newSession_child.html
@@ -1,11 +1,6 @@
 <html>
     <head><title>Hello, world!</title></head>
     <body>
         <p>I'm the child</p>
-        <script>
-            setTimeout(function() {
-                window.close();
-            }, 1000);
-        </script>
     </body>
 </html>
\ No newline at end of file
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
@@ -22,17 +22,17 @@ import kotlin.reflect.KClass
  * Common base class for tests using GeckoSessionTestRule,
  * providing the test rule and other utilities.
  */
 open class BaseSessionTest(noErrorCollector: Boolean = false) {
     companion object {
         const val INVALID_URI = "http://www.test.invalid/"
         const val HELLO_HTML_PATH = "/assets/www/hello.html"
         const val HELLO2_HTML_PATH = "/assets/www/hello2.html"
-        const val NEW_SESSION_HTML_PATH = "/assets/www/newSession.html";
+        const val NEW_SESSION_HTML_PATH = "/assets/www/newSession.html"
         const val NEW_SESSION_CHILD_HTML_PATH = "/assets/www/newSession_child.html"
         const val CLICK_TO_RELOAD_HTML_PATH = "/assets/www/clickToReload.html"
         const val TITLE_CHANGE_HTML_PATH = "/assets/www/titleChange.html"
         const val DOWNLOAD_HTML_PATH = "/assets/www/download.html"
     }
 
     @get:Rule val sessionRule = GeckoSessionTestRule()
 
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
@@ -3,23 +3,22 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.geckoview.test
 
 import org.mozilla.geckoview.GeckoResponse
 import org.mozilla.geckoview.GeckoSession
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.NullDelegate
-import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI
 import org.mozilla.geckoview.test.util.Callbacks
 
 import android.support.test.filters.MediumTest
 import android.support.test.runner.AndroidJUnit4
 import org.hamcrest.Matchers.*
-import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 @MediumTest
 class NavigationDelegateTest : BaseSessionTest() {
 
     @Test fun load() {
@@ -342,45 +341,169 @@ class NavigationDelegateTest : BaseSessi
 
             @AssertCalled(count = 1, order = [2])
             override fun onPageStop(session: GeckoSession, success: Boolean) {
                 assertThat("Load should succeed", success, equalTo(true))
             }
         })
     }
 
-    @WithDisplay(width = 128, height = 128)
-    @Ignore
-    @Test fun onNewSession_calledForNewWindow() {
+    @WithDevToolsAPI
+    @Test fun onNewSession_calledForWindowOpen() {
+        // Disable popup blocker.
+        sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false))
+
         sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH)
-        sessionRule.waitForPageStop()
+        sessionRule.session.waitForPageStop()
+
+        sessionRule.session.evaluateJS("window.open('newSession_child.html', '_blank')")
 
-        sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
-            @AssertCalled(count = 1)
+        sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate {
+            @AssertCalled(count = 1, order = [1])
+            override fun onLoadRequest(session: GeckoSession, uri: String, where: Int, flags: Int, response: GeckoResponse<Boolean>) {
+                assertThat("URI should be correct", uri, endsWith(NEW_SESSION_CHILD_HTML_PATH))
+                assertThat("Where should be correct", where,
+                           equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_NEW))
+            }
+
+            @AssertCalled(count = 1, order = [2])
             override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
-                response.respond(null)
+                assertThat("URI should be correct", uri, endsWith(NEW_SESSION_CHILD_HTML_PATH))
             }
         })
-
-        sessionRule.session.synthesizeTap(5, 5)
-        sessionRule.waitUntilCalled(GeckoSession.NavigationDelegate::class, "onNewSession")
     }
 
-    @WithDisplay(width = 128, height = 128)
-    @Ignore
-    @Test(expected = IllegalArgumentException::class)
-    fun onNewSession_doesNotAllowOpened() {
+    @WithDevToolsAPI
+    @Test fun onNewSession_calledForTargetBlankLink() {
         sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH)
-        sessionRule.waitForPageStop()
+        sessionRule.session.waitForPageStop()
+
+        sessionRule.session.evaluateJS("$('#targetBlankLink').click()")
 
-        sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
+        sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate {
+            // We get two onLoadRequest calls for the link click,
+            // one when loading the URL and one when opening a new window.
+            @AssertCalled(count = 2, order = [1])
+            override fun onLoadRequest(session: GeckoSession, uri: String, where: Int, flags: Int, response: GeckoResponse<Boolean>) {
+                assertThat("URI should be correct", uri, endsWith(NEW_SESSION_CHILD_HTML_PATH))
+                assertThat("Where should be correct", where,
+                           equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_NEW))
+            }
+
+            @AssertCalled(count = 1, order = [2])
+            override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
+                assertThat("URI should be correct", uri, endsWith(NEW_SESSION_CHILD_HTML_PATH))
+            }
+        })
+    }
+
+    private fun delegateNewSession(): GeckoSession {
+        val newSession = sessionRule.createClosedSession()
+
+        sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
             @AssertCalled(count = 1)
             override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
-                val newSession = sessionRule.createClosedSession(session.settings)
-                newSession.open()
                 response.respond(newSession)
             }
         })
 
-        sessionRule.session.synthesizeTap(5, 5)
-        sessionRule.waitUntilCalled(GeckoSession.NavigationDelegate::class, "onNewSession")
+        return newSession
+    }
+
+    @WithDevToolsAPI
+    @Test fun onNewSession_childShouldLoad() {
+        sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH)
+        sessionRule.session.waitForPageStop()
+
+        val newSession = delegateNewSession()
+        sessionRule.session.evaluateJS("$('#targetBlankLink').click()")
+        newSession.waitForPageStop()
+
+        newSession.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
+            @AssertCalled(count = 1)
+            override fun onPageStart(session: GeckoSession, url: String) {
+                assertThat("URL should match", url, endsWith(NEW_SESSION_CHILD_HTML_PATH))
+            }
+
+            @AssertCalled(count = 1)
+            override fun onPageStop(session: GeckoSession, success: Boolean) {
+                assertThat("Load should succeed", success, equalTo(true))
+            }
+        })
+    }
+
+    @WithDevToolsAPI
+    @Test fun onNewSession_setWindowOpener() {
+        sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH)
+        sessionRule.session.waitForPageStop()
+
+        val newSession = delegateNewSession()
+        sessionRule.session.evaluateJS("$('#targetBlankLink').click()")
+        newSession.waitForPageStop()
+
+        assertThat("window.opener should be set",
+                   newSession.evaluateJS("window.opener.location.pathname") as String,
+                   equalTo(NEW_SESSION_HTML_PATH))
+    }
+
+    @WithDevToolsAPI
+    @Test fun onNewSession_supportNoOpener() {
+        sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH)
+        sessionRule.session.waitForPageStop()
+
+        val newSession = delegateNewSession()
+        sessionRule.session.evaluateJS("$('#noOpenerLink').click()")
+        newSession.waitForPageStop()
+
+        assertThat("window.opener should not be set",
+                   newSession.evaluateJS("window.opener"), nullValue())
+    }
+
+    @WithDevToolsAPI
+    @Test fun onNewSession_notCalledForHandledLoads() {
+        sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH)
+        sessionRule.session.waitForPageStop()
+
+        sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
+            override fun onLoadRequest(session: GeckoSession, uri: String, where: Int, flags: Int, response: GeckoResponse<Boolean>) {
+                // Pretend we handled the target="_blank" link click.
+                response.respond(uri.endsWith(NEW_SESSION_CHILD_HTML_PATH))
+            }
+        })
+
+        sessionRule.session.evaluateJS("$('#targetBlankLink').click()")
+
+        sessionRule.session.reload()
+        sessionRule.session.waitForPageStop()
+
+        // Assert that onNewSession was not called for the link click.
+        sessionRule.session.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
+            @AssertCalled(count = 2)
+            override fun onLoadRequest(session: GeckoSession, uri: String, where: Int, flags: Int, response: GeckoResponse<Boolean>) {
+                assertThat("URI must match", uri,
+                           endsWith(forEachCall(NEW_SESSION_CHILD_HTML_PATH, NEW_SESSION_HTML_PATH)))
+            }
+
+            @AssertCalled(count = 0)
+            override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
+            }
+        })
+    }
+
+    @WithDevToolsAPI
+    @Test(expected = IllegalArgumentException::class)
+    fun onNewSession_doesNotAllowOpened() {
+        sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH)
+        sessionRule.session.waitForPageStop()
+
+        sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
+            @AssertCalled(count = 1)
+            override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
+                response.respond(sessionRule.createOpenSession())
+            }
+        })
+
+        sessionRule.session.evaluateJS("$('#targetBlankLink').click()")
+
+        sessionRule.session.waitUntilCalled(GeckoSession.NavigationDelegate::class,
+                                            "onNewSession")
     }
 }
--- a/mobile/android/modules/geckoview/GeckoViewNavigation.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewNavigation.jsm
@@ -170,18 +170,17 @@ class GeckoViewNavigation extends GeckoV
 
     return browser.contentWindow;
   }
 
   // nsIBrowserDOMWindow.
   createContentWindowInFrame(aUri, aParams, aWhere, aFlags, aNextTabParentId,
                              aName) {
     debug `createContentWindowInFrame: uri=${aUri && aUri.spec}
-                                       params=${aParams} where=${aWhere}
-                                       flags=${aFlags}
+                                       where=${aWhere} flags=${aFlags}
                                        nextTabParentId=${aNextTabParentId}
                                        name=${aName}`;
 
     if (LoadURIDelegate.load(this.window, this.eventDispatcher,
                              aUri, aWhere, aFlags)) {
       // The app has handled the load, abort open-window handling.
       Components.returnCode = Cr.NS_ERROR_ABORT;
       return null;