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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java

Issue 1989283002: Upstream: Launch WebApkActivity from WebAPK. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Introduce WebApkActivity. Created 4 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.chrome.browser.webapps; 5 package org.chromium.chrome.browser.webapps;
6 6
7 import android.app.Activity; 7 import android.app.Activity;
8 import android.content.Intent; 8 import android.content.Intent;
9 import android.net.Uri; 9 import android.net.Uri;
10 import android.os.Build; 10 import android.os.Build;
11 import android.os.Bundle; 11 import android.os.Bundle;
12 import android.util.Base64; 12 import android.util.Base64;
13 13
14 import org.chromium.base.ApiCompatibilityUtils; 14 import org.chromium.base.ApiCompatibilityUtils;
15 import org.chromium.base.ApplicationStatus; 15 import org.chromium.base.ApplicationStatus;
16 import org.chromium.base.CommandLine;
16 import org.chromium.base.ContextUtils; 17 import org.chromium.base.ContextUtils;
17 import org.chromium.base.Log; 18 import org.chromium.base.Log;
19 import org.chromium.chrome.browser.ChromeSwitches;
18 import org.chromium.chrome.browser.IntentHandler; 20 import org.chromium.chrome.browser.IntentHandler;
19 import org.chromium.chrome.browser.ShortcutHelper; 21 import org.chromium.chrome.browser.ShortcutHelper;
20 import org.chromium.chrome.browser.document.ChromeLauncherActivity; 22 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
21 import org.chromium.chrome.browser.metrics.LaunchMetrics; 23 import org.chromium.chrome.browser.metrics.LaunchMetrics;
22 import org.chromium.chrome.browser.tab.Tab; 24 import org.chromium.chrome.browser.tab.Tab;
23 import org.chromium.chrome.browser.util.IntentUtils; 25 import org.chromium.chrome.browser.util.IntentUtils;
26 import org.chromium.webapk.lib.common.WebApkConstants;
24 27
25 import java.lang.ref.WeakReference; 28 import java.lang.ref.WeakReference;
26 29
27 /** 30 /**
28 * Launches web apps. This was separated from the ChromeLauncherActivity becaus e the 31 * Launches web apps. This was separated from the ChromeLauncherActivity becaus e the
29 * ChromeLauncherActivity is not allowed to be excluded from Android's Recents: crbug.com/517426. 32 * ChromeLauncherActivity is not allowed to be excluded from Android's Recents: crbug.com/517426.
30 */ 33 */
31 public class WebappLauncherActivity extends Activity { 34 public class WebappLauncherActivity extends Activity {
32 /** 35 /**
33 * Action fired when an Intent is trying to launch a WebappActivity. 36 * Action fired when an Intent is trying to launch a WebappActivity.
(...skipping 10 matching lines...) Expand all
44 if (webappInfo == null) { 47 if (webappInfo == null) {
45 super.onCreate(null); 48 super.onCreate(null);
46 ApiCompatibilityUtils.finishAndRemoveTask(this); 49 ApiCompatibilityUtils.finishAndRemoveTask(this);
47 return; 50 return;
48 } 51 }
49 52
50 super.onCreate(savedInstanceState); 53 super.onCreate(savedInstanceState);
51 Intent intent = getIntent(); 54 Intent intent = getIntent();
52 String webappId = webappInfo.id(); 55 String webappId = webappInfo.id();
53 String webappUrl = webappInfo.uri().toString(); 56 String webappUrl = webappInfo.uri().toString();
57 String webApkPackageName = webappInfo.webApkPackageName();
54 int webappSource = webappInfo.source(); 58 int webappSource = webappInfo.source();
55 59
56 if (webappId != null && webappUrl != null) { 60 if (webappId != null && webappUrl != null) {
57 String webappMacString = IntentUtils.safeGetStringExtra( 61 String webappMacString = IntentUtils.safeGetStringExtra(
58 intent, ShortcutHelper.EXTRA_MAC); 62 intent, ShortcutHelper.EXTRA_MAC);
59 byte[] webappMac = 63 byte[] webappMac =
60 webappMacString == null ? null : Base64.decode(webappMacStri ng, Base64.DEFAULT); 64 webappMacString == null ? null : Base64.decode(webappMacStri ng, Base64.DEFAULT);
61 65
62 Intent launchIntent = null; 66 Intent launchIntent = null;
63 67
64 // Permit the launch to a standalone web app frame if the intent was sent by Chrome, or 68 // Permit the launch to a standalone web app frame if the intent was sent by Chrome, or
65 // if the MAC is present and valid for the URL to be opened. 69 // if the MAC is present and valid for the URL to be opened.
66 boolean isTrusted = IntentHandler.wasIntentSenderChrome(intent, 70 boolean isTrusted = IntentHandler.wasIntentSenderChrome(intent,
67 ContextUtils.getApplicationContext()); 71 ContextUtils.getApplicationContext());
68 boolean isUrlValid = (webappMac != null 72 boolean isUrlValid = (webappMac != null
69 && WebappAuthenticator.isUrlValid(this, webappUrl, webappMac )); 73 && WebappAuthenticator.isUrlValid(this, webappUrl, webappMac ));
74 boolean isValidWebApk = isValidWebApk(webApkPackageName);
75 if (webApkPackageName != null && !isValidWebApk) {
76 isUrlValid = false;
77 }
70 78
71 if (isTrusted || isUrlValid) { 79 if (isTrusted || isUrlValid) {
72 LaunchMetrics.recordHomeScreenLaunchIntoStandaloneActivity(webap pUrl, webappSource); 80 LaunchMetrics.recordHomeScreenLaunchIntoStandaloneActivity(webap pUrl, webappSource);
73 81
74 String activityName = WebappActivity.class.getName(); 82 // Create an intent to launch the Webapp in an unmapped WebappAc tivity or
75 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 83 // WebApkActivity.
76 // Specifically assign the app to a particular WebappActivit y instance. 84 launchIntent = createWebappLaunchIntent(webappInfo, isValidWebAp k);
77 int activityIndex = ActivityAssigner.instance(this).assign(w ebappId);
78 activityName += String.valueOf(activityIndex);
79 }
80
81 // Create an intent to launch the Webapp in an unmapped WebappAc tivity.
82 launchIntent = new Intent();
83 launchIntent.setClassName(this, activityName);
84 webappInfo.setWebappIntentExtras(launchIntent);
85
86 // On L+, firing intents with the exact same data should relaunc h a particular
87 // Activity.
88 launchIntent.setAction(Intent.ACTION_VIEW);
89 launchIntent.setData(Uri.parse(WebappActivity.WEBAPP_SCHEME + ": //" + webappId));
90 } else { 85 } else {
91 Log.e(TAG, "Shortcut (%s) opened in Chrome.", webappUrl); 86 Log.e(TAG, "Shortcut (%s) opened in Chrome.", webappUrl);
92 87
93 // The shortcut data doesn't match the current encoding. Change the intent action 88 // The shortcut data doesn't match the current encoding. Change the intent action
94 // launch the URL with a VIEW Intent in the regular browser. 89 // launch the URL with a VIEW Intent in the regular browser.
95 launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webappUr l)); 90 launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webappUr l));
96 launchIntent.setClassName(getPackageName(), ChromeLauncherActivi ty.class.getName()); 91 launchIntent.setClassName(getPackageName(), ChromeLauncherActivi ty.class.getName());
97 launchIntent.putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE _NEW_TAB, true); 92 launchIntent.putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE _NEW_TAB, true);
98 launchIntent.putExtra(ShortcutHelper.EXTRA_SOURCE, webappSource) ; 93 launchIntent.putExtra(ShortcutHelper.EXTRA_SOURCE, webappSource) ;
94 launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
95 | ApiCompatibilityUtils.getActivityNewDocumentFlag());
99 } 96 }
100 97
101 launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
102 | ApiCompatibilityUtils.getActivityNewDocumentFlag());
103 startActivity(launchIntent); 98 startActivity(launchIntent);
104 } 99 }
105 100
106 ApiCompatibilityUtils.finishAndRemoveTask(this); 101 ApiCompatibilityUtils.finishAndRemoveTask(this);
107 } 102 }
108 103
104 private Intent createWebappLaunchIntent(WebappInfo info, boolean isValidWebA pk) {
105 String activityName = isValidWebApk ? WebApkActivity.class.getName()
106 : WebappActivity.class.getName();
107 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
108 // Specifically assign the app to a particular WebappActivity instan ce.
109 int activityIndex = ActivityAssigner.instance(this).assign(info.id() );
110 activityName += String.valueOf(activityIndex);
111 }
112
113 // Create an intent to launch the Webapp in an unmapped WebappActivity.
114 Intent launchIntent = new Intent();
115 launchIntent.setClassName(this, activityName);
116 info.setWebappIntentExtras(launchIntent);
117
118 // On L+, firing intents with the exact same data should relaunch a part icular
119 // Activity.
120 launchIntent.setAction(Intent.ACTION_VIEW);
121 launchIntent.setData(Uri.parse(WebappActivity.WEBAPP_SCHEME + "://" + in fo.id()));
122
123 if (!isValidWebApk) {
124 // For WebAPK, we don't start a new task for WebApkActivity, it is just on top
125 // of the WebAPK's main activity and in the same task.
gone 2016/05/25 21:50:14 nit: Indentation is messed up.
Xi Han 2016/05/26 17:23:36 Updated:)
126 launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
127 | ApiCompatibilityUtils.getActivityNewDocumentFlag());
128 }
129 return launchIntent;
130 }
131
109 /** 132 /**
110 * Brings a live WebappActivity back to the foreground if one exists for the given tab ID. 133 * Brings a live WebappActivity back to the foreground if one exists for the given tab ID.
111 * @param tabId ID of the Tab to bring back to the foreground. 134 * @param tabId ID of the Tab to bring back to the foreground.
112 * @return True if a live WebappActivity was found, false otherwise. 135 * @return True if a live WebappActivity was found, false otherwise.
113 */ 136 */
114 public static boolean bringWebappToFront(int tabId) { 137 public static boolean bringWebappToFront(int tabId) {
115 if (tabId == Tab.INVALID_TAB_ID) return false; 138 if (tabId == Tab.INVALID_TAB_ID) return false;
116 139
117 for (WeakReference<Activity> activityRef : ApplicationStatus.getRunningA ctivities()) { 140 for (WeakReference<Activity> activityRef : ApplicationStatus.getRunningA ctivities()) {
118 Activity activity = activityRef.get(); 141 Activity activity = activityRef.get();
119 if (activity == null || !(activity instanceof WebappActivity)) conti nue; 142 if (activity == null || !(activity instanceof WebappActivity)) conti nue;
120 143
121 WebappActivity webappActivity = (WebappActivity) activity; 144 WebappActivity webappActivity = (WebappActivity) activity;
122 if (webappActivity.getActivityTab() != null 145 if (webappActivity.getActivityTab() != null
123 && webappActivity.getActivityTab().getId() == tabId) { 146 && webappActivity.getActivityTab().getId() == tabId) {
124 Tab tab = webappActivity.getActivityTab(); 147 Tab tab = webappActivity.getActivityTab();
125 tab.getTabWebContentsDelegateAndroid().activateContents(); 148 tab.getTabWebContentsDelegateAndroid().activateContents();
126 return true; 149 return true;
127 } 150 }
128 } 151 }
129 152
130 return false; 153 return false;
131 } 154 }
155
156 /**
157 * Checks whether the package being targeted is a valid WebAPK.
158 * @param webapkPackageName The package name of the requested WebAPK.
159 * @return true iff all validation criteria are met.
160 */
161 private boolean isValidWebApk(String webapkPackageName) {
162 // TODO(hanxi): Adds more validation checks. For example, whether the We bAPK is signed
163 // by the WebAPK Minting Server.
164 return CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_WEBAPK)
165 && webapkPackageName != null
166 && webapkPackageName.startsWith(WebApkConstants.WEBAPK_PACKAGE_P REFIX);
167 }
132 } 168 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698