--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -176,20 +176,17 @@ import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
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,
BookmarkEditFragment.Callbacks,
BrowserSearch.OnEditSuggestionListener,
BrowserSearch.OnSearchListener,
DynamicToolbarAnimator.MetricsListener,
DynamicToolbarAnimator.ToolbarChromeProxy,
@@ -442,21 +439,16 @@ public class BrowserApp extends GeckoApp
if (HardwareUtils.isTablet() && msg == TabEvents.SELECTED) {
updateEditingModeForTab(tab);
}
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
// selected tab. However, that means this code should be run again and the initial state
// changes will be overridden. As an optimization, we can skip this update, but it may have
// unknown side-effects so we don't.
if (!Tabs.getInstance().isSelectedTab(selectedTab)) {
Log.w(LOGTAG, "updateEditingModeForTab: Given tab is expected to be selected tab");
@@ -1188,48 +1180,16 @@ public class BrowserApp extends GeckoApp
processTabQueue();
for (BrowserAppDelegate delegate : delegates) {
delegate.onResume(this);
}
}
@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();
if (mIsAbortingAppLaunch) {
return;
}
if (mHasResumed) {
// Register for Prompt:ShowTop so we can foreground this activity even if it's hidden.
@@ -2428,19 +2388,19 @@ public class BrowserApp extends GeckoApp
return false;
}
final Tabs tabs = Tabs.getInstance();
final Tab selectedTab = tabs.getSelectedTab();
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) {
return false;
}
return maybeSwitchToTab(tab.getId());
}
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -101,17 +101,16 @@ import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
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;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -145,21 +144,16 @@ public abstract class GeckoApp extends G
public static final String ACTION_INIT_PW = "org.mozilla.gecko.INIT_PW";
public static final String ACTION_SWITCH_TAB = "org.mozilla.gecko.SWITCH_TAB";
public static final String ACTION_SHUTDOWN = "org.mozilla.gecko.SHUTDOWN";
public static final String INTENT_REGISTER_STUMBLER_LISTENER = "org.mozilla.gecko.STUMBLER_REGISTER_LOCAL_LISTENER";
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";
public static final String PREFS_WAS_STOPPED = "wasStopped";
public static final String PREFS_CRASHED_COUNT = "crashedCount";
public static final String PREFS_CLEANUP_TEMP_FILES = "cleanupTempFiles";
// Originally, this was only used for the telemetry core ping logic. To avoid
@@ -174,19 +168,16 @@ public abstract class GeckoApp extends G
private static final int CLEANUP_DEFERRAL_SECONDS = 15;
// Length of time in ms during which crashes are classified as startup crashes
// for crash loop detection purposes.
private static final int STARTUP_PHASE_DURATION_MS = 30 * 1000;
private static boolean sAlreadyLoaded;
- protected boolean mIgnoreLastSelectedTab;
- protected static WeakReference<GeckoApp> mLastActiveGeckoApp;
-
protected RelativeLayout mRootLayout;
protected RelativeLayout mMainLayout;
protected RelativeLayout mGeckoLayout;
private OrientationEventListener mCameraOrientationEventListener;
protected MenuPanel mMenuPanel;
protected Menu mMenu;
protected boolean mIsRestoringActivity;
@@ -204,29 +195,23 @@ public abstract class GeckoApp extends G
private FullScreenHolder mFullScreenPluginContainer;
private View mFullScreenPluginView;
protected boolean mLastSessionCrashed;
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 {
private JSONArray tabs;
private JSONObject windowObject;
private boolean loadingExternalURL;
- private int selectedTabId = INVALID_TAB_ID;
-
private boolean selectNextTab;
private boolean tabsWereSkipped;
private boolean tabsWereProcessed;
private SparseIntArray tabIdMap;
/**
* @param loadingExternalURL Pass true if we're going to open an additional tab to load an
@@ -243,25 +228,16 @@ public abstract class GeckoApp extends G
public boolean allTabsSkipped() {
return tabsWereSkipped && !tabsWereProcessed;
}
public int getNewTabId(int oldTabId) {
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()) {
// This is a tab pointing to about:home with no history. We won't restore
// this tab. If we end up restoring no tabs then the browser will decide
// whether it needs to open about:home or a different 'homepage'. If we'd
// always restore about:home only tabs then we'd never open the homepage.
// See bug 1261008.
@@ -287,19 +263,16 @@ public abstract class GeckoApp extends G
int flags = Tabs.LOADURL_NEW_TAB;
flags |= ((loadingExternalURL || !sessionTab.isSelected()) ? Tabs.LOADURL_DELAY_LOAD : 0);
flags |= (tabObject.optBoolean("desktopMode") ? Tabs.LOADURL_DESKTOP : 0);
flags |= (tabObject.optBoolean("isPrivate") ? Tabs.LOADURL_PRIVATE : 0);
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());
selectNextTab = false;
}
ThreadUtils.postToUiThread(new Runnable() {
@Override
@@ -413,40 +386,16 @@ public abstract class GeckoApp extends G
resetOptionsMenu();
resetFormAssistPopup();
}
break;
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:
if (Tabs.getInstance().isSelectedTab(tab))
resetOptionsMenu();
break;
}
}
@@ -671,18 +620,16 @@ public abstract class GeckoApp extends G
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
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() { }
public void addPrivateTab() { }
public void showNormalTabs() { }
@@ -1252,21 +1199,16 @@ public abstract class GeckoApp extends G
finish();
return;
}
// The clock starts...now. Better hurry!
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);
// GeckoLoader wants to dig some environment variables out of the
// incoming intent, so pass it in here. GeckoLoader will do its
// business later and dispose of the reference.
GeckoLoader.setLastIntent(intent);
@@ -1303,19 +1245,16 @@ public abstract class GeckoApp extends G
// This happens when the GeckoApp activity is destroyed by Android
// without killing the entire application (see Bug 769269).
// Now that we've got multiple GeckoApp-based activities, this can
// also happen if we're not the first activity to run within a session.
mIsRestoringActivity = true;
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"));
sAlreadyLoaded = true;
GeckoThread.initMainProcess(/* profile */ null, args,
/* debugging */ ACTION_DEBUG.equals(action));
@@ -1713,27 +1652,17 @@ public abstract class GeckoApp extends G
*/
protected void loadStartupTab(final String url, final SafeIntent intent, final int flags) {
// Invalid url
if (url == null) {
loadStartupTab(flags, intent.getAction());
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) {
final String passedUri;
final String uri = getURIFromIntent(intent);
if (!TextUtils.isEmpty(uri)) {
passedUri = uri;
@@ -1863,20 +1792,16 @@ public abstract class GeckoApp extends G
}
if (GeckoThread.isRunning()) {
geckoConnected();
}
}
}
- protected void onTabOpenFromIntent(Tab tab) { }
-
- protected void onTabSelectFromIntent(Tab tab) { }
-
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onGlobalLayout() {
if (Versions.preJB) {
mMainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
mMainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
@@ -1940,21 +1865,16 @@ public abstract class GeckoApp extends G
// Update all parent tab IDs ...
parser.updateParentId(tabs);
windowObject.put("tabs", tabs);
// ... and for recently closed tabs as well (if we've got any).
final JSONArray closedTabs = windowObject.optJSONArray("closedTabs");
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) {
throw new SessionRestoreException(e);
}
} else {
if (parser.allTabsSkipped() || sessionDataValid) {
// If we intentionally skipped all tabs we've read from the session file, we
@@ -1962,39 +1882,21 @@ public abstract class GeckoApp extends G
// can infer that the exception wasn't due to a damaged session store file.
// The same applies if the session file was syntactically valid and
// simply didn't contain any tabs.
mShouldRestore = false;
}
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) {
throw new IllegalStateException("Must not call getAppEventDispatcher() until after onCreate()");
}
return mLayerView.getEventDispatcher();
}
@@ -2127,19 +2029,16 @@ public abstract class GeckoApp extends G
}
}
});
return;
}
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
if (!mInitialized) {
setIntent(externalIntent);
return;
}
@@ -2200,18 +2099,17 @@ public abstract class GeckoApp extends G
// We only care about comparing session UUIDs if one was specified in the intent.
// Otherwise, we just try matching the tab ID with one of our open tabs.
return tabToCheck != null && (!intent.hasExtra(INTENT_EXTRA_SESSION_UUID) ||
GeckoApplication.getSessionUUID().equals(intentSessionUUID));
}
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);
}
/**
* Handles getting a URI from an intent in a way that is backwards-
* compatible with our previous implementations.
*/
protected String getURIFromIntent(SafeIntent intent) {
final String action = intent.getAction();
@@ -2256,43 +2154,16 @@ public abstract class GeckoApp extends G
if (mIsAbortingAppLaunch) {
return;
}
foregrounded = true;
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();
}
// We use two times: a pseudo-unique wall-clock time to identify the
// current session across power cycles, and the elapsed realtime to
// track the duration of the session.
@@ -2327,22 +2198,16 @@ public abstract class GeckoApp extends G
Log.w(LOGTAG, "Can't record session: rec is null.");
}
}
});
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);
if (!mWindowFocusInitialized && hasFocus) {
mWindowFocusInitialized = true;
// XXX our editor tests require the GeckoView to have focus to pass, so we have to
// manually shift focus to the GeckoView. requestFocus apparently doesn't work at
@@ -2361,18 +2226,16 @@ public abstract class GeckoApp extends G
if (mIsAbortingAppLaunch) {
super.onPause();
return;
}
foregrounded = false;
- mLastActiveGeckoApp = new WeakReference<GeckoApp>(this);
-
final HealthRecorder rec = mHealthRecorder;
final Context context = this;
// In some way it's sad that Android will trigger StrictMode warnings
// here as the whole point is to save to disk while the activity is not
// interacting with the user.
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
@@ -2690,23 +2553,22 @@ public abstract class GeckoApp extends G
if (tab.doBack()) {
return;
}
if (tab.isExternal()) {
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;
}
final int parentId = tab.getParentId();
final Tab parent = tabs.getTab(parentId);
if (parent != null) {
// The back button should always return to the parent (not a sibling).
--- a/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
@@ -223,60 +223,25 @@ public final class IntentHelper implemen
if (mimeType != null && mimeType.length() > 0) {
shareIntent.setType(mimeType);
}
return shareIntent;
}
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());
intent.putExtra(INTENT_EXTRA_SESSION_UUID, GeckoApplication.getSessionUUID());
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
* the specified URI.
*
* @param context a <code>Context</code> instance.
* @param targetURI the string spec of the URI to open.
* @param mimeType an optional MIME type string.
--- a/mobile/android/base/java/org/mozilla/gecko/PrivateTab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/PrivateTab.java
@@ -6,18 +6,18 @@
package org.mozilla.gecko;
import android.content.Context;
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
protected void saveThumbnailToDB(final BrowserDB db) {}
@Override
public void setMetadata(JSONObject metadata) {}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/SingleTabActivity.java
+++ /dev/null
@@ -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);
- }
- }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/Tab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tab.java
@@ -7,68 +7,61 @@ package org.mozilla.gecko;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.Future;
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;
import org.mozilla.gecko.icons.IconCallback;
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;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
public class Tab {
private static final String LOGTAG = "GeckoTab";
private static Pattern sColorPattern;
private final int mId;
- private TabType mType;
private final BrowserDB mDB;
private long mLastUsed;
private String mUrl;
private String mBaseDomain;
private String mUserRequested; // The original url requested. May be typed by the user or sent by an extneral app for example.
private String mTitle;
private Bitmap mFavicon;
private String mFaviconUrl;
private String mApplicationId; // Intended to be null after explicit user action.
private IconRequestBuilder mIconRequestBuilder;
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;
private BitmapDrawable mThumbnail;
private volatile int mParentId;
// Indicates the url was loaded from a source external to the app. This will be cleared
// when the user explicitly loads a new url (e.g. clicking a link is not explicit).
private final boolean mExternal;
@@ -84,17 +77,16 @@ public class Tab {
private final Context mAppContext;
private ErrorType mErrorType = ErrorType.NONE;
private volatile int mLoadProgress;
private volatile int mRecordingCount;
private volatile boolean mIsAudioPlaying;
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
* e.g. the most recent folder for the bookmarks panel, or any other state that should be
* persisted. This is then used e.g. when returning to homepanels via history.
*/
private Bundle mMostRecentHomePanelData;
@@ -120,21 +112,20 @@ public class Tab {
public enum ErrorType {
CERT_ERROR, // Pages with certificate problems
BLOCKED, // Pages blocked for phishing or malware warnings
NET_ERROR, // All other types of error
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 = "";
mExternal = external;
mParentId = parentId;
mTitle = title == null ? "" : title;
mSiteIdentity = new SiteIdentity();
mContentType = "";
@@ -294,32 +285,20 @@ public class Tab {
public synchronized String getFaviconURL() {
return mFaviconUrl;
}
public boolean hasFeeds() {
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;
}
public boolean hasLoadedFromCache() {
return mLoadedFromCache;
}
@@ -479,28 +458,20 @@ public class Tab {
mFavicon = null;
mFaviconUrl = null;
}
public void setHasFeeds(boolean hasFeeds) {
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;
}
public void setLoadedFromCache(boolean loadedFromCache) {
mLoadedFromCache = loadedFromCache;
}
@@ -784,60 +755,16 @@ public class Tab {
public boolean getDesktopMode() {
return mDesktopMode;
}
public boolean isPrivate() {
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.
*
* @param progressPercentage Percentage to set progress to (0-100)
*/
void setLoadProgress(int progressPercentage) {
mLoadProgress = progressPercentage;
}
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -28,17 +28,16 @@ import org.mozilla.gecko.preferences.Gec
import org.mozilla.gecko.promotion.AddToHomeScreenPromotion;
import org.mozilla.gecko.reader.ReaderModeUtils;
import org.mozilla.gecko.skin.SkinConfig;
import org.mozilla.gecko.util.BundleEventListener;
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;
import android.accounts.OnAccountsUpdateListener;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.sqlite.SQLiteException;
@@ -47,17 +46,16 @@ import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Browser;
import android.support.annotation.UiThread;
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";
public static final String INTENT_EXTRA_TAB_ID = "TabId";
public static final String INTENT_EXTRA_SESSION_UUID = "SessionUUID";
private static final String PRIVATE_TAB_INTENT_EXTRA = "private_tab";
@@ -84,18 +82,16 @@ public class Tabs implements BundleEvent
public static final int LOADURL_PINNED = 1 << 3;
public static final int LOADURL_DELAY_LOAD = 1 << 4;
public static final int LOADURL_DESKTOP = 1 << 5;
public static final int LOADURL_BACKGROUND = 1 << 6;
/** Indicates the url has been specified by a source external to the app. */
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;
public static final int INVALID_TAB_ID = -1;
// Used to indicate a new tab should be appended to the current tabs.
public static final int NEW_LAST_INDEX = -1;
private static final AtomicInteger sTabId = new AtomicInteger(0);
@@ -193,33 +189,31 @@ public class Tabs implements BundleEvent
}
}
public void detachFromContext() {
mLayerView = null;
}
/**
- * 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
* the number of private tabs.
*
* @return the number of tabs in the current private state
*/
public synchronized int getDisplayCount() {
// 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++;
}
}
return count;
}
public int isOpen(String url) {
for (Tab tab : mOrder) {
@@ -243,19 +237,19 @@ public class Tabs implements BundleEvent
};
// It's safe to use the db here since we aren't doing any I/O.
final GeckoProfile profile = GeckoProfile.get(mAppContext);
BrowserDB.from(profile).registerBookmarkObserver(getContentResolver(), mBookmarksContentObserver);
}
}
- 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);
if (tabIndex > -1) {
mOrder.add(tabIndex, tab);
if (tabPositionCache.mOrderPosition >= tabIndex) {
tabPositionCache.mTabId = INVALID_TAB_ID;
@@ -263,37 +257,38 @@ public class Tabs implements BundleEvent
} else {
mOrder.add(tab);
}
}
// 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;
}
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++;
}
}
return privacySpecificIndex > -1 ? privacySpecificIndex : NEW_LAST_INDEX;
}
public synchronized void removeTab(int id) {
if (mTabs.containsKey(id)) {
@@ -340,54 +335,37 @@ public class Tabs implements BundleEvent
if (mOrder.isEmpty()) {
return false;
}
selectTab(mOrder.get(mOrder.size() - 1).getId());
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;
}
}
return null;
}
/**
* Gets the selected tab.
@@ -478,61 +456,40 @@ public class Tabs implements BundleEvent
/** Return the tab that will be selected by default after this one is closed */
public Tab getNextTab(Tab tab) {
Tab selectedTab = getSelectedTab();
if (selectedTab != tab)
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;
else
return parent;
}
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;
}
/**
* @return the current GeckoApp instance, or throws if
* we aren't correctly initialized.
*/
@@ -595,18 +552,17 @@ public class Tabs implements BundleEvent
// Tab was already closed; abort
return;
}
} else {
tab = addTab(id, url, message.getBoolean("external"),
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"))
selectTab(id);
}
if (message.getBoolean("delayLoad"))
tab.setState(Tab.STATE_DELAYED);
@@ -863,39 +819,38 @@ public class Tabs implements BundleEvent
/**
* Looks for an open tab with the given URL.
* @param url the URL of the tab we're looking for
*
* @return first Tab with the given URL, or null if there is no such tab.
*/
@RobocopTarget
public Tab getFirstTabForUrl(String url) {
- return getFirstTabForUrlHelper(url, null, TabType.BROWSING);
+ return getFirstTabForUrlHelper(url, null);
}
/**
* Looks for an open tab with the given URL and private state.
* @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())) {
return tab;
}
}
return null;
@@ -906,31 +861,29 @@ public class Tabs implements BundleEvent
* state.
*
* @param url
* The URL of the tab we're looking for. The url parameter can be
* the actual article URL or the reader mode article URL.
* @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;
}
url = ReaderModeUtils.stripAboutReaderUrl(url);
for (Tab tab : mOrder) {
- if (isPrivate != tab.isPrivate() || type != tab.getType()) {
+ if (isPrivate != tab.isPrivate()) {
continue;
}
String tabUrl = tab.getURL();
if (AboutPages.isAboutReader(tabUrl)) {
tabUrl = ReaderModeUtils.stripAboutReaderUrl(tabUrl);
if (url.equals(tabUrl)) {
return tab;
}
@@ -1001,29 +954,24 @@ public class Tabs implements BundleEvent
// delayLoad implies background tab
boolean background = delayLoad || (flags & LOADURL_BACKGROUND) != 0;
boolean isPrivate = (flags & LOADURL_PRIVATE) != 0 || (intent != null && intent.getBooleanExtra(PRIVATE_TAB_INTENT_EXTRA, false));
boolean userEntered = (flags & LOADURL_USER_ENTERED) != 0;
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);
data.putInt("parentId", parentId);
data.putBoolean("userEntered", userEntered);
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 :
intent.getStringExtra(Browser.EXTRA_APPLICATION_ID);
if (applicationId == null) {
needsNewTab = (flags & LOADURL_NEW_TAB) != 0;
} else {
// If you modify this code, be careful that intent != null.
@@ -1062,29 +1010,20 @@ public class Tabs implements BundleEvent
// The URL is updated for the tab once Gecko responds with the
// Tab:Added data. We can preliminarily set the tab's URL as
// long as it's a valid URI.
String tabUrl = (url != null && Uri.parse(url).getScheme() != null) ? url : null;
// 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.
tabToSelect.setShouldShowToolbarWithoutAnimationOnFirstSelection(true);
}
}
mEventDispatcher.dispatch("Tab:Load", data);
--- a/mobile/android/base/java/org/mozilla/gecko/home/TwoLinePageRow.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/TwoLinePageRow.java
@@ -1,32 +1,30 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.home;
-import java.lang.ref.WeakReference;
import java.util.concurrent.Future;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.TextViewCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
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;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserContract.Combined;
import org.mozilla.gecko.db.BrowserContract.URLColumns;
import org.mozilla.gecko.distribution.PartnerBookmarksProviderProxy;
import org.mozilla.gecko.icons.IconDescriptor;
@@ -200,23 +198,22 @@ public class TwoLinePageRow extends Line
/**
* Replaces the page URL with "Switch to tab" if there is already a tab open with that URL.
* Only looks for tabs that are either private or non-private, depending on the current
* selected tab.
*/
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) {
setUrl(mPageUrl);
setSwitchToTabIcon(NO_ICON);
} else {
setUrl(R.string.switch_to_tab);
setSwitchToTabIcon(R.drawable.ic_url_bar_tab);
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabStrip.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabStrip.java
@@ -19,43 +19,38 @@ import android.view.ViewTreeObserver;
import org.mozilla.gecko.BrowserApp.TabStripInterface;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Tab;
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";
private final TabStripView tabStripView;
private final ThemedImageButton addTabButton;
private final TabsListener tabsListener;
private OnTabAddedOrRemovedListener tabChangedListener;
// 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);
}
public TabStrip(Context context, AttributeSet attrs) {
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);
addTabButton = (ThemedImageButton) findViewById(R.id.tablet_add_tab);
addTabButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Tabs tabs = Tabs.getInstance();
@@ -113,20 +108,16 @@ public class TabStrip extends ThemedLine
public void setOnTabChangedListener(OnTabAddedOrRemovedListener listener) {
tabChangedListener = listener;
}
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();
break;
case ADDED:
final int tabIndex = Integer.parseInt(data);
tabStripView.addTab(tab, tabIndex);
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
@@ -26,37 +26,32 @@ import android.support.v7.widget.helper.
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;
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;
private final Paint fadingEdgePaint;
private final int fadingEdgeSize;
public TabStripView(Context context, AttributeSet attrs) {
super(context, attrs);
- type = TabType.BROWSING;
-
fadingEdgePaint = new Paint();
final Resources resources = getResources();
fadingEdgeSize =
resources.getDimensionPixelOffset(R.dimen.tablet_tab_strip_fading_edge_size);
animatorListener = new TabAnimatorListener();
setChildrenDrawingOrderEnabled(true);
@@ -80,17 +75,17 @@ public class TabStripView extends Recycl
}
/* package */ void refreshTabs() {
// Store a different copy of the tabs, so that we don't have
// to worry about accidentally updating it on the wrong thread.
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);
}
}
adapter.refresh(tabs);
updateSelectedPosition();
}
@@ -99,17 +94,17 @@ public class TabStripView extends Recycl
}
/* package */ void restoreTabs() {
refreshTabs();
animateRestoredTabs();
}
/* package */ void addTab(Tab tab, int position) {
- if (tab.isPrivate() != isPrivate || tab.getType() != type) {
+ if (tab.isPrivate() != isPrivate) {
return;
}
adapter.addTab(tab, position);
}
/* package */ void removeTab(Tab tab) {
adapter.removeTab(tab);
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayout.java
@@ -15,38 +15,34 @@ import android.content.res.TypedArray;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
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,
RecyclerViewClickSupport.OnItemClickListener,
TabsTouchHelperCallback.DismissListener,
TabsTouchHelperCallback.DragListener {
private static final String LOGTAG = "Gecko" + TabsLayout.class.getSimpleName();
private final boolean isPrivate;
- private final TabType type;
private TabsPanel tabsPanel;
private final TabsLayoutAdapter tabsAdapter;
public TabsLayout(Context context, AttributeSet attrs, int itemViewLayoutResId) {
super(context, attrs);
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,
/* close on click listener */
new Button.OnClickListener() {
@Override
public void onClick(View v) {
// The view here is the close button, which has a reference
@@ -95,20 +91,16 @@ public abstract class TabsLayout extends
}
protected void autoHidePanel() {
tabsPanel.autoHidePanel();
}
@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);
tabIndex = tabIndex == Tabs.NEW_LAST_INDEX ? tabsAdapter.getItemCount() : tabIndex;
tabsAdapter.notifyTabInserted(tab, tabIndex);
if (addAtIndexRequiresScroll(tabIndex)) {
// (The SELECTED tab is updated *after* this call to ADDED, so don't just call
// scrollSelectedTabToTopOfTray().)
@@ -184,17 +176,17 @@ public abstract class TabsLayout extends
private void refreshTabsData() {
// Store a different copy of the tabs, so that we don't have to worry about
// accidentally updating it on the wrong thread.
final ArrayList<Tab> tabData = new ArrayList<>();
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);
}
}
tabsAdapter.setTabs(tabData);
scrollSelectedTabToTopOfTray();
}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -852,17 +852,16 @@ gbjar.sources += ['java/org/mozilla/geck
'restrictions/RestrictionConfiguration.java',
'restrictions/RestrictionProvider.java',
'restrictions/Restrictions.java',
'ScreenshotObserver.java',
'search/SearchEngine.java',
'search/SearchEngineManager.java',
'SessionParser.java',
'SharedPreferencesHelper.java',
- 'SingleTabActivity.java',
'SiteIdentity.java',
'SnackbarBuilder.java',
'SuggestClient.java',
'switchboard/AsyncConfigLoader.java',
'switchboard/DeviceUuidFactory.java',
'switchboard/Preferences.java',
'switchboard/Switch.java',
'switchboard/SwitchBoard.java',
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1877,18 +1877,17 @@ var BrowserApp = {
let params = {
selected: ("selected" in data) ? data.selected : !delayLoad,
parentId: ("parentId" in data) ? data.parentId : -1,
flags: flags,
tabID: data.tabID,
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;
if (data.engine) {
let engine = Services.search.getEngineByName(data.engine);
if (engine) {
let submission = engine.getSubmission(url);
@@ -3396,23 +3395,16 @@ nsBrowserAccess.prototype = {
// If OPEN_SWITCHTAB was not handled above, we need to open a new tab,
// along with other OPEN_ values that create a new tab.
let newTab = (aWhere == Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW ||
aWhere == Ci.nsIBrowserDOMWindow.OPEN_NEWTAB ||
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) {
let parent = BrowserApp.getTabForWindow(aOpener.top);
if (parent) {
parentId = parent.id;
isPrivate = PrivateBrowsingUtils.isBrowserPrivate(parent.browser);
}
@@ -3582,19 +3574,16 @@ Tab.prototype = {
// When the tab is stubbed from Java, there's a window between the stub
// creation and the tab creation in Gecko where the stub could be removed
// or the selected tab can change (which is easiest to hit during startup).
// To prevent these races, we need to differentiate between tab stubs from
// 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;
stub = true;
} else {
let jenv = JNI.GetForThread();
let jTabs = JNI.LoadClass(jenv, "org.mozilla.gecko.Tabs", {
static_methods: [
@@ -3607,17 +3596,16 @@ Tab.prototype = {
this.desktopMode = ("desktopMode" in aParams) ? aParams.desktopMode : false;
this._parentId = ("parentId" in aParams && typeof aParams.parentId == "number")
? aParams.parentId : -1;
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,
external: ("external" in aParams) ? aParams.external : false,
selected: ("selected" in aParams || aParams.cancelEditMode === true)
? aParams.selected !== false || aParams.cancelEditMode === true : true,
cancelEditMode: aParams.cancelEditMode === true,
title: truncate(title, MAX_TITLE_LENGTH),
@@ -3670,18 +3658,17 @@ Tab.prototype = {
entries: [{
url: aURL,
title: truncate(title, MAX_TITLE_LENGTH)
}],
index: 1,
desktopMode: this.desktopMode,
isPrivate: isPrivate,
tabId: this.id,
- parentId: this.parentId,
- type: this.type
+ parentId: this.parentId
};
if (aParams.delayLoad) {
// If this is a zombie tab, mark the browser for delay loading, which will
// restore the tab when selected using the session data added above
this.browser.__SS_restore = true;
this.browser.setAttribute("pending", "true");
} else {
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -679,26 +679,17 @@ SessionStore.prototype = {
this.saveStateDelayed();
}
},
onTabClose: function ss_onTabClose(aWindow, aBrowser, aTabIndex) {
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;
}
if (aWindow.BrowserApp.tabs.length > 0) {
// Bundle this browser's data and extra data and save in the closedTabs
// window property
data.extData = aBrowser.__SS_extdata || {};
@@ -806,19 +797,17 @@ SessionStore.prototype = {
onTabSelect: function ss_onTabSelect(aWindow, aBrowser) {
if (this._loadState != STATE_RUNNING) {
return;
}
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) {
this.restoreZombieTab(tab);
} else {
log("keeping as zombie tab " + tabId);
}
// The tab id passed through Tab:KeepZombified is valid for one TabSelect only.
@@ -1073,20 +1062,16 @@ SessionStore.prototype = {
normalData.windows.push(normalWin);
privateData.windows.push({ tabs: [] });
// Split the session data into private and non-private data objects.
// Non-private session data will be saved to disk, and private session
// 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) {
savedWin.selected = savedWin.tabs.length; // 1-based index
}
}
}
@@ -1135,33 +1120,32 @@ SessionStore.prototype = {
let tab = aWindow.BrowserApp.getTabForBrowser(aBrowser);
tabData.entries = aHistory.entries;
tabData.index = aHistory.index;
tabData.attributes = { image: aBrowser.mIconURL };
tabData.desktopMode = tab.desktopMode;
tabData.isPrivate = aBrowser.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing;
tabData.tabId = tab.id;
tabData.parentId = tab.parentId;
- tabData.type = tab.type;
aBrowser.__SS_data = tabData;
},
_collectWindowData: function ss__collectWindowData(aWindow) {
// Ignore windows not tracked by SessionStore
if (!aWindow.__SSID || !this._windows[aWindow.__SSID]) {
return;
}
let winData = this._windows[aWindow.__SSID];
winData.tabs = [];
let selectedTab = aWindow.BrowserApp.selectedTab;
- if (selectedTab != null && selectedTab.type == "BROWSING") {
+ if (selectedTab != null) {
winData.selectedTabId = selectedTab.id;
}
let tabs = aWindow.BrowserApp.tabs;
for (let i = 0; i < tabs.length; i++) {
let browser = tabs[i].browser;
if (browser.__SS_data) {
let tabData = browser.__SS_data;
@@ -1457,25 +1441,16 @@ SessionStore.prototype = {
this._windows[window.__SSID].selectedTabId = tab.id;
} else {
// Mark the browser for delay loading
tab.browser.__SS_restore = true;
tab.browser.setAttribute("pending", "true");
}
}
- 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;
log("_restoreWindow() loaded " + state.windows[0].closedTabs.length + " closed tabs");
}
},
getClosedTabCount: function ss_getClosedTabCount(aWindow) {
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilterOpenTab.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilterOpenTab.java
@@ -12,18 +12,16 @@ import org.mozilla.gecko.PrivateTab;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.TabsProvider;
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.
* - verifies that tabs are filtered by querying.
*/
public class testFilterOpenTab extends ContentProviderTest {
private static final String[] TABS_PROJECTION_COLUMNS = new String[] {
BrowserContract.Tabs.TITLE,
@@ -51,21 +49,21 @@ public class testFilterOpenTab extends C
return mProvider.query(BrowserContract.Tabs.CONTENT_URI,
TABS_PROJECTION_COLUMNS,
LOCAL_TABS_SELECTION,
null,
null);
}
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
public void setUp() throws Exception {
super.setUp(sTabProviderCallable, BrowserContract.TABS_AUTHORITY, "tabs.db");
mTests.add(new TestInsertLocalTabs());
}