Commit 3c311875 authored by Peter E Conn's avatar Peter E Conn Committed by Commit Bot

🛃 Notify Custom Tab host when the user Opens in Browser.

Chrome Custom Tabs have a menu item allowing users to open that page in
their browser. Pass an extraCallback to the Custom Tab host to notify
them.

Bug: 806891
Change-Id: Ia67e8033d261f9be4735f446a3e5a96b58a24f6c
Reviewed-on: https://chromium-review.googlesource.com/890746
Commit-Queue: Peter Conn <peconn@chromium.org>
Reviewed-by: default avatarBernhard Bauer <bauerb@chromium.org>
Reviewed-by: default avatarBenoit L <lizeb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#533302}
parent f18cc9d3
......@@ -1020,8 +1020,10 @@ public class CustomTabActivity extends ChromeActivity {
RecordUserAction.record("MobileMenuAddToBookmarks");
return true;
} else if (id == R.id.open_in_browser_id) {
openCurrentUrlInBrowser(false);
RecordUserAction.record("CustomTabsMenuOpenInChrome");
if (openCurrentUrlInBrowser(false)) {
RecordUserAction.record("CustomTabsMenuOpenInChrome");
mConnection.notifyOpenInBrowser(mSession);
}
return true;
} else if (id == R.id.info_menu_id) {
if (getTabModelSelector().getCurrentTab() == null) return false;
......
......@@ -88,6 +88,8 @@ public class CustomTabsConnection {
@VisibleForTesting
static final String PAGE_LOAD_METRICS_CALLBACK = "NavigationMetrics";
static final String BOTTOM_BAR_SCROLL_STATE_CALLBACK = "onBottomBarScrollStateChanged";
@VisibleForTesting
static final String OPEN_IN_BROWSER_CALLBACK = "onOpenInBrowser";
// For CustomTabs.SpeculationStatusOnStart, see tools/metrics/enums.xml. Append only.
private static final int SPECULATION_STATUS_ON_START_ALLOWED = 0;
......@@ -1010,18 +1012,10 @@ public class CustomTabsConnection {
* @param hidden Whether the bottom bar is hidden or shown.
*/
public void onBottomBarScrollStateChanged(CustomTabsSessionToken session, boolean hidden) {
if (!shouldSendBottomBarScrollStateForSession(session)) return;
CustomTabsCallback callback = mClientManager.getCallbackForSession(session);
Bundle args = new Bundle();
args.putBoolean("hidden", hidden);
try {
callback.extraCallback(BOTTOM_BAR_SCROLL_STATE_CALLBACK, args);
} catch (Exception e) {
// Pokemon exception handling, see below and crbug.com/517023.
return;
}
if (mLogRequests) {
if (safeExtraCallback(session, BOTTOM_BAR_SCROLL_STATE_CALLBACK, args) && mLogRequests) {
logCallback("extraCallback(" + BOTTOM_BAR_SCROLL_STATE_CALLBACK + ")", hidden);
}
}
......@@ -1108,16 +1102,38 @@ public class CustomTabsConnection {
* should be a key specifying the metric name and the metric value as the value.
*/
boolean notifyPageLoadMetrics(CustomTabsSessionToken session, Bundle args) {
if (safeExtraCallback(session, PAGE_LOAD_METRICS_CALLBACK, args)) {
logPageLoadMetricsCallback(args);
return true;
}
return false;
}
/**
* Notifies the application that the user has selected to open the page in their browser.
* @param session Session identifier.
* @return true if success. To protect Chrome exceptions in the client application are swallowed
* and false is returned.
*/
boolean notifyOpenInBrowser(CustomTabsSessionToken session) {
return safeExtraCallback(session, OPEN_IN_BROWSER_CALLBACK,
getExtrasBundleForNavigationEventForSession(session));
}
/**
* Wraps calling extraCallback in a try/catch so exceptions thrown by the host app don't crash
* Chrome. See https://crbug.com/517023.
*/
private boolean safeExtraCallback(CustomTabsSessionToken session, String callbackName,
Bundle args) {
CustomTabsCallback callback = mClientManager.getCallbackForSession(session);
if (callback == null) return false;
try {
callback.extraCallback(PAGE_LOAD_METRICS_CALLBACK, args);
callback.extraCallback(callbackName, args);
} catch (Exception e) {
// Pokemon exception handling, see above and crbug.com/517023.
return false;
}
logPageLoadMetricsCallback(args);
return true;
}
......
......@@ -678,8 +678,26 @@ public class CustomTabActivityTest {
@Test
@SmallTest
@RetryOnFailure
public void testOpenInBrowser() throws InterruptedException {
mCustomTabActivityTestRule.startCustomTabActivityWithIntent(createMinimalCustomTabIntent());
public void testOpenInBrowser() throws InterruptedException, TimeoutException {
// Augment the CustomTabsSession to catch the callback.
CallbackHelper callbackTriggered = new CallbackHelper();
CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
@Override
public void extraCallback(String callbackName, Bundle args) {
if (callbackName.equals(CustomTabsConnection.OPEN_IN_BROWSER_CALLBACK)) {
callbackTriggered.notifyCalled();
}
}
});
Intent intent = new CustomTabsIntent.Builder(session).build().intent;
intent.setData(Uri.parse(mTestPage));
intent.setComponent(new ComponentName(
InstrumentationRegistry.getTargetContext(), ChromeLauncherActivity.class));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW);
filter.addDataScheme(Uri.parse(mTestServer.getURL("/")).getScheme());
final ActivityMonitor monitor =
......@@ -702,6 +720,8 @@ public class CustomTabActivityTest {
return InstrumentationRegistry.getInstrumentation().checkMonitorHit(monitor, 1);
}
});
callbackTriggered.waitForCallback(0);
}
/**
......
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