Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/MainActivity.java

Issue 2858563004: Add support for webapk without runtimeHost (Closed)
Patch Set: Delete private data before switching host browser. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.webapk.shell_apk; 5 package org.chromium.webapk.shell_apk;
6 6
7 import android.app.Activity;
8 import android.content.ActivityNotFoundException; 7 import android.content.ActivityNotFoundException;
9 import android.content.Intent; 8 import android.content.Intent;
10 import android.content.pm.ApplicationInfo; 9 import android.content.pm.ApplicationInfo;
11 import android.content.pm.PackageManager; 10 import android.content.pm.PackageManager;
12 import android.content.pm.PackageManager.NameNotFoundException; 11 import android.content.pm.PackageManager.NameNotFoundException;
13 import android.net.Uri; 12 import android.net.Uri;
14 import android.os.Bundle; 13 import android.os.Bundle;
14 import android.support.v4.app.DialogFragment;
15 import android.support.v4.app.FragmentActivity;
16 import android.text.TextUtils;
15 import android.util.Log; 17 import android.util.Log;
16 18
17 import org.chromium.webapk.lib.common.WebApkConstants; 19 import org.chromium.webapk.lib.common.WebApkConstants;
18 import org.chromium.webapk.lib.common.WebApkMetaDataKeys; 20 import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
19 21
20 import java.net.URISyntaxException; 22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.util.Set;
21 25
22 /** 26 /**
23 * WebAPK's main Activity. 27 * WebAPK's main Activity.
24 */ 28 */
25 public class MainActivity extends Activity { 29 public class MainActivity
30 extends FragmentActivity implements ChooseHostBrowserDialogFragment.Dial ogListener {
26 private static final String TAG = "cr_MainActivity"; 31 private static final String TAG = "cr_MainActivity";
27 32
28 /** 33 /**
29 * Name of class which launches browser in WebAPK mode. 34 * Name of class which launches browser in WebAPK mode.
30 */ 35 */
31 private static final String HOST_BROWSER_LAUNCHER_CLASS_NAME = 36 private static final String HOST_BROWSER_LAUNCHER_CLASS_NAME =
32 "org.chromium.webapk.lib.runtime_library.HostBrowserLauncher"; 37 "org.chromium.webapk.lib.runtime_library.HostBrowserLauncher";
33 38
34 // Action for launching {@link WebappLauncherActivity}. Must stay in sync wi th 39 // Action for launching {@link WebappLauncherActivity}. Must stay in sync wi th
35 // {@link WebappLauncherActivity#ACTION_START_WEBAPP}. 40 // {@link WebappLauncherActivity#ACTION_START_WEBAPP}.
36 public static final String ACTION_START_WEBAPK = 41 public static final String ACTION_START_WEBAPK =
37 "com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_W EBAPP"; 42 "com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_W EBAPP";
38 43
39 // Must stay in sync with 44 // Must stay in sync with
40 // {@link org.chromium.chrome.browser.ShortcutHelper#REUSE_URL_MATCHING_TAB_ ELSE_NEW_TAB}. 45 // {@link org.chromium.chrome.browser.ShortcutHelper#REUSE_URL_MATCHING_TAB_ ELSE_NEW_TAB}.
41 private static final String REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB = 46 private static final String REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB =
42 "REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB"; 47 "REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB";
43 48
44 /** 49 /**
45 * Key for passing app icon id. 50 * Key for passing app icon id.
46 */ 51 */
47 private static final String KEY_APP_ICON_ID = "app_icon_id"; 52 private static final String KEY_APP_ICON_ID = "app_icon_id";
48 53
54 private String mOverrideUrl;
55 private String mStartUrl;
56
57 // A dialog that asks user to choose runtime host to launch this WebAPK.
58 private DialogFragment mDialog;
49 /** 59 /**
50 * Creates install Intent. 60 * Creates install Intent.
51 * @param packageName Package to install. 61 * @param packageName Package to install.
52 * @return The intent. 62 * @return The intent.
53 */ 63 */
54 public static Intent createInstallIntent(String packageName) { 64 public static Intent createInstallIntent(String packageName) {
55 String marketUrl = "market://details?id=" + packageName; 65 String marketUrl = "market://details?id=" + packageName;
56 return new Intent(Intent.ACTION_VIEW, Uri.parse(marketUrl)); 66 return new Intent(Intent.ACTION_VIEW, Uri.parse(marketUrl));
57 } 67 }
58 68
59 @Override 69 @Override
60 protected void onCreate(Bundle savedInstanceState) { 70 protected void onCreate(Bundle savedInstanceState) {
61 super.onCreate(savedInstanceState); 71 super.onCreate(savedInstanceState);
62 launch(); 72 launch();
pkotwicz 2017/05/24 04:19:29 I don't think that having a separate launch() func
Xi Han 2017/05/24 16:52:37 Agree, deleted.
63 finish();
64 } 73 }
65 74
66 /** 75 /**
67 * Launches WebAPK. 76 * Launches WebAPK.
68 */ 77 */
69 private void launch() { 78 private void launch() {
70 String overrideUrl = getOverrideUrl(); 79 mOverrideUrl = getOverrideUrl();
71 String startUrl = (overrideUrl != null) ? overrideUrl : getStartUrl(); 80 mStartUrl = (mOverrideUrl != null) ? mOverrideUrl : getStartUrl();
72 if (startUrl == null) { 81 if (mStartUrl == null) {
82 finish();
73 return; 83 return;
74 } 84 }
75 85
76 if (launchHostBrowserInWebApkMode(startUrl, overrideUrl)) { 86 launchHostBrowserInWebApkMode();
77 return;
78 }
79 if (launchBrowser(startUrl)) {
80 return;
81 }
82 installBrowser();
83 } 87 }
84 88
85 /** 89 /**
86 * Launches host browser in WebAPK mode. 90 * Launches host browser in WebAPK mode.
87 * @return True if successful. 91 * @return True if successful.
88 */ 92 */
89 private boolean launchHostBrowserInWebApkMode(String startUrl, String overri deUrl) { 93 private void launchHostBrowserInWebApkMode() {
pkotwicz 2017/05/24 04:19:29 I think that it now makes sense to merge this func
Xi Han 2017/05/24 16:52:37 Acknowledged.
90 Log.v(TAG, "Url of the WebAPK: " + startUrl); 94 Log.v(TAG, "Url of the WebAPK: " + mStartUrl);
91 String packageName = getPackageName(); 95 String packageName = getPackageName();
92 Log.v(TAG, "Package name of the WebAPK:" + packageName); 96 Log.v(TAG, "Package name of the WebAPK:" + packageName);
93 97
94 String runtimeHost = WebApkUtils.getHostBrowserPackageName(this); 98 String runtimeHost = WebApkUtils.getHostBrowserPackageName(this);
95 boolean isFromExternalIntent = (overrideUrl != null); 99 if (!TextUtils.isEmpty(runtimeHost) && launchInHostBrowser(runtimeHost)) {
100 finish();
101 } else {
pkotwicz 2017/05/24 04:19:29 My preference is to make the try/catch statement a
Xi Han 2017/05/24 16:52:37 Done.
102 try {
103 mDialog = ChooseHostBrowserDialogFragment.newInstance(new URL(mS tartUrl).getHost());
104 mDialog.show(getSupportFragmentManager(), "ChooseHostBrowserDial ogFragment");
105 } catch (MalformedURLException e) {
106 Log.e(TAG, "Unable to create a dialog to choose the host browser .");
107 finish();
108 }
109 }
110 }
111
112 /** Retrieves URL from the intent's data. Returns null if a URL could not be retrieved. */
113 private String getOverrideUrl() {
114 String overrideUrl = getIntent().getDataString();
115 if (overrideUrl != null && overrideUrl.startsWith("https:")) {
116 return overrideUrl;
117 }
118 return null;
119 }
120
121 /** Returns the start URL from the Android Manifest. */
122 private String getStartUrl() {
123 ApplicationInfo appInfo;
124 try {
125 appInfo = getPackageManager().getApplicationInfo(
126 getPackageName(), PackageManager.GET_META_DATA);
127 } catch (NameNotFoundException e) {
128 return null;
129 }
130 return appInfo.metaData.getString(WebApkMetaDataKeys.START_URL);
131 }
132
133 @Override
134 public void onHostBrowserSelected(String runtimeHost) {
135 Set<String> installedBrowsers = WebApkUtils.getInstalledBrowsers(getPack ageManager());
136 if (installedBrowsers.contains(runtimeHost)) {
137 launchInHostBrowser(runtimeHost);
138 } else {
139 installBrowser(runtimeHost);
140 }
141 // It is safe to cache the runtimeHost to the share pref if user didn't install the browser
142 // in {@link installBrowser}. On next launch, {@link WebApkUtils#getHost BrowserPackageName}
143 // will catch it, and the dialog to choose host browser will show again. If user did install
144 // the browser chosen, saving the runtimeHost to the shared pref can avo id the dialog to
145 // show.
146 WebApkUtils.writeHostBrowserToSharedPref(this, runtimeHost);
147 finish();
148 }
149
150 @Override
151 public void onQuit() {
152 finish();
153 }
154
155 private boolean launchInHostBrowser(String runtimeHost) {
156 boolean isFromExternalIntent = (mOverrideUrl != null);
96 int source = getIntent().getIntExtra(WebApkConstants.EXTRA_SOURCE, 0); 157 int source = getIntent().getIntExtra(WebApkConstants.EXTRA_SOURCE, 0);
97 if (isFromExternalIntent && source == WebApkConstants.SHORTCUT_SOURCE_UN KNOWN) { 158 if (isFromExternalIntent && source == WebApkConstants.SHORTCUT_SOURCE_UN KNOWN) {
98 source = WebApkConstants.SHORTCUT_SOURCE_EXTERNAL_INTENT; 159 source = WebApkConstants.SHORTCUT_SOURCE_EXTERNAL_INTENT;
99 } 160 }
100 161
101 // The override URL is non null when the WebAPK is launched from a deep link. The WebAPK 162 // The override URL is non null when the WebAPK is launched from a deep link. The WebAPK
102 // should navigate to the URL in the deep link even if the WebAPK is alr eady open. 163 // should navigate to the URL in the deep link even if the WebAPK is alr eady open.
103 Intent intent = new Intent(); 164 Intent intent = new Intent();
104 intent.setAction(ACTION_START_WEBAPK); 165 intent.setAction(ACTION_START_WEBAPK);
105 intent.setPackage(runtimeHost); 166 intent.setPackage(runtimeHost);
106 intent.putExtra(WebApkConstants.EXTRA_URL, startUrl) 167 intent.putExtra(WebApkConstants.EXTRA_URL, mStartUrl)
107 .putExtra(WebApkConstants.EXTRA_SOURCE, source) 168 .putExtra(WebApkConstants.EXTRA_SOURCE, source)
108 .putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, packageName ) 169 .putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, getPackageN ame())
109 .putExtra(WebApkConstants.EXTRA_WEBAPK_FORCE_NAVIGATION, isFromE xternalIntent); 170 .putExtra(WebApkConstants.EXTRA_WEBAPK_FORCE_NAVIGATION, isFromE xternalIntent);
110 171
111 try { 172 try {
112 startActivity(intent); 173 startActivity(intent);
113 return true; 174 return true;
114 } catch (ActivityNotFoundException e) { 175 } catch (ActivityNotFoundException e) {
115 Log.w(TAG, "Unable to launch browser in WebAPK mode."); 176 Log.w(TAG, "Unable to launch browser in WebAPK mode.");
116 e.printStackTrace(); 177 e.printStackTrace();
117 return false; 178 return false;
118 } 179 }
119 } 180 }
120 181
121 /** 182 /**
122 * Launches browser (not necessarily the host browser).
123 * @param startUrl URL to navigate browser to.
124 * @return True if successful.
125 */
126 private boolean launchBrowser(String startUrl) {
127 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl));
128 intent.addCategory(Intent.CATEGORY_BROWSABLE);
129
130 // The WebAPK can handle {@link startUrl}. Set a selector to prevent the WebAPK from
131 // launching itself.
132 try {
133 Intent selectorIntent = Intent.parseUri("https://", Intent.URI_INTEN T_SCHEME);
134 intent.setSelector(selectorIntent);
135 } catch (URISyntaxException e) {
136 return false;
137 }
138
139 // Add extras in case that the URL is launched in Chrome.
140 int source =
141 getIntent().getIntExtra(WebApkConstants.EXTRA_SOURCE, Intent.URI _INTENT_SCHEME);
142 intent.putExtra(REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true)
143 .putExtra(WebApkConstants.EXTRA_SOURCE, source);
144
145 try {
146 startActivity(intent);
147 } catch (ActivityNotFoundException e) {
148 return false;
149 }
150 return true;
151 }
152
153 /**
154 * Launches the Play Store with the host browser's page. 183 * Launches the Play Store with the host browser's page.
155 */ 184 */
156 private void installBrowser() { 185 private void installBrowser(String hostBrowserPackageName) {
157 String hostBrowserPackageName = WebApkUtils.getHostBrowserPackageName(th is);
158 if (hostBrowserPackageName == null) {
159 return;
160 }
161
162 try { 186 try {
163 startActivity(createInstallIntent(hostBrowserPackageName)); 187 startActivity(createInstallIntent(hostBrowserPackageName));
164 } catch (ActivityNotFoundException e) { 188 } catch (ActivityNotFoundException e) {
165 } 189 }
166 } 190 }
167
168 /** Retrieves URL from the intent's data. Returns null if a URL could not be retrieved. */
169 private String getOverrideUrl() {
170 String overrideUrl = getIntent().getDataString();
171 if (overrideUrl != null && overrideUrl.startsWith("https:")) {
172 return overrideUrl;
173 }
174 return null;
175 }
176
177 /** Returns the start URL from the Android Manifest. */
178 private String getStartUrl() {
179 ApplicationInfo appInfo;
180 try {
181 appInfo = getPackageManager().getApplicationInfo(
182 getPackageName(), PackageManager.GET_META_DATA);
183 } catch (NameNotFoundException e) {
184 return null;
185 }
186 return appInfo.metaData.getString(WebApkMetaDataKeys.START_URL);
187 }
188 } 191 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698