Commit 1b5a273a authored by Ran Ji's avatar Ran Ji Committed by Commit Bot

Replace CCT by Minimal UI in WebAPK.

Stop opening a CCT for out-of-scope navigations from WebappActivities.

Bug: 830946, 771418
Change-Id: Ied9c33518488f0bab38366bf2e8b8532c71e3819
Reviewed-on: https://chromium-review.googlesource.com/1003552
Commit-Queue: Ran Ji <ranj@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarPeter Kotwicz <pkotwicz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551731}
parent 09e5a869
......@@ -102,13 +102,6 @@ interface ExternalNavigationDelegate {
*/
void startFileIntent(Intent intent, String referrerUrl, boolean needsToCloseTab);
/**
* Launches a Chrome Custom Tab to be shown on top of a WebappActivity.
* @param url
* @param launchInNewTask Whether the CCT should be launched in a new task.
*/
void launchCctForWebappUrl(String url, boolean launchInNewTask);
/**
* Clobber the current tab and try not to pass an intent when it should be handled by Chrome
* so that we can deliver HTTP referrer information safely.
......
......@@ -19,7 +19,6 @@ import android.os.Build;
import android.os.StrictMode;
import android.provider.Browser;
import android.provider.Telephony;
import android.support.customtabs.CustomTabsIntent;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.WindowManager.BadTokenException;
......@@ -523,17 +522,6 @@ public class ExternalNavigationDelegateImpl implements ExternalNavigationDelegat
tab.loadUrl(loadUrlParams);
}
@Override
public void launchCctForWebappUrl(String url, boolean launchInNewTask) {
Context context = getAvailableContext();
if (!(context instanceof WebappActivity)) return;
CustomTabsIntent customTabIntent =
((WebappActivity) context).buildCustomTabIntentForURL(url);
if (launchInNewTask) customTabIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
customTabIntent.launchUrl(context, Uri.parse(url));
}
@Override
public OverrideUrlLoadingResult clobberCurrentTab(String url, String referrerUrl) {
int transitionType = PageTransition.LINK;
......
......@@ -448,23 +448,6 @@ public class ExternalNavigationHandler {
return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT;
}
// For normal links in a webapp, launch a CCT when a user navigates to a link which
// is outside of the webapp's scope. This is the preferred handling for when a user
// navigates outside of a webapp's scope. The benefit of showing out-of-scope web
// content in a CCT is that the state of the in-scope page (e.g. scroll position) is
// preserved and is available when the user closes the CCT. This enables the state
// of the twitter.com web page to be preserved when a user taps an out-of-scope
// link. WebappActivity has fallback behavior for cases that a CCT is not launched
// (e.g. JS navigation when PWA is in the background). The fallback behavior changes
// the appearance of the WebappActivity to make it look like a CCT.
if (webappScopePolicyDirective
== WebappScopePolicy.NavigationDirective.LAUNCH_CCT) {
mDelegate.launchCctForWebappUrl(params.getUrl(),
params.shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent());
if (DEBUG) Log.i(TAG, "OVERRIDE_WITH_EXTERNAL_INTENT: Launch CCT");
return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT;
}
if (DEBUG) Log.i(TAG, "NO_OVERRIDE: No specialized handler for URL");
return OverrideUrlLoadingResult.NO_OVERRIDE;
}
......
......@@ -16,10 +16,8 @@ import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.os.SystemClock;
import android.provider.Browser;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.customtabs.CustomTabsIntent;
import android.support.customtabs.CustomTabsService;
import android.support.customtabs.CustomTabsSessionToken;
import android.support.customtabs.TrustedWebUtils;
......@@ -50,7 +48,6 @@ import org.chromium.chrome.browser.browserservices.OriginVerifier;
import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.customtabs.CustomTabAppMenuPropertiesDelegate;
import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver;
import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
......@@ -771,23 +768,6 @@ public class WebappActivity extends SingleTabActivity {
getBrowserSession());
}
public CustomTabsIntent buildCustomTabIntentForURL(String url) {
CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();
intentBuilder.setShowTitle(true);
if (mWebappInfo.hasValidThemeColor()) {
// Need to cast as themeColor is a long to contain possible error results.
intentBuilder.setToolbarColor((int) mWebappInfo.themeColor());
}
CustomTabsIntent customTabIntent = intentBuilder.build();
customTabIntent.intent.setPackage(getPackageName());
customTabIntent.intent.putExtra(
CustomTabIntentDataProvider.EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER, true);
customTabIntent.intent.putExtra(
CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE, getActivityType());
customTabIntent.intent.putExtra(Browser.EXTRA_APPLICATION_ID, mWebappInfo.apkPackageName());
return customTabIntent;
}
private void updateToolbarCloseButtonVisibility() {
if (WebappBrowserControlsDelegate.shouldShowToolbarCloseButton(this)) {
getToolbarManager().setCloseButtonDrawable(
......
......@@ -19,38 +19,22 @@ public enum WebappScopePolicy {
public boolean isUrlInScope(WebappInfo info, String url) {
return UrlUtilities.sameDomainOrHost(info.uri().toString(), url, true);
}
@Override
protected boolean openOffScopeNavsInCct() {
// This is motivated by redirect based OAuth. Legacy web apps cannot capture in-scope
// URLs to WebappActivity. Redirect based OAuth therefore would move the user to CCT
// and keeps them there even after redirecting back to in-scope URL.
// See crbug.com/771418
return false;
}
},
STRICT {
@Override
public boolean isUrlInScope(WebappInfo info, String url) {
return UrlUtilities.isUrlWithinScope(url, info.scopeUri().toString());
}
@Override
protected boolean openOffScopeNavsInCct() {
return true;
}
};
@Retention(RetentionPolicy.SOURCE)
@IntDef({NavigationDirective.NORMAL_BEHAVIOR,
NavigationDirective.IGNORE_EXTERNAL_INTENT_REQUESTS, NavigationDirective.LAUNCH_CCT})
NavigationDirective.IGNORE_EXTERNAL_INTENT_REQUESTS})
public @interface NavigationDirective {
// No special handling.
int NORMAL_BEHAVIOR = 0;
// The navigation should stay in the webapp. External intent handlers should be ignored.
int IGNORE_EXTERNAL_INTENT_REQUESTS = 1;
// The navigation should launch a CCT.
int LAUNCH_CCT = 2;
}
/**
......@@ -59,17 +43,9 @@ public enum WebappScopePolicy {
*/
abstract boolean isUrlInScope(WebappInfo info, String url);
/**
* @return {@code true} if off-scope URLs should be handled by the Chrome Custom Tab,
* {@code false} otherwise.
*/
protected abstract boolean openOffScopeNavsInCct();
/** Applies the scope policy for navigation to {@link url}. */
public @NavigationDirective int applyPolicyForNavigationToUrl(WebappInfo info, String url) {
if (isUrlInScope(info, url)) return NavigationDirective.IGNORE_EXTERNAL_INTENT_REQUESTS;
return openOffScopeNavsInCct() ? NavigationDirective.LAUNCH_CCT
: NavigationDirective.NORMAL_BEHAVIOR;
return NavigationDirective.NORMAL_BEHAVIOR;
}
}
......@@ -1281,7 +1281,7 @@ public class ExternalNavigationHandlerTest {
/**
* Test that when a webapp with "STRICT scope policy" is navigated outside of the webapp's scope
* by "tapping a link" that a Chrome Custom Tab is launched.
* by "tapping a link" that a Chrome Custom Tab is not launched.
*/
@Test
@SmallTest
......@@ -1293,8 +1293,7 @@ public class ExternalNavigationHandlerTest {
mDelegate.setReferrerWebappPackageName(twaPackageName);
checkUrl(SEARCH_RESULT_URL_FOR_TOM_HANKS)
.expecting(
OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, START_WEBAPP_CCT);
.expecting(OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE);
}
/**
......@@ -1570,11 +1569,6 @@ public class ExternalNavigationHandlerTest {
startFileIntentCalled = true;
}
@Override
public void launchCctForWebappUrl(String url, boolean launchInNewTask) {
startWebappCctIntentCalled = true;
}
@Override
public OverrideUrlLoadingResult clobberCurrentTab(String url, String referrerUrl) {
mNewUrlAfterClobbering = url;
......
......@@ -23,9 +23,6 @@ import org.chromium.base.test.util.ScalableTimeout;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.DeferredStartupHandler;
import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
import org.chromium.chrome.browser.util.IntentUtils;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.ChromeTabUtils;
......@@ -134,7 +131,7 @@ public class WebApkIntegrationTest {
startWebApkActivity("org.chromium.webapk", "https://pwa.rocks/");
waitUntilSplashscreenHides();
// We navigate outside origin and expect Custom Tab to open on top of WebApkActivity.
// We navigate outside origin and expect CCT toolbar to show on top of WebApkActivity.
mActivityTestRule.runJavaScriptCodeInCurrentTab(
"window.top.location = 'https://www.google.com/'");
......@@ -142,22 +139,16 @@ public class WebApkIntegrationTest {
@Override
public boolean isSatisfied() {
Activity activity = ApplicationStatus.getLastTrackedFocusedActivity();
if (!(activity instanceof CustomTabActivity)) {
return false;
}
CustomTabActivity customTab = (CustomTabActivity) activity;
return customTab.getActivityTab() != null
WebappActivity webAppActivity = (WebappActivity) activity;
return webAppActivity.getActivityTab() != null
// Dropping the TLD as Google can redirect to a local site.
&& customTab.getActivityTab().getUrl().startsWith("https://www.google.");
&& webAppActivity.getActivityTab().getUrl().startsWith(
"https://www.google.");
}
});
CustomTabActivity customTab =
(CustomTabActivity) ApplicationStatus.getLastTrackedFocusedActivity();
Assert.assertTrue(
"Sending to external handlers needs to be enabled for redirect back (e.g. OAuth).",
IntentUtils.safeGetBooleanExtra(customTab.getIntent(),
CustomTabIntentDataProvider.EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER, false));
WebappActivityTestRule.assertToolbarShowState(
(WebappActivity) ApplicationStatus.getLastTrackedFocusedActivity(), true);
}
/**
......
......@@ -167,6 +167,16 @@ public class WebappActivityTestRule extends ChromeActivityTestRule<WebappActivit
waitUntilIdle();
}
public static void assertToolbarShowState(
final ChromeActivity activity, final boolean showState) {
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
Assert.assertEquals(showState, activity.getActivityTab().canShowBrowserControls());
}
});
}
/**
* Waits until any loads in progress of the activity under test have completed.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment