Index: chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java |
index a88063610d22b56e782c5cfaddd3ccf9e09ac6ea..44faade0141a2d1de1323fbe0c1fd46d0f637015 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java |
@@ -22,6 +22,7 @@ import android.text.TextUtils; |
import android.util.Log; |
import android.util.Pair; |
import android.view.ContextMenu; |
+import android.view.ContextThemeWrapper; |
import android.view.KeyEvent; |
import android.view.View; |
import android.view.View.OnClickListener; |
@@ -163,13 +164,6 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
/** Used for logging. */ |
private static final String TAG = "Tab"; |
- /** |
- * The {@link Activity} used to create {@link View}s and other Android components. Unlike |
- * {@link #mApplicationContext}, this is not publicly exposed to help prevent leaking the |
- * {@link Activity}. |
- */ |
- protected final ChromeActivity mActivity; |
- |
private long mNativeTabAndroid; |
/** Unique id of this tab (within its container). */ |
@@ -184,6 +178,8 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
*/ |
private final Context mApplicationContext; |
+ private final ContextThemeWrapper mThemedContext; |
+ |
/** Gives {@link Tab} a way to interact with the Android window. */ |
private final WindowAndroid mWindowAndroid; |
@@ -388,23 +384,25 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
private final Runnable mCloseContentsRunnable = new Runnable() { |
@Override |
public void run() { |
- boolean isSelected = mActivity.getTabModelSelector().getCurrentTab() == Tab.this; |
- mActivity.getTabModelSelector().closeTab(Tab.this); |
+ TabModelSelector selector = getTabModelSelector(); |
+ if (selector == null) return; |
+ boolean isSelected = selector.getCurrentTab() == Tab.this; |
+ selector.closeTab(Tab.this); |
// If the parent Tab belongs to another Activity, fire the Intent to bring it back. |
if (isSelected && getParentIntent() != null |
- && mActivity.getIntent() != getParentIntent()) { |
- boolean mayLaunch = FeatureUtilities.isDocumentMode(mActivity) |
+ && getActivity().getIntent() != getParentIntent()) { |
+ boolean mayLaunch = FeatureUtilities.isDocumentMode(mApplicationContext) |
? isParentInAndroidOverview() : true; |
- if (mayLaunch) mActivity.startActivity(getParentIntent()); |
+ if (mayLaunch) getActivity().startActivity(getParentIntent()); |
} |
} |
/** If the API allows it, returns whether a Task still exists for the parent Activity. */ |
@TargetApi(Build.VERSION_CODES.LOLLIPOP) |
private boolean isParentInAndroidOverview() { |
- ActivityManager activityManager = |
- (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE); |
+ ActivityManager activityManager = (ActivityManager) mApplicationContext. |
+ getSystemService(Context.ACTIVITY_SERVICE); |
for (ActivityManager.AppTask task : activityManager.getAppTasks()) { |
Intent taskIntent = DocumentUtils.getBaseIntentFromTask(task); |
if (taskIntent != null && taskIntent.filterEquals(getParentIntent())) return true; |
@@ -467,10 +465,11 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@Override |
public void onOpenInNewTab(String url, Referrer referrer) { |
+ if (getTabModelSelector() == null) return; |
RecordUserAction.record("MobileNewTabOpened"); |
LoadUrlParams loadUrlParams = new LoadUrlParams(url); |
loadUrlParams.setReferrer(referrer); |
- mActivity.getTabModelSelector().openNewTab(loadUrlParams, |
+ getTabModelSelector().openNewTab(loadUrlParams, |
TabLaunchType.FROM_LONGPRESS_BACKGROUND, Tab.this, isIncognito()); |
} |
@@ -486,8 +485,9 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@Override |
public void onOpenInNewIncognitoTab(String url) { |
+ if (getTabModelSelector() == null) return; |
RecordUserAction.record("MobileNewTabOpened"); |
- mActivity.getTabModelSelector().openNewTab(new LoadUrlParams(url), |
+ getTabModelSelector().openNewTab(new LoadUrlParams(url), |
TabLaunchType.FROM_LONGPRESS_FOREGROUND, Tab.this, true); |
} |
@@ -506,11 +506,12 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@Override |
public void onOpenImageInNewTab(String url, Referrer referrer) { |
+ if (getTabModelSelector() == null) return; |
boolean useOriginal = isSpdyProxyEnabledForUrl(url); |
LoadUrlParams loadUrlParams = new LoadUrlParams(url); |
loadUrlParams.setVerbatimHeaders(useOriginal ? PAGESPEED_PASSTHROUGH_HEADERS : null); |
loadUrlParams.setReferrer(referrer); |
- mActivity.getTabModelSelector().openNewTab(loadUrlParams, |
+ getTabModelSelector().openNewTab(loadUrlParams, |
TabLaunchType.FROM_LONGPRESS_BACKGROUND, Tab.this, isIncognito()); |
} |
@@ -552,9 +553,8 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
// When the dialog is visible, keeping the refresh animation active |
// in the background is distracting and unnecessary (and likely to |
// jank when the dialog is shown). |
- if (mSwipeRefreshHandler != null) { |
- mSwipeRefreshHandler.reset(); |
- } |
+ if (mSwipeRefreshHandler != null) mSwipeRefreshHandler.reset(); |
+ if (getActivity() == null) return; |
RepostFormWarningDialog warningDialog = new RepostFormWarningDialog( |
new Runnable() { |
@Override |
@@ -567,7 +567,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
getWebContents().getNavigationController().continuePendingReload(); |
} |
}); |
- warningDialog.show(mActivity.getFragmentManager(), null); |
+ warningDialog.show(getActivity().getFragmentManager(), null); |
} |
@Override |
@@ -609,12 +609,13 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
observer.webContentsCreated(Tab.this, sourceWebContents, openerRenderFrameId, |
frameName, targetUrl, newWebContents); |
} |
+ if (getActivity() == null) return; |
// The URL can't be taken from the WebContents if it's paused. Save it for later. |
assert mWebContentsUrlMapping == null; |
mWebContentsUrlMapping = Pair.create(newWebContents, targetUrl); |
// TODO(dfalcantara): Re-remove this once crbug.com/508366 is fixed. |
- TabCreator tabCreator = mActivity.getTabCreator(isIncognito()); |
+ TabCreator tabCreator = getActivity().getTabCreator(isIncognito()); |
if (tabCreator != null && tabCreator.createsTabsAsynchronously()) { |
DocumentWebContentsDelegate.getInstance().attachDelegate(newWebContents); |
@@ -656,15 +657,17 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
private Pair<WebContents, String> mWebContentsUrlMapping; |
protected TabModel getTabModel() { |
+ if (getTabModelSelector() == null) return null; |
// TODO(dfalcantara): Remove this when DocumentActivity.getTabModelSelector() |
// can return a TabModelSelector that activateContents() can use. |
- return mActivity.getTabModelSelector().getModel(isIncognito()); |
+ return getTabModelSelector().getModel(isIncognito()); |
} |
@Override |
public boolean shouldResumeRequestsForCreatedWindow() { |
+ if (getActivity() == null) return false; |
// Pause the WebContents if an Activity has to be created for it first. |
- TabCreator tabCreator = mActivity.getTabCreator(isIncognito()); |
+ TabCreator tabCreator = getActivity().getTabCreator(isIncognito()); |
assert tabCreator != null; |
return !tabCreator.createsTabsAsynchronously(); |
} |
@@ -673,8 +676,8 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
public boolean addNewContents(WebContents sourceWebContents, WebContents webContents, |
int disposition, Rect initialPosition, boolean userGesture) { |
assert mWebContentsUrlMapping.first == webContents; |
- |
- TabCreator tabCreator = mActivity.getTabCreator(isIncognito()); |
+ if (getActivity() == null) return false; |
+ TabCreator tabCreator = getActivity().getTabCreator(isIncognito()); |
assert tabCreator != null; |
// Grab the URL, which might not be available via the Tab. |
@@ -703,8 +706,9 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@Override |
public void activateContents() { |
boolean activityIsDestroyed = false; |
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { |
- activityIsDestroyed = mActivity.isDestroyed(); |
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 |
+ && getActivity() != null) { |
+ activityIsDestroyed = getActivity().isDestroyed(); |
} |
if (activityIsDestroyed || !isInitialized()) { |
Log.e(TAG, "Activity destroyed before calling activateContents(). Bailing out."); |
@@ -748,21 +752,23 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@Override |
public boolean takeFocus(boolean reverse) { |
+ if (getActivity() == null) return false; |
+ Activity activity = getActivity(); |
if (reverse) { |
- View menuButton = mActivity.findViewById(R.id.menu_button); |
+ View menuButton = activity.findViewById(R.id.menu_button); |
if (menuButton == null || !menuButton.isShown()) { |
- menuButton = mActivity.findViewById(R.id.document_menu_button); |
+ menuButton = activity.findViewById(R.id.document_menu_button); |
} |
if (menuButton != null && menuButton.isShown()) { |
return menuButton.requestFocus(); |
} |
- View tabSwitcherButton = mActivity.findViewById(R.id.tab_switcher_button); |
+ View tabSwitcherButton = activity.findViewById(R.id.tab_switcher_button); |
if (tabSwitcherButton != null && tabSwitcherButton.isShown()) { |
return tabSwitcherButton.requestFocus(); |
} |
} else { |
- View urlBar = mActivity.findViewById(R.id.url_bar); |
+ View urlBar = activity.findViewById(R.id.url_bar); |
if (urlBar != null) return urlBar.requestFocus(); |
} |
return false; |
@@ -770,8 +776,9 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@Override |
public void handleKeyboardEvent(KeyEvent event) { |
+ if (getActivity() == null) return; |
if (event.getAction() == KeyEvent.ACTION_DOWN) { |
- if (mActivity.onKeyDown(event.getKeyCode(), event)) return; |
+ if (getActivity().onKeyDown(event.getKeyCode(), event)) return; |
// Handle the Escape key here (instead of in KeyboardShortcuts.java), so it doesn't |
// interfere with other parts of the activity (e.g. the URL bar). |
@@ -806,7 +813,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
case KeyEvent.KEYCODE_MEDIA_CLOSE: |
case KeyEvent.KEYCODE_MEDIA_EJECT: |
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: |
- AudioManager am = (AudioManager) mActivity.getSystemService( |
+ AudioManager am = (AudioManager) mApplicationContext.getSystemService( |
Context.AUDIO_SERVICE); |
am.dispatchMediaKeyEvent(e); |
break; |
@@ -885,7 +892,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@Override |
public void performWebSearch(String searchQuery) { |
- if (TextUtils.isEmpty(searchQuery)) return; |
+ if (TextUtils.isEmpty(searchQuery) || getTabModelSelector() == null) return; |
String url = TemplateUrlService.getInstance().getUrlForSearchQuery(searchQuery); |
String headers = GeolocationHeader.getGeoHeader(getApplicationContext(), url, |
isIncognito()); |
@@ -893,13 +900,14 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
LoadUrlParams loadUrlParams = new LoadUrlParams(url); |
loadUrlParams.setVerbatimHeaders(headers); |
loadUrlParams.setTransitionType(PageTransition.GENERATED); |
- mActivity.getTabModelSelector().openNewTab(loadUrlParams, |
+ getTabModelSelector().openNewTab(loadUrlParams, |
TabLaunchType.FROM_LONGPRESS_FOREGROUND, Tab.this, isIncognito()); |
} |
@Override |
public ContentVideoViewClient getContentVideoViewClient() { |
- return new ActivityContentVideoViewClient(mActivity) { |
+ assert getActivity() != null; |
+ return new ActivityContentVideoViewClient(getActivity()) { |
@Override |
public void enterFullscreenVideo(View view) { |
super.enterFullscreenVideo(view); |
@@ -1154,17 +1162,17 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
* @param window An instance of a {@link WindowAndroid}. |
* @param frozenState State containing information about this Tab, if it was persisted. |
*/ |
- public Tab(int id, int parentId, boolean incognito, ChromeActivity activity, |
+ public Tab(int id, int parentId, boolean incognito, Context context, |
WindowAndroid window, TabLaunchType type, TabState frozenState) { |
mId = TabIdManager.getInstance().generateValidId(id); |
mParentId = parentId; |
mIncognito = incognito; |
- mActivity = activity; |
- mApplicationContext = activity != null ? activity.getApplicationContext() : null; |
+ mApplicationContext = context != null ? context.getApplicationContext() : null; |
+ mThemedContext = new ContextThemeWrapper(mApplicationContext, R.style.MainTheme); |
mWindowAndroid = window; |
mLaunchType = type; |
- if (mActivity != null) { |
- Resources resources = mActivity.getResources(); |
+ if (mApplicationContext != null) { |
+ Resources resources = mApplicationContext.getResources(); |
mIdealFaviconSize = resources.getDimensionPixelSize(R.dimen.default_favicon_size); |
mDefaultThemeColor = mIncognito |
? ApiCompatibilityUtils.getColor(resources, R.color.incognito_primary_color) |
@@ -1196,6 +1204,18 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
}; |
} |
+ protected ChromeActivity getActivity() { |
+ if (getWindowAndroid() == null) return null; |
+ Activity activity = getWindowAndroid().getActivity().get(); |
+ if (!(activity instanceof ChromeActivity)) return null; |
+ return (ChromeActivity) activity; |
+ } |
+ |
+ protected TabModelSelector getTabModelSelector() { |
+ if (getActivity() == null) return null; |
+ return getActivity().getTabModelSelector(); |
+ } |
+ |
/** |
* TODO(aurimas): remove this method once Tab and ChromeTab are merged. |
*/ |
@@ -1451,7 +1471,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
if (printingController == null) return; |
printingController.setPendingPrint(new TabPrinter(this), |
- new PrintManagerDelegateImpl(mActivity)); |
+ new PrintManagerDelegateImpl(mApplicationContext)); |
} |
/** |
@@ -1857,7 +1877,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
* @return {@link AppBannerManager} to be used for this tab. May be null. |
*/ |
protected AppBannerManager createAppBannerManager() { |
- return new AppBannerManager(this, mActivity); |
+ return new AppBannerManager(this); |
} |
/** |
@@ -2009,9 +2029,9 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
* {@link ContentViewCore}. |
*/ |
protected void initContentViewCore(WebContents webContents) { |
- ContentViewCore cvc = new ContentViewCore(mActivity); |
- ContentView cv = ContentView.createContentView(mActivity, cvc); |
- cv.setContentDescription(mActivity.getResources().getString( |
+ ContentViewCore cvc = new ContentViewCore(mThemedContext); |
+ ContentView cv = ContentView.createContentView(mThemedContext, cvc); |
+ cv.setContentDescription(mApplicationContext.getResources().getString( |
R.string.accessibility_content_view)); |
cvc.initialize(cv, cv, webContents, getWindowAndroid()); |
setContentViewCore(cvc); |
@@ -2045,7 +2065,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
assert false; |
mContentViewParent.removeAllViews(); |
} |
- mContentViewParent = new FrameLayout(mActivity); |
+ mContentViewParent = new FrameLayout(mThemedContext); |
mContentViewParent.addView(cvc.getContainerView(), |
new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); |
@@ -2064,13 +2084,14 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
if (mInfoBarContainer == null) { |
// The InfoBarContainer needs to be created after the ContentView has been natively |
// initialized. |
- mInfoBarContainer = new InfoBarContainer(mActivity, getId(), mContentViewParent, this); |
+ mInfoBarContainer = new InfoBarContainer( |
+ mThemedContext, getId(), mContentViewParent, this); |
} else { |
mInfoBarContainer.onParentViewChanged(getId(), mContentViewParent); |
} |
mInfoBarContainer.setContentViewCore(mContentViewCore); |
- mSwipeRefreshHandler = new SwipeRefreshHandler(mActivity); |
+ mSwipeRefreshHandler = new SwipeRefreshHandler(mThemedContext); |
mSwipeRefreshHandler.setContentViewCore(mContentViewCore); |
for (TabObserver observer : mObservers) observer.onContentChanged(this); |
@@ -2080,11 +2101,15 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
// web views. |
mContentViewCore.setShouldSetAccessibilityFocusOnPageLoad(true); |
- mDownloadDelegate = new ChromeDownloadDelegate(mActivity, |
- mActivity.getTabModelSelector(), this); |
+ mDownloadDelegate = new ChromeDownloadDelegate(mThemedContext, this); |
cvc.setDownloadDelegate(mDownloadDelegate); |
} |
+ public boolean closeTab() { |
+ if (getTabModelSelector() == null) return false; |
+ return getTabModelSelector().closeTab(this); |
+ } |
+ |
/** |
* Constructs and shows a sad tab (Aw, Snap!). |
*/ |
@@ -2110,7 +2135,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
// Make sure we are not adding the "Aw, snap" view over an existing one. |
assert mSadTabView == null; |
mSadTabView = SadTabViewFactory.createSadTabView( |
- mActivity, suggestionAction, reloadButtonAction); |
+ mThemedContext, suggestionAction, reloadButtonAction); |
// Show the sad tab inside ContentView. |
getContentViewCore().getContainerView().addView( |
@@ -2316,7 +2341,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
*/ |
@CalledByNative |
public boolean loadIfNeeded() { |
- if (mActivity == null) { |
+ if (getActivity() == null) { |
Log.e(TAG, "Tab couldn't be loaded because Context was null."); |
return false; |
} |
@@ -2630,7 +2655,7 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
* return null. |
*/ |
public SnackbarManager getSnackbarManager() { |
- return mActivity.getSnackbarManager(); |
+ return getActivity() != null ? getActivity().getSnackbarManager() : null; |
} |
/** |
@@ -2646,9 +2671,9 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
@CalledByNative |
public void swapWebContents( |
WebContents webContents, boolean didStartLoad, boolean didFinishLoad) { |
- ContentViewCore cvc = new ContentViewCore(mActivity); |
- ContentView cv = ContentView.createContentView(mActivity, cvc); |
- cv.setContentDescription(mActivity.getResources().getString( |
+ ContentViewCore cvc = new ContentViewCore(mThemedContext); |
+ ContentView cv = ContentView.createContentView(mThemedContext, cvc); |
+ cv.setContentDescription(mApplicationContext.getResources().getString( |
R.string.accessibility_content_view)); |
cvc.initialize(cv, cv, webContents, getWindowAndroid()); |
swapContentViewCore(cvc, false, didStartLoad, didFinishLoad); |
@@ -3107,13 +3132,13 @@ public class Tab implements ViewGroup.OnHierarchyChangeListener, |
// If shouldIgnoreNewTab returns true, the intent is handled by another |
// activity. As a result, don't launch a new tab to open the URL. |
- if (shouldIgnoreNewTab(url, incognito)) return; |
+ if (shouldIgnoreNewTab(url, incognito) || getTabModelSelector() == null) return; |
LoadUrlParams loadUrlParams = new LoadUrlParams(url); |
loadUrlParams.setVerbatimHeaders(extraHeaders); |
loadUrlParams.setPostData(postData); |
loadUrlParams.setIsRendererInitiated(isRendererInitiated); |
- mActivity.getTabModelSelector().openNewTab( |
+ getTabModelSelector().openNewTab( |
loadUrlParams, tabLaunchType, parentTab, incognito); |
} |