OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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.hosted; |
| 6 |
| 7 import android.app.Activity; |
| 8 import android.app.PendingIntent; |
| 9 import android.app.PendingIntent.CanceledException; |
| 10 import android.content.Context; |
| 11 import android.content.Intent; |
| 12 import android.graphics.Bitmap; |
| 13 import android.graphics.Color; |
| 14 import android.net.Uri; |
| 15 import android.os.Bundle; |
| 16 import android.text.TextUtils; |
| 17 import android.util.Pair; |
| 18 |
| 19 import com.google.android.apps.chrome.R; |
| 20 |
| 21 import org.chromium.base.Log; |
| 22 |
| 23 import java.util.ArrayList; |
| 24 import java.util.List; |
| 25 |
| 26 /** |
| 27 * A model class that parses intent from third-party apps and provides results t
o |
| 28 * {@link HostedActivity}. |
| 29 */ |
| 30 public class HostedIntentDataProvider { |
| 31 private static final String TAG = "HostedIntentDataProvider"; |
| 32 |
| 33 /** |
| 34 * Extra used to match the session. Its value is a long returned by |
| 35 * {@link IBrowserConnectionService#newSession}. |
| 36 */ |
| 37 public static final String EXTRA_HOSTED_SESSION_ID = "hosted:session_id"; |
| 38 |
| 39 /** |
| 40 * Extra that changes the background color for the omnibox. colorRes is an i
nt that specifies a |
| 41 * color |
| 42 */ |
| 43 public static final String EXTRA_HOSTED_TOOLBAR_COLOR = "hosted:toolbar_colo
r"; |
| 44 |
| 45 /** |
| 46 * Bundle used for the action button parameters. |
| 47 */ |
| 48 public static final String EXTRA_HOSTED_ACTION_BUTTON_BUNDLE = "hosted:actio
n_button_bundle"; |
| 49 |
| 50 /** |
| 51 * Key that specifies the Bitmap to be used as the image source for the acti
on button. |
| 52 */ |
| 53 public static final String KEY_HOSTED_ICON = "hosted:icon"; |
| 54 |
| 55 /** |
| 56 * Key that specifies the PendingIntent to launch when the action button or
menu item was |
| 57 * clicked. Chrome will be calling {@link PendingIntent#send()} on clicks af
ter adding the url |
| 58 * as data. The client app can call {@link Intent#getDataString()} to get th
e url. |
| 59 */ |
| 60 public static final String KEY_HOSTED_PENDING_INTENT = "hosted:pending_inten
t"; |
| 61 |
| 62 /** |
| 63 * Use an {@code ArrayList<Bundle>} for specifying menu related params. Ther
e should be a |
| 64 * separate Bundle for each custom menu item. |
| 65 */ |
| 66 public static final String EXTRA_HOSTED_MENU_ITEMS = "hosted:menu_items"; |
| 67 |
| 68 /** |
| 69 * Key for the title of a menu item. |
| 70 */ |
| 71 public static final String KEY_HOSTED_MENU_TITLE = "hosted:menu_title"; |
| 72 |
| 73 /** |
| 74 * Bundle constructed out of ActivityOptions that Chrome will be running whe
n it finishes |
| 75 * HostedActivity. A similar ActivityOptions for starting Chrome should be c
onstructed and |
| 76 * given to the startActivity() call that launches Chrome. |
| 77 */ |
| 78 public static final String EXTRA_HOSTED_EXIT_ANIMATION_BUNDLE = "hosted:exit
_animation_bundle"; |
| 79 |
| 80 /** |
| 81 * An invalid session ID, used when none is provided in the intent. |
| 82 */ |
| 83 public static final long INVALID_SESSION_ID = -1; |
| 84 |
| 85 private static final String BUNDLE_PACKAGE_NAME = "android:packageName"; |
| 86 private static final String BUNDLE_ENTER_ANIMATION_RESOURCE = "android:animE
nterRes"; |
| 87 private static final String BUNDLE_EXIT_ANIMATION_RESOURCE = "android:animEx
itRes"; |
| 88 private final long mSessionId; |
| 89 private int mToolbarColor; |
| 90 private Bitmap mIcon; |
| 91 private PendingIntent mActionButtonPendingIntent; |
| 92 private List<Pair<String, PendingIntent>> mMenuEntries = new ArrayList<>(); |
| 93 private Bundle mAnimationBundle; |
| 94 |
| 95 /** |
| 96 * Constructs a {@link HostedIntentDataProvider}. |
| 97 */ |
| 98 public HostedIntentDataProvider(Intent intent, Context context) { |
| 99 if (intent == null) assert false; |
| 100 |
| 101 mSessionId = intent.getLongExtra(EXTRA_HOSTED_SESSION_ID, INVALID_SESSIO
N_ID); |
| 102 retrieveToolbarColor(intent, context); |
| 103 Bundle actionButtonBundle = intent.getBundleExtra(EXTRA_HOSTED_ACTION_BU
TTON_BUNDLE); |
| 104 if (actionButtonBundle != null) { |
| 105 mIcon = (Bitmap) actionButtonBundle.getParcelable(KEY_HOSTED_ICON); |
| 106 mActionButtonPendingIntent = (PendingIntent) actionButtonBundle.getP
arcelable( |
| 107 KEY_HOSTED_PENDING_INTENT); |
| 108 } |
| 109 List<Bundle> menuItems = intent.getParcelableArrayListExtra(EXTRA_HOSTED
_MENU_ITEMS); |
| 110 if (menuItems != null) { |
| 111 for (Bundle bundle : menuItems) { |
| 112 String title = bundle.getString(KEY_HOSTED_MENU_TITLE); |
| 113 PendingIntent pendingIntent = bundle.getParcelable(KEY_HOSTED_PE
NDING_INTENT); |
| 114 if (TextUtils.isEmpty(title) || pendingIntent == null) continue; |
| 115 mMenuEntries.add(new Pair<String, PendingIntent>(title, pendingI
ntent)); |
| 116 } |
| 117 } |
| 118 mAnimationBundle = intent.getBundleExtra(EXTRA_HOSTED_EXIT_ANIMATION_BUN
DLE); |
| 119 } |
| 120 |
| 121 /** |
| 122 * Processes the color passed from the client app and updates {@link #mToolb
arColor}. |
| 123 */ |
| 124 private void retrieveToolbarColor(Intent intent, Context context) { |
| 125 int color = intent.getIntExtra(EXTRA_HOSTED_TOOLBAR_COLOR, |
| 126 context.getResources().getColor(R.color.default_primary_color)); |
| 127 int defaultColor = context.getResources().getColor(R.color.default_prima
ry_color); |
| 128 |
| 129 if (color == Color.TRANSPARENT) color = defaultColor; |
| 130 |
| 131 // Ignore any transparency value. |
| 132 color |= 0xFF000000; |
| 133 |
| 134 mToolbarColor = color; |
| 135 } |
| 136 |
| 137 /** |
| 138 * @return The session ID specified in the intent. Will be |
| 139 * INVALID_SESSION_ID if it is not set in the intent. |
| 140 */ |
| 141 public long getSessionId() { |
| 142 return mSessionId; |
| 143 } |
| 144 |
| 145 /** |
| 146 * @return The toolbar color specified in the intent. Will return the color
of |
| 147 * default_primary_color, if not set in the intent. |
| 148 */ |
| 149 public int getToolbarColor() { |
| 150 return mToolbarColor; |
| 151 } |
| 152 |
| 153 /** |
| 154 * @return Whether the client app has provided sufficient info for the toolb
ar to show the |
| 155 * action button. |
| 156 */ |
| 157 public boolean shouldShowActionButton() { |
| 158 return mIcon != null && mActionButtonPendingIntent != null; |
| 159 } |
| 160 |
| 161 /** |
| 162 * @return The icon used for the action button. Will be null if not set in t
he intent. |
| 163 */ |
| 164 public Bitmap getActionButtonIcon() { |
| 165 return mIcon; |
| 166 } |
| 167 |
| 168 /** |
| 169 * @return Titles of menu items that were passed from client app via intent. |
| 170 */ |
| 171 public List<String> getMenuTitles() { |
| 172 ArrayList<String> list = new ArrayList<>(); |
| 173 for (Pair<String, PendingIntent> pair : mMenuEntries) { |
| 174 list.add(pair.first); |
| 175 } |
| 176 return list; |
| 177 } |
| 178 |
| 179 /** |
| 180 * Triggers the client-defined action when the user clicks a custom menu ite
m. |
| 181 * @param menuIndex The index that the menu item is shown in the result of |
| 182 * {@link #getMenuTitles()} |
| 183 */ |
| 184 public void clickMenuItemWithUrl(Context context, int menuIndex, String url)
{ |
| 185 Intent addedIntent = new Intent(); |
| 186 addedIntent.setData(Uri.parse(url)); |
| 187 try { |
| 188 PendingIntent pendingIntent = mMenuEntries.get(menuIndex).second; |
| 189 pendingIntent.send(context, 0, addedIntent); |
| 190 } catch (CanceledException e) { |
| 191 Log.e(TAG, "Hosted chrome failed to send pending intent."); |
| 192 } |
| 193 } |
| 194 |
| 195 /** |
| 196 * @return Whether chrome should animate when it finishes. We show animation
s only if the client |
| 197 * app has supplied the correct animation resources via intent extra
. |
| 198 */ |
| 199 public boolean shouldAnimateOnFinish() { |
| 200 return mAnimationBundle != null && getClientPackageName() != null; |
| 201 } |
| 202 |
| 203 /** |
| 204 * @return The package name of the client app. This is used for a workaround
in order to |
| 205 * retrieve the client's animation resources. |
| 206 */ |
| 207 public String getClientPackageName() { |
| 208 if (mAnimationBundle == null) return null; |
| 209 return mAnimationBundle.getString(BUNDLE_PACKAGE_NAME); |
| 210 } |
| 211 |
| 212 /** |
| 213 * @return The resource id for enter animation, which is used in |
| 214 * {@link Activity#overridePendingTransition(int, int)}. |
| 215 */ |
| 216 public int getAnimationEnterRes() { |
| 217 return shouldAnimateOnFinish() ? mAnimationBundle.getInt(BUNDLE_ENTER_AN
IMATION_RESOURCE) |
| 218 : 0; |
| 219 } |
| 220 |
| 221 /** |
| 222 * @return The resource id for exit animation, which is used in |
| 223 * {@link Activity#overridePendingTransition(int, int)}. |
| 224 */ |
| 225 public int getAnimationExitRes() { |
| 226 return shouldAnimateOnFinish() ? mAnimationBundle.getInt(BUNDLE_EXIT_ANI
MATION_RESOURCE) |
| 227 : 0; |
| 228 } |
| 229 |
| 230 /** |
| 231 * Send the pending intent for the current action button with the given url
as data. |
| 232 * @param context The context to use for sending the {@link PendingIntent}. |
| 233 * @param url The url to attach as additional data to the {@link PendingInte
nt}. |
| 234 */ |
| 235 public void sendButtonPendingIntentWithUrl(Context context, String url) { |
| 236 assert mActionButtonPendingIntent != null; |
| 237 Intent addedIntent = new Intent(); |
| 238 addedIntent.setData(Uri.parse(url)); |
| 239 try { |
| 240 mActionButtonPendingIntent.send(context, 0, addedIntent); |
| 241 } catch (CanceledException e) { |
| 242 Log.e(TAG, "CanceledException while sending pending intent in hosted
mode"); |
| 243 } |
| 244 } |
| 245 } |
OLD | NEW |