1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.browserservices;
6 
7 import android.app.PendingIntent;
8 import android.content.ComponentName;
9 import android.content.Intent;
10 import android.graphics.Color;
11 import android.graphics.drawable.Drawable;
12 import android.widget.RemoteViews;
13 
14 import androidx.annotation.IntDef;
15 import androidx.annotation.Nullable;
16 import androidx.browser.customtabs.CustomTabsIntent;
17 import androidx.browser.customtabs.CustomTabsSessionToken;
18 import androidx.browser.trusted.TrustedWebActivityDisplayMode;
19 import androidx.browser.trusted.sharing.ShareData;
20 import androidx.browser.trusted.sharing.ShareTarget;
21 
22 import org.chromium.chrome.browser.customtabs.CustomButtonParams;
23 import org.chromium.chrome.browser.flags.ActivityType;
24 import org.chromium.chrome.browser.webapps.WebApkExtras;
25 import org.chromium.chrome.browser.webapps.WebappExtras;
26 import org.chromium.device.mojom.ScreenOrientationLockType;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.Collections;
31 import java.util.List;
32 
33 /**
34  * Base class for model classes which parse incoming intent for customization data.
35  */
36 public abstract class BrowserServicesIntentDataProvider {
37     // The type of UI for Custom Tab to use.
38     @IntDef({CustomTabsUiType.DEFAULT, CustomTabsUiType.MEDIA_VIEWER,
39             CustomTabsUiType.PAYMENT_REQUEST, CustomTabsUiType.INFO_PAGE,
40             CustomTabsUiType.READER_MODE, CustomTabsUiType.MINIMAL_UI_WEBAPP,
41             CustomTabsUiType.OFFLINE_PAGE})
42     @Retention(RetentionPolicy.SOURCE)
43     public @interface CustomTabsUiType {
44         int DEFAULT = 0;
45         int MEDIA_VIEWER = 1;
46         int PAYMENT_REQUEST = 2;
47         int INFO_PAGE = 3;
48         int READER_MODE = 4;
49         int MINIMAL_UI_WEBAPP = 5;
50         int OFFLINE_PAGE = 6;
51         int READ_LATER = 7;
52     }
53 
54     // The type of Disclosure for TWAs to use.
55     @IntDef({TwaDisclosureUi.DEFAULT, TwaDisclosureUi.V1_INFOBAR,
56             TwaDisclosureUi.V2_NOTIFICATION_OR_SNACKBAR})
57     @Retention(RetentionPolicy.SOURCE)
58     public @interface TwaDisclosureUi {
59         int DEFAULT = -1;
60         int V1_INFOBAR = 0;
61         int V2_NOTIFICATION_OR_SNACKBAR = 1;
62     }
63 
64     /**
65      * @return The type of the Activity;
66      */
getActivityType()67     public abstract @ActivityType int getActivityType();
68 
69     /**
70      * @return the Intent this instance was created with.
71      */
72     @Nullable
getIntent()73     public Intent getIntent() {
74         return null;
75     }
76 
77     /**
78      * @return The session specified in the intent, or null.
79      */
80     @Nullable
getSession()81     public CustomTabsSessionToken getSession() {
82         return null;
83     }
84 
85     /**
86      * @return The keep alive service intent specified in the intent, or null.
87      */
88     @Nullable
getKeepAliveServiceIntent()89     public Intent getKeepAliveServiceIntent() {
90         return null;
91     }
92 
93     /**
94      * @return Whether chrome should animate when it finishes. We show animations only if the client
95      *         app has supplied the correct animation resources via intent extra.
96      */
shouldAnimateOnFinish()97     public boolean shouldAnimateOnFinish() {
98         return false;
99     }
100 
101     /**
102      * @return The package name of the client app. This is used for a workaround in order to
103      *         retrieve the client's animation resources.
104      */
105     @Nullable
getClientPackageName()106     public String getClientPackageName() {
107         return null;
108     }
109 
110     /**
111      * @return The resource id for enter animation, which is used in
112      *         {@link Activity#overridePendingTransition(int, int)}.
113      */
getAnimationEnterRes()114     public int getAnimationEnterRes() {
115         return 0;
116     }
117 
118     /**
119      * @return The resource id for exit animation, which is used in
120      *         {@link Activity#overridePendingTransition(int, int)}.
121      */
getAnimationExitRes()122     public int getAnimationExitRes() {
123         return 0;
124     }
125 
126     /**
127      * Checks whether or not the Intent is from Chrome or other trusted first party.
128      *
129      * @deprecated This method is not reliable, see https://crbug.com/832124
130      */
131     @Deprecated
isTrustedIntent()132     public boolean isTrustedIntent() {
133         return false;
134     }
135 
136     /**
137      * @return The URL that should be used from this intent. If it is a WebLite url, it may be
138      *         overridden if the Data Reduction Proxy is using Lo-Fi previews.
139      * Must be called only after native has loaded.
140      */
141     @Nullable
getUrlToLoad()142     public String getUrlToLoad() {
143         return null;
144     }
145 
146     /**
147      * @return Whether url bar hiding should be enabled in the custom tab.
148      */
shouldEnableUrlBarHiding()149     public boolean shouldEnableUrlBarHiding() {
150         return true;
151     }
152 
153     /**
154      * @return The toolbar color.
155      */
getToolbarColor()156     public int getToolbarColor() {
157         return Color.WHITE;
158     }
159 
160     /**
161      * @return Whether the intent specifies a custom toolbar color.
162      */
hasCustomToolbarColor()163     public boolean hasCustomToolbarColor() {
164         return false;
165     }
166 
167     /**
168      * @return The navigation bar color specified in the intent, or null if not specified.
169      */
170     @Nullable
getNavigationBarColor()171     public Integer getNavigationBarColor() {
172         return null;
173     }
174 
175     /**
176      * @return The navigation bar divider color specified in the intent, or null if not specified.
177      */
178     @Nullable
getNavigationBarDividerColor()179     public Integer getNavigationBarDividerColor() {
180         return null;
181     }
182 
183     /**
184      * @return The drawable of the icon of close button shown in the custom tab toolbar.
185      */
186     @Nullable
getCloseButtonDrawable()187     public Drawable getCloseButtonDrawable() {
188         return null;
189     }
190 
191     /**
192      * @return The title visibility state for the toolbar.
193      */
getTitleVisibilityState()194     public int getTitleVisibilityState() {
195         return CustomTabsIntent.NO_TITLE;
196     }
197 
198     /**
199      * @return Whether the default share item should be shown in the menu.
200      */
shouldShowShareMenuItem()201     public boolean shouldShowShareMenuItem() {
202         return false;
203     }
204 
205     /**
206      * @return The params for the custom buttons that show on the toolbar.
207      */
getCustomButtonsOnToolbar()208     public List<CustomButtonParams> getCustomButtonsOnToolbar() {
209         return Collections.emptyList();
210     }
211 
212     /**
213      * @return The list of params representing the buttons on the bottombar.
214      */
getCustomButtonsOnBottombar()215     public List<CustomButtonParams> getCustomButtonsOnBottombar() {
216         return Collections.emptyList();
217     }
218 
219     /**
220      * @return The color of the bottom bar.
221      */
getBottomBarColor()222     public int getBottomBarColor() {
223         return getToolbarColor();
224     }
225 
226     /**
227      * @return The {@link RemoteViews} to show on the bottom bar, or null if the extra is not
228      *         specified.
229      */
230     @Nullable
getBottomBarRemoteViews()231     public RemoteViews getBottomBarRemoteViews() {
232         return null;
233     }
234 
235     /**
236      * @return A array of {@link View} ids, of which the onClick event is handled by the Activity.
237      */
238     @Nullable
getClickableViewIDs()239     public int[] getClickableViewIDs() {
240         return null;
241     }
242 
243     /**
244      * @return The {@link PendingIntent} that is sent when the user clicks on the remote view.
245      */
246     @Nullable
getRemoteViewsPendingIntent()247     public PendingIntent getRemoteViewsPendingIntent() {
248         return null;
249     }
250 
251     /**
252      * Gets params for all custom buttons, which is the combination of
253      * {@link #getCustomButtonsOnBottombar()} and {@link #getCustomButtonsOnToolbar()}.
254      */
getAllCustomButtons()255     public List<CustomButtonParams> getAllCustomButtons() {
256         return Collections.emptyList();
257     }
258 
259     /**
260       @return Titles of menu items that were passed from client app via intent.
261      */
getMenuTitles()262     public List<String> getMenuTitles() {
263         return Collections.emptyList();
264     }
265 
266     /**
267      * @return Whether or not the Activity is being launched by an intent fired by Chrome itself.
268      */
isOpenedByChrome()269     public boolean isOpenedByChrome() {
270         return false;
271     }
272 
273     @CustomTabsUiType
getUiType()274     public int getUiType() {
275         return CustomTabsUiType.DEFAULT;
276     }
277 
278     /**
279      * @return URL that should be loaded in place of the URL in {@link Intent#getData()}.
280      */
281     @Nullable
getMediaViewerUrl()282     public String getMediaViewerUrl() {
283         return null;
284     }
285 
286     /**
287      * @return Whether to enable the embedded media experience.
288      */
shouldEnableEmbeddedMediaExperience()289     public boolean shouldEnableEmbeddedMediaExperience() {
290         return false;
291     }
292 
isFromMediaLauncherActivity()293     public boolean isFromMediaLauncherActivity() {
294         return false;
295     }
296 
297     /**
298      * @return Initial RGB background color.
299      */
getInitialBackgroundColor()300     public int getInitialBackgroundColor() {
301         return Color.TRANSPARENT;
302     }
303 
304     /**
305      * @return Whether there should be a star button in the menu.
306      */
shouldShowStarButton()307     public boolean shouldShowStarButton() {
308         return true;
309     }
310 
311     /**
312      * @return Whether there should be a download button in the menu.
313      */
shouldShowDownloadButton()314     public boolean shouldShowDownloadButton() {
315         return true;
316     }
317 
318     /**
319      * @return Whether the Activity should be opened in incognito mode.
320      */
isIncognito()321     public boolean isIncognito() {
322         return false;
323     }
324 
325     /**
326      * @return Whether the Activity should attempt to display a Trusted Web Activity.
327      */
isTrustedWebActivity()328     public final boolean isTrustedWebActivity() {
329         return getActivityType() == ActivityType.TRUSTED_WEB_ACTIVITY;
330     }
331 
332     /**
333      * @return Whether the Activity is either a Webapp or a WebAPK activity.
334      */
isWebappOrWebApkActivity()335     public final boolean isWebappOrWebApkActivity() {
336         return getActivityType() == ActivityType.WEBAPP
337                 || getActivityType() == ActivityType.WEB_APK;
338     }
339 
340     /**
341      * @return Whether the Activity is a WebAPK activity.
342      */
isWebApkActivity()343     public final boolean isWebApkActivity() {
344         return getActivityType() == ActivityType.WEB_APK;
345     }
346 
347     /**
348      * @return Whether the Activity should attempt to load a dynamic module.
349      *
350      * Will return false if native is not initialized.
351      */
isDynamicModuleEnabled()352     public boolean isDynamicModuleEnabled() {
353         return false;
354     }
355 
356     /**
357      * Returns {@link TrustedWebActivityDisplayMode} supplied in the intent.
358      */
359     @Nullable
getTwaDisplayMode()360     public TrustedWebActivityDisplayMode getTwaDisplayMode() {
361         return null;
362     }
363 
364     /**
365      * Returns {@link ScreenOrientationLockType} supplied in the intent.
366      */
getDefaultOrientation()367     public int getDefaultOrientation() {
368         return ScreenOrientationLockType.DEFAULT;
369     }
370 
371     /**
372      * @return The component name of the module entry point, or null if not specified.
373      */
374     @Nullable
getModuleComponentName()375     public ComponentName getModuleComponentName() {
376         return null;
377     }
378 
379     /**
380      * @return The resource identifier for the dex that contains module code. {@code 0} if no dex
381      * resource is provided.
382      */
383     @Nullable
getModuleDexAssetName()384     public String getModuleDexAssetName() {
385         return null;
386     }
387 
388     /**
389      * @return Additional origins associated with a Trusted Web Activity client app.
390      */
391     @Nullable
getTrustedWebActivityAdditionalOrigins()392     public List<String> getTrustedWebActivityAdditionalOrigins() {
393         return null;
394     }
395 
396     /**
397      * @return ISO 639 code of target language the page should be translated to.
398      * This method requires native.
399      */
400     @Nullable
getTranslateLanguage()401     public String getTranslateLanguage() {
402         return null;
403     }
404 
405     /**
406      * Returns {@link ShareTarget} describing the share target, or null if there is no associated
407      * share target.
408      */
409     @Nullable
getShareTarget()410     public ShareTarget getShareTarget() {
411         return null;
412     }
413 
414     /**
415      * Returns {@link ShareData} if there is data to be shared, and null otherwise.
416      */
417     @Nullable
getShareData()418     public ShareData getShareData() {
419         return null;
420     }
421 
422     /**
423      * Returns {@link WebappExtras} if the intent targets a webapp, and null otherwise.
424      */
425     @Nullable
getWebappExtras()426     public WebappExtras getWebappExtras() {
427         return null;
428     }
429 
430     /**
431      * Returns {@link WebApkExtras} if the intent targets a WebAPK, and null otherwise.
432      */
433     @Nullable
getWebApkExtras()434     public WebApkExtras getWebApkExtras() {
435         return null;
436     }
437 
438     /**
439      * @return Whether the bottom bar should be shown.
440      */
shouldShowBottomBar()441     public final boolean shouldShowBottomBar() {
442         return !getCustomButtonsOnBottombar().isEmpty() || getBottomBarRemoteViews() != null;
443     }
444 
445     /**
446      * Searches for the toolbar button with the given {@code id} and returns its index.
447      * @param id The ID of a toolbar button to search for.
448      * @return The index of the toolbar button with the given {@code id}, or -1 if no such button
449      *         can be found.
450      */
getCustomToolbarButtonIndexForId(int id)451     public final int getCustomToolbarButtonIndexForId(int id) {
452         List<CustomButtonParams> toolbarButtons = getCustomButtonsOnToolbar();
453         for (int i = 0; i < toolbarButtons.size(); i++) {
454             if (toolbarButtons.get(i).getId() == id) return i;
455         }
456         return -1;
457     }
458 
459     /**
460      * @return The {@link CustomButtonParams} (either on the toolbar or bottom bar) with the given
461      *         {@code id}, or null if no such button can be found.
462      */
463     @Nullable
getButtonParamsForId(int id)464     public final CustomButtonParams getButtonParamsForId(int id) {
465         List<CustomButtonParams> customButtonParams = getAllCustomButtons();
466         for (CustomButtonParams params : customButtonParams) {
467             // A custom button params will always carry an ID. If the client calls updateVisuals()
468             // without an id, we will assign the toolbar action button id to it.
469             if (id == params.getId()) return params;
470         }
471         return null;
472     }
473 
474     /**
475      * @return See {@link #getUiType()}.
476      */
isMediaViewer()477     public final boolean isMediaViewer() {
478         return getUiType() == CustomTabsUiType.MEDIA_VIEWER;
479     }
480 
481     /**
482      * @return If the Activity is an info page.
483      */
isInfoPage()484     public final boolean isInfoPage() {
485         return getUiType() == CustomTabsUiType.INFO_PAGE;
486     }
487 
488     /**
489      * @return Whether the Activity is for payment request.
490      */
isForPaymentRequest()491     public final boolean isForPaymentRequest() {
492         return getUiType() == CustomTabsUiType.PAYMENT_REQUEST;
493     }
494 
495     @Nullable
getFocusIntent()496     public PendingIntent getFocusIntent() {
497         return null;
498     }
499 
500     @TwaDisclosureUi
getTwaDisclosureUi()501     public int getTwaDisclosureUi() {
502         return TwaDisclosureUi.DEFAULT;
503     }
504 
505     @Nullable
getGsaExperimentIds()506     public int[] getGsaExperimentIds() {
507         return null;
508     }
509 
510     /**
511      * Returns true if omnibox should hide cct related visits.
512      */
shouldHideOmniboxSuggestionsForCctVisits()513     public boolean shouldHideOmniboxSuggestionsForCctVisits() {
514         return false;
515     }
516 
517     /**
518      * Returns true if visits from cct should be hidden.
519      */
shouldHideCctVisits()520     public boolean shouldHideCctVisits() {
521         return false;
522     }
523 
524     /**
525      * Returns true if new notification requests from cct should be blocked.
526      */
shouldBlockNewNotificationRequests()527     public boolean shouldBlockNewNotificationRequests() {
528         return false;
529     }
530 
531     /**
532      * Returns true if 'open in chrome' should be shown in the tab context menu.
533      */
shouldShowOpenInChromeMenuItemInContextMenu()534     public boolean shouldShowOpenInChromeMenuItemInContextMenu() {
535         return true;
536     }
537 
538     /**
539      * Returns true if 'open in chrome' should be shown in the app menu.
540      */
shouldShowOpenInChromeMenuItem()541     public boolean shouldShowOpenInChromeMenuItem() {
542         return true;
543     }
544 
545     /**
546      * @return Whether the incognito icon in the toolbar should be hidden in cct-incognito mode.
547      */
shouldHideIncognitoIconOnToolbarInCct()548     public boolean shouldHideIncognitoIconOnToolbarInCct() {
549         return false;
550     }
551 }
552