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