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

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/document/DocumentActivity.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 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
(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.document;
6
7 import android.annotation.TargetApi;
8 import android.app.Activity;
9 import android.content.Intent;
10 import android.content.res.Configuration;
11 import android.graphics.Bitmap;
12 import android.graphics.Color;
13 import android.net.Uri;
14 import android.os.Build;
15 import android.text.TextUtils;
16 import android.util.Log;
17 import android.view.KeyEvent;
18 import android.view.Menu;
19 import android.view.View;
20 import android.view.ViewGroup;
21 import android.view.Window;
22
23 import com.google.android.apps.chrome.R;
24
25 import org.chromium.base.ActivityState;
26 import org.chromium.base.ApplicationStatus;
27 import org.chromium.base.SysUtils;
28 import org.chromium.base.VisibleForTesting;
29 import org.chromium.base.library_loader.LibraryLoader;
30 import org.chromium.base.metrics.RecordUserAction;
31 import org.chromium.chrome.browser.ChromeMobileApplication;
32 import org.chromium.chrome.browser.CompositorChromeActivity;
33 import org.chromium.chrome.browser.IntentHandler;
34 import org.chromium.chrome.browser.KeyboardShortcuts;
35 import org.chromium.chrome.browser.Tab;
36 import org.chromium.chrome.browser.TabState;
37 import org.chromium.chrome.browser.UrlConstants;
38 import org.chromium.chrome.browser.UrlUtilities;
39 import org.chromium.chrome.browser.appmenu.AppMenuHandler;
40 import org.chromium.chrome.browser.appmenu.AppMenuObserver;
41 import org.chromium.chrome.browser.appmenu.ChromeAppMenuPropertiesDelegate;
42 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerDocument;
43 import org.chromium.chrome.browser.document.DocumentTab.DocumentTabObserver;
44 import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkUtils;
45 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
46 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
47 import org.chromium.chrome.browser.metrics.UmaUtils;
48 import org.chromium.chrome.browser.ntp.DocumentNewTabPage;
49 import org.chromium.chrome.browser.ntp.NewTabPage;
50 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
51 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
52 import org.chromium.chrome.browser.preferences.bandwidth.BandwidthReductionPrefe rences;
53 import org.chromium.chrome.browser.preferences.bandwidth.DataReductionPromoScree n;
54 import org.chromium.chrome.browser.signin.SigninPromoScreen;
55 import org.chromium.chrome.browser.ssl.ConnectionSecurityHelperSecurityLevel;
56 import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector;
57 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
58 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
59 import org.chromium.chrome.browser.tabmodel.document.ActivityDelegate;
60 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModel;
61 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModel.Initializa tionObserver;
62 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelImpl;
63 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelSelector;
64 import org.chromium.chrome.browser.toolbar.ToolbarControlContainer;
65 import org.chromium.chrome.browser.toolbar.ToolbarHelper;
66 import org.chromium.chrome.browser.util.FeatureUtilities;
67 import org.chromium.chrome.browser.util.IntentUtils;
68 import org.chromium.chrome.browser.widget.ControlContainer;
69 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
70 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager;
71 import org.chromium.components.service_tab_launcher.ServiceTabLauncher;
72 import org.chromium.content.browser.ContentVideoView;
73 import org.chromium.content.browser.ContentViewCore;
74 import org.chromium.content_public.browser.LoadUrlParams;
75 import org.chromium.content_public.browser.NavigationEntry;
76 import org.chromium.content_public.browser.navigation_controller.LoadURLType;
77 import org.chromium.content_public.common.Referrer;
78 import org.chromium.ui.base.PageTransition;
79
80 /**
81 * This is the main activity for Chrome while running in document mode. Each ac tivity
82 * instance represents a single web page at a time while providing Chrome functi onality.
83 *
84 * <p>
85 * Tab switching is handled via the system wide Android task management system.
86 */
87 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
88 public class DocumentActivity extends CompositorChromeActivity {
89 protected static final String KEY_INITIAL_URL = "DocumentActivity.KEY_INITIA L_URL";
90
91 private static final String TAG = "DocumentActivity";
92
93 private static final int APP_ICON_MIN_SIZE_DP = 32;
94 private static final int APP_ICON_SIZE_DP = 64;
95 private static final int APP_ICON_CORNER_RADIUS_DP = 3;
96 private static final int APP_ICON_TEXT_SIZE_DP = 30;
97 private static final int APP_ICON_DEFAULT_BACKGROUND_COLOR = Color.rgb(50, 5 0, 50);
98
99 // Animation exit duration defined in chrome/android/java/res/anim/menu_exit .xml as 150ms,
100 // plus add another 20ms for a re-layout.
101 private static final int MENU_EXIT_ANIMATION_WAIT_MS = 170;
102
103 private DocumentTabModel mTabModel;
104 private InitializationObserver mTabInitializationObserver;
105
106 private Bitmap mIcon;
107 // Indicates whether mIcon was generated by RoundedIconGenerator.
108 private boolean mIsUsingGeneratedIcon;
109
110 private Integer mThemeColor;
111 private int mDefaultThemeColor;
112
113 private DocumentTab mDocumentTab;
114 private ToolbarHelper mToolbarHelper;
115
116 private ChromeAppMenuPropertiesDelegate mChromeAppMenuPropertiesDelegate;
117 private AppMenuHandler mAppMenuHandler;
118 private RoundedIconGenerator mDocumentAppIconGenerator;
119 private FindToolbarManager mFindToolbarManager;
120 private boolean mRecordedStartupUma;
121
122 // Whether the page has started loading in this (browser) process once alrea dy. Must only be
123 // used from the UI thread.
124 private static boolean sIsFirstPageLoadStart = true;
125
126 /** Whether the DocumentTab has already been added to the TabModel. */
127 private boolean mNeedsToBeAddedToTabModel;
128
129 @Override
130 protected boolean isStartedUpCorrectly(Intent intent) {
131 int tabId = ActivityDelegate.getTabIdFromIntent(getIntent());
132 boolean isDocumentMode = FeatureUtilities.isDocumentMode(this);
133 boolean isStartedUpCorrectly = tabId != Tab.INVALID_TAB_ID && isDocument Mode;
134 if (!isStartedUpCorrectly) {
135 Log.e(TAG, "Discarding Intent: Tab = " + tabId + ", Document mode = " + isDocumentMode);
136 }
137 return isStartedUpCorrectly;
138 }
139
140 @Override
141 public void preInflationStartup() {
142 // Decide whether to record startup UMA histograms. This is done early in the main
143 // Activity.onCreate() to avoid recording navigation delays when they re quire user input to
144 // proceed. See more details in ChromeTabbedActivity.preInflationStartup ().
145 if (!LibraryLoader.isInitialized()) {
146 UmaUtils.setRunningApplicationStart(true);
147 }
148
149 DocumentTabModelSelector.setPrioritizedTabId(
150 ActivityDelegate.getTabIdFromIntent(getIntent()));
151
152 mTabModel = ChromeMobileApplication.getDocumentTabModelSelector().getMod el(isIncognito());
153 mTabModel.startTabStateLoad();
154 updateLastTabId();
155
156 SingleTabModelSelector selector = new SingleTabModelSelector(this, isInc ognito(), false) {
157 @Override
158 public Tab openNewTab(LoadUrlParams loadUrlParams, TabLaunchType typ e, Tab parent,
159 boolean incognito) {
160 PendingDocumentData params = null;
161 if (loadUrlParams.getPostData() != null
162 || loadUrlParams.getVerbatimHeaders() != null
163 || loadUrlParams.getReferrer() != null) {
164 params = new PendingDocumentData();
165 params.postData = loadUrlParams.getPostData();
166 params.extraHeaders = loadUrlParams.getVerbatimHeaders();
167 params.referrer = loadUrlParams.getReferrer();
168 }
169
170 int launchMode = type == TabLaunchType.FROM_LONGPRESS_BACKGROUND
171 ? ChromeLauncherActivity.LAUNCH_MODE_AFFILIATED
172 : ChromeLauncherActivity.LAUNCH_MODE_FOREGROUND;
173 Activity parentActivity =
174 parent == null ? null : parent.getWindowAndroid().getAct ivity().get();
175 ChromeLauncherActivity.launchDocumentInstance(parentActivity, in cognito,
176 launchMode, loadUrlParams.getUrl(),
177 DocumentMetricIds.STARTED_BY_WINDOW_OPEN,
178 loadUrlParams.getTransitionType(), false, params);
179 return null;
180 }
181 };
182 setTabModelSelector(selector);
183
184 super.preInflationStartup();
185
186 supportRequestWindowFeature(Window.FEATURE_ACTION_MODE_OVERLAY);
187 }
188
189 @Override
190 protected int getControlContainerLayoutId() {
191 return R.layout.control_container;
192 }
193
194 @Override
195 public void postInflationStartup() {
196 super.postInflationStartup();
197
198 ToolbarControlContainer controlContainer =
199 ((ToolbarControlContainer) findViewById(R.id.control_container)) ;
200 mChromeAppMenuPropertiesDelegate = new ChromeAppMenuPropertiesDelegate(t his);
201 mAppMenuHandler = new AppMenuHandler(this, mChromeAppMenuPropertiesDeleg ate,
202 R.menu.main_menu);
203 mToolbarHelper = new ToolbarHelper(this, controlContainer, mAppMenuHandl er,
204 mChromeAppMenuPropertiesDelegate, getCompositorViewHolder().getI nvalidator());
205
206 final int tabId = ActivityDelegate.getTabIdFromIntent(getIntent());
207 mTabInitializationObserver = new InitializationObserver(mTabModel) {
208 @Override
209 public boolean isSatisfied(int currentState) {
210 return currentState >= DocumentTabModelImpl.STATE_LOAD_TAB_S TATE_BG_END
211 || mTabModel.isTabStateReady(tabId);
212 }
213
214 @Override
215 public boolean isCanceled() {
216 return isDestroyed() || isFinishing();
217 }
218
219 @Override
220 public void runImmediately() {
221 initializeUI();
222 }
223 };
224 }
225
226 @Override
227 @VisibleForTesting
228 public AppMenuHandler getAppMenuHandler() {
229 return mAppMenuHandler;
230 }
231
232 @Override
233 public void prepareMenu(Menu menu) {
234 if (isNewTabPage() && !isIncognito()) {
235 menu.findItem(R.id.new_tab_menu_id).setVisible(false);
236 }
237 }
238
239 @Override
240 public void finishNativeInitialization() {
241 ChromePreferenceManager preferenceManager =
242 ChromePreferenceManager.getInstance(this);
243 if (isNewTabPage() && FirstRunStatus.getFirstRunFlowComplete(this)) {
244 // Only show promos on second NTP.
245 if (preferenceManager.getPromosSkippedOnFirstStart()) {
246 // Data reduction promo should be temporarily suppressed if the sign in promo is
247 // shown to avoid nagging users too much.
248 if (!SigninPromoScreen.launchSigninPromoIfNeeded(this)) {
249 DataReductionPromoScreen.launchDataReductionPromo(this);
250 }
251 } else {
252 preferenceManager.setPromosSkippedOnFirstStart(true);
253 }
254 }
255
256 FirstRunSignInProcessor.start(this);
257
258 if (!preferenceManager.hasAttemptedMigrationOnUpgrade()) {
259 InitializationObserver observer = new InitializationObserver(
260 ChromeMobileApplication.getDocumentTabModelSelector().getMod el(false)) {
261 @Override
262 protected void runImmediately() {
263 DocumentMigrationHelper.migrateTabsToDocumentForUpgrade(Docu mentActivity.this,
264 DocumentMigrationHelper.FINALIZE_MODE_NO_ACTION);
265 }
266
267 @Override
268 public boolean isSatisfied(int currentState) {
269 return currentState == DocumentTabModelImpl.STATE_FULLY_LOAD ED;
270 }
271
272 @Override
273 public boolean isCanceled() {
274 return false;
275 }
276 };
277
278 observer.runWhenReady();
279 }
280
281 getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
282 Window.PROGRESS_VISIBILITY_OFF);
283
284 // Initialize the native-side TabModels so that the Profile is available when necessary.
285 ChromeMobileApplication.getDocumentTabModelSelector().onNativeLibraryRea dy();
286 mTabInitializationObserver.runWhenReady();
287
288 if (mNeedsToBeAddedToTabModel) {
289 mNeedsToBeAddedToTabModel = false;
290 mTabModel.addTab(getIntent(), mDocumentTab);
291 getTabModelSelector().setTab(mDocumentTab);
292 }
293
294 super.finishNativeInitialization();
295 }
296
297 @Override
298 protected void onDeferredStartup() {
299 super.onDeferredStartup();
300 mToolbarHelper.onDeferredStartup();
301 }
302
303 @Override
304 public boolean hasDoneFirstDraw() {
305 return mToolbarHelper.hasDoneFirstDraw();
306 }
307
308 /**
309 * @return The ID of the Tab.
310 */
311 protected final int determineTabId() {
312 int tabId = ActivityDelegate.getTabIdFromIntent(getIntent());
313 if (tabId == Tab.INVALID_TAB_ID && mDocumentTab != null) tabId = mDocume ntTab.getId();
314 return tabId;
315 }
316
317 /**
318 * Determine the last known URL that this Document was displaying when it wa s stopped.
319 * @return URL that the user was last known to have seen, or null if one cou ldn't be found.
320 */
321 private String determineLastKnownUrl() {
322 int tabId = determineTabId();
323 String url = mTabModel.getCurrentUrlForDocument(tabId);
324 if (TextUtils.isEmpty(url)) url = determineInitialUrl(tabId);
325 return url;
326 }
327
328 /**
329 * Determine the URL that this Document was initially opened for. It can be stashed in multiple
330 * locations because IncognitoDocumentActivities are disallowed from passing URLs in the Intent.
331 * @param tabId ID of the Tab owned by this Activity.
332 * @return Initial URL, or null if it couldn't be determined.
333 */
334 protected String determineInitialUrl(int tabId) {
335 String initialUrl = null;
336
337 // Check if the TabModel has it.
338 if (mTabModel != null) {
339 initialUrl = mTabModel.getInitialUrlForDocument(tabId);
340 }
341
342 // Check if the URL was passed through the Intent.
343 if (TextUtils.isEmpty(initialUrl) && getIntent() != null) {
344 initialUrl = IntentHandler.getUrlFromIntent(getIntent());
345 }
346
347 // Check the Tab's history.
348 if (TextUtils.isEmpty(initialUrl) && mDocumentTab != null
349 && mDocumentTab.getWebContents() != null) {
350 NavigationEntry entry =
351 mDocumentTab.getWebContents().getNavigationController().getE ntryAtIndex(0);
352 if (entry != null) initialUrl = entry.getOriginalUrl();
353 }
354
355 return initialUrl;
356 }
357
358 @Override
359 public CharSequence onCreateDescription() {
360 return mDocumentTab != null ? mDocumentTab.getTitle() : "";
361 }
362
363 @Override
364 public final DocumentTab getActivityTab() {
365 return mDocumentTab;
366 }
367
368 @Override
369 public void onStartWithNative() {
370 super.onStartWithNative();
371 handleDocumentUma();
372 ChromeLauncherActivity.sendExceptionCount();
373 }
374
375 private void handleDocumentUma() {
376 if (mRecordedStartupUma) {
377 DocumentUma.recordStartedBy(
378 DocumentMetricIds.STARTED_BY_ACTIVITY_BROUGHT_TO_FOREGROUND) ;
379 } else {
380 mRecordedStartupUma = true;
381
382 if (getSavedInstanceState() == null) {
383 DocumentUma.recordStartedBy(getPackageName(), getIntent());
384 } else {
385 DocumentUma.recordStartedBy(DocumentMetricIds.STARTED_BY_ACTIVIT Y_RESTARTED);
386 }
387 }
388 DocumentUma.recordInDocumentMode(true);
389 }
390
391 @Override
392 public void onPause() {
393 // If finishing, release all the active media players as we don't know w hen onStop()
394 // will get called.
395 super.onPause();
396 if (isFinishing() && mDocumentTab != null && mDocumentTab.getWebContents () != null) {
397 mDocumentTab.getWebContents().releaseMediaPlayers();
398 }
399 }
400
401 @Override
402 public void onWindowFocusChanged(boolean hasWindowFocus) {
403 if (hasWindowFocus) updateLastTabId();
404 }
405
406 @Override
407 public void onResume() {
408 super.onResume();
409
410 if (getIntent() != null) {
411 DocumentUtils.finishOtherTasksWithTabID(
412 ActivityDelegate.getTabIdFromIntent(getIntent()), getTaskId( ));
413 }
414 }
415
416 @Override
417 public void onResumeWithNative() {
418 super.onResumeWithNative();
419
420 if (mDocumentTab != null) {
421 PendingDocumentData pendingData = ChromeMobileApplication.getDocumen tTabModelSelector()
422 .removePendingDocumentData(ActivityDelegate.getTabIdFromInte nt(getIntent()));
423 if (pendingData != null && pendingData.url != null) {
424 loadLastKnownUrl(pendingData);
425 }
426 mDocumentTab.show(TabSelectionType.FROM_USER);
427 }
428 }
429
430 @Override
431 protected void onDestroyInternal() {
432 if (mToolbarHelper != null) mToolbarHelper.destroy();
433
434 super.onDestroyInternal();
435 }
436
437 @Override
438 public void onStopWithNative() {
439 if (mDocumentTab != null) {
440 mDocumentTab.setShouldPreserve(!IntentUtils.safeGetBooleanExtra(getI ntent(),
441 IntentHandler.EXTRA_APPEND_TASK, false));
442 mTabModel.updateEntry(getIntent(), mDocumentTab);
443 }
444 if (mAppMenuHandler != null) mAppMenuHandler.hideAppMenu();
445 super.onStopWithNative();
446 }
447
448 @Override
449 public SingleTabModelSelector getTabModelSelector() {
450 return (SingleTabModelSelector) super.getTabModelSelector();
451 }
452
453 @Override
454 public void onConfigurationChanged(Configuration newConfig) {
455 if (mAppMenuHandler != null) mAppMenuHandler.hideAppMenu();
456 super.onConfigurationChanged(newConfig);
457 }
458
459 @Override
460 public void onOrientationChange(int orientation) {
461 super.onOrientationChange(orientation);
462 mToolbarHelper.onOrientationChange();
463 }
464
465 @Override
466 protected void onAccessibilityModeChanged(boolean enabled) {
467 super.onAccessibilityModeChanged(enabled);
468 mToolbarHelper.onAccessibilityStatusChanged(enabled);
469 }
470
471 private void loadLastKnownUrl(PendingDocumentData pendingData) {
472 Intent intent = getIntent();
473 if (pendingData != null && pendingData.originalIntent != null) {
474 intent = pendingData.originalIntent;
475 }
476 boolean isIntentChromeOrFirstParty = IntentHandler.isIntentChromeOrFirst Party(intent,
477 getApplicationContext());
478 int transitionType = intent == null ? PageTransition.LINK
479 : IntentUtils.safeGetIntExtra(intent, IntentHandler.EXTRA_PAGE_T RANSITION_TYPE,
480 PageTransition.LINK);
481 if ((transitionType != PageTransition.TYPED)
482 && (transitionType != PageTransition.LINK)
483 && !isIntentChromeOrFirstParty) {
484 // Only 1st party authenticated applications can set the transition type to be
485 // anything other than TYPED for security reasons.
486 transitionType = PageTransition.LINK;
487 }
488
489 if (transitionType == PageTransition.LINK) {
490 transitionType |= PageTransition.FROM_API;
491 }
492
493 String url = (pendingData != null && pendingData.url != null) ? pendingD ata.url :
494 determineLastKnownUrl();
495
496 LoadUrlParams loadUrlParams = new LoadUrlParams(url, transitionType);
497 if (getIntent() != null) {
498 loadUrlParams.setIntentReceivedTimestamp(getOnCreateTimestampUptimeM s());
499 }
500
501 Uri referrerExtra = null;
502 if (isIntentChromeOrFirstParty
503 && IntentUtils.safeGetParcelableExtra(intent, Intent.EXTRA_REFER RER) != null) {
504 referrerExtra = (Uri) IntentUtils.safeGetParcelableExtra(intent, Int ent.EXTRA_REFERRER);
505 loadUrlParams.setReferrer(new Referrer(
506 referrerExtra.toString(), 1 /* WebReferrerPolicyDefault */)) ;
507 }
508
509 if (pendingData != null) {
510 if (pendingData.postData != null) {
511 loadUrlParams.setPostData(pendingData.postData);
512 loadUrlParams.setLoadType(LoadURLType.BROWSER_INITIATED_HTTP_POS T);
513 }
514 loadUrlParams.setVerbatimHeaders(pendingData.extraHeaders);
515 loadUrlParams.setReferrer(pendingData.referrer);
516 mDocumentTab.getTabRedirectHandler().updateIntent(pendingData.origin alIntent);
517 } else {
518 if (getIntent() != null) {
519 try {
520 intent = IntentUtils.safeGetParcelableExtra(getIntent(),
521 IntentHandler.EXTRA_ORIGINAL_INTENT);
522 } catch (Throwable t) {
523 // Ignore exception.
524 }
525 }
526 mDocumentTab.getTabRedirectHandler().updateIntent(intent);
527 }
528
529 mDocumentTab.loadUrl(loadUrlParams);
530 if (pendingData != null && pendingData.requestId > 0) {
531 ServiceTabLauncher.onWebContentsForRequestAvailable(
532 pendingData.requestId, mDocumentTab.getWebContents());
533 }
534
535 if (getIntent() != null && IntentUtils.safeGetBooleanExtra(getIntent(),
536 IntentHandler.EXTRA_USE_DESKTOP_USER_AGENT, false)) {
537 // The desktop user agent can't be carried over without the Tab alre ady having a URL,
538 // so we're forced to set the user agent and then reload the page.
539 mDocumentTab.setUseDesktopUserAgent(true, true);
540 }
541 }
542
543 @Override
544 public void terminateIncognitoSession() {
545 ChromeMobileApplication.getDocumentTabModelSelector().getModel(true).clo seAllTabs();
546 }
547
548 private void initializeUI() {
549 mDefaultThemeColor = isIncognito()
550 ? getResources().getColor(R.color.incognito_primary_color)
551 : getResources().getColor(R.color.default_primary_color);
552 PendingDocumentData pendingData = ChromeMobileApplication.getDocumentTab ModelSelector()
553 .removePendingDocumentData(ActivityDelegate.getTabIdFromIntent(g etIntent()));
554 int tabId = determineTabId();
555 TabState tabState = mTabModel.getTabStateForDocument(tabId);
556 mDocumentTab = DocumentTab.create(DocumentActivity.this, isIncognito(),
557 getWindowAndroid(), determineLastKnownUrl(),
558 pendingData != null ? pendingData.webContents : null,
559 pendingData != null ? pendingData.webContentsPaused : false, tab State);
560 if (mTabModel.isNativeInitialized()) {
561 mTabModel.addTab(getIntent(), mDocumentTab);
562 } else {
563 mNeedsToBeAddedToTabModel = true;
564 }
565
566 mAppMenuHandler.addObserver(new AppMenuObserver() {
567 @Override
568 public void onMenuVisibilityChanged(boolean isVisible) {
569 if (!isVisible) {
570 mChromeAppMenuPropertiesDelegate.onMenuDismissed();
571 }
572 }
573 });
574
575 getTabModelSelector().setTab(mDocumentTab);
576
577 if (!mDocumentTab.didRestoreState() || (pendingData != null && pendingDa ta.url != null)) {
578 if (!mDocumentTab.isCreatedWithWebContents()) {
579 // Don't load tabs in the background on low end devices. We will call
580 // loadLastKnownUrl() in onResumeWithNative() next time activity is resumed.
581 int launchMode = IntentUtils.safeGetIntExtra(getIntent(),
582 ChromeLauncherActivity.EXTRA_LAUNCH_MODE,
583 ChromeLauncherActivity.LAUNCH_MODE_FOREGROUND);
584 if (SysUtils.isLowEndDevice()
585 && launchMode == ChromeLauncherActivity.LAUNCH_MODE_AFFI LIATED
586 && pendingData != null) {
587 // onResumeWithNative() wants pendingData.url to be non-null
588 if (pendingData.url == null) {
589 pendingData.url = determineLastKnownUrl();
590 }
591 ChromeMobileApplication.getDocumentTabModelSelector().addPen dingDocumentData(
592 ActivityDelegate.getTabIdFromIntent(getIntent()), pe ndingData);
593 // Use the URL as the document title until tab is loaded
594 updateTaskDescription(pendingData.url, null);
595 } else {
596 loadLastKnownUrl(pendingData);
597 }
598 }
599 mDocumentTab.setShouldPreserve(IntentUtils.safeGetBooleanExtra(getIn tent(),
600 IntentHandler.EXTRA_PRESERVE_TASK, false));
601 }
602
603 ToolbarControlContainer controlContainer =
604 (ToolbarControlContainer) findViewById(R.id.control_container);
605 LayoutManagerDocument layoutDriver = new LayoutManagerDocument(getCompos itorViewHolder());
606 initializeCompositorContent(layoutDriver, findViewById(R.id.url_bar),
607 (ViewGroup) findViewById(android.R.id.content), controlContainer );
608
609 mFindToolbarManager = new FindToolbarManager(this, getTabModelSelector() ,
610 mToolbarHelper.getContextualMenuBar()
611 .getCustomSelectionActionModeCallback());
612 controlContainer.setFindToolbarManager(mFindToolbarManager);
613 if (getContextualSearchManager() != null) {
614 getContextualSearchManager().setFindToolbarManager(mFindToolbarManag er);
615 }
616
617 mToolbarHelper.initializeControls(
618 mFindToolbarManager, null, layoutDriver, null, null, null, null) ;
619
620 mDocumentTab.setFullscreenManager(getFullscreenManager());
621
622 mDocumentTab.addObserver(new DocumentTabObserver() {
623 @Override
624 public void onPageLoadStarted(Tab tab) {
625 // Discard startup navigation measurements when the user interfe red and started the
626 // 2nd navigation (in activity lifetime) in parallel.
627 if (!sIsFirstPageLoadStart) {
628 UmaUtils.setRunningApplicationStart(false);
629 } else {
630 sIsFirstPageLoadStart = false;
631 }
632 }
633
634 @Override
635 public void onWebContentsSwapped(Tab tab, boolean didStartLoad, bool ean didFinishLoad) {
636 if (!didStartLoad) return;
637 mThemeColor = tab.getWebContents().getThemeColor(mDefaultThemeCo lor);
638 mIcon = null;
639 updateTaskDescription();
640 }
641
642 @Override
643 protected void onFaviconReceived(Bitmap image) {
644 super.onFaviconReceived(image);
645 int newHeight = image.getHeight();
646 int newWidth = image.getWidth();
647 int minSize =
648 (int) getResources().getDisplayMetrics().density * APP_I CON_MIN_SIZE_DP;
649 if (newHeight < minSize || newWidth < minSize) return;
650 if (mIcon != null && !mIsUsingGeneratedIcon && mIcon.getWidth() >= newWidth
651 && mIcon.getHeight() >= newHeight) {
652 return;
653 }
654 mIcon = image;
655 mIsUsingGeneratedIcon = false;
656 updateTaskDescription();
657 }
658
659 @Override
660 public void onUrlUpdated(Tab tab) {
661 assert mDocumentTab == tab;
662
663 updateTaskDescription();
664 mTabModel.updateEntry(getIntent(), mDocumentTab);
665 }
666
667 @Override
668 public void onTitleUpdated(Tab tab) {
669 super.onTitleUpdated(tab);
670 updateTaskDescription();
671 }
672
673 @Override
674 public void onSSLStateUpdated(Tab tab) {
675 int securityLevel = tab.getSecurityLevel();
676 if (securityLevel == ConnectionSecurityHelperSecurityLevel.SECUR ITY_ERROR
677 || securityLevel == ConnectionSecurityHelperSecurityLeve l.SECURITY_WARNING
678 || securityLevel
679 == ConnectionSecurityHelperSecurityLevel.SECURITY_POL ICY_WARNING) {
680 resetThemeColorAndIcon();
681 }
682 }
683
684 @Override
685 public void onDidNavigateMainFrame(Tab tab, String url, String baseU rl,
686 boolean isNavigationToDifferentPage, boolean isFragmentNavig ation,
687 int statusCode) {
688 if (!isNavigationToDifferentPage) return;
689 mIcon = null;
690 }
691
692 @Override
693 public void onLoadStopped(Tab tab) {
694 assert mDocumentTab == tab;
695
696 updateTaskDescription();
697 mTabModel.updateEntry(getIntent(), mDocumentTab);
698 }
699
700 @Override
701 public void onDidChangeThemeColor(int color) {
702 if (color == Color.TRANSPARENT) color = mDefaultThemeColor;
703
704 // Ignore any transparency value.
705 color |= 0xFF000000;
706
707 mThemeColor = Integer.valueOf(color);
708 updateTaskDescription();
709 }
710
711 @Override
712 public void onDidAttachInterstitialPage(Tab tab) {
713 resetThemeColorAndIcon();
714 }
715
716 @Override
717 public void onDidDetachInterstitialPage(Tab tab) {
718 mThemeColor = tab.getWebContents().getThemeColor(mDefaultThemeCo lor);
719 mIcon = null;
720 updateTaskDescription();
721 }
722
723 @Override
724 public void onCrash(Tab tab, boolean sadTabShown) {
725 int currentState = ApplicationStatus.getStateForActivity(Documen tActivity.this);
726 if (currentState != ActivityState.STOPPED) return;
727
728 if (!isTaskRoot() || IntentUtils.safeGetBooleanExtra(getIntent() ,
729 IntentHandler.EXTRA_APPEND_TASK, false)) {
730 return;
731 }
732
733 // Finishing backgrounded Activities whose renderers have crashe d allows us to
734 // destroy them and return resources sooner than if we wait for Android to destroy
735 // the Activities themselves. Problematically, this also remove s
736 // IncognitoDocumentActivity instances from Android's Recents me nu and auto-closes
737 // the tab. Instead, take a hit and keep the Activities alive - - Android will
738 // eventually destroy the Activities, anyway (crbug.com/450292).
739 if (!isIncognito()) finish();
740 }
741
742 @Override
743 public void onSetCoveredByChildActivity() {
744 mTabModel.updateEntry(getIntent(), mDocumentTab);
745 }
746 });
747
748 removeWindowBackground();
749
750 if (mDocumentTab != null) {
751 BandwidthReductionPreferences.launchDataReductionSSLInfoBar(
752 DocumentActivity.this, mDocumentTab.getWebContents());
753 }
754 }
755
756 private void resetThemeColorAndIcon() {
757 mThemeColor = null;
758 mIcon = null;
759 updateTaskDescription();
760 }
761
762 private void updateLastTabId() {
763 ChromeMobileApplication.getDocumentTabModelSelector().selectModel(isInco gnito());
764 int tabId = mDocumentTab == null
765 ? ActivityDelegate.getTabIdFromIntent(getIntent()) : mDocumentT ab.getId();
766 mTabModel.setLastShownId(tabId);
767 }
768
769 @Override
770 public boolean handleBackPressed() {
771 if (mDocumentTab == null) return false;
772
773 View view = ContentVideoView.getContentVideoView();
774 if (view != null && view.getContext() == this) {
775 ContentVideoView.getContentVideoView().exitFullscreen(false);
776 return true;
777 }
778
779 if (getFullscreenManager().getPersistentFullscreenMode()) {
780 getFullscreenManager().setPersistentFullscreenMode(false);
781 return true;
782 }
783
784 if (mDocumentTab.canGoBack()) {
785 mDocumentTab.goBack();
786 } else if (!mDocumentTab.shouldPreserve()) {
787 finishAndRemoveTask();
788 } else {
789 moveTaskToBack(true);
790 }
791 return true;
792 }
793
794 @Override
795 public boolean createContextualSearchTab(ContentViewCore searchContentViewCo re) {
796 NavigationEntry entry =
797 searchContentViewCore.getWebContents().getNavigationController() .getPendingEntry();
798 String url = entry != null
799 ? entry.getUrl() : searchContentViewCore.getWebContents().getUrl ();
800 PendingDocumentData documentData = new PendingDocumentData();
801 ChromeLauncherActivity.launchDocumentInstance(this, false,
802 ChromeLauncherActivity.LAUNCH_MODE_FOREGROUND, url,
803 DocumentMetricIds.STARTED_BY_CONTEXTUAL_SEARCH,
804 PageTransition.LINK, false, documentData);
805 return false;
806 }
807
808 @Override
809 public boolean onMenuOrKeyboardAction(int id, boolean fromMenu) {
810 if (id == R.id.new_tab_menu_id) {
811 mHandler.postDelayed(new Runnable() {
812 @Override
813 public void run() {
814 launchNtp(false);
815 }
816 }, MENU_EXIT_ANIMATION_WAIT_MS);
817 RecordUserAction.record("MobileMenuNewTab");
818 RecordUserAction.record("MobileNewTabOpened");
819 } else if (id == R.id.new_incognito_tab_menu_id) {
820 // This action must be recorded before opening the incognito tab sin ce UMA actions
821 // are dropped when an incognito tab is open.
822 RecordUserAction.record("MobileMenuNewIncognitoTab");
823 RecordUserAction.record("MobileNewTabOpened");
824 mHandler.postDelayed(new Runnable() {
825 @Override
826 public void run() {
827 launchNtp(true);
828 }
829 }, MENU_EXIT_ANIMATION_WAIT_MS);
830 } else if (id == R.id.all_bookmarks_menu_id) {
831 if (!EnhancedBookmarkUtils.showEnhancedBookmarkIfEnabled(this)) {
832 DocumentNewTabPage.launchBookmarksDialog(this, mDocumentTab, get TabModelSelector());
833 }
834 RecordUserAction.record("MobileMenuAllBookmarks");
835 } else if (id == R.id.recent_tabs_menu_id) {
836 DocumentNewTabPage.launchRecentTabsDialog(this, mDocumentTab, false) ;
837 RecordUserAction.record("MobileMenuOpenTabs");
838 } else if (id == R.id.find_in_page_id) {
839 mFindToolbarManager.showToolbar();
840 if (fromMenu) {
841 RecordUserAction.record("MobileMenuFindInPage");
842 } else {
843 RecordUserAction.record("MobileShortcutFindInPage");
844 }
845 } else if (id == R.id.show_menu) {
846 if (mToolbarHelper.isInitialized()) {
847 mAppMenuHandler.showAppMenu(mToolbarHelper.getMenuAnchor(), true ,
848 false);
849 }
850 } else if (id == R.id.focus_url_bar) {
851 if (mToolbarHelper.isInitialized()) mToolbarHelper.setUrlBarFocus(tr ue);
852 } else {
853 return super.onMenuOrKeyboardAction(id, fromMenu);
854 }
855 return true;
856 }
857
858 @Override
859 public boolean dispatchKeyEvent(KeyEvent event) {
860 Boolean result = KeyboardShortcuts.dispatchKeyEvent(event, this,
861 mToolbarHelper.isInitialized());
862 return result != null ? result : super.dispatchKeyEvent(event);
863 }
864
865 @Override
866 public boolean onKeyDown(int keyCode, KeyEvent event) {
867 if (!mToolbarHelper.isInitialized()) return false;
868 return KeyboardShortcuts.onKeyDown(event, this, true, false)
869 || super.onKeyDown(keyCode, event);
870 }
871
872 @Override
873 public boolean shouldShowAppMenu() {
874 if (mDocumentTab == null || !mToolbarHelper.isInitialized()) {
875 return false;
876 }
877
878 return super.shouldShowAppMenu();
879 }
880
881 private void updateTaskDescription() {
882 if (mDocumentTab == null) {
883 updateTaskDescription(null, null);
884 return;
885 }
886
887 if (isNewTabPage() && !isIncognito()) {
888 // NTP needs a new color in recents, but uses the default applicatio n title and icon;
889 updateTaskDescription(null, null);
890 return;
891 }
892
893 String label = mDocumentTab.getTitle();
894 String domain = UrlUtilities.getDomainAndRegistry(mDocumentTab.getUrl(), false);
895 if (TextUtils.isEmpty(label)) {
896 label = domain;
897 }
898 if (mIcon == null && TextUtils.isEmpty(label)) {
899 updateTaskDescription(null, null);
900 return;
901 }
902
903 if (isIncognito()) {
904 mIcon = null;
905 } else if (mIcon == null) {
906 if (mDocumentAppIconGenerator == null) {
907 mDocumentAppIconGenerator = new RoundedIconGenerator(this,
908 APP_ICON_SIZE_DP, APP_ICON_SIZE_DP,
909 APP_ICON_CORNER_RADIUS_DP, APP_ICON_DEFAULT_BACKGROUND_C OLOR,
910 APP_ICON_TEXT_SIZE_DP);
911 }
912 mIcon = mDocumentAppIconGenerator.generateIconForUrl(mDocumentTab.ge tUrl());
913 mIsUsingGeneratedIcon = true;
914 }
915
916 updateTaskDescription(label, mIcon);
917 }
918
919 protected int getThemeColor() {
920 if (isIncognito()) {
921 return mDefaultThemeColor;
922 } else {
923 return mThemeColor != null ? mThemeColor.intValue() : mDefaultThemeC olor;
924 }
925 }
926
927 private boolean shouldUseDefaultStatusBarColor() {
928 return isIncognito() || mThemeColor == null || mThemeColor == mDefaultTh emeColor;
929 }
930
931 protected void updateTaskDescription(String label, Bitmap icon) {
932 int color = getThemeColor();
933 DocumentUtils.updateTaskDescription(this, label, icon, color,
934 shouldUseDefaultStatusBarColor());
935 mToolbarHelper.setThemeColor(color);
936
937 ControlContainer controlContainer =
938 (ControlContainer) findViewById(R.id.control_container);
939 controlContainer.getToolbarResourceAdapter().invalidate(null);
940 }
941
942 /**
943 * @return Whether the {@link DocumentTab} this activity uses is incognito.
944 */
945 protected boolean isIncognito() {
946 return false;
947 }
948
949 /**
950 * @return Whether this activity contains a tab that is showing the new tab page.
951 */
952 boolean isNewTabPage() {
953 String url;
954 if (mDocumentTab == null) {
955 // If the Tab hasn't been created yet, then we're really early in in itialization.
956 // Use a combination of the original URL from the Intent and whether or not the Tab is
957 // retargetable to know whether or not the user navigated away from the NTP.
958 // If the Entry doesn't exist, then the DocumentActivity never got a chance to add
959 // itself to the TabList and is likely to be retargetable.
960 int tabId = ActivityDelegate.getTabIdFromIntent(getIntent());
961 url = IntentHandler.getUrlFromIntent(getIntent());
962 if (mTabModel.hasEntryForTabId(tabId) && !mTabModel.isRetargetable(t abId)) return false;
963 } else {
964 url = mDocumentTab.getUrl();
965 }
966 return NewTabPage.isNTPUrl(url);
967 }
968
969 /**
970 * Determines whether the given class can be classified as a DocumentActivit y (this includes
971 * both regular document activity and incognito document activity).
972 * @param className The class name to inspect.
973 * @return Whether the className is that of a document activity.
974 */
975 public static boolean isDocumentActivity(String className) {
976 return TextUtils.equals(className, IncognitoDocumentActivity.class.getNa me())
977 || TextUtils.equals(className, DocumentActivity.class.getName()) ;
978 }
979
980 /**
981 * Launch a new DocumentActivity showing the new tab page.
982 * @param incognito Whether the new NTP should be in incognito mode.
983 */
984 private void launchNtp(boolean incognito) {
985 if (incognito && !PrefServiceBridge.getInstance().isIncognitoModeEnabled ()) return;
986 ChromeLauncherActivity.launchDocumentInstance(this, incognito,
987 ChromeLauncherActivity.LAUNCH_MODE_RETARGET, UrlConstants.NTP_UR L,
988 DocumentMetricIds.STARTED_BY_OPTIONS_MENU, PageTransition.AUTO_T OPLEVEL, false,
989 null);
990 }
991 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698