1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.login;
6 
7 import android.support.test.InstrumentationRegistry;
8 
9 import androidx.test.filters.MediumTest;
10 
11 import org.hamcrest.Matchers;
12 import org.junit.After;
13 import org.junit.Before;
14 import org.junit.Rule;
15 import org.junit.Test;
16 import org.junit.runner.RunWith;
17 
18 import org.chromium.base.Callback;
19 import org.chromium.base.test.util.CallbackHelper;
20 import org.chromium.base.test.util.CommandLineFlags;
21 import org.chromium.base.test.util.Criteria;
22 import org.chromium.base.test.util.CriteriaHelper;
23 import org.chromium.base.test.util.Restriction;
24 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
25 import org.chromium.chrome.browser.flags.ChromeSwitches;
26 import org.chromium.chrome.browser.tab.SadTab;
27 import org.chromium.chrome.browser.tab.Tab;
28 import org.chromium.chrome.browser.tab.TabLaunchType;
29 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
30 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
31 import org.chromium.chrome.test.util.ChromeTabUtils;
32 import org.chromium.content_public.browser.test.util.TestThreadUtils;
33 import org.chromium.content_public.common.ContentUrlConstants;
34 import org.chromium.net.test.EmbeddedTestServer;
35 
36 import java.util.concurrent.atomic.AtomicReference;
37 
38 /**
39  * Tests for the Android specific HTTP auth UI.
40  */
41 @RunWith(ChromeJUnit4ClassRunner.class)
42 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
43 public class ChromeHttpAuthHandlerTest {
44     @Rule
45     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
46 
47     @Rule
48     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
49 
50     private EmbeddedTestServer mTestServer;
51 
52     @Before
setUp()53     public void setUp() throws Exception {
54         mActivityTestRule.startMainActivityOnBlankPage();
55         mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
56     }
57 
58     @After
tearDown()59     public void tearDown() {
60         if (mTestServer != null) mTestServer.stopAndDestroyServer();
61     }
62 
63     @Test
64     @MediumTest
authDialogShows()65     public void authDialogShows() throws Exception {
66         ChromeHttpAuthHandler handler = triggerAuth();
67         verifyAuthDialogVisibility(handler, true);
68     }
69 
70     @Test
71     @MediumTest
authDialogDismissOnNavigation()72     public void authDialogDismissOnNavigation() throws Exception {
73         ChromeHttpAuthHandler handler = triggerAuth();
74         verifyAuthDialogVisibility(handler, true);
75         ChromeTabUtils.loadUrlOnUiThread(mActivityTestRule.getActivity().getActivityTab(),
76                 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
77         verifyAuthDialogVisibility(handler, false);
78     }
79 
80     @Test
81     @MediumTest
authDialogDismissOnTabSwitched()82     public void authDialogDismissOnTabSwitched() throws Exception {
83         ChromeHttpAuthHandler handler = triggerAuth();
84         verifyAuthDialogVisibility(handler, true);
85         TestThreadUtils.runOnUiThreadBlocking(
86                 ()
87                         -> mActivityTestRule.getActivity().getTabCreator(false).launchUrl(
88                                 "about:blank", TabLaunchType.FROM_CHROME_UI));
89         verifyAuthDialogVisibility(handler, false);
90     }
91 
92     @Test
93     @MediumTest
authDialogDismissOnTabClosed()94     public void authDialogDismissOnTabClosed() throws Exception {
95         ChromeHttpAuthHandler handler = triggerAuth();
96         verifyAuthDialogVisibility(handler, true);
97         ChromeTabUtils.closeCurrentTab(
98                 InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
99         verifyAuthDialogVisibility(handler, false);
100     }
101 
102     @Test
103     @MediumTest
104     @Restriction(Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE)
authDialogSuppressedOnBackgroundTab()105     public void authDialogSuppressedOnBackgroundTab() throws Exception {
106         Tab firstTab = mActivityTestRule.getActivity().getActivityTab();
107         ChromeTabUtils.newTabFromMenu(
108                 InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
109         // If the first tab was closed due to OOM, then just exit the test.
110         if (TestThreadUtils.runOnUiThreadBlocking(
111                     () -> firstTab.isClosing() || SadTab.isShowing(firstTab))) {
112             return;
113         }
114         ChromeHttpAuthHandler handler = triggerAuthForTab(firstTab);
115         verifyAuthDialogVisibility(handler, false);
116     }
117 
triggerAuth()118     private ChromeHttpAuthHandler triggerAuth() throws Exception {
119         return triggerAuthForTab(mActivityTestRule.getActivity().getActivityTab());
120     }
121 
triggerAuthForTab(Tab tab)122     private ChromeHttpAuthHandler triggerAuthForTab(Tab tab) throws Exception {
123         AtomicReference<ChromeHttpAuthHandler> handlerRef = new AtomicReference<>();
124         CallbackHelper handlerCallback = new CallbackHelper();
125         Callback<ChromeHttpAuthHandler> callback = (handler) -> {
126             handlerRef.set(handler);
127             handlerCallback.notifyCalled();
128         };
129         TestThreadUtils.runOnUiThreadBlocking(
130                 () -> { ChromeHttpAuthHandler.setTestCreationCallback(callback); });
131 
132         String url = mTestServer.getURL("/auth-basic");
133         ChromeTabUtils.loadUrlOnUiThread(tab, url);
134         handlerCallback.waitForFirst();
135         TestThreadUtils.runOnUiThreadBlocking(
136                 () -> { ChromeHttpAuthHandler.setTestCreationCallback(null); });
137         return handlerRef.get();
138     }
139 
verifyAuthDialogVisibility(ChromeHttpAuthHandler handler, boolean isVisible)140     private void verifyAuthDialogVisibility(ChromeHttpAuthHandler handler, boolean isVisible) {
141         CriteriaHelper.pollUiThread(
142                 () -> Criteria.checkThat(handler.isShowingAuthDialog(), Matchers.is(isVisible)));
143     }
144 }
145