Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java

Issue 1557803002: [Custom Tabs] Implement Bottombar (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698