New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 792371 link

Starred by 3 users

Issue metadata

Status: WontFix
Owner:
Closed: Aug 6
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 2
Type: Bug



Sign in to add a comment

Confirm multiple custom tab behavior

Project Member Reported by mattcary@chromium.org, Dec 6 2017

Issue description

Lijie observed the following. 

1) If two CCTs intents, first A and then B, are sent VERY close to each other in time, two tabs will open --- one for each intent.
2) Adding a few hundred milliseconds delay between the two intents results in only one CCT instance being re-used.
3) In case of 2), if the added delay is somewhat long (~1s), the URL A will be logged in the browser history. When the back button is pressed while on the tab for B, CCT navigates to A.
4) In case of 2), if the added delay is somewhat short (~400ms), the first intent will NOT be logged in the browser history. So pressing the back button closes CCT and brings back AGSA. The navigation to A is visible in the tab before being replaced by B.

We should confirm what the behavior for multiple CCT intents is supposed to be---it's not clear to me if we case (3) to happen all the time or case (4). The current ambiguous behavior seems wrong.

AGSA would like to trigger case 4) all the time.
Is there some signal that we should wait for before sending out the second intent to reuse the same tab instance?
How can they be sure that case 3) doesn't happen?


 

Comment 1 by lizeb@chromium.org, Dec 6 2017

I haven't reproduced it yet, but I think I have a reasonable theory for where this comes from.

Opening several URLs in the same tab is only possible when using a session. The general flow is:
1. Chrome receives an intent, and extracts the session from it. Let's assume there is a session.
2. If the session is the one of the currently foreground custom tab, navigate the tab to the new URL. Otherwise, create a new tab, and set the current active session to the session.

Intent dispatch is asynchronous, meaning that sending two intents back to back doesn't guarantee that the first one has been processed. I'm not even sure they are guaranteed to be processed in order, though in practice they are.

What may happen then is:
1. First intent is received, there is no active session, create a tab
2. Second intent is received, and the session has not been set yet, so create a new tab.

Note that in this case, a third intent coming at a later time will navigate the second tab.

About logging in the browser history, Custom Tabs don't behave any differently from a normal Chrome tab. Browser history is recorded in HistoryTabHelper::DidFinishNavigation(), which runs on the UI thread after the navigation commits. What likely happens here is that the second navigation in the same tab comes before the first one has committed and the tab helper has run, meaning that it is not recorded. It might be something else, but I'm pretty confident that the behavior doesn't diverge from regular chrome tabs.
Thanks for the details, I figured it was something like that, that saves me a lot of sleuthing.

The question is what the right behavior is. In particular, we don't want there to be a race between tab creation and history logging.

Is case (3) really intended, where the user has to navigate through several history steps before returning to the client? I guess that would imply that your step (2) isn't the right behavior, ie, if there is a currently foreground CCT, instead of navigating that tab, it should be destroyed and a new tab created. It appears that's the behavior desired by AGSA.

But maybe that is desired behavior; I don't want to break the implementation.

Looking through the CCT docs isn't very enlightening, the case of multiple intents doesn't seem to be addressed.

Comment 3 by lizeb@chromium.org, Dec 6 2017

To fully solve the issue, there are a few things we can do:
1. Intent race:
  a. Move the session setting to earlier in the initialization
  b. Skip LauncherActivity
  c. Provide a synchronous Service API to launch a tab, that would only return once the session has been recorded.
2. Back going to the parent app after a second navigation:
  - Provide an option to clear the history list when sending an intent. This should not be the default.


For the first issue, (a) and (b) are likely to make the race window narrower, but not eliminate it completely. (c) requires a service change, and will only be available with newer chrome releases, after the client app updates the client code.

For the second one, this behavior should not be the default, but it seems workable, provided that there aren't any dragons lurking there, need to confirm that first. Since this would not be the default, it would require client app changes as well.

Comment 4 by lizeb@chromium.org, Dec 6 2017

Cc: renlijie@google.com
I'm not sure that the theory of two sessions being created is what actually is going on.
Did some debugging and seems like it's always reusing the same session...

NAVIGATION_STARTED = 1;
NAVIGATION_FINISHED = 2;
NAVIGATION_FAILED = 3;
NAVIGATION_ABORTED = 4;
TAB_SHOWN = 5;
TAB_HIDDEN = 6;

two tabs case:
E/CustomTabsSession(14610): session: com.google.android.libraries.chromecustomtabs.CctSession@1760c197
E/CustomTabsSession(14610): onNavigationEvent#1
E/CustomTabsSession(14610): received: Bundle[{transportRtt=110, httpRtt=153, effectiveConnectionType=5}] https://www.kitguru.net/components/graphic-cards/damien-cox/amds-vega-11-might-not-be-a-dedicated-gpu-after-all/
E/CustomTabsSession(14610): onNavigationEvent#5
E/CustomTabsSession(14610): session: com.google.android.libraries.chromecustomtabs.CctSession@1760c197
E/CustomTabsSession(14610): onNavigationEvent#5
E/CustomTabsSession(14610): onNavigationEvent#1
E/CustomTabsSession(14610): received: Bundle[{transportRtt=100, httpRtt=153, effectiveConnectionType=5}] https://googleweblight.com/i?u=https%3A%2F%2Fwww.kitguru.net%2Fcomponents%2Fgraphic-cards%2Fdamien-cox%2Famds-vega-11-might-not-be-a-dedicated-gpu-after-all%2F&norewrite=1

one tab case:
E/CustomTabsSession(14610): session: com.google.android.libraries.chromecustomtabs.CctSession@1760c197
E/CustomTabsSession(14610): onNavigationEvent#1
E/CustomTabsSession(14610): received: Bundle[{transportRtt=110, httpRtt=153, effectiveConnectionType=5}] https://www.kitguru.net/components/graphic-cards/damien-cox/amds-vega-11-might-not-be-a-dedicated-gpu-after-all/
E/CustomTabsSession(14610): onNavigationEvent#5
E/CustomTabsSession(14610): session: com.google.android.libraries.chromecustomtabs.CctSession@1760c197
E/CustomTabsSession(14610): onNavigationEvent#6
E/CustomTabsSession(14610): onNavigationEvent#3
E/CustomTabsSession(14610): onNavigationEvent#1
E/CustomTabsSession(14610): received: Bundle[{transportRtt=80, httpRtt=155, effectiveConnectionType=5}] https://googleweblight.com/i?u=https%3A%2F%2Fwww.kitguru.net%2Fcomponents%2Fgraphic-cards%2Fdamien-cox%2Famds-vega-11-might-not-be-a-dedicated-gpu-after-all%2F&norewrite=1

Sorry, I think we weren't very clear.

If you use two sessions, you should get consistent behavior. Since, IIUC, you are using a single session, starting two intents is vulnerable to the race.
Whether or not the history gets replaced depends on if the first navigation committed before the second intent got processed. I suspect that's what the navigation_failed event means in the one tab case.

In the two tab case, the second intent is received before the first intent appears in the foreground tab. So it gets its own tab.
Thanks for the explanation Matt.
Status: WontFix (was: Started)
Obsoleting due to age/complexity/apparent non-importance. Feel free to re-open if that's not the case.

Sign in to add a comment