1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.browser;
17
18import android.app.Activity;
19import android.content.Intent;
20import android.net.Uri;
21import android.provider.Browser;
22import android.test.ActivityInstrumentationTestCase2;
23import android.text.TextUtils;
24import android.webkit.WebView;
25
26public class IntentHandlerTests extends ActivityInstrumentationTestCase2<BrowserActivity> {
27
28    // How long to wait to receive onPageStarted
29    static final int START_LOAD_TIMEOUT = 20000; // ms
30    static final int POLL_INTERVAL = 50; // ms
31    boolean mHasStarted = false;
32
33    public IntentHandlerTests() {
34        super(BrowserActivity.class);
35    }
36
37    public void testSwitchToTabWithUrl() throws Throwable {
38        Intent intent = new Intent(Intent.ACTION_VIEW);
39        intent.setData(Uri.parse("http://google.com/"));
40        sendIntent(intent);
41        Controller controller = getActivity().getController();
42        Tab tabGoogle = controller.getCurrentTab();
43        assertNotNull("Current tab (google.com", tabGoogle);
44        assertEquals("http://google.com/", tabGoogle.getOriginalUrl());
45        assertEquals(1, controller.getTabs().size());
46        intent.setData(Uri.parse("http://maps.google.com/"));
47        sendIntent(intent);
48        Tab tabMaps = controller.getCurrentTab();
49        assertNotSame(tabGoogle, tabMaps);
50        assertNotNull("Current tab (maps.google.com)", tabMaps);
51        assertEquals(2, controller.getTabs().size());
52        intent.setData(Uri.parse("http://google.com/"));
53        sendIntent(intent);
54        assertEquals(tabGoogle, controller.getCurrentTab());
55        assertEquals(2, controller.getTabs().size());
56    }
57
58    public void testShortcut() throws Throwable {
59        Intent intent = BookmarkUtils.createShortcutIntent("http://google.com/");
60        sendIntent(intent);
61        Controller controller = getActivity().getController();
62        Tab tabGoogle = controller.getCurrentTab();
63        assertEquals("http://google.com/", tabGoogle.getOriginalUrl());
64        assertEquals(1, controller.getTabs().size());
65        sendIntent(intent);
66        assertEquals(1, controller.getTabs().size());
67        assertEquals(tabGoogle, controller.getCurrentTab());
68        directlyLoadUrl(tabGoogle, "http://maps.google.com/");
69        sendIntent(intent);
70        if (BrowserActivity.isTablet(getActivity())) {
71            assertEquals(2, controller.getTabs().size());
72            assertNotSame(tabGoogle, controller.getCurrentTab());
73            assertEquals("http://maps.google.com/", tabGoogle.getOriginalUrl());
74            Tab currentTab = controller.getCurrentTab();
75            assertEquals("http://google.com/", currentTab.getOriginalUrl());
76        } else {
77            assertEquals(1, controller.getTabs().size());
78            assertEquals(tabGoogle, controller.getCurrentTab());
79            assertEquals("http://google.com/", tabGoogle.getOriginalUrl());
80        }
81    }
82
83    public void testApplication() throws Throwable {
84        Intent intent = new Intent(Intent.ACTION_VIEW);
85        intent.setData(Uri.parse("http://google.com/"));
86        intent.putExtra(Browser.EXTRA_APPLICATION_ID, getClass().getName());
87        sendIntent(intent);
88        Controller controller = getActivity().getController();
89        Tab tabGoogle = controller.getCurrentTab();
90        assertNotNull("Current tab (google.com", tabGoogle);
91        assertEquals("http://google.com/", tabGoogle.getOriginalUrl());
92        assertEquals(1, controller.getTabs().size());
93        intent.setData(Uri.parse("http://maps.google.com/"));
94        sendIntent(intent);
95        Tab tabMaps = controller.getCurrentTab();
96        assertEquals("http://maps.google.com/", tabMaps.getOriginalUrl());
97        if (BrowserActivity.isTablet(getActivity())) {
98            assertEquals(2, controller.getTabs().size());
99            assertNotSame(tabGoogle, tabMaps);
100            assertEquals("http://google.com/", tabGoogle.getOriginalUrl());
101        } else {
102            assertEquals(1, controller.getTabs().size());
103            assertEquals(tabGoogle, tabMaps);
104        }
105    }
106
107    /**
108     * Simulate clicking a link by loading a URL directly on the WebView,
109     * bypassing Tab, Controller, etc..
110     * @throws Throwable
111     */
112    private void directlyLoadUrl(final Tab tab, final String url) throws Throwable {
113        runTestOnUiThread(new Runnable() {
114            @Override
115            public void run() {
116                WebView web = tab.getWebView();
117                web.loadUrl(url);
118            }
119        });
120        waitForLoadStart(tab, url);
121    }
122
123    void waitForLoadStart(final Tab tab, final String url) throws InterruptedException {
124        long start = System.currentTimeMillis();
125        while (!TextUtils.equals(tab.getOriginalUrl(), url)) {
126            if (start + START_LOAD_TIMEOUT < System.currentTimeMillis()) {
127                throw new RuntimeException("Didn't receive onPageStarted!");
128            }
129            Thread.sleep(POLL_INTERVAL);
130        }
131    }
132
133    private void sendIntent(final Intent intent) throws Throwable {
134        sendIntent(intent, true);
135    }
136
137    private void sendIntent(final Intent intent, boolean waitForLoadStart) throws Throwable {
138        if (!mHasStarted) {
139            // Prevent crash recovery from happening
140            intent.putExtra(Controller.NO_CRASH_RECOVERY, true);
141            setActivityIntent(intent);
142            getActivity();
143        } else {
144            final Activity activity = getActivity();
145            runTestOnUiThread(new Runnable() {
146                @Override
147                public void run() {
148                    getInstrumentation().callActivityOnNewIntent(activity, intent);
149                }
150            });
151        }
152        if (waitForLoadStart) {
153            String url = intent.getDataString();
154            Tab tab = getActivity().getController().getCurrentTab();
155            waitForLoadStart(tab, url);
156        }
157    }
158
159    @Override
160    public BrowserActivity getActivity() {
161        mHasStarted = true;
162        return super.getActivity();
163    }
164}
165