OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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.tab; | 5 package org.chromium.chrome.browser.tab; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.content.Intent; | 9 import android.content.Intent; |
10 import android.content.res.Resources; | 10 import android.content.res.Resources; |
11 import android.graphics.Bitmap; | 11 import android.graphics.Bitmap; |
12 import android.graphics.Color; | 12 import android.graphics.Color; |
13 import android.os.Handler; | 13 import android.os.Handler; |
14 import android.os.Message; | 14 import android.os.Message; |
15 import android.provider.Browser; | 15 import android.provider.Browser; |
16 import android.text.TextUtils; | 16 import android.text.TextUtils; |
17 import android.util.Log; | 17 import android.util.Log; |
| 18 import android.view.ContextThemeWrapper; |
18 import android.view.View; | 19 import android.view.View; |
19 import android.view.View.OnClickListener; | 20 import android.view.View.OnClickListener; |
20 import android.view.ViewGroup; | 21 import android.view.ViewGroup; |
21 import android.view.ViewGroup.LayoutParams; | 22 import android.view.ViewGroup.LayoutParams; |
22 import android.widget.FrameLayout; | 23 import android.widget.FrameLayout; |
23 | 24 |
24 import org.chromium.base.ApiCompatibilityUtils; | 25 import org.chromium.base.ApiCompatibilityUtils; |
25 import org.chromium.base.ApplicationStatus; | 26 import org.chromium.base.ApplicationStatus; |
26 import org.chromium.base.ObserverList; | 27 import org.chromium.base.ObserverList; |
27 import org.chromium.base.ObserverList.RewindableIterator; | 28 import org.chromium.base.ObserverList.RewindableIterator; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 * The required page load percentage for the page to be considered ready ass
uming the | 129 * The required page load percentage for the page to be considered ready ass
uming the |
129 * TextureView is also ready. | 130 * TextureView is also ready. |
130 */ | 131 */ |
131 private static final int CONSIDERED_READY_LOAD_PERCENTAGE = 100; | 132 private static final int CONSIDERED_READY_LOAD_PERCENTAGE = 100; |
132 | 133 |
133 /** Used for logging. */ | 134 /** Used for logging. */ |
134 private static final String TAG = "Tab"; | 135 private static final String TAG = "Tab"; |
135 | 136 |
136 /** | 137 /** |
137 * The {@link Activity} used to create {@link View}s and other Android compo
nents. Unlike | 138 * The {@link Activity} used to create {@link View}s and other Android compo
nents. Unlike |
138 * {@link #mApplicationContext}, this is not publicly exposed to help preven
t leaking the | 139 * {@link #mThemedApplicationContext}, this is not publicly exposed to help
prevent leaking the |
139 * {@link Activity}. | 140 * {@link Activity}. |
140 */ | 141 */ |
141 protected final ChromeActivity mActivity; | 142 protected final ChromeActivity mActivity; |
142 | 143 |
143 private long mNativeTabAndroid; | 144 private long mNativeTabAndroid; |
144 | 145 |
145 /** Unique id of this tab (within its container). */ | 146 /** Unique id of this tab (within its container). */ |
146 private final int mId; | 147 private final int mId; |
147 | 148 |
148 /** Whether or not this tab is an incognito tab. */ | 149 /** Whether or not this tab is an incognito tab. */ |
149 private final boolean mIncognito; | 150 private final boolean mIncognito; |
150 | 151 |
151 /** | 152 /** |
152 * An Application {@link Context}. Unlike {@link #mActivity}, this is the o
nly one that is | 153 * An Application {@link Context}. Unlike {@link #mActivity}, this is the o
nly one that is |
153 * publicly exposed to help prevent leaking the {@link Activity}. | 154 * publicly exposed to help prevent leaking the {@link Activity}. |
154 */ | 155 */ |
155 private final Context mApplicationContext; | 156 private final Context mThemedApplicationContext; |
156 | 157 |
157 /** Gives {@link Tab} a way to interact with the Android window. */ | 158 /** Gives {@link Tab} a way to interact with the Android window. */ |
158 private final WindowAndroid mWindowAndroid; | 159 private final WindowAndroid mWindowAndroid; |
159 | 160 |
160 /** Whether or not this {@link Tab} is initialized and should be interacted
with. */ | 161 /** Whether or not this {@link Tab} is initialized and should be interacted
with. */ |
161 private boolean mIsInitialized; | 162 private boolean mIsInitialized; |
162 | 163 |
163 /** The current native page (e.g. chrome-native://newtab), or {@code null} i
f there is none. */ | 164 /** The current native page (e.g. chrome-native://newtab), or {@code null} i
f there is none. */ |
164 private NativePage mNativePage; | 165 private NativePage mNativePage; |
165 | 166 |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 * accounting. When null, TabUma will not be initialize
d. | 537 * accounting. When null, TabUma will not be initialize
d. |
537 * @param frozenState State containing information about this Tab, if it was
persisted. | 538 * @param frozenState State containing information about this Tab, if it was
persisted. |
538 */ | 539 */ |
539 public Tab(int id, int parentId, boolean incognito, ChromeActivity activity, | 540 public Tab(int id, int parentId, boolean incognito, ChromeActivity activity, |
540 WindowAndroid window, TabLaunchType type, TabCreationState creationS
tate, | 541 WindowAndroid window, TabLaunchType type, TabCreationState creationS
tate, |
541 TabState frozenState) { | 542 TabState frozenState) { |
542 mId = TabIdManager.getInstance().generateValidId(id); | 543 mId = TabIdManager.getInstance().generateValidId(id); |
543 mParentId = parentId; | 544 mParentId = parentId; |
544 mIncognito = incognito; | 545 mIncognito = incognito; |
545 mActivity = activity; | 546 mActivity = activity; |
546 mApplicationContext = activity != null ? activity.getApplicationContext(
) : null; | 547 mThemedApplicationContext = activity != null ? new ContextThemeWrapper( |
| 548 activity.getApplicationContext(), ChromeActivity.getThemeId()) :
null; |
547 mWindowAndroid = window; | 549 mWindowAndroid = window; |
548 mLaunchType = type; | 550 mLaunchType = type; |
549 if (mActivity != null) { | 551 if (mThemedApplicationContext != null) { |
550 Resources resources = mActivity.getResources(); | 552 Resources resources = mThemedApplicationContext.getResources(); |
551 mIdealFaviconSize = resources.getDimensionPixelSize(R.dimen.default_
favicon_size); | 553 mIdealFaviconSize = resources.getDimensionPixelSize(R.dimen.default_
favicon_size); |
552 mDefaultThemeColor = mIncognito | 554 mDefaultThemeColor = mIncognito |
553 ? ApiCompatibilityUtils.getColor(resources, R.color.incognit
o_primary_color) | 555 ? ApiCompatibilityUtils.getColor(resources, R.color.incognit
o_primary_color) |
554 : ApiCompatibilityUtils.getColor(resources, R.color.default_
primary_color); | 556 : ApiCompatibilityUtils.getColor(resources, R.color.default_
primary_color); |
555 } else { | 557 } else { |
556 mIdealFaviconSize = 16; | 558 mIdealFaviconSize = 16; |
557 mDefaultThemeColor = 0; | 559 mDefaultThemeColor = 0; |
558 } | 560 } |
559 | 561 |
560 // Restore data from the TabState, if it existed. | 562 // Restore data from the TabState, if it existed. |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 */ | 800 */ |
799 public int getHeight() { | 801 public int getHeight() { |
800 View view = getView(); | 802 View view = getView(); |
801 return view != null ? view.getHeight() : 0; | 803 return view != null ? view.getHeight() : 0; |
802 } | 804 } |
803 | 805 |
804 /** | 806 /** |
805 * @return The application {@link Context} associated with this tab. | 807 * @return The application {@link Context} associated with this tab. |
806 */ | 808 */ |
807 protected Context getApplicationContext() { | 809 protected Context getApplicationContext() { |
808 return mApplicationContext; | 810 return mThemedApplicationContext.getApplicationContext(); |
809 } | 811 } |
810 | 812 |
811 /** | 813 /** |
812 * @return The infobar container. | 814 * @return The infobar container. |
813 */ | 815 */ |
814 public final InfoBarContainer getInfoBarContainer() { | 816 public final InfoBarContainer getInfoBarContainer() { |
815 return mInfoBarContainer; | 817 return mInfoBarContainer; |
816 } | 818 } |
817 | 819 |
818 /** @return An opaque "state" object that can be persisted to storage. */ | 820 /** @return An opaque "state" object that can be persisted to storage. */ |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 mIsInitialized = true; | 1475 mIsInitialized = true; |
1474 } | 1476 } |
1475 | 1477 |
1476 /** | 1478 /** |
1477 * Creates and initializes the {@link ContentViewCore}. | 1479 * Creates and initializes the {@link ContentViewCore}. |
1478 * | 1480 * |
1479 * @param webContents The WebContents object that will be used to build the | 1481 * @param webContents The WebContents object that will be used to build the |
1480 * {@link ContentViewCore}. | 1482 * {@link ContentViewCore}. |
1481 */ | 1483 */ |
1482 protected void initContentViewCore(WebContents webContents) { | 1484 protected void initContentViewCore(WebContents webContents) { |
1483 ContentViewCore cvc = new ContentViewCore(mActivity); | 1485 ContentViewCore cvc = new ContentViewCore(mThemedApplicationContext); |
1484 ContentView cv = ContentView.createContentView(mActivity, cvc); | 1486 ContentView cv = ContentView.createContentView(mThemedApplicationContext
, cvc); |
1485 cv.setContentDescription(mActivity.getResources().getString( | 1487 cv.setContentDescription(mThemedApplicationContext.getResources().getStr
ing( |
1486 R.string.accessibility_content_view)); | 1488 R.string.accessibility_content_view)); |
1487 cvc.initialize(cv, cv, webContents, getWindowAndroid()); | 1489 cvc.initialize(cv, cv, webContents, getWindowAndroid()); |
1488 setContentViewCore(cvc); | 1490 setContentViewCore(cvc); |
1489 } | 1491 } |
1490 | 1492 |
1491 /** | 1493 /** |
1492 * Completes the {@link ContentViewCore} specific initialization around a na
tive WebContents | 1494 * Completes the {@link ContentViewCore} specific initialization around a na
tive WebContents |
1493 * pointer. {@link #getNativePage()} will still return the {@link NativePage
} if there is one. | 1495 * pointer. {@link #getNativePage()} will still return the {@link NativePage
} if there is one. |
1494 * All initialization that needs to reoccur after a web contents swap should
be added here. | 1496 * All initialization that needs to reoccur after a web contents swap should
be added here. |
1495 * <p /> | 1497 * <p /> |
(...skipping 15 matching lines...) Expand all Loading... |
1511 | 1513 |
1512 // Wrap the ContentView in a FrameLayout, which will contain both th
e ContentView and | 1514 // Wrap the ContentView in a FrameLayout, which will contain both th
e ContentView and |
1513 // the InfoBarContainer. The alternative -- placing the InfoBarConta
iner inside the | 1515 // the InfoBarContainer. The alternative -- placing the InfoBarConta
iner inside the |
1514 // ContentView -- causes problems since then the ContentView would c
ontain both real | 1516 // ContentView -- causes problems since then the ContentView would c
ontain both real |
1515 // views (the infobars) and virtual views (the web page elements), w
hich breaks Android | 1517 // views (the infobars) and virtual views (the web page elements), w
hich breaks Android |
1516 // accessibility. http://crbug.com/416663 | 1518 // accessibility. http://crbug.com/416663 |
1517 if (mContentViewParent != null) { | 1519 if (mContentViewParent != null) { |
1518 assert false; | 1520 assert false; |
1519 mContentViewParent.removeAllViews(); | 1521 mContentViewParent.removeAllViews(); |
1520 } | 1522 } |
1521 mContentViewParent = new FrameLayout(mActivity); | 1523 mContentViewParent = new FrameLayout(mThemedApplicationContext); |
1522 mContentViewParent.addView(cvc.getContainerView(), | 1524 mContentViewParent.addView(cvc.getContainerView(), |
1523 new FrameLayout.LayoutParams( | 1525 new FrameLayout.LayoutParams( |
1524 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT
)); | 1526 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT
)); |
1525 | 1527 |
1526 mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(th
is, mActivity); | 1528 mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(th
is, mActivity); |
1527 mWebContentsObserver = | 1529 mWebContentsObserver = |
1528 new TabWebContentsObserver(mContentViewCore.getWebContents()
, this); | 1530 new TabWebContentsObserver(mContentViewCore.getWebContents()
, this); |
1529 | 1531 |
1530 if (mContentViewClient != null) { | 1532 if (mContentViewClient != null) { |
1531 mContentViewCore.setContentViewClient(mContentViewClient); | 1533 mContentViewCore.setContentViewClient(mContentViewClient); |
1532 } | 1534 } |
1533 | 1535 |
1534 assert mNativeTabAndroid != 0; | 1536 assert mNativeTabAndroid != 0; |
1535 nativeInitWebContents( | 1537 nativeInitWebContents( |
1536 mNativeTabAndroid, mIncognito, mContentViewCore, mWebContent
sDelegate, | 1538 mNativeTabAndroid, mIncognito, mContentViewCore, mWebContent
sDelegate, |
1537 new TabContextMenuPopulator( | 1539 new TabContextMenuPopulator( |
1538 mDelegateFactory.createContextMenuPopulator(this, mA
ctivity), this)); | 1540 mDelegateFactory.createContextMenuPopulator(this, mA
ctivity), this)); |
1539 | 1541 |
1540 // In the case where restoring a Tab or showing a prerendered one we
already have a | 1542 // In the case where restoring a Tab or showing a prerendered one we
already have a |
1541 // valid infobar container, no need to recreate one. | 1543 // valid infobar container, no need to recreate one. |
1542 if (mInfoBarContainer == null) { | 1544 if (mInfoBarContainer == null) { |
1543 // The InfoBarContainer needs to be created after the ContentVie
w has been natively | 1545 // The InfoBarContainer needs to be created after the ContentVie
w has been natively |
1544 // initialized. | 1546 // initialized. |
1545 mInfoBarContainer = | 1547 mInfoBarContainer = new InfoBarContainer( |
1546 new InfoBarContainer(mActivity, getId(), mContentViewPar
ent, this); | 1548 mThemedApplicationContext, getId(), mContentViewParent,
this); |
1547 } else { | 1549 } else { |
1548 mInfoBarContainer.onParentViewChanged(getId(), mContentViewParen
t); | 1550 mInfoBarContainer.onParentViewChanged(getId(), mContentViewParen
t); |
1549 } | 1551 } |
1550 mInfoBarContainer.setContentViewCore(mContentViewCore); | 1552 mInfoBarContainer.setContentViewCore(mContentViewCore); |
1551 | 1553 |
1552 mSwipeRefreshHandler = new SwipeRefreshHandler(mActivity); | 1554 mSwipeRefreshHandler = new SwipeRefreshHandler(mThemedApplicationCon
text); |
1553 mSwipeRefreshHandler.setContentViewCore(mContentViewCore); | 1555 mSwipeRefreshHandler.setContentViewCore(mContentViewCore); |
1554 | 1556 |
1555 for (TabObserver observer : mObservers) observer.onContentChanged(th
is); | 1557 for (TabObserver observer : mObservers) observer.onContentChanged(th
is); |
1556 | 1558 |
1557 // For browser tabs, we want to set accessibility focus to the page | 1559 // For browser tabs, we want to set accessibility focus to the page |
1558 // when it loads. This is not the default behavior for embedded | 1560 // when it loads. This is not the default behavior for embedded |
1559 // web views. | 1561 // web views. |
1560 mContentViewCore.setShouldSetAccessibilityFocusOnPageLoad(true); | 1562 mContentViewCore.setShouldSetAccessibilityFocusOnPageLoad(true); |
1561 | 1563 |
1562 mDownloadDelegate = new ChromeDownloadDelegate(mActivity, | 1564 mDownloadDelegate = new ChromeDownloadDelegate(mThemedApplicationCon
text, |
1563 mActivity.getTabModelSelector(), this); | 1565 mActivity.getTabModelSelector(), this); |
1564 cvc.setDownloadDelegate(mDownloadDelegate); | 1566 cvc.setDownloadDelegate(mDownloadDelegate); |
1565 | 1567 |
1566 setInterceptNavigationDelegate(mDelegateFactory | 1568 setInterceptNavigationDelegate(mDelegateFactory |
1567 .createInterceptNavigationDelegate(this, mActivity)); | 1569 .createInterceptNavigationDelegate(this, mActivity)); |
1568 | 1570 |
1569 if (mGestureStateListener == null) { | 1571 if (mGestureStateListener == null) { |
1570 mGestureStateListener = createGestureStateListener(); | 1572 mGestureStateListener = createGestureStateListener(); |
1571 } | 1573 } |
1572 cvc.addGestureStateListener(mGestureStateListener); | 1574 cvc.addGestureStateListener(mGestureStateListener); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1634 OnClickListener reloadButtonAction = new OnClickListener() { | 1636 OnClickListener reloadButtonAction = new OnClickListener() { |
1635 @Override | 1637 @Override |
1636 public void onClick(View view) { | 1638 public void onClick(View view) { |
1637 reload(); | 1639 reload(); |
1638 } | 1640 } |
1639 }; | 1641 }; |
1640 | 1642 |
1641 // Make sure we are not adding the "Aw, snap" view over an existing
one. | 1643 // Make sure we are not adding the "Aw, snap" view over an existing
one. |
1642 assert mSadTabView == null; | 1644 assert mSadTabView == null; |
1643 mSadTabView = SadTabViewFactory.createSadTabView( | 1645 mSadTabView = SadTabViewFactory.createSadTabView( |
1644 mActivity, suggestionAction, reloadButtonAction); | 1646 mThemedApplicationContext, suggestionAction, reloadButtonAct
ion); |
1645 | 1647 |
1646 // Show the sad tab inside ContentView. | 1648 // Show the sad tab inside ContentView. |
1647 getContentViewCore().getContainerView().addView( | 1649 getContentViewCore().getContainerView().addView( |
1648 mSadTabView, new FrameLayout.LayoutParams( | 1650 mSadTabView, new FrameLayout.LayoutParams( |
1649 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT
)); | 1651 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT
)); |
1650 for (TabObserver observer : mObservers) observer.onContentChanged(th
is); | 1652 for (TabObserver observer : mObservers) observer.onContentChanged(th
is); |
1651 } | 1653 } |
1652 FullscreenManager fullscreenManager = getFullscreenManager(); | 1654 FullscreenManager fullscreenManager = getFullscreenManager(); |
1653 if (fullscreenManager != null) { | 1655 if (fullscreenManager != null) { |
1654 fullscreenManager.setPositionsForTabToNonFullscreen(); | 1656 fullscreenManager.setPositionsForTabToNonFullscreen(); |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2131 @CalledByNative | 2133 @CalledByNative |
2132 private long getNativePtr() { | 2134 private long getNativePtr() { |
2133 return mNativeTabAndroid; | 2135 return mNativeTabAndroid; |
2134 } | 2136 } |
2135 | 2137 |
2136 /** This is currently called when committing a pre-rendered page. */ | 2138 /** This is currently called when committing a pre-rendered page. */ |
2137 @VisibleForTesting | 2139 @VisibleForTesting |
2138 @CalledByNative | 2140 @CalledByNative |
2139 public void swapWebContents( | 2141 public void swapWebContents( |
2140 WebContents webContents, boolean didStartLoad, boolean didFinishLoad
) { | 2142 WebContents webContents, boolean didStartLoad, boolean didFinishLoad
) { |
2141 ContentViewCore cvc = new ContentViewCore(mActivity); | 2143 ContentViewCore cvc = new ContentViewCore(mThemedApplicationContext); |
2142 ContentView cv = ContentView.createContentView(mActivity, cvc); | 2144 ContentView cv = ContentView.createContentView(mThemedApplicationContext
, cvc); |
2143 cv.setContentDescription(mActivity.getResources().getString( | 2145 cv.setContentDescription(mThemedApplicationContext.getResources().getStr
ing( |
2144 R.string.accessibility_content_view)); | 2146 R.string.accessibility_content_view)); |
2145 cvc.initialize(cv, cv, webContents, getWindowAndroid()); | 2147 cvc.initialize(cv, cv, webContents, getWindowAndroid()); |
2146 swapContentViewCore(cvc, false, didStartLoad, didFinishLoad); | 2148 swapContentViewCore(cvc, false, didStartLoad, didFinishLoad); |
2147 } | 2149 } |
2148 | 2150 |
2149 /** | 2151 /** |
2150 * Called to swap out the current view with the one passed in. | 2152 * Called to swap out the current view with the one passed in. |
2151 * | 2153 * |
2152 * @param newContentViewCore The content view that should be swapped into th
e tab. | 2154 * @param newContentViewCore The content view that should be swapped into th
e tab. |
2153 * @param deleteOldNativeWebContents Whether to delete the native web | 2155 * @param deleteOldNativeWebContents Whether to delete the native web |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2860 private native void nativeSetInterceptNavigationDelegate(long nativeTabAndro
id, | 2862 private native void nativeSetInterceptNavigationDelegate(long nativeTabAndro
id, |
2861 InterceptNavigationDelegate delegate); | 2863 InterceptNavigationDelegate delegate); |
2862 private native void nativeAttachToTabContentManager(long nativeTabAndroid, | 2864 private native void nativeAttachToTabContentManager(long nativeTabAndroid, |
2863 TabContentManager tabContentManager); | 2865 TabContentManager tabContentManager); |
2864 private native void nativeAttachOverlayContentViewCore(long nativeTabAndroid
, | 2866 private native void nativeAttachOverlayContentViewCore(long nativeTabAndroid
, |
2865 ContentViewCore content, boolean visible); | 2867 ContentViewCore content, boolean visible); |
2866 private native void nativeDetachOverlayContentViewCore(long nativeTabAndroid
, | 2868 private native void nativeDetachOverlayContentViewCore(long nativeTabAndroid
, |
2867 ContentViewCore content); | 2869 ContentViewCore content); |
2868 private native boolean nativeHasPrerenderedUrl(long nativeTabAndroid, String
url); | 2870 private native boolean nativeHasPrerenderedUrl(long nativeTabAndroid, String
url); |
2869 } | 2871 } |
OLD | NEW |