1// Copyright 2013 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
5package org.chromium.chrome.browser;
6
7import android.content.Intent;
8import android.test.FlakyTest;
9
10import org.chromium.base.test.util.UrlUtils;
11import org.chromium.chrome.shell.ChromeShellActivity;
12import org.chromium.chrome.shell.ChromeShellApplication;
13import org.chromium.chrome.shell.ChromeShellApplicationObserver;
14import org.chromium.chrome.shell.ChromeShellTestBase;
15import org.chromium.content.browser.test.util.Criteria;
16import org.chromium.content.browser.test.util.CriteriaHelper;
17
18/**
19 * Tests org.chromium.chrome.browser.ShortcutHelper and it's C++ counterpart.
20 */
21public class ShortcutHelperTest extends ChromeShellTestBase {
22    private static final String WEBAPP_ACTION_NAME = "WEBAPP_ACTION";
23
24    private static final String WEBAPP_TITLE = "Webapp shortcut";
25    private static final String WEBAPP_HTML = UrlUtils.encodeHtmlDataUri(
26            "<html><head>"
27            + "<meta name=\"mobile-web-app-capable\" content=\"yes\" />"
28            + "<title>" + WEBAPP_TITLE + "</title>"
29            + "</head><body>Webapp capable</body></html>");
30    private static final String EDITED_WEBAPP_TITLE = "Webapp shortcut edited";
31
32    private static final String SECOND_WEBAPP_TITLE = "Webapp shortcut #2";
33    private static final String SECOND_WEBAPP_HTML = UrlUtils.encodeHtmlDataUri(
34            "<html><head>"
35            + "<meta name=\"mobile-web-app-capable\" content=\"yes\" />"
36            + "<title>" + SECOND_WEBAPP_TITLE + "</title>"
37            + "</head><body>Webapp capable again</body></html>");
38
39    private static final String NORMAL_TITLE = "Plain shortcut";
40    private static final String NORMAL_HTML = UrlUtils.encodeHtmlDataUri(
41            "<html>"
42            + "<head><title>" + NORMAL_TITLE + "</title></head>"
43            + "<body>Not Webapp capable</body></html>");
44
45    private static final String META_APP_NAME_TITLE = "Web application-name";
46    private static final String META_APP_NAME_HTML = UrlUtils.encodeHtmlDataUri(
47            "<html><head>"
48            + "<meta name=\"mobile-web-app-capable\" content=\"yes\" />"
49            + "<meta name=\"application-name\" content=\"" + META_APP_NAME_TITLE + "\">"
50            + "<title>Not the right title</title>"
51            + "</head><body>Webapp capable</body></html>");
52
53    private static class TestObserver implements ChromeShellApplicationObserver {
54        Intent mFiredIntent;
55
56        @Override
57        public boolean onSendBroadcast(Intent intent) {
58            if (intent.hasExtra(Intent.EXTRA_SHORTCUT_NAME)) {
59                // Stop a shortcut from really being added.
60                mFiredIntent = intent;
61                return false;
62            }
63
64            return true;
65        }
66
67        public void reset() {
68            mFiredIntent = null;
69        }
70    }
71
72    private ChromeShellActivity mActivity;
73    private TestObserver mTestObserver;
74
75    @Override
76    public void setUp() throws Exception {
77        ShortcutHelper.setFullScreenAction(WEBAPP_ACTION_NAME);
78        mActivity = launchChromeShellWithBlankPage();
79
80        // Set up the observer.
81        mTestObserver = new TestObserver();
82        ChromeShellApplication application =
83                (ChromeShellApplication) mActivity.getApplication();
84        application.addObserver(mTestObserver);
85
86        super.setUp();
87    }
88
89    /**
90     * @MediumTest
91     * @Feature("{Webapp}")
92     * crbug.com/303486
93     */
94    @FlakyTest
95    public void testAddWebappShortcuts() throws InterruptedException {
96        // Add a webapp shortcut and make sure the intent's parameters make sense.
97        addShortcutToURL(WEBAPP_HTML, "");
98        Intent firedIntent = mTestObserver.mFiredIntent;
99        assertEquals(WEBAPP_TITLE, firedIntent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
100
101        Intent launchIntent = firedIntent.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
102        assertEquals(WEBAPP_HTML, launchIntent.getStringExtra(ShortcutHelper.EXTRA_URL));
103        assertEquals(WEBAPP_ACTION_NAME, launchIntent.getAction());
104        assertEquals(mActivity.getPackageName(), launchIntent.getPackage());
105
106        // Add a second shortcut and make sure it matches the second webapp's parameters.
107        mTestObserver.reset();
108        addShortcutToURL(SECOND_WEBAPP_HTML, "");
109        Intent newFiredIntent = mTestObserver.mFiredIntent;
110        assertEquals(SECOND_WEBAPP_TITLE,
111                newFiredIntent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
112
113        Intent newLaunchIntent = newFiredIntent.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
114        assertEquals(SECOND_WEBAPP_HTML, newLaunchIntent.getStringExtra(ShortcutHelper.EXTRA_URL));
115        assertEquals(WEBAPP_ACTION_NAME, newLaunchIntent.getAction());
116        assertEquals(mActivity.getPackageName(), newLaunchIntent.getPackage());
117    }
118
119    /**
120     * @MediumTest
121     * @Feature("{Webapp}")
122     * crbug.com/303486
123     */
124    @FlakyTest
125    public void testAddBookmarkShortcut() throws InterruptedException {
126        addShortcutToURL(NORMAL_HTML, "");
127
128        // Make sure the intent's parameters make sense.
129        Intent firedIntent = mTestObserver.mFiredIntent;
130        assertEquals(NORMAL_TITLE, firedIntent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
131
132        Intent launchIntent = firedIntent.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
133        assertEquals(mActivity.getPackageName(), launchIntent.getPackage());
134        assertEquals(Intent.ACTION_VIEW, launchIntent.getAction());
135        assertEquals(NORMAL_HTML, launchIntent.getDataString());
136    }
137
138    /**
139     * @MediumTest
140     * @Feature("{Webapp}")
141     * crbug.com/303486
142     */
143    @FlakyTest
144    public void testAddWebappShortcutsWithoutTitleEdit() throws InterruptedException {
145        // Add a webapp shortcut to check unedited title.
146        addShortcutToURL(WEBAPP_HTML, "");
147        Intent firedIntent = mTestObserver.mFiredIntent;
148        assertEquals(WEBAPP_TITLE, firedIntent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
149    }
150
151    /**
152     * @MediumTest
153     * @Feature("{Webapp}")
154     * crbug.com/303486
155     */
156    @FlakyTest
157    public void testAddWebappShortcutsWithTitleEdit() throws InterruptedException {
158        // Add a webapp shortcut to check edited title.
159        addShortcutToURL(WEBAPP_HTML, EDITED_WEBAPP_TITLE);
160        Intent firedIntent = mTestObserver.mFiredIntent;
161        assertEquals(EDITED_WEBAPP_TITLE , firedIntent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
162    }
163
164    /**
165     * @MediumTest
166     * @Feature("{Webapp}")
167     * crbug.com/303486
168     */
169    @FlakyTest
170    public void testAddWebappShortcutsWithApplicationName() throws InterruptedException {
171        // Add a webapp shortcut to check edited title.
172        addShortcutToURL(META_APP_NAME_HTML, "");
173        Intent firedIntent = mTestObserver.mFiredIntent;
174        assertEquals(META_APP_NAME_TITLE , firedIntent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
175    }
176
177    private void addShortcutToURL(String url, final String title) throws InterruptedException {
178        loadUrlWithSanitization(url);
179        assertTrue(waitForActiveShellToBeDoneLoading());
180
181        // Add the shortcut.
182        getInstrumentation().runOnMainSync(new Runnable() {
183            @Override
184            public void run() {
185                final ShortcutHelper shortcutHelper = new ShortcutHelper(
186                        mActivity.getApplicationContext(), mActivity.getActiveTab());
187                // Calling initialize() isn't strictly required but it is
188                // testing this code path.
189                shortcutHelper.initialize(new ShortcutHelper.OnInitialized() {
190                    @Override
191                    public void onInitialized(String t) {
192                        shortcutHelper.addShortcut(title);
193                    }
194                });
195            }
196        });
197
198        // Make sure that the shortcut was added.
199        assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
200            @Override
201            public boolean isSatisfied() {
202                return mTestObserver.mFiredIntent != null;
203            }
204        }));
205    }
206}
207