Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.customtabs; | 5 package org.chromium.chrome.browser.customtabs; |
| 6 | 6 |
| 7 import android.content.Intent; | 7 import android.content.Intent; |
| 8 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
| 9 import android.net.Uri; | 9 import android.net.Uri; |
| 10 import android.os.IBinder; | 10 import android.os.IBinder; |
| 11 import android.support.customtabs.CustomTabsCallback; | 11 import android.support.customtabs.CustomTabsCallback; |
| 12 import android.support.customtabs.CustomTabsIntent; | 12 import android.support.customtabs.CustomTabsIntent; |
| 13 import android.text.TextUtils; | 13 import android.text.TextUtils; |
| 14 import android.view.KeyEvent; | 14 import android.view.KeyEvent; |
| 15 import android.view.MenuItem; | 15 import android.view.MenuItem; |
| 16 import android.view.View; | 16 import android.view.View; |
| 17 import android.view.View.OnClickListener; | 17 import android.view.View.OnClickListener; |
| 18 import android.view.ViewGroup; | 18 import android.view.ViewGroup; |
| 19 import android.view.ViewStub; | |
| 19 import android.view.Window; | 20 import android.view.Window; |
| 21 import android.widget.ImageButton; | |
| 20 | 22 |
| 21 import org.chromium.base.ApiCompatibilityUtils; | 23 import org.chromium.base.ApiCompatibilityUtils; |
| 22 import org.chromium.base.Log; | 24 import org.chromium.base.Log; |
| 23 import org.chromium.base.ThreadUtils; | 25 import org.chromium.base.ThreadUtils; |
| 24 import org.chromium.base.VisibleForTesting; | 26 import org.chromium.base.VisibleForTesting; |
| 25 import org.chromium.base.metrics.RecordHistogram; | 27 import org.chromium.base.metrics.RecordHistogram; |
| 26 import org.chromium.base.metrics.RecordUserAction; | 28 import org.chromium.base.metrics.RecordUserAction; |
| 27 import org.chromium.chrome.R; | 29 import org.chromium.chrome.R; |
| 28 import org.chromium.chrome.browser.ChromeActivity; | 30 import org.chromium.chrome.browser.ChromeActivity; |
| 29 import org.chromium.chrome.browser.IntentHandler; | 31 import org.chromium.chrome.browser.IntentHandler; |
| 30 import org.chromium.chrome.browser.IntentHandler.ExternalAppId; | 32 import org.chromium.chrome.browser.IntentHandler.ExternalAppId; |
| 31 import org.chromium.chrome.browser.KeyboardShortcuts; | 33 import org.chromium.chrome.browser.KeyboardShortcuts; |
| 32 import org.chromium.chrome.browser.WebContentsFactory; | 34 import org.chromium.chrome.browser.WebContentsFactory; |
| 33 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; | 35 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; |
| 34 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange Reason; | 36 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange Reason; |
| 35 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerDocument; | 37 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerDocument; |
| 36 import org.chromium.chrome.browser.datausage.DataUseTabUIManager; | 38 import org.chromium.chrome.browser.datausage.DataUseTabUIManager; |
| 37 import org.chromium.chrome.browser.rappor.RapporServiceBridge; | 39 import org.chromium.chrome.browser.rappor.RapporServiceBridge; |
| 38 import org.chromium.chrome.browser.tab.Tab; | 40 import org.chromium.chrome.browser.tab.Tab; |
| 39 import org.chromium.chrome.browser.tab.TabIdManager; | 41 import org.chromium.chrome.browser.tab.TabIdManager; |
| 40 import org.chromium.chrome.browser.tab.TopControlsVisibilityDelegate; | 42 import org.chromium.chrome.browser.tab.TopControlsVisibilityDelegate; |
| 41 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; | 43 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; |
| 42 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; | 44 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
| 43 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; | 45 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; |
| 44 import org.chromium.chrome.browser.tabmodel.TabModelObserver; | 46 import org.chromium.chrome.browser.tabmodel.TabModelObserver; |
| 45 import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; | 47 import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; |
| 46 import org.chromium.chrome.browser.toolbar.ToolbarControlContainer; | 48 import org.chromium.chrome.browser.toolbar.ToolbarControlContainer; |
| 47 import org.chromium.chrome.browser.util.ColorUtils; | 49 import org.chromium.chrome.browser.util.ColorUtils; |
| 48 import org.chromium.chrome.browser.util.IntentUtils; | 50 import org.chromium.chrome.browser.util.IntentUtils; |
| 51 import org.chromium.chrome.browser.widget.FadingShadow; | |
| 52 import org.chromium.chrome.browser.widget.FadingShadowView; | |
| 49 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager; | 53 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager; |
| 50 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; | 54 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; |
| 51 import org.chromium.content_public.browser.LoadUrlParams; | 55 import org.chromium.content_public.browser.LoadUrlParams; |
| 52 import org.chromium.content_public.browser.WebContents; | 56 import org.chromium.content_public.browser.WebContents; |
| 53 import org.chromium.content_public.common.Referrer; | 57 import org.chromium.content_public.common.Referrer; |
| 54 import org.chromium.ui.base.PageTransition; | 58 import org.chromium.ui.base.PageTransition; |
| 55 | 59 |
| 60 import java.util.List; | |
| 61 | |
| 56 /** | 62 /** |
| 57 * The activity for custom tabs. It will be launched on top of a client's task. | 63 * The activity for custom tabs. It will be launched on top of a client's task. |
| 58 */ | 64 */ |
| 59 public class CustomTabActivity extends ChromeActivity { | 65 public class CustomTabActivity extends ChromeActivity { |
| 60 private static final String TAG = "CustomTabActivity"; | 66 private static final String TAG = "CustomTabActivity"; |
| 61 private static CustomTabContentHandler sActiveContentHandler; | 67 private static CustomTabContentHandler sActiveContentHandler; |
| 62 | 68 |
| 63 private FindToolbarManager mFindToolbarManager; | 69 private FindToolbarManager mFindToolbarManager; |
| 64 private CustomTabIntentDataProvider mIntentDataProvider; | 70 private CustomTabIntentDataProvider mIntentDataProvider; |
| 65 private IBinder mSession; | 71 private IBinder mSession; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 119 | 125 |
| 120 String url = IntentHandler.getUrlFromIntent(intent); | 126 String url = IntentHandler.getUrlFromIntent(intent); |
| 121 if (TextUtils.isEmpty(url)) return false; | 127 if (TextUtils.isEmpty(url)) return false; |
| 122 sActiveContentHandler.loadUrlAndTrackFromTimestamp(new LoadUrlParams(url ), | 128 sActiveContentHandler.loadUrlAndTrackFromTimestamp(new LoadUrlParams(url ), |
| 123 IntentHandler.getTimestampFromIntent(intent)); | 129 IntentHandler.getTimestampFromIntent(intent)); |
| 124 return true; | 130 return true; |
| 125 } | 131 } |
| 126 | 132 |
| 127 /** | 133 /** |
| 128 * Checks whether the active {@link CustomTabContentHandler} belongs to the given session, and | 134 * Checks whether the active {@link CustomTabContentHandler} belongs to the given session, and |
| 129 * if true, update toolbar's action button. | 135 * if true, update toolbar's custom button. |
| 130 * @param session The {@link IBinder} that the calling client represents . | 136 * @param session The {@link IBinder} that the calling client represents . |
| 131 * @param bitmap The new icon for action button. | 137 * @param bitmap The new icon for action button. |
| 132 * @param description The new content description for the action button. | 138 * @param description The new content description for the action button. |
| 133 * @return Whether the update is successful. | 139 * @return Whether the update is successful. |
| 134 */ | 140 */ |
| 135 static boolean updateActionButton(IBinder session, Bitmap bitmap, String des cription) { | 141 static boolean updateCustomButton(IBinder session, int id, Bitmap bitmap, St ring description) { |
| 136 ThreadUtils.assertOnUiThread(); | 142 ThreadUtils.assertOnUiThread(); |
| 137 // Do nothing if there is no activity or the activity does not belong to this session. | 143 // Do nothing if there is no activity or the activity does not belong to this session. |
| 138 if (sActiveContentHandler == null || !sActiveContentHandler.getSession() .equals(session)) { | 144 if (sActiveContentHandler == null || !sActiveContentHandler.getSession() .equals(session)) { |
| 139 return false; | 145 return false; |
| 140 } | 146 } |
| 141 return sActiveContentHandler.updateActionButton(bitmap, description); | 147 return sActiveContentHandler.updateCustomButton(id, bitmap, description) ; |
| 142 } | 148 } |
| 143 | 149 |
| 144 @Override | 150 @Override |
| 145 public boolean isCustomTab() { | 151 public boolean isCustomTab() { |
| 146 return true; | 152 return true; |
| 147 } | 153 } |
| 148 | 154 |
| 149 @Override | 155 @Override |
| 150 public void onStart() { | 156 public void onStart() { |
| 151 super.onStart(); | 157 super.onStart(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 168 mIntentDataProvider = new CustomTabIntentDataProvider(getIntent(), this) ; | 174 mIntentDataProvider = new CustomTabIntentDataProvider(getIntent(), this) ; |
| 169 supportRequestWindowFeature(Window.FEATURE_ACTION_MODE_OVERLAY); | 175 supportRequestWindowFeature(Window.FEATURE_ACTION_MODE_OVERLAY); |
| 170 } | 176 } |
| 171 | 177 |
| 172 @Override | 178 @Override |
| 173 public void postInflationStartup() { | 179 public void postInflationStartup() { |
| 174 super.postInflationStartup(); | 180 super.postInflationStartup(); |
| 175 setTabModelSelector(new TabModelSelectorImpl(this, 0, getWindowAndroid() , false)); | 181 setTabModelSelector(new TabModelSelectorImpl(this, 0, getWindowAndroid() , false)); |
| 176 getToolbarManager().setCloseButtonDrawable(mIntentDataProvider.getCloseB uttonDrawable()); | 182 getToolbarManager().setCloseButtonDrawable(mIntentDataProvider.getCloseB uttonDrawable()); |
| 177 getToolbarManager().setShowTitle(mIntentDataProvider.getTitleVisibilityS tate() | 183 getToolbarManager().setShowTitle(mIntentDataProvider.getTitleVisibilityS tate() |
| 178 == CustomTabIntentDataProvider.SHOW_PAGE_TITLE); | 184 == CustomTabsIntent.SHOW_PAGE_TITLE); |
| 179 int toolbarColor = mIntentDataProvider.getToolbarColor(); | 185 int toolbarColor = mIntentDataProvider.getToolbarColor(); |
| 180 getToolbarManager().updatePrimaryColor(toolbarColor); | 186 getToolbarManager().updatePrimaryColor(toolbarColor); |
| 181 if (toolbarColor != ApiCompatibilityUtils.getColor( | 187 if (toolbarColor != ApiCompatibilityUtils.getColor( |
| 182 getResources(), R.color.default_primary_color)) { | 188 getResources(), R.color.default_primary_color)) { |
| 183 ApiCompatibilityUtils.setStatusBarColor(getWindow(), | 189 ApiCompatibilityUtils.setStatusBarColor(getWindow(), |
| 184 ColorUtils.getDarkenedColorForStatusBar(toolbarColor)); | 190 ColorUtils.getDarkenedColorForStatusBar(toolbarColor)); |
| 185 } | 191 } |
| 186 | 192 |
| 187 // Setting task title and icon to be null will preserve the client app's title and icon. | 193 // Setting task title and icon to be null will preserve the client app's title and icon. |
| 188 ApiCompatibilityUtils.setTaskDescription(this, null, null, toolbarColor) ; | 194 ApiCompatibilityUtils.setTaskDescription(this, null, null, toolbarColor) ; |
| 189 showActionButton(); | 195 showCustomButtonOnToolbar(); |
| 196 showBottombarIfNecessary(); | |
| 190 } | 197 } |
| 191 | 198 |
| 192 @Override | 199 @Override |
| 193 public void finishNativeInitialization() { | 200 public void finishNativeInitialization() { |
| 194 mSession = mIntentDataProvider.getSession(); | 201 mSession = mIntentDataProvider.getSession(); |
| 195 // If extra headers have been passed, cancel any current prerender, as | 202 // If extra headers have been passed, cancel any current prerender, as |
| 196 // prerendering doesn't support extra headers. | 203 // prerendering doesn't support extra headers. |
| 197 if (IntentHandler.getExtraHeadersFromIntent(getIntent()) != null) { | 204 if (IntentHandler.getExtraHeadersFromIntent(getIntent()) != null) { |
| 198 CustomTabsConnection.getInstance(getApplication()).cancelPrerender(m Session); | 205 CustomTabsConnection.getInstance(getApplication()).cancelPrerender(m Session); |
| 199 } | 206 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 public IBinder getSession() { | 238 public IBinder getSession() { |
| 232 return mSession; | 239 return mSession; |
| 233 } | 240 } |
| 234 | 241 |
| 235 @Override | 242 @Override |
| 236 public boolean shouldIgnoreIntent(Intent intent) { | 243 public boolean shouldIgnoreIntent(Intent intent) { |
| 237 return mIntentHandler.shouldIgnoreIntent(CustomTabActivity.this, intent); | 244 return mIntentHandler.shouldIgnoreIntent(CustomTabActivity.this, intent); |
| 238 } | 245 } |
| 239 | 246 |
| 240 @Override | 247 @Override |
| 241 public boolean updateActionButton(Bitmap bitmap, String description) { | 248 public boolean updateCustomButton(int id, Bitmap bitmap, String desc ription) { |
| 242 mIntentDataProvider.getActionButtonParams().update(bitmap, descr iption); | 249 List<CustomButtonParams> list = mIntentDataProvider.getAllCustom Buttons(); |
| 243 return showActionButton(); | 250 for (CustomButtonParams params : list) { |
| 251 if (params.getId() == id) { | |
| 252 params.update(bitmap, description); | |
| 253 } | |
| 254 } | |
| 255 // TODO(ianwen): support bottombar here. | |
|
Yusuf
2016/01/06 23:02:55
so right now, we can't change icons on the bottom
Ian Wen
2016/01/07 03:09:50
In this CL it is not implemented. Will upload a fo
| |
| 256 return showCustomButtonOnToolbar(); | |
| 244 } | 257 } |
| 245 }; | 258 }; |
| 246 DataUseTabUIManager.onCustomTabInitialNavigation(mainTab, | 259 DataUseTabUIManager.onCustomTabInitialNavigation(mainTab, |
| 247 CustomTabsConnection.getInstance(getApplication()) | 260 CustomTabsConnection.getInstance(getApplication()) |
| 248 .getClientPackageNameForSession(mSession), | 261 .getClientPackageNameForSession(mSession), |
| 249 IntentHandler.getUrlFromIntent(getIntent())); | 262 IntentHandler.getUrlFromIntent(getIntent())); |
| 250 mainTab.setAppAssociatedWith(CustomTabsConnection.getInstance(getApplica tion()) | 263 mainTab.setAppAssociatedWith(CustomTabsConnection.getInstance(getApplica tion()) |
| 251 .getClientPackageNameForSession(mSession)); | 264 .getClientPackageNameForSession(mSession)); |
| 252 recordClientPackageName(); | 265 recordClientPackageName(); |
| 253 loadUrlInCurrentTab(new LoadUrlParams(IntentHandler.getUrlFromIntent(get Intent())), | 266 loadUrlInCurrentTab(new LoadUrlParams(IntentHandler.getUrlFromIntent(get Intent())), |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 if (getCurrentTabModel().getCount() > 1) { | 438 if (getCurrentTabModel().getCount() > 1) { |
| 426 getCurrentTabModel().closeTab(getActivityTab(), false, false, fa lse); | 439 getCurrentTabModel().closeTab(getActivityTab(), false, false, fa lse); |
| 427 } else { | 440 } else { |
| 428 finish(); | 441 finish(); |
| 429 } | 442 } |
| 430 } | 443 } |
| 431 return true; | 444 return true; |
| 432 } | 445 } |
| 433 | 446 |
| 434 /** | 447 /** |
| 435 * Properly setup action button on the toolbar. Does nothing if invalid data is provided by | 448 * Configures the custom button on toolbar. Does nothing if invalid data is provided by clients. |
| 436 * clients. | |
| 437 */ | 449 */ |
| 438 private boolean showActionButton() { | 450 private boolean showCustomButtonOnToolbar() { |
| 439 if (!mIntentDataProvider.shouldShowActionButton()) return false; | 451 CustomButtonParams params = mIntentDataProvider.getCustomButtonOnToolbar (); |
| 440 ActionButtonParams params = mIntentDataProvider.getActionButtonParams(); | 452 if (params == null) return false; |
| 441 getToolbarManager().setCustomActionButton( | 453 getToolbarManager().setCustomActionButton( |
| 442 params.getIcon(getResources()), | 454 params.getIcon(getResources()), |
| 443 params.getDescription(), | 455 params.getDescription(), |
| 444 new OnClickListener() { | 456 new OnClickListener() { |
| 445 @Override | 457 @Override |
| 446 public void onClick(View v) { | 458 public void onClick(View v) { |
| 447 mIntentDataProvider.sendButtonPendingIntentWithUrl( | 459 mIntentDataProvider.sendButtonPendingIntentWithUrl( |
| 448 getApplicationContext(), getActivityTab().getUrl ()); | 460 getApplicationContext(), getActivityTab().getUrl ()); |
| 449 RecordUserAction.record("CustomTabsCustomActionButtonCli ck"); | 461 RecordUserAction.record("CustomTabsCustomActionButtonCli ck"); |
| 450 } | 462 } |
| 451 }); | 463 }); |
| 452 return true; | 464 return true; |
| 453 } | 465 } |
| 454 | 466 |
| 467 /** | |
| 468 * Inflates the bottom bar {@link ViewStub} and its shadow, and populates it with items. | |
| 469 */ | |
| 470 private void showBottombarIfNecessary() { | |
| 471 if (!mIntentDataProvider.shouldShowBottomBar()) return; | |
| 472 | |
| 473 ViewStub bottombarStub = ((ViewStub) findViewById(R.id.buttombar_stub)); | |
| 474 bottombarStub.setLayoutResource(R.layout.custom_tabs_bottombar); | |
| 475 bottombarStub.inflate(); | |
| 476 | |
| 477 // Unlike others, this shadow docks itself at bottom and casts graphics upwards. | |
| 478 FadingShadowView shadow = (FadingShadowView) findViewById(R.id.bottombar _shadow); | |
| 479 shadow.setVisibility(View.VISIBLE); | |
| 480 shadow.init(ApiCompatibilityUtils.getColor(getResources(), | |
| 481 R.color.toolbar_shadow_color), FadingShadow.POSITION_BOTTOM); | |
| 482 | |
| 483 ViewGroup bottomBar = (ViewGroup) findViewById(R.id.bottombar); | |
| 484 bottomBar.setBackgroundColor(mIntentDataProvider.getToolbarColor()); | |
| 485 List<CustomButtonParams> items = mIntentDataProvider.getCustomButtonsOnB ottombar(); | |
| 486 for (CustomButtonParams params : items) { | |
| 487 if (params.showOnToolbar()) continue; | |
| 488 ImageButton button = params.toBottomBarButton(this, bottomBar); | |
| 489 bottomBar.addView(button); | |
| 490 } | |
| 491 } | |
| 492 | |
| 455 @Override | 493 @Override |
| 456 public boolean shouldShowAppMenu() { | 494 public boolean shouldShowAppMenu() { |
| 457 return getActivityTab() != null && getToolbarManager().isInitialized(); | 495 return getActivityTab() != null && getToolbarManager().isInitialized(); |
| 458 } | 496 } |
| 459 | 497 |
| 460 @Override | 498 @Override |
| 461 protected void showAppMenuForKeyboardEvent() { | 499 protected void showAppMenuForKeyboardEvent() { |
| 462 if (!shouldShowAppMenu()) return; | 500 if (!shouldShowAppMenu()) return; |
| 463 super.showAppMenuForKeyboardEvent(); | 501 super.showAppMenuForKeyboardEvent(); |
| 464 } | 502 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 | 584 |
| 547 /** | 585 /** |
| 548 * @return The {@link CustomTabIntentDataProvider} for this {@link CustomTab Activity}. For test | 586 * @return The {@link CustomTabIntentDataProvider} for this {@link CustomTab Activity}. For test |
| 549 * purposes only. | 587 * purposes only. |
| 550 */ | 588 */ |
| 551 @VisibleForTesting | 589 @VisibleForTesting |
| 552 CustomTabIntentDataProvider getIntentDataProvider() { | 590 CustomTabIntentDataProvider getIntentDataProvider() { |
| 553 return mIntentDataProvider; | 591 return mIntentDataProvider; |
| 554 } | 592 } |
| 555 } | 593 } |
| OLD | NEW |