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

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

Issue 2010403002: Upstream: Add WebAPK security check in WebappLauncherActivity. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pkotwicz@'s comments. Created 4 years, 6 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.CommandLine;
17 import org.chromium.base.ContextUtils; 17 import org.chromium.base.ContextUtils;
18 import org.chromium.base.Log; 18 import org.chromium.base.Log;
19 import org.chromium.chrome.browser.ChromeSwitches; 19 import org.chromium.chrome.browser.ChromeSwitches;
20 import org.chromium.chrome.browser.IntentHandler; 20 import org.chromium.chrome.browser.IntentHandler;
21 import org.chromium.chrome.browser.ShortcutHelper; 21 import org.chromium.chrome.browser.ShortcutHelper;
22 import org.chromium.chrome.browser.document.ChromeLauncherActivity; 22 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
23 import org.chromium.chrome.browser.metrics.LaunchMetrics; 23 import org.chromium.chrome.browser.metrics.LaunchMetrics;
24 import org.chromium.chrome.browser.tab.Tab; 24 import org.chromium.chrome.browser.tab.Tab;
25 import org.chromium.chrome.browser.util.IntentUtils; 25 import org.chromium.chrome.browser.util.IntentUtils;
26 import org.chromium.webapk.lib.common.WebApkConstants; 26 import org.chromium.webapk.lib.client.WebApkValidator;
27 27
28 import java.lang.ref.WeakReference; 28 import java.lang.ref.WeakReference;
29 29
30 /** 30 /**
31 * 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
32 * 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.
33 */ 33 */
34 public class WebappLauncherActivity extends Activity { 34 public class WebappLauncherActivity extends Activity {
35 /** 35 /**
36 * Action fired when an Intent is trying to launch a WebappActivity. 36 * Action fired when an Intent is trying to launch a WebappActivity.
(...skipping 14 matching lines...) Expand all
51 } 51 }
52 52
53 super.onCreate(savedInstanceState); 53 super.onCreate(savedInstanceState);
54 Intent intent = getIntent(); 54 Intent intent = getIntent();
55 String webappId = webappInfo.id(); 55 String webappId = webappInfo.id();
56 String webappUrl = webappInfo.uri().toString(); 56 String webappUrl = webappInfo.uri().toString();
57 String webApkPackageName = webappInfo.webApkPackageName(); 57 String webApkPackageName = webappInfo.webApkPackageName();
58 int webappSource = webappInfo.source(); 58 int webappSource = webappInfo.source();
59 59
60 if (webappId != null && webappUrl != null) { 60 if (webappId != null && webappUrl != null) {
61 String webappMacString = IntentUtils.safeGetStringExtra(
62 intent, ShortcutHelper.EXTRA_MAC);
63 byte[] webappMac =
64 webappMacString == null ? null : Base64.decode(webappMacStri ng, Base64.DEFAULT);
65
66 Intent launchIntent = null; 61 Intent launchIntent = null;
67 62
68 // Permit the launch to a standalone web app frame if the intent was sent by Chrome, or 63 // Permit the launch to a standalone web app frame if:
gone 2016/05/27 18:20:49 if any of the following are true
Xi Han 2016/05/27 18:33:49 Done.
69 // if the MAC is present and valid for the URL to be opened. 64 // - the request was for a WebAPK that is valid;
70 boolean isTrusted = IntentHandler.wasIntentSenderChrome(intent, 65 // - the MAC is present and valid for the homescreen shortcut to be opened;
71 ContextUtils.getApplicationContext()); 66 // - the intent was sent by Chrome.
72 boolean isUrlValid = (webappMac != null 67 boolean isValidWebApk = isValidWebApk(webApkPackageName, webappUrl);
73 && WebappAuthenticator.isUrlValid(this, webappUrl, webappMac ));
74 boolean isValidWebApk = isValidWebApk(webApkPackageName);
75 if (webApkPackageName != null && !isValidWebApk) {
76 isUrlValid = false;
77 }
78 68
79 if (isTrusted || isUrlValid) { 69 if (isValidWebApk
70 || isValidFullscreenPWA(webappUrl, IntentUtils.safeGetString Extra(
71 intent, ShortcutHelper.EXTRA_MAC))
72 || wasIntentFromChrome(intent)) {
80 LaunchMetrics.recordHomeScreenLaunchIntoStandaloneActivity(webap pUrl, webappSource); 73 LaunchMetrics.recordHomeScreenLaunchIntoStandaloneActivity(webap pUrl, webappSource);
81 launchIntent = createWebappLaunchIntent(webappInfo, isValidWebAp k); 74 launchIntent = createWebappLaunchIntent(webappInfo, isValidWebAp k);
82 } else { 75 } else {
83 Log.e(TAG, "Shortcut (%s) opened in Chrome.", webappUrl); 76 Log.e(TAG, "Shortcut (%s) opened in Chrome.", webappUrl);
84 77
85 // The shortcut data doesn't match the current encoding. Change the intent action 78 // The shortcut data doesn't match the current encoding. Change the intent action
86 // launch the URL with a VIEW Intent in the regular browser. 79 // launch the URL with a VIEW Intent in the regular browser.
87 launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webappUr l)); 80 launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webappUr l));
88 launchIntent.setClassName(getPackageName(), ChromeLauncherActivi ty.class.getName()); 81 launchIntent.setClassName(getPackageName(), ChromeLauncherActivi ty.class.getName());
89 launchIntent.putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE _NEW_TAB, true); 82 launchIntent.putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE _NEW_TAB, true);
90 launchIntent.putExtra(ShortcutHelper.EXTRA_SOURCE, webappSource) ; 83 launchIntent.putExtra(ShortcutHelper.EXTRA_SOURCE, webappSource) ;
91 launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 84 launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
92 | ApiCompatibilityUtils.getActivityNewDocumentFlag()); 85 | ApiCompatibilityUtils.getActivityNewDocumentFlag());
93 } 86 }
94 87
95 startActivity(launchIntent); 88 startActivity(launchIntent);
96 } 89 }
97 90
98 ApiCompatibilityUtils.finishAndRemoveTask(this); 91 ApiCompatibilityUtils.finishAndRemoveTask(this);
99 } 92 }
100 93
101 /** 94 /**
95 * Returns whether the MAC is present and valid for the fullscreen Progressi ve Web App to be
gone 2016/05/27 18:20:49 Web apps are currently almost never Progressive.
Xi Han 2016/05/27 18:33:49 Thanks!
96 * opened.
97 * @param url the url to launch.
98 * @param mac the MAC code provided which must match the requested url.
99 * @return whether the supplied MAC is valid for the supplied url.
100 */
101 private boolean isValidFullscreenPWA(String url, String mac) {
102 return mac != null
103 && WebappAuthenticator.isUrlValid(this, url, Base64.decode(mac, Base64.DEFAULT));
104 }
105
106 private boolean wasIntentFromChrome(Intent intent) {
107 return IntentHandler.wasIntentSenderChrome(intent,
gone 2016/05/27 18:20:49 does this not fit on a line?
Xi Han 2016/05/27 18:33:49 Updated.
108 ContextUtils.getApplicationContext());
109 }
110
111 /*
102 * Creates an Intent to launch the web app. 112 * Creates an Intent to launch the web app.
103 * @param info Information about the web app. 113 * @param info Information about the web app.
104 * @param isWebApk If true, launch the app as a WebApkActivity. If false, l aunch the app as 114 * @param isWebApk If true, launch the app as a WebApkActivity. If false, l aunch the app as
105 * a WebappActivity. 115 * a WebappActivity.
106 */ 116 */
107 private Intent createWebappLaunchIntent(WebappInfo info, boolean isWebApk) { 117 private Intent createWebappLaunchIntent(WebappInfo info, boolean isWebApk) {
108 String activityName = isWebApk ? WebApkActivity.class.getName() 118 String activityName = isWebApk ? WebApkActivity.class.getName()
109 : WebappActivity.class.getName(); 119 : WebappActivity.class.getName();
110 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 120 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
111 // Specifically assign the app to a particular WebappActivity instan ce. 121 // Specifically assign the app to a particular WebappActivity instan ce.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 Tab tab = webappActivity.getActivityTab(); 160 Tab tab = webappActivity.getActivityTab();
151 tab.getTabWebContentsDelegateAndroid().activateContents(); 161 tab.getTabWebContentsDelegateAndroid().activateContents();
152 return true; 162 return true;
153 } 163 }
154 } 164 }
155 165
156 return false; 166 return false;
157 } 167 }
158 168
159 /** 169 /**
160 * Checks whether the package being targeted is a valid WebAPK. 170 * Checks whether the package being targeted is a valid WebAPK and whether t he url supplied
161 * @param webapkPackageName The package name of the requested WebAPK. 171 * can be fulfilled by that WebAPK.
172 *
173 * @param webApkPackage The package name of the requested WebAPK.
174 * @param url The url to navigate to.
162 * @return true iff all validation criteria are met. 175 * @return true iff all validation criteria are met.
163 */ 176 */
164 private boolean isValidWebApk(String webapkPackageName) { 177 private boolean isValidWebApk(String webApkPackage, String url) {
165 // TODO(hanxi): Adds more validation checks. For example, whether the We bAPK is signed 178 if (!CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_WEBAPK)
166 // by the WebAPK Minting Server. 179 || webApkPackage == null) {
167 return CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_WEBAPK) 180 return false;
168 && webapkPackageName != null 181 }
169 && webapkPackageName.startsWith(WebApkConstants.WEBAPK_PACKAGE_P REFIX); 182 if (!WebApkValidator.isValidWebApk(this, webApkPackage)) {
183 Log.d(TAG, "%s is not valid WebAPK", webApkPackage);
184 return false;
185 }
186 if (!webApkPackage.equals(WebApkValidator.queryWebApkPackage(this, url)) ) {
187 Log.d(TAG, "%s is not within scope of %s WebAPK", url, webApkPackage );
188 return false;
189 }
190 return true;
170 } 191 }
171 } 192 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698