зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1366098 - Part 1 - Remove Fennec tab type infrastructure. r=walkingice
The new, preferred solution for displaying additional web content outside of our normal tab infrastructure and UI is to use a separate GeckoView instance. Therefore, the support for different having additional "tab" types that aren't displayed in the normal UI, as well as for multiple GeckoApp instances displaying different tabs is no longer needed and can be removed. MozReview-Commit-ID: FNx0gJIKybr --HG-- extra : rebase_source : 4059e03db9586317c9c2928cef1d6dc98406319b
This commit is contained in:
Родитель
c4457d0462
Коммит
3c712524f9
|
@ -181,10 +181,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.mozilla.gecko.Tab.TabType;
|
||||
import static org.mozilla.gecko.Tabs.INVALID_TAB_ID;
|
||||
import static org.mozilla.gecko.mma.MmaDelegate.NEW_TAB;
|
||||
|
||||
public class BrowserApp extends GeckoApp
|
||||
implements ActionModePresenter,
|
||||
AnchoredPopup.OnVisibilityChangeListener,
|
||||
|
@ -447,11 +444,6 @@ public class BrowserApp extends GeckoApp
|
|||
super.onTabChanged(tab, msg, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean saveAsLastSelectedTab(Tab tab) {
|
||||
return tab.getType() == TabType.BROWSING;
|
||||
}
|
||||
|
||||
private void updateEditingModeForTab(final Tab selectedTab) {
|
||||
// (bug 1086983 comment 11) Because the tab may be selected from the gecko thread and we're
|
||||
// running this code on the UI thread, the selected tab argument may not still refer to the
|
||||
|
@ -1192,38 +1184,6 @@ public class BrowserApp extends GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restoreLastSelectedTab() {
|
||||
if (mLastSelectedTabId < 0) {
|
||||
// Normally, session restore will select the correct tab when starting up, however this
|
||||
// is linked to Gecko powering up. If we're not the first activity to launch, the
|
||||
// previously running activity might have already overwritten this by selecting a tab of
|
||||
// its own.
|
||||
// Therefore we check whether the session file parser has left a note for us with the
|
||||
// correct tab to be initially selected on *BrowserApp* startup.
|
||||
SharedPreferences prefs = getSharedPreferencesForProfile();
|
||||
mLastSelectedTabId = prefs.getInt(STARTUP_SELECTED_TAB, INVALID_TAB_ID);
|
||||
mLastSessionUUID = prefs.getString(STARTUP_SESSION_UUID, null);
|
||||
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.remove(STARTUP_SELECTED_TAB);
|
||||
editor.remove(STARTUP_SESSION_UUID);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
final Tabs tabs = Tabs.getInstance();
|
||||
final Tab tabToSelect = tabs.getTab(mLastSelectedTabId);
|
||||
|
||||
if (tabToSelect != null && GeckoApplication.getSessionUUID().equals(mLastSessionUUID) &&
|
||||
tabToSelect.getType() == TabType.BROWSING) {
|
||||
tabs.selectTab(mLastSelectedTabId);
|
||||
} else {
|
||||
if (!tabs.selectLastTab(TabType.BROWSING)) {
|
||||
tabs.loadUrl(Tabs.getHomepageForStartupTab(this), Tabs.LOADURL_NEW_TAB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
@ -2433,9 +2393,9 @@ public class BrowserApp extends GeckoApp
|
|||
final Tab tab;
|
||||
|
||||
if (AboutPages.isAboutReader(url)) {
|
||||
tab = tabs.getFirstReaderTabForUrl(url, selectedTab.isPrivate(), selectedTab.getType());
|
||||
tab = tabs.getFirstReaderTabForUrl(url, selectedTab.isPrivate());
|
||||
} else {
|
||||
tab = tabs.getFirstTabForUrl(url, selectedTab.isPrivate(), selectedTab.getType());
|
||||
tab = tabs.getFirstTabForUrl(url, selectedTab.isPrivate());
|
||||
}
|
||||
|
||||
if (tab == null) {
|
||||
|
|
|
@ -106,7 +106,6 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -150,11 +149,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
public static final String EXTRA_STATE_BUNDLE = "stateBundle";
|
||||
|
||||
protected static final String LAST_SELECTED_TAB = "lastSelectedTab";
|
||||
protected static final String LAST_SESSION_UUID = "lastSessionUUID";
|
||||
protected static final String STARTUP_SELECTED_TAB = "restoredSelectedTab";
|
||||
protected static final String STARTUP_SESSION_UUID = "restorationSessionUUID";
|
||||
|
||||
public static final String PREFS_ALLOW_STATE_BUNDLE = "allowStateBundle";
|
||||
public static final String PREFS_FLASH_USAGE = "playFlashCount";
|
||||
public static final String PREFS_VERSION_CODE = "versionCode";
|
||||
|
@ -179,9 +173,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
private static boolean sAlreadyLoaded;
|
||||
|
||||
protected boolean mIgnoreLastSelectedTab;
|
||||
protected static WeakReference<GeckoApp> mLastActiveGeckoApp;
|
||||
|
||||
protected RelativeLayout mRootLayout;
|
||||
protected RelativeLayout mMainLayout;
|
||||
|
||||
|
@ -209,10 +200,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
protected boolean mShouldRestore;
|
||||
private boolean mSessionRestoreParsingFinished = false;
|
||||
|
||||
protected int mLastSelectedTabId = INVALID_TAB_ID;
|
||||
protected String mLastSessionUUID = null;
|
||||
protected boolean mSuppressActivitySwitch = false;
|
||||
|
||||
private boolean foregrounded = false;
|
||||
|
||||
private static final class LastSessionParser extends SessionParser {
|
||||
|
@ -220,8 +207,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
private JSONObject windowObject;
|
||||
private boolean loadingExternalURL;
|
||||
|
||||
private int selectedTabId = INVALID_TAB_ID;
|
||||
|
||||
private boolean selectNextTab;
|
||||
private boolean tabsWereSkipped;
|
||||
private boolean tabsWereProcessed;
|
||||
|
@ -248,15 +233,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
return tabIdMap.get(oldTabId, INVALID_TAB_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The index of the tab that should be selected according to the session store data.
|
||||
* In conjunction with opening external tabs, this might not be the tab that
|
||||
* actually gets selected in the end, though.
|
||||
*/
|
||||
public int getStoredSelectedTabId() {
|
||||
return selectedTabId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabRead(final SessionTab sessionTab) {
|
||||
if (sessionTab.isAboutHomeWithoutHistory()) {
|
||||
|
@ -292,9 +268,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
final Tab tab = Tabs.getInstance().loadUrl(sessionTab.getUrl(), flags);
|
||||
|
||||
if (sessionTab.isSelected() || selectNextTab) {
|
||||
selectedTabId = tab.getId();
|
||||
}
|
||||
if (selectNextTab) {
|
||||
// We did not restore the selected tab previously. Now let's select this tab.
|
||||
Tabs.getInstance().selectTab(tab.getId());
|
||||
|
@ -418,30 +391,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
case SELECTED:
|
||||
resetOptionsMenu();
|
||||
resetFormAssistPopup();
|
||||
|
||||
if (foregrounded) {
|
||||
tab.setWasSelectedInForeground(true);
|
||||
}
|
||||
|
||||
if (mLastSelectedTabId != INVALID_TAB_ID && foregrounded &&
|
||||
// mSuppressActivitySwitch implies that we want to defer a pending
|
||||
// activity switch because we're actually about to leave the app.
|
||||
!mSuppressActivitySwitch && !tab.matchesActivity(this)) {
|
||||
startActivity(IntentHelper.getTabSwitchIntent(tab));
|
||||
} else if (saveAsLastSelectedTab(tab)) {
|
||||
mLastSelectedTabId = tab.getId();
|
||||
mLastSessionUUID = GeckoApplication.getSessionUUID();
|
||||
}
|
||||
break;
|
||||
|
||||
case CLOSED:
|
||||
if (saveAsLastSelectedTab(tab)) {
|
||||
if (mLastSelectedTabId == tab.getId() &&
|
||||
GeckoApplication.getSessionUUID().equals(mLastSessionUUID)) {
|
||||
mLastSelectedTabId = Tabs.INVALID_TAB_ID;
|
||||
mLastSessionUUID = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESKTOP_MODE_CHANGE:
|
||||
|
@ -676,8 +625,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
outState.putBoolean(SAVED_STATE_IN_BACKGROUND, isApplicationInBackground());
|
||||
outState.putString(SAVED_STATE_PRIVATE_SESSION, mPrivateBrowsingSession);
|
||||
outState.putInt(LAST_SELECTED_TAB, mLastSelectedTabId);
|
||||
outState.putString(LAST_SESSION_UUID, mLastSessionUUID);
|
||||
}
|
||||
|
||||
public void addTab() { }
|
||||
|
@ -1257,11 +1204,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
mJavaUiStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_JAVAUI");
|
||||
mGeckoReadyStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_GECKOREADY");
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mLastSelectedTabId = savedInstanceState.getInt(LAST_SELECTED_TAB);
|
||||
mLastSessionUUID = savedInstanceState.getString(LAST_SESSION_UUID);
|
||||
}
|
||||
|
||||
final SafeIntent intent = new SafeIntent(getIntent());
|
||||
|
||||
earlyStartJavaSampler(intent);
|
||||
|
@ -1308,9 +1250,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
Telemetry.addToHistogram("FENNEC_RESTORING_ACTIVITY", 1);
|
||||
|
||||
} else {
|
||||
// We're going to restore the last session and/or open a startup/external tab.
|
||||
mIgnoreLastSelectedTab = true;
|
||||
|
||||
final String action = intent.getAction();
|
||||
final String args = GeckoApplication.addDefaultGeckoArgs(
|
||||
intent.getStringExtra("args"));
|
||||
|
@ -1718,17 +1657,7 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
return;
|
||||
}
|
||||
|
||||
final Tab newTab = Tabs.getInstance().loadUrlWithIntentExtras(url, intent, flags);
|
||||
if (ThreadUtils.isOnUiThread()) {
|
||||
onTabOpenFromIntent(newTab);
|
||||
} else {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onTabOpenFromIntent(newTab);
|
||||
}
|
||||
});
|
||||
}
|
||||
Tabs.getInstance().loadUrlWithIntentExtras(url, intent, flags);
|
||||
}
|
||||
|
||||
protected String getIntentURI(SafeIntent intent) {
|
||||
|
@ -1868,10 +1797,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
}
|
||||
}
|
||||
|
||||
protected void onTabOpenFromIntent(Tab tab) { }
|
||||
|
||||
protected void onTabSelectFromIntent(Tab tab) { }
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
|
@ -1945,11 +1870,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
parser.updateParentId(closedTabs);
|
||||
windowObject.putOpt("closedTabs", closedTabs);
|
||||
|
||||
if (isExternalURL) {
|
||||
// Pass on the tab we would have selected if we weren't going to open an
|
||||
// external URL later on.
|
||||
windowObject.put("selectedTabId", parser.getStoredSelectedTabId());
|
||||
}
|
||||
sessionString = new JSONObject().put(
|
||||
"windows", new JSONArray().put(windowObject)).toString();
|
||||
} catch (final JSONException e) {
|
||||
|
@ -1967,29 +1887,11 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
throw new SessionRestoreException("No tabs could be read from session file");
|
||||
}
|
||||
|
||||
if (saveSelectedStartupTab()) {
|
||||
// This activity is something other than our normal tabbed browsing interface and is
|
||||
// going to overwrite our tab selection. Therefore we should stash it away for later, so
|
||||
// e.g. BrowserApp can display the correct tab if starting up later during this session.
|
||||
SharedPreferences.Editor prefs = getSharedPreferencesForProfile().edit();
|
||||
prefs.putInt(STARTUP_SELECTED_TAB, parser.getStoredSelectedTabId());
|
||||
prefs.putString(STARTUP_SESSION_UUID, GeckoApplication.getSessionUUID());
|
||||
prefs.apply();
|
||||
}
|
||||
|
||||
final GeckoBundle restoreData = new GeckoBundle(1);
|
||||
restoreData.putString("sessionString", sessionString);
|
||||
return restoreData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activities that don't implement a normal tabbed browsing UI and overwrite the tab selection
|
||||
* made by session restoring should probably override this and return true.
|
||||
*/
|
||||
protected boolean saveSelectedStartupTab() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public @NonNull EventDispatcher getAppEventDispatcher() {
|
||||
if (mLayerView == null) {
|
||||
|
@ -2132,9 +2034,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
final boolean isFirstTab = !mWasFirstTabShownAfterActivityUnhidden;
|
||||
mWasFirstTabShownAfterActivityUnhidden = true; // Reset since we'll be loading a tab.
|
||||
if (!Intent.ACTION_MAIN.equals(action)) {
|
||||
mIgnoreLastSelectedTab = true;
|
||||
}
|
||||
|
||||
// if we were previously OOM killed, we can end up here when launching
|
||||
// from external shortcuts, so set this as the intent for initialization
|
||||
|
@ -2205,8 +2104,7 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
protected void handleSelectTabIntent(SafeIntent intent) {
|
||||
final int tabId = intent.getIntExtra(INTENT_EXTRA_TAB_ID, INVALID_TAB_ID);
|
||||
final Tab selectedTab = Tabs.getInstance().selectTab(tabId);
|
||||
onTabSelectFromIntent(selectedTab);
|
||||
Tabs.getInstance().selectTab(tabId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2261,33 +2159,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
GeckoAppShell.setScreenOrientationDelegate(this);
|
||||
|
||||
// If mIgnoreLastSelectedTab is set, we're either the first activity to run, so our startup
|
||||
// code will (have) handle(d) tab selection, or else we've received a new intent and want to
|
||||
// open and select a new tab as well.
|
||||
if (!mIgnoreLastSelectedTab) {
|
||||
Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
||||
|
||||
// We need to check if we've selected a different tab while no GeckoApp-based activity
|
||||
// was in foreground and catch up with any activity switches that might be needed.
|
||||
if (selectedTab != null && !selectedTab.getWasSelectedInForeground()) {
|
||||
selectedTab.setWasSelectedInForeground(true);
|
||||
if (!selectedTab.matchesActivity(this)) {
|
||||
startActivity(IntentHelper.getTabSwitchIntent(selectedTab));
|
||||
}
|
||||
|
||||
// When backing out of the app closes the current tab and therefore selects
|
||||
// another tab, we don't switch activities even if the newly selected tab has a
|
||||
// different type, because doing so would bring us into the foreground again.
|
||||
// As this means that the currently selected tab doesn't match the last active
|
||||
// GeckoApp, we need to check mSuppressActivitySwitch here as well.
|
||||
} else if (mLastActiveGeckoApp == null || mLastActiveGeckoApp.get() != this ||
|
||||
mSuppressActivitySwitch) {
|
||||
restoreLastSelectedTab();
|
||||
}
|
||||
}
|
||||
mSuppressActivitySwitch = false;
|
||||
mIgnoreLastSelectedTab = false;
|
||||
|
||||
int newOrientation = getResources().getConfiguration().orientation;
|
||||
if (GeckoScreenOrientation.getInstance().update(newOrientation)) {
|
||||
refreshChrome();
|
||||
|
@ -2332,12 +2203,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
Restrictions.update(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on activity resume if a different (or no) GeckoApp-based activity was previously
|
||||
* active within our application.
|
||||
*/
|
||||
protected void restoreLastSelectedTab() { }
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
@ -2366,8 +2231,6 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
|
||||
foregrounded = false;
|
||||
|
||||
mLastActiveGeckoApp = new WeakReference<GeckoApp>(this);
|
||||
|
||||
final HealthRecorder rec = mHealthRecorder;
|
||||
final Context context = this;
|
||||
|
||||
|
@ -2695,13 +2558,12 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
onDone();
|
||||
Tab nextSelectedTab = Tabs.getInstance().getNextTab(tab);
|
||||
// Closing the tab will select the next tab. There's no need to unzombify it
|
||||
// if we're really exiting - switching activities is a different matter, though.
|
||||
if (nextSelectedTab != null && nextSelectedTab.getType() == tab.getType()) {
|
||||
// if we're exiting.
|
||||
if (nextSelectedTab != null) {
|
||||
final GeckoBundle data = new GeckoBundle(1);
|
||||
data.putInt("nextSelectedTabId", nextSelectedTab.getId());
|
||||
EventDispatcher.getInstance().dispatch("Tab:KeepZombified", data);
|
||||
}
|
||||
mSuppressActivitySwitch = true;
|
||||
tabs.closeTab(tab);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -228,33 +228,8 @@ public final class IntentHelper implements BundleEventListener {
|
|||
}
|
||||
|
||||
public static Intent getTabSwitchIntent(final Tab tab) {
|
||||
final Intent intent;
|
||||
switch (tab.getType()) {
|
||||
case CUSTOMTAB:
|
||||
if (tab.getCustomTabIntent() != null) {
|
||||
intent = tab.getCustomTabIntent().getUnsafe();
|
||||
} else {
|
||||
intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(tab.getURL()));
|
||||
}
|
||||
break;
|
||||
case WEBAPP:
|
||||
intent = new Intent(GeckoApp.ACTION_WEBAPP);
|
||||
final String manifestPath = tab.getManifestPath();
|
||||
try {
|
||||
intent.setData(getStartUriFromManifest(manifestPath));
|
||||
} catch (IOException | JSONException e) {
|
||||
Log.e(LOGTAG, "Failed to get start URI from manifest", e);
|
||||
intent.setData(Uri.parse(tab.getURL()));
|
||||
}
|
||||
intent.putExtra(WebAppActivity.MANIFEST_PATH, manifestPath);
|
||||
break;
|
||||
default:
|
||||
intent = new Intent(GeckoApp.ACTION_SWITCH_TAB);
|
||||
break;
|
||||
}
|
||||
|
||||
intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, tab.getTargetClassNameForTab());
|
||||
final Intent intent = new Intent(GeckoApp.ACTION_SWITCH_TAB);
|
||||
intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(BrowserContract.SKIP_TAB_QUEUE_FLAG, true);
|
||||
intent.putExtra(INTENT_EXTRA_TAB_ID, tab.getId());
|
||||
|
@ -262,16 +237,6 @@ public final class IntentHelper implements BundleEventListener {
|
|||
return intent;
|
||||
}
|
||||
|
||||
// TODO: When things have settled down a bit, we should split this and everything similar
|
||||
// TODO: in the WebAppActivity into a dedicated WebAppManifest class (bug 1353868).
|
||||
private static Uri getStartUriFromManifest(String manifestPath) throws IOException, JSONException {
|
||||
File manifestFile = new File(manifestPath);
|
||||
final JSONObject manifest = FileUtils.readJSONObjectFromFile(manifestFile);
|
||||
final JSONObject manifestField = manifest.getJSONObject("manifest");
|
||||
|
||||
return Uri.parse(manifestField.getString("start_url"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a URI, a MIME type, an Android intent "action", and a title,
|
||||
* produce an intent which can be used to start an activity to open
|
||||
|
|
|
@ -11,8 +11,8 @@ import org.json.JSONObject;
|
|||
import org.mozilla.gecko.db.BrowserDB;
|
||||
|
||||
public class PrivateTab extends Tab {
|
||||
public PrivateTab(Context context, int id, String url, boolean external, int parentId, String title, TabType type) {
|
||||
super(context, id, url, external, parentId, title, type);
|
||||
public PrivateTab(Context context, int id, String url, boolean external, int parentId, String title) {
|
||||
super(context, id, url, external, parentId, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.View;
|
||||
|
||||
import org.mozilla.gecko.mozglue.SafeIntent;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_SESSION_UUID;
|
||||
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_TAB_ID;
|
||||
import static org.mozilla.gecko.Tabs.INVALID_TAB_ID;
|
||||
|
||||
public abstract class SingleTabActivity extends GeckoApp {
|
||||
|
||||
private static final long SHOW_CONTENT_DELAY = 300;
|
||||
|
||||
private View mainLayout;
|
||||
private View contentView;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
final Intent externalIntent = getIntent();
|
||||
|
||||
decideTabAction(new SafeIntent(externalIntent), savedInstanceState);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
// GeckoApp's default behaviour is to reset the intent if we've got any
|
||||
// savedInstanceState, which we don't want here.
|
||||
setIntent(externalIntent);
|
||||
|
||||
mainLayout = findViewById(R.id.main_layout);
|
||||
contentView = findViewById(R.id.gecko_layout);
|
||||
if ((mainLayout != null) && (contentView != null)) {
|
||||
@ColorInt final int bg = ContextCompat.getColor(this, android.R.color.white);
|
||||
mainLayout.setBackgroundColor(bg);
|
||||
contentView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent externalIntent) {
|
||||
final SafeIntent intent = new SafeIntent(externalIntent);
|
||||
|
||||
if (decideTabAction(intent, null)) {
|
||||
// GeckoApp will handle tab selection.
|
||||
super.onNewIntent(intent.getUnsafe());
|
||||
} else {
|
||||
loadTabFromIntent(intent);
|
||||
}
|
||||
// Again, unlike GeckoApp's default behaviour we want to keep the intent around
|
||||
// because we might still require its data (e.g. to get custom tab customisations).
|
||||
setIntent(intent.getUnsafe());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean saveSelectedStartupTab() {
|
||||
// We ignore the tab selection made by session restoring in order to display our own tab,
|
||||
// so we should save that tab's ID in case the user starts up our normal browsing UI later
|
||||
// during the session.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restoreLastSelectedTab() {
|
||||
if (!mInitialized) {
|
||||
// During startup from onCreate(), initialize() will handle selecting the startup tab.
|
||||
// If this here is called afterwards, it's a no-op anyway. If for some reason
|
||||
// (e.g. debugging) initialize() takes longer than usual and hasn't finished by the time
|
||||
// onResume() runs and calls us, we just exit early so as not to interfere.
|
||||
return;
|
||||
}
|
||||
|
||||
final Tabs tabs = Tabs.getInstance();
|
||||
final Tab tabToSelect = tabs.getTab(mLastSelectedTabId);
|
||||
|
||||
// If the tab we've stored is still existing and valid select it...
|
||||
if (tabToSelect != null && GeckoApplication.getSessionUUID().equals(mLastSessionUUID) &&
|
||||
tabToSelect.matchesActivity(this)) {
|
||||
tabs.selectTab(mLastSelectedTabId);
|
||||
} else {
|
||||
// ... otherwise fall back to the intent data and open a new tab.
|
||||
loadTabFromIntent(new SafeIntent(getIntent()));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTabFromIntent(final SafeIntent intent) {
|
||||
final int flags = getNewTabFlags();
|
||||
loadStartupTab(getIntentURI(intent), intent, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if we're going to select an existing tab, false if we want to load a new tab.
|
||||
*/
|
||||
private boolean decideTabAction(@NonNull final SafeIntent intent,
|
||||
@Nullable final Bundle savedInstanceState) {
|
||||
final Tabs tabs = Tabs.getInstance();
|
||||
|
||||
if (hasGeckoTab(intent)) {
|
||||
final Tab tabToSelect = tabs.getTab(intent.getIntExtra(INTENT_EXTRA_TAB_ID, INVALID_TAB_ID));
|
||||
if (tabToSelect.matchesActivity(this)) {
|
||||
// Nothing further to do here, GeckoApp will select the correct
|
||||
// tab from the intent.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// The intent doesn't refer to a valid tab, so don't pass that data on.
|
||||
intent.getUnsafe().removeExtra(INTENT_EXTRA_TAB_ID);
|
||||
intent.getUnsafe().removeExtra(INTENT_EXTRA_SESSION_UUID);
|
||||
// The tab data in the intent can become stale if we've been killed, or have
|
||||
// closed the tab/changed its type since the original intent.
|
||||
// We therefore attempt to fall back to the last selected tab. In onNewIntent,
|
||||
// we can directly use the stored data, otherwise we'll look for it in the
|
||||
// savedInstanceState.
|
||||
final int lastSelectedTabId;
|
||||
final String lastSessionUUID;
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
lastSelectedTabId = savedInstanceState.getInt(LAST_SELECTED_TAB);
|
||||
lastSessionUUID = savedInstanceState.getString(LAST_SESSION_UUID);
|
||||
} else {
|
||||
lastSelectedTabId = mLastSelectedTabId;
|
||||
lastSessionUUID = mLastSessionUUID;
|
||||
}
|
||||
|
||||
final Tab tabToSelect = tabs.getTab(lastSelectedTabId);
|
||||
if (tabToSelect != null && GeckoApplication.getSessionUUID().equals(lastSessionUUID) &&
|
||||
tabToSelect.matchesActivity(this)) {
|
||||
intent.getUnsafe().putExtra(INTENT_EXTRA_TAB_ID, lastSelectedTabId);
|
||||
intent.getUnsafe().putExtra(INTENT_EXTRA_SESSION_UUID, lastSessionUUID);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we end up here, this means that there's no suitable tab we can take over.
|
||||
// Instead, we'll just open a new tab from the data specified in the intent.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* For us here, mLastSelectedTabId/Hash will hold the tab that will be selected when the
|
||||
* activity is resumed/recreated, unless
|
||||
* - it has been explicitly overridden through an intent
|
||||
* - the tab cannot be found, in which case the URI passed as intent data will instead be
|
||||
* opened in a new tab.
|
||||
* Therefore, we only update the stored tab data from those two locations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called when an intent or onResume() has caused us to load and select a new tab.
|
||||
*
|
||||
* @param tab The new tab that has been opened and selected.
|
||||
*/
|
||||
@Override
|
||||
protected void onTabOpenFromIntent(Tab tab) {
|
||||
mLastSelectedTabId = tab.getId();
|
||||
mLastSessionUUID = GeckoApplication.getSessionUUID();
|
||||
showContentView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an intent has caused us to select an already existing tab.
|
||||
*
|
||||
* @param tab The already existing tab that has been selected for this activity.
|
||||
*/
|
||||
@Override
|
||||
protected void onTabSelectFromIntent(Tab tab) {
|
||||
mLastSelectedTabId = tab.getId();
|
||||
mLastSessionUUID = GeckoApplication.getSessionUUID();
|
||||
showContentView();
|
||||
}
|
||||
|
||||
// Bug 1369681 - a workaround to prevent flash in first launch.
|
||||
// This will be removed once we have GeckoView based implementation.
|
||||
private void showContentView() {
|
||||
if ((contentView != null)
|
||||
&& (mainLayout != null)
|
||||
&& (contentView.getVisibility() == View.INVISIBLE)) {
|
||||
ThreadUtils.postDelayedToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ColorInt final int bg =
|
||||
ContextCompat.getColor(mainLayout.getContext(), android.R.color.white);
|
||||
mainLayout.setBackgroundColor(bg);
|
||||
contentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}, SHOW_CONTENT_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.customtabs.CustomTabsActivity;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.db.URLMetadata;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
|
@ -21,16 +20,13 @@ import org.mozilla.gecko.icons.IconDescriptor;
|
|||
import org.mozilla.gecko.icons.IconRequestBuilder;
|
||||
import org.mozilla.gecko.icons.IconResponse;
|
||||
import org.mozilla.gecko.icons.Icons;
|
||||
import org.mozilla.gecko.mozglue.SafeIntent;
|
||||
import org.mozilla.gecko.reader.ReaderModeUtils;
|
||||
import org.mozilla.gecko.reader.ReadingListHelper;
|
||||
import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.webapps.WebAppIndexer;
|
||||
import org.mozilla.gecko.widget.SiteLogins;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -46,7 +42,6 @@ public class Tab {
|
|||
|
||||
private static Pattern sColorPattern;
|
||||
private final int mId;
|
||||
private TabType mType;
|
||||
private final BrowserDB mDB;
|
||||
private long mLastUsed;
|
||||
private String mUrl;
|
||||
|
@ -61,9 +56,7 @@ public class Tab {
|
|||
private Future<IconResponse> mRunningIconRequest;
|
||||
|
||||
private boolean mHasFeeds;
|
||||
private SafeIntent mCustomTabIntent;
|
||||
private String mManifestUrl;
|
||||
private String mManifestPath;
|
||||
private boolean mHasOpenSearch;
|
||||
private final SiteIdentity mSiteIdentity;
|
||||
private SiteLogins mSiteLogins;
|
||||
|
@ -89,7 +82,6 @@ public class Tab {
|
|||
private volatile boolean mIsMediaPlaying;
|
||||
private String mMostRecentHomePanel;
|
||||
private boolean mShouldShowToolbarWithoutAnimationOnFirstSelection;
|
||||
private boolean mWasSelectedInForeground;
|
||||
|
||||
/*
|
||||
* Bundle containing restore data for the panel referenced in mMostRecentHomePanel. This can be
|
||||
|
@ -125,11 +117,10 @@ public class Tab {
|
|||
NONE // Non error pages
|
||||
}
|
||||
|
||||
public Tab(Context context, int id, String url, boolean external, int parentId, String title, TabType type) {
|
||||
public Tab(Context context, int id, String url, boolean external, int parentId, String title) {
|
||||
mAppContext = context.getApplicationContext();
|
||||
mDB = BrowserDB.from(context);
|
||||
mId = id;
|
||||
mType = type;
|
||||
mUrl = url;
|
||||
mBaseDomain = "";
|
||||
mUserRequested = "";
|
||||
|
@ -299,22 +290,10 @@ public class Tab {
|
|||
return mHasFeeds;
|
||||
}
|
||||
|
||||
public SafeIntent getCustomTabIntent() {
|
||||
return mCustomTabIntent;
|
||||
}
|
||||
|
||||
public String getManifestUrl() {
|
||||
return mManifestUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If not empty, the path to a locally installed copy of the Progressive Web App
|
||||
* manifest file for this tab.
|
||||
*/
|
||||
public String getManifestPath() {
|
||||
return mManifestPath;
|
||||
}
|
||||
|
||||
public boolean hasOpenSearch() {
|
||||
return mHasOpenSearch;
|
||||
}
|
||||
|
@ -484,18 +463,10 @@ public class Tab {
|
|||
mHasFeeds = hasFeeds;
|
||||
}
|
||||
|
||||
public void setCustomTabIntent(SafeIntent intent) {
|
||||
mCustomTabIntent = intent;
|
||||
}
|
||||
|
||||
public void setManifestUrl(String manifestUrl) {
|
||||
mManifestUrl = manifestUrl;
|
||||
}
|
||||
|
||||
public void setManifestPath(String manifestPath) {
|
||||
mManifestPath = manifestPath;
|
||||
}
|
||||
|
||||
public void setHasOpenSearch(boolean hasOpenSearch) {
|
||||
mHasOpenSearch = hasOpenSearch;
|
||||
}
|
||||
|
@ -789,50 +760,6 @@ public class Tab {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void setWasSelectedInForeground(boolean state) {
|
||||
mWasSelectedInForeground = state;
|
||||
}
|
||||
|
||||
public boolean getWasSelectedInForeground() {
|
||||
return mWasSelectedInForeground;
|
||||
}
|
||||
|
||||
public TabType getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
public enum TabType {
|
||||
BROWSING,
|
||||
CUSTOMTAB,
|
||||
WEBAPP
|
||||
}
|
||||
|
||||
/**
|
||||
* @return False if the tab is not matching the activity passed as argument.
|
||||
*/
|
||||
public boolean matchesActivity(final Activity activity) {
|
||||
final String activityName = activity.getClass().getName();
|
||||
return activityName.equals(getTargetClassNameForTab());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The class name of the activity that should preferably be displaying this tab.
|
||||
*/
|
||||
public String getTargetClassNameForTab() {
|
||||
final TabType type = getType();
|
||||
|
||||
switch (type) {
|
||||
case CUSTOMTAB:
|
||||
return CustomTabsActivity.class.getName();
|
||||
case WEBAPP:
|
||||
final int index = WebAppIndexer.getInstance().getIndexForManifest(
|
||||
getManifestPath(), mAppContext);
|
||||
return WebAppIndexer.WEBAPP_CLASS + index;
|
||||
default:
|
||||
return AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tab load progress to the given percentage.
|
||||
*
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.mozilla.gecko.util.EventCallback;
|
|||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.JavaUtil;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.webapps.WebAppActivity;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
|
@ -52,7 +51,6 @@ import android.support.v4.content.ContextCompat;
|
|||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import static org.mozilla.gecko.Tab.TabType;
|
||||
|
||||
public class Tabs implements BundleEventListener {
|
||||
private static final String LOGTAG = "GeckoTabs";
|
||||
|
@ -89,8 +87,6 @@ public class Tabs implements BundleEventListener {
|
|||
public static final int LOADURL_EXTERNAL = 1 << 7;
|
||||
/** Indicates the tab is the first shown after Firefox is hidden and restored. */
|
||||
public static final int LOADURL_FIRST_AFTER_ACTIVITY_UNHIDDEN = 1 << 8;
|
||||
public static final int LOADURL_CUSTOMTAB = 1 << 9;
|
||||
public static final int LOADURL_WEBAPP = 1 << 10;
|
||||
|
||||
private static final long PERSIST_TABS_AFTER_MILLISECONDS = 1000 * 2;
|
||||
|
||||
|
@ -198,8 +194,7 @@ public class Tabs implements BundleEventListener {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the tab count corresponding to the category and private state of the
|
||||
* selected tab.
|
||||
* Gets the tab count corresponding to the private state of the selected tab.
|
||||
*
|
||||
* If the selected tab is a non-private tab, this will return the number of
|
||||
* non-private tabs; likewise, if this is a private tab, this will return
|
||||
|
@ -211,10 +206,9 @@ public class Tabs implements BundleEventListener {
|
|||
// Once mSelectedTab is non-null, it cannot be null for the remainder
|
||||
// of the object's lifetime.
|
||||
boolean getPrivate = mSelectedTab != null && mSelectedTab.isPrivate();
|
||||
TabType type = mSelectedTab != null ? mSelectedTab.getType() : TabType.BROWSING;
|
||||
int count = 0;
|
||||
for (Tab tab : mOrder) {
|
||||
if (tab.isPrivate() == getPrivate && tab.getType() == type) {
|
||||
if (tab.isPrivate() == getPrivate) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -248,9 +242,9 @@ public class Tabs implements BundleEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
private Tab addTab(int id, String url, boolean external, int parentId, String title, boolean isPrivate, int tabIndex, TabType type) {
|
||||
final Tab tab = isPrivate ? new PrivateTab(mAppContext, id, url, external, parentId, title, type) :
|
||||
new Tab(mAppContext, id, url, external, parentId, title, type);
|
||||
private Tab addTab(int id, String url, boolean external, int parentId, String title, boolean isPrivate, int tabIndex) {
|
||||
final Tab tab = isPrivate ? new PrivateTab(mAppContext, id, url, external, parentId, title) :
|
||||
new Tab(mAppContext, id, url, external, parentId, title);
|
||||
synchronized (this) {
|
||||
lazyRegisterBookmarkObserver();
|
||||
mTabs.put(id, tab);
|
||||
|
@ -268,19 +262,20 @@ public class Tabs implements BundleEventListener {
|
|||
// Suppress the ADDED event to prevent animation of tabs created via session restore.
|
||||
if (mInitialTabsAdded) {
|
||||
notifyListeners(tab, TabEvents.ADDED,
|
||||
Integer.toString(getPrivacySpecificTabIndex(tabIndex, isPrivate, type)));
|
||||
Integer.toString(getPrivacySpecificTabIndex(tabIndex, isPrivate)));
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index, among those tabs of the chosen {@code type} whose privacy setting matches
|
||||
* {@code isPrivate}, of the tab at position {@code index} in {@code mOrder}. Returns
|
||||
* {@code NEW_LAST_INDEX} when {@code index} is {@code NEW_LAST_INDEX} or no matches were
|
||||
* Return the index, among those tabs whose privacy setting matches {@code isPrivate},
|
||||
* of the tab at position {@code index} in {@code mOrder}.
|
||||
*
|
||||
* @return {@code NEW_LAST_INDEX} when {@code index} is {@code NEW_LAST_INDEX} or no matches were
|
||||
* found.
|
||||
*/
|
||||
private int getPrivacySpecificTabIndex(int index, boolean isPrivate, TabType type) {
|
||||
private int getPrivacySpecificTabIndex(int index, boolean isPrivate) {
|
||||
if (index == NEW_LAST_INDEX) {
|
||||
return NEW_LAST_INDEX;
|
||||
}
|
||||
|
@ -288,7 +283,7 @@ public class Tabs implements BundleEventListener {
|
|||
int privacySpecificIndex = -1;
|
||||
for (int i = 0; i <= index; i++) {
|
||||
final Tab tab = mOrder.get(i);
|
||||
if (tab.isPrivate() == isPrivate && tab.getType() == type) {
|
||||
if (tab.isPrivate() == isPrivate) {
|
||||
privacySpecificIndex++;
|
||||
}
|
||||
}
|
||||
|
@ -345,44 +340,27 @@ public class Tabs implements BundleEventListener {
|
|||
return true;
|
||||
}
|
||||
|
||||
public synchronized boolean selectLastTab(Tab.TabType targetType) {
|
||||
if (mOrder.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Tab tabToSelect = mOrder.get(mOrder.size() - 1);
|
||||
if (tabToSelect.getType() != targetType) {
|
||||
tabToSelect = getPreviousTabFrom(tabToSelect, false, targetType);
|
||||
if (tabToSelect == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
selectTab(tabToSelect.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getIndexOf(Tab tab) {
|
||||
return mOrder.lastIndexOf(tab);
|
||||
}
|
||||
|
||||
private Tab getNextTabFrom(Tab tab, boolean getPrivate, TabType type) {
|
||||
private Tab getNextTabFrom(Tab tab, boolean getPrivate) {
|
||||
int numTabs = mOrder.size();
|
||||
int index = getIndexOf(tab);
|
||||
for (int i = index + 1; i < numTabs; i++) {
|
||||
Tab next = mOrder.get(i);
|
||||
if (next.isPrivate() == getPrivate && next.getType() == type) {
|
||||
if (next.isPrivate() == getPrivate) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Tab getPreviousTabFrom(Tab tab, boolean getPrivate, TabType type) {
|
||||
private Tab getPreviousTabFrom(Tab tab, boolean getPrivate) {
|
||||
int index = getIndexOf(tab);
|
||||
for (int i = index - 1; i >= 0; i--) {
|
||||
Tab prev = mOrder.get(i);
|
||||
if (prev.isPrivate() == getPrivate && prev.getType() == type) {
|
||||
if (prev.isPrivate() == getPrivate) {
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -483,22 +461,21 @@ public class Tabs implements BundleEventListener {
|
|||
return selectedTab;
|
||||
|
||||
boolean getPrivate = tab.isPrivate();
|
||||
TabType type = tab.getType();
|
||||
Tab nextTab = getNextTabFrom(tab, getPrivate, type);
|
||||
Tab nextTab = getNextTabFrom(tab, getPrivate);
|
||||
if (nextTab == null)
|
||||
nextTab = getPreviousTabFrom(tab, getPrivate, type);
|
||||
nextTab = getPreviousTabFrom(tab, getPrivate);
|
||||
if (nextTab == null && getPrivate) {
|
||||
// If there are no private tabs remaining, get the last normal tab.
|
||||
nextTab = getFallbackNextTab(type);
|
||||
}
|
||||
if (nextTab == null && type != TabType.BROWSING) {
|
||||
// If there are no non-private tabs of the same type remaining,
|
||||
// fall back to TabType.BROWSING.
|
||||
nextTab = getFallbackNextTab(TabType.BROWSING);
|
||||
Tab lastTab = mOrder.get(mOrder.size() - 1);
|
||||
if (!lastTab.isPrivate()) {
|
||||
nextTab = lastTab;
|
||||
} else {
|
||||
nextTab = getPreviousTabFrom(lastTab, false);
|
||||
}
|
||||
}
|
||||
|
||||
Tab parent = getTab(tab.getParentId());
|
||||
if (parent != null && parent.getType() == type) {
|
||||
if (parent != null) {
|
||||
// If the next tab is a sibling, switch to it. Otherwise go back to the parent.
|
||||
if (nextTab != null && nextTab.getParentId() == tab.getParentId())
|
||||
return nextTab;
|
||||
|
@ -508,26 +485,6 @@ public class Tabs implements BundleEventListener {
|
|||
return nextTab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally, {@link #getNextTab(Tab)} will attempt to find a tab of the same privacy mode and
|
||||
* {@link TabType} as the currently selected tab. If no such tab exists, we will first fall back
|
||||
* to non-private tabs if the current tab is a private tab. If we can't find any non-private
|
||||
* tabs of the same type, we then start looking for any non-private {@link TabType#BROWSING} tabs.
|
||||
*
|
||||
* @param type The {@link TabType} of tab to be searched.
|
||||
* @return A non-private tab of the type specified or null if none could be found.
|
||||
*/
|
||||
private Tab getFallbackNextTab(TabType type) {
|
||||
Tab nextTab;
|
||||
Tab lastTab = mOrder.get(mOrder.size() - 1);
|
||||
if (!lastTab.isPrivate() && lastTab.getType() == type) {
|
||||
nextTab = lastTab;
|
||||
} else {
|
||||
nextTab = getPreviousTabFrom(lastTab, false, type);
|
||||
}
|
||||
return nextTab;
|
||||
}
|
||||
|
||||
public Iterable<Tab> getTabsInOrder() {
|
||||
return mOrder;
|
||||
}
|
||||
|
@ -600,8 +557,7 @@ public class Tabs implements BundleEventListener {
|
|||
message.getInt("parentId"),
|
||||
message.getString("title"),
|
||||
message.getBoolean("isPrivate"),
|
||||
message.getInt("tabIndex"),
|
||||
TabType.valueOf(message.getString("tabType")));
|
||||
message.getInt("tabIndex"));
|
||||
// If we added the tab as a stub, we should have already
|
||||
// selected it, so ignore this flag for stubbed tabs.
|
||||
if (message.getBoolean("selected"))
|
||||
|
@ -868,7 +824,7 @@ public class Tabs implements BundleEventListener {
|
|||
*/
|
||||
@RobocopTarget
|
||||
public Tab getFirstTabForUrl(String url) {
|
||||
return getFirstTabForUrlHelper(url, null, TabType.BROWSING);
|
||||
return getFirstTabForUrlHelper(url, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -876,21 +832,20 @@ public class Tabs implements BundleEventListener {
|
|||
* @param url the URL of the tab we're looking for
|
||||
* @param isPrivate if true, only look for tabs that are private. if false,
|
||||
* only look for tabs that are non-private.
|
||||
* @param type the type of the tab we're looking for
|
||||
*
|
||||
* @return first Tab with the given URL, or null if there is no such tab.
|
||||
*/
|
||||
public Tab getFirstTabForUrl(String url, boolean isPrivate, TabType type) {
|
||||
return getFirstTabForUrlHelper(url, isPrivate, type);
|
||||
public Tab getFirstTabForUrl(String url, boolean isPrivate) {
|
||||
return getFirstTabForUrlHelper(url, isPrivate);
|
||||
}
|
||||
|
||||
private Tab getFirstTabForUrlHelper(String url, Boolean isPrivate, TabType type) {
|
||||
private Tab getFirstTabForUrlHelper(String url, Boolean isPrivate) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Tab tab : mOrder) {
|
||||
if (isPrivate != null && isPrivate != tab.isPrivate() || type != tab.getType()) {
|
||||
if (isPrivate != null && isPrivate != tab.isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
if (url.equals(tab.getURL())) {
|
||||
|
@ -911,13 +866,11 @@ public class Tabs implements BundleEventListener {
|
|||
* @param isPrivate
|
||||
* If true, only look for tabs that are private. If false, only
|
||||
* look for tabs that are not private.
|
||||
* @param type
|
||||
* The type of the tab we're looking for.
|
||||
*
|
||||
* @return The first Tab with the given URL, or null if there is no such
|
||||
* tab.
|
||||
*/
|
||||
public Tab getFirstReaderTabForUrl(String url, boolean isPrivate, TabType type) {
|
||||
public Tab getFirstReaderTabForUrl(String url, boolean isPrivate) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -925,7 +878,7 @@ public class Tabs implements BundleEventListener {
|
|||
url = ReaderModeUtils.stripAboutReaderUrl(url);
|
||||
|
||||
for (Tab tab : mOrder) {
|
||||
if (isPrivate != tab.isPrivate() || type != tab.getType()) {
|
||||
if (isPrivate != tab.isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
String tabUrl = tab.getURL();
|
||||
|
@ -1006,10 +959,6 @@ public class Tabs implements BundleEventListener {
|
|||
boolean desktopMode = (flags & LOADURL_DESKTOP) != 0;
|
||||
boolean external = (flags & LOADURL_EXTERNAL) != 0;
|
||||
final boolean isFirstShownAfterActivityUnhidden = (flags & LOADURL_FIRST_AFTER_ACTIVITY_UNHIDDEN) != 0;
|
||||
final boolean customTab = (flags & LOADURL_CUSTOMTAB) != 0;
|
||||
final boolean webappTab = (flags & LOADURL_WEBAPP) != 0;
|
||||
final TabType type = customTab ? TabType.CUSTOMTAB :
|
||||
webappTab ? TabType.WEBAPP : TabType.BROWSING;
|
||||
|
||||
data.putString("url", url);
|
||||
data.putString("engine", searchEngine);
|
||||
|
@ -1018,7 +967,6 @@ public class Tabs implements BundleEventListener {
|
|||
data.putBoolean("isPrivate", isPrivate);
|
||||
data.putBoolean("pinned", (flags & LOADURL_PINNED) != 0);
|
||||
data.putBoolean("desktopMode", desktopMode);
|
||||
data.putString("tabType", type.name());
|
||||
|
||||
final boolean needsNewTab;
|
||||
final String applicationId = (intent == null) ? null :
|
||||
|
@ -1067,19 +1015,10 @@ public class Tabs implements BundleEventListener {
|
|||
// Add the new tab to the end of the tab order.
|
||||
final int tabIndex = NEW_LAST_INDEX;
|
||||
|
||||
tabToSelect = addTab(tabId, tabUrl, external, parentId, url, isPrivate, tabIndex, type);
|
||||
tabToSelect = addTab(tabId, tabUrl, external, parentId, url, isPrivate, tabIndex);
|
||||
tabToSelect.setDesktopMode(desktopMode);
|
||||
tabToSelect.setApplicationId(applicationId);
|
||||
if (intent != null) {
|
||||
if (customTab) {
|
||||
// The intent can contain all sorts of customisations, so we save it in case
|
||||
// we need to launch a new custom tab activity for this tab.
|
||||
tabToSelect.setCustomTabIntent(intent);
|
||||
}
|
||||
if (intent.hasExtra(WebAppActivity.MANIFEST_PATH)) {
|
||||
tabToSelect.setManifestPath(intent.getStringExtra(WebAppActivity.MANIFEST_PATH));
|
||||
}
|
||||
}
|
||||
|
||||
if (isFirstShownAfterActivityUnhidden) {
|
||||
// We just opened Firefox so we want to show
|
||||
// the toolbar but not animate it to avoid jank.
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -21,7 +20,6 @@ import android.widget.ImageView;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mozilla.gecko.AboutPages;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
|
@ -205,13 +203,12 @@ public class TwoLinePageRow extends LinearLayout
|
|||
protected void updateDisplayedUrl() {
|
||||
final Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
||||
final boolean isPrivate = (selectedTab != null) && (selectedTab.isPrivate());
|
||||
final Tab.TabType type = selectedTab != null ? selectedTab.getType() : Tab.TabType.BROWSING;
|
||||
|
||||
// We always want to display the underlying page url, however for readermode pages
|
||||
// we navigate to the about:reader equivalent, hence we need to use that url when finding
|
||||
// existing tabs
|
||||
final String navigationUrl = mHasReaderCacheItem ? ReaderModeUtils.getAboutReaderForUrl(mPageUrl) : mPageUrl;
|
||||
Tab tab = Tabs.getInstance().getFirstTabForUrl(navigationUrl, isPrivate, type);
|
||||
Tab tab = Tabs.getInstance().getFirstTabForUrl(navigationUrl, isPrivate);
|
||||
|
||||
|
||||
if (!mShowIcons || tab == null) {
|
||||
|
|
|
@ -24,8 +24,6 @@ import org.mozilla.gecko.Tabs;
|
|||
import org.mozilla.gecko.widget.themed.ThemedImageButton;
|
||||
import org.mozilla.gecko.widget.themed.ThemedLinearLayout;
|
||||
|
||||
import static org.mozilla.gecko.Tab.TabType;
|
||||
|
||||
public class TabStrip extends ThemedLinearLayout
|
||||
implements TabStripInterface {
|
||||
private static final String LOGTAG = "GeckoTabStrip";
|
||||
|
@ -39,7 +37,6 @@ public class TabStrip extends ThemedLinearLayout
|
|||
// True when the tab strip isn't visible to the user due to something being drawn over it.
|
||||
private boolean tabStripIsCovered;
|
||||
private boolean tabsNeedUpdating;
|
||||
private final TabType type;
|
||||
|
||||
public TabStrip(Context context) {
|
||||
this(context, null);
|
||||
|
@ -49,8 +46,6 @@ public class TabStrip extends ThemedLinearLayout
|
|||
super(context, attrs);
|
||||
setOrientation(HORIZONTAL);
|
||||
|
||||
type = TabType.BROWSING;
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.tab_strip_inner, this);
|
||||
tabStripView = (TabStripView) findViewById(R.id.tab_strip);
|
||||
|
||||
|
@ -118,10 +113,6 @@ public class TabStrip extends ThemedLinearLayout
|
|||
private class TabsListener implements Tabs.OnTabsChangedListener {
|
||||
@Override
|
||||
public void onTabChanged(Tab tab, Tabs.TabEvents msg, String data) {
|
||||
if (msg != Tabs.TabEvents.RESTORED && tab.getType() != type) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg) {
|
||||
case RESTORED:
|
||||
tabStripView.restoreTabs();
|
||||
|
|
|
@ -31,15 +31,12 @@ import android.view.animation.DecelerateInterpolator;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mozilla.gecko.Tab.TabType;
|
||||
|
||||
public class TabStripView extends RecyclerView
|
||||
implements TabsTouchHelperCallback.DragListener {
|
||||
private static final int ANIM_TIME_MS = 200;
|
||||
private static final DecelerateInterpolator ANIM_INTERPOLATOR = new DecelerateInterpolator();
|
||||
|
||||
private final TabStripAdapter adapter;
|
||||
private final TabType type;
|
||||
private boolean isPrivate;
|
||||
|
||||
private final TabAnimatorListener animatorListener;
|
||||
|
@ -50,8 +47,6 @@ public class TabStripView extends RecyclerView
|
|||
public TabStripView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
type = TabType.BROWSING;
|
||||
|
||||
fadingEdgePaint = new Paint();
|
||||
final Resources resources = getResources();
|
||||
fadingEdgeSize =
|
||||
|
@ -85,7 +80,7 @@ public class TabStripView extends RecyclerView
|
|||
final List<Tab> tabs = new ArrayList<>();
|
||||
|
||||
for (final Tab tab : Tabs.getInstance().getTabsInOrder()) {
|
||||
if (tab.isPrivate() == isPrivate && tab.getType() == type) {
|
||||
if (tab.isPrivate() == isPrivate) {
|
||||
tabs.add(tab);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +99,7 @@ public class TabStripView extends RecyclerView
|
|||
}
|
||||
|
||||
/* package */ void addTab(Tab tab, int position) {
|
||||
if (tab.isPrivate() != isPrivate || tab.getType() != type) {
|
||||
if (tab.isPrivate() != isPrivate) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@ import android.widget.Button;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.mozilla.gecko.Tab.TabType;
|
||||
|
||||
public abstract class TabsLayout extends RecyclerView
|
||||
implements TabsPanel.TabsLayout,
|
||||
Tabs.OnTabsChangedListener,
|
||||
|
@ -32,7 +30,6 @@ public abstract class TabsLayout extends RecyclerView
|
|||
private static final String LOGTAG = "Gecko" + TabsLayout.class.getSimpleName();
|
||||
|
||||
private final boolean isPrivate;
|
||||
private final TabType type;
|
||||
private TabsPanel tabsPanel;
|
||||
private final TabsLayoutAdapter tabsAdapter;
|
||||
|
||||
|
@ -41,7 +38,6 @@ public abstract class TabsLayout extends RecyclerView
|
|||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabsLayout);
|
||||
isPrivate = (a.getInt(R.styleable.TabsLayout_tabs, 0x0) == 1);
|
||||
type = TabType.BROWSING;
|
||||
a.recycle();
|
||||
|
||||
tabsAdapter = new TabsLayoutAdapter(context, itemViewLayoutResId, isPrivate,
|
||||
|
@ -100,10 +96,6 @@ public abstract class TabsLayout extends RecyclerView
|
|||
|
||||
@Override
|
||||
public void onTabChanged(Tab tab, Tabs.TabEvents msg, String data) {
|
||||
if (msg != Tabs.TabEvents.RESTORED && tab.getType() != type) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg) {
|
||||
case ADDED:
|
||||
int tabIndex = Integer.parseInt(data);
|
||||
|
@ -189,7 +181,7 @@ public abstract class TabsLayout extends RecyclerView
|
|||
final Iterable<Tab> allTabs = Tabs.getInstance().getTabsInOrder();
|
||||
|
||||
for (final Tab tab : allTabs) {
|
||||
if (tab.isPrivate() == isPrivate && tab.getType() == type) {
|
||||
if (tab.isPrivate() == isPrivate) {
|
||||
tabData.add(tab);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -857,7 +857,6 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
|
|||
'search/SearchEngineManager.java',
|
||||
'SessionParser.java',
|
||||
'SharedPreferencesHelper.java',
|
||||
'SingleTabActivity.java',
|
||||
'SiteIdentity.java',
|
||||
'SnackbarBuilder.java',
|
||||
'SuggestClient.java',
|
||||
|
|
|
@ -1882,8 +1882,7 @@ var BrowserApp = {
|
|||
isPrivate: (data.isPrivate === true),
|
||||
pinned: (data.pinned === true),
|
||||
delayLoad: (delayLoad === true),
|
||||
desktopMode: (data.desktopMode === true),
|
||||
tabType: ("tabType" in data) ? data.tabType : "BROWSING"
|
||||
desktopMode: (data.desktopMode === true)
|
||||
};
|
||||
|
||||
params.userRequested = url;
|
||||
|
@ -3401,13 +3400,6 @@ nsBrowserAccess.prototype = {
|
|||
aWhere == Ci.nsIBrowserDOMWindow.OPEN_SWITCHTAB);
|
||||
let isPrivate = false;
|
||||
|
||||
if (aOpener != null) {
|
||||
let parent = BrowserApp.getTabForWindow(aOpener.top);
|
||||
if (parent != null) {
|
||||
newTab = newTab && parent.tabType != "CUSTOMTAB";
|
||||
}
|
||||
}
|
||||
|
||||
if (newTab) {
|
||||
let parentId = -1;
|
||||
if (!isExternal && aOpener) {
|
||||
|
@ -3587,9 +3579,6 @@ Tab.prototype = {
|
|||
// Java and new tabs from Gecko.
|
||||
let stub = false;
|
||||
|
||||
// The authoritative list of possible tab types is the TabType enum in Tab.java.
|
||||
this.type = "tabType" in aParams ? aParams.tabType : "BROWSING";
|
||||
|
||||
if (!aParams.zombifying) {
|
||||
if ("tabID" in aParams) {
|
||||
this.id = aParams.tabID;
|
||||
|
@ -3612,7 +3601,6 @@ Tab.prototype = {
|
|||
let message = {
|
||||
type: "Tab:Added",
|
||||
tabID: this.id,
|
||||
tabType: this.type,
|
||||
uri: truncate(uri, MAX_URI_LENGTH),
|
||||
parentId: this.parentId,
|
||||
tabIndex: ("tabIndex" in aParams) ? aParams.tabIndex : -1,
|
||||
|
@ -3675,8 +3663,7 @@ Tab.prototype = {
|
|||
desktopMode: this.desktopMode,
|
||||
isPrivate: isPrivate,
|
||||
tabId: this.id,
|
||||
parentId: this.parentId,
|
||||
type: this.type
|
||||
parentId: this.parentId
|
||||
};
|
||||
|
||||
if (aParams.delayLoad) {
|
||||
|
|
|
@ -684,16 +684,7 @@ SessionStore.prototype = {
|
|||
let data = aBrowser.__SS_data;
|
||||
let tab = aWindow.BrowserApp.getTabForId(data.tabId);
|
||||
|
||||
let windowData = this._windows[aWindow.__SSID];
|
||||
if (windowData.selectedTabId == tab.id) {
|
||||
// Normally, we will first select another tab anyway before closing the previous tab, which
|
||||
// would make this logic moot. However we only update the selected tab when selecting a normal
|
||||
// BROWSING-type tab, so we include this just to be on the safe side - although normally there
|
||||
// should always be at least one BROWSING-type tab open.
|
||||
windowData.selectedTabId = INVALID_TAB_ID;
|
||||
}
|
||||
|
||||
if (this._maxTabsUndo == 0 || this._sessionDataIsEmpty(data) || tab.type != "BROWSING") {
|
||||
if (this._maxTabsUndo == 0 || this._sessionDataIsEmpty(data)) {
|
||||
this._lastClosedTabIndex = INVALID_TAB_INDEX;
|
||||
return;
|
||||
}
|
||||
|
@ -811,9 +802,7 @@ SessionStore.prototype = {
|
|||
let tab = aWindow.BrowserApp.getTabForBrowser(aBrowser);
|
||||
let tabId = tab.id;
|
||||
|
||||
if (tab.type == "BROWSING") {
|
||||
this._windows[aWindow.__SSID].selectedTabId = tabId;
|
||||
}
|
||||
this._windows[aWindow.__SSID].selectedTabId = tabId;
|
||||
|
||||
// Restore the resurrected browser
|
||||
if (tabId != this._keepAsZombieTabId) {
|
||||
|
@ -1078,10 +1067,6 @@ SessionStore.prototype = {
|
|||
// data will be sent to Java for Android to hold it in memory.
|
||||
for (let i = 0; i < win.tabs.length; ++i) {
|
||||
let tab = win.tabs[i];
|
||||
if (tab.type != "BROWSING") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let savedWin = tab.isPrivate ? privateData.windows[winIndex] : normalData.windows[winIndex];
|
||||
savedWin.tabs.push(tab);
|
||||
if (win.selectedTabId === tab.tabId) {
|
||||
|
@ -1140,7 +1125,6 @@ SessionStore.prototype = {
|
|||
tabData.isPrivate = aBrowser.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing;
|
||||
tabData.tabId = tab.id;
|
||||
tabData.parentId = tab.parentId;
|
||||
tabData.type = tab.type;
|
||||
|
||||
aBrowser.__SS_data = tabData;
|
||||
},
|
||||
|
@ -1156,7 +1140,7 @@ SessionStore.prototype = {
|
|||
|
||||
let selectedTab = aWindow.BrowserApp.selectedTab;
|
||||
|
||||
if (selectedTab != null && selectedTab.type == "BROWSING") {
|
||||
if (selectedTab != null) {
|
||||
winData.selectedTabId = selectedTab.id;
|
||||
}
|
||||
|
||||
|
@ -1462,15 +1446,6 @@ SessionStore.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
if (state.windows[0].hasOwnProperty("selectedTabId") &&
|
||||
this._windows[window.__SSID].selectedTabId == INVALID_TAB_ID) {
|
||||
// If none of the restored tabs was the selected tab, we might be opening an URL from an
|
||||
// external intent. If this new tab is a normal BROWSING tab, we'll catch its selection
|
||||
// anyway, however if we've opened a custom tab/web app or anything like that we want to
|
||||
// ignore it. So instead, we store the tab we would have selected from the session file.
|
||||
this._windows[window.__SSID].selectedTabId = state.windows[0].selectedTabId;
|
||||
}
|
||||
|
||||
// Restore the closed tabs array on the current window.
|
||||
if (state.windows[0].closedTabs && this._maxTabsUndo > 0) {
|
||||
this._windows[window.__SSID].closedTabs = state.windows[0].closedTabs;
|
||||
|
|
|
@ -17,8 +17,6 @@ import android.content.ContentProvider;
|
|||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
||||
import static org.mozilla.gecko.Tab.TabType;
|
||||
|
||||
/**
|
||||
* Tests that local tabs are filtered prior to upload.
|
||||
* - create a set of tabs and persists them through TabsAccessor.
|
||||
|
@ -56,11 +54,11 @@ public class testFilterOpenTab extends ContentProviderTest {
|
|||
}
|
||||
|
||||
private Tab createTab(int id, String url, boolean external, int parentId, String title) {
|
||||
return new Tab((Context) getActivity(), id, url, external, parentId, title, TabType.BROWSING);
|
||||
return new Tab((Context) getActivity(), id, url, external, parentId, title);
|
||||
}
|
||||
|
||||
private Tab createPrivateTab(int id, String url, boolean external, int parentId, String title) {
|
||||
return new PrivateTab((Context) getActivity(), id, url, external, parentId, title, TabType.BROWSING);
|
||||
return new PrivateTab((Context) getActivity(), id, url, external, parentId, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Загрузка…
Ссылка в новой задаче