--- a/mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java
@@ -40,17 +40,17 @@ public final class HomeConfig {
* third-party services to create panels with varying types of content.
*/
@RobocopTarget
public static enum PanelType implements Parcelable {
TOP_SITES("top_sites", TopSitesPanel.class),
BOOKMARKS("bookmarks", BookmarksPanel.class),
HISTORY("history", CombinedHistoryPanel.class),
COMBINED_HISTORY("combined_history", CombinedHistoryPanel.class),
- REMOTE_TABS("remote_tabs", RemoteTabsPanel.class),
+ REMOTE_TABS("remote_tabs", CombinedHistoryPanel.class),
READING_LIST("reading_list", ReadingListPanel.class),
RECENT_TABS("recent_tabs", RecentTabsPanel.class),
DYNAMIC("dynamic", DynamicPanel.class);
private final String mId;
private final Class<?> mPanelClass;
PanelType(String id, Class<?> panelClass) {
@@ -1635,23 +1635,21 @@ public final class HomeConfig {
public static int getTitleResourceIdForBuiltinPanelType(PanelType panelType) {
switch (panelType) {
case TOP_SITES:
return R.string.home_top_sites_title;
case BOOKMARKS:
return R.string.bookmarks_title;
+ case REMOTE_TABS:
case HISTORY:
case COMBINED_HISTORY:
return R.string.home_history_title;
- case REMOTE_TABS:
- return R.string.home_remote_tabs_title;
-
case READING_LIST:
return R.string.reading_list_title;
case RECENT_TABS:
return R.string.recent_tabs_title;
default:
throw new IllegalArgumentException("Only for built-in panel types: " + panelType);
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/home/RemoteTabsBaseFragment.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/* -*- 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 android.accounts.Account;
-import android.content.Context;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.Loader;
-import android.support.v4.widget.SwipeRefreshLayout;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.RemoteClientsDialogFragment.RemoteClientsListener;
-import org.mozilla.gecko.RemoteTabsExpandableListAdapter;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.RemoteClient;
-import org.mozilla.gecko.fxa.FirefoxAccounts;
-import org.mozilla.gecko.fxa.SyncStatusListener;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Fragment backed by <code>ExpandableListAdapter<code> to displays tabs from other devices.
- */
-public abstract class RemoteTabsBaseFragment extends HomeFragment implements RemoteClientsListener {
- // Logging tag name.
- private static final String LOGTAG = "GeckoRemoteTabsBaseFragment";
-
- private static final String[] STAGES_TO_SYNC_ON_REFRESH = new String[] { "clients", "tabs" };
-
- // Update the "Last synced:" timestamps this frequently.
- private static final long LAST_SYNCED_TIME_UPDATE_INTERVAL_IN_MILLISECONDS = 60 * 1000; // Once a minute.
-
- // Cursor loader ID.
- protected static final int LOADER_ID_REMOTE_TABS = 0;
-
- // Dialog fragment TAG.
- protected static final String DIALOG_TAG_REMOTE_TABS = "dialog_tag_remote_tabs";
-
- // Maintain group collapsed and hidden state.
- // Only accessed from the UI thread.
- protected static RemoteTabsExpandableListState sState;
-
- // Adapter for the list of remote tabs.
- protected RemoteTabsExpandableListAdapter mAdapter;
-
- // List of hidden remote clients.
- // Only accessed from the UI thread.
- protected final List<RemoteClient> mHiddenClients = new ArrayList<>();
-
- // Callbacks used for the loader.
- protected CursorLoaderCallbacks mCursorLoaderCallbacks;
-
- // Child refresh layout view.
- protected SwipeRefreshLayout mRefreshLayout;
-
- // Sync listener that stops refreshing when a sync is completed.
- protected RemoteTabsSyncListener mSyncStatusListener;
-
- // Reference to the View to display when there are no results.
- protected View mEmptyView;
-
- // The footer view to display when there are hidden devices not shown.
- protected View mFooterView;
-
- // Used to post update last synced time requests. Should always execute on the main (UI) thread.
- protected Handler mHandler;
-
- // Runnable to update last synced time.
- protected Runnable mLastSyncedTimeUpdateRunnable;
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- mRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.remote_tabs_refresh_layout);
- mRefreshLayout.setColorSchemeResources(R.color.fennec_ui_orange, R.color.action_orange);
- mRefreshLayout.setOnRefreshListener(new RemoteTabsRefreshListener());
-
- mSyncStatusListener = new RemoteTabsSyncListener();
- FirefoxAccounts.addSyncStatusListener(mSyncStatusListener);
-
- mHandler = new Handler(); // Attached to current (assumed to be UI) thread.
- mLastSyncedTimeUpdateRunnable = new LastSyncTimeUpdateRunnable();
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- // This races when multiple Fragments are created. That's okay: one
- // will win, and thereafter, all will be okay. If we create and then
- // drop an instance the shared SharedPreferences backing all the
- // instances will maintain the state for us. Since everything happens on
- // the UI thread, this doesn't even need to be volatile.
- if (sState == null) {
- sState = new RemoteTabsExpandableListState(GeckoSharedPrefs.forProfile(getActivity()));
- }
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
-
- if (mSyncStatusListener != null) {
- FirefoxAccounts.removeSyncStatusListener(mSyncStatusListener);
- mSyncStatusListener = null;
- }
-
- if (mLastSyncedTimeUpdateRunnable != null) {
- mHandler.removeCallbacks(mLastSyncedTimeUpdateRunnable);
- mLastSyncedTimeUpdateRunnable = null;
- mHandler = null;
- }
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- if (!(menuInfo instanceof RemoteTabsClientContextMenuInfo)) {
- // Long pressed item was not a RemoteTabsGroup item. Superclass
- // can handle this.
- super.onCreateContextMenu(menu, view, menuInfo);
- return;
- }
-
- // Long pressed item was a remote client; provide the appropriate menu.
- final MenuInflater inflater = new MenuInflater(view.getContext());
- inflater.inflate(R.menu.home_remote_tabs_client_contextmenu, menu);
-
- final RemoteTabsClientContextMenuInfo info = (RemoteTabsClientContextMenuInfo) menuInfo;
- menu.setHeaderTitle(info.client.name);
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- if (super.onContextItemSelected(item)) {
- // HomeFragment was able to handle to selected item.
- return true;
- }
-
- final ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo();
- if (!(menuInfo instanceof RemoteTabsClientContextMenuInfo)) {
- return false;
- }
-
- final RemoteTabsClientContextMenuInfo info = (RemoteTabsClientContextMenuInfo) menuInfo;
-
- final int itemId = item.getItemId();
- if (itemId == R.id.home_remote_tabs_hide_client) {
- sState.setClientHidden(info.client.guid, true);
- getLoaderManager().restartLoader(LOADER_ID_REMOTE_TABS, null, mCursorLoaderCallbacks);
- return true;
- }
-
- return false;
- }
-
- @Override
- public void onClients(List<RemoteClient> clients) {
- // The clients listed were hidden and have been checked by the user. We
- // interpret that as "show these clients now".
- for (RemoteClient client : clients) {
- sState.setClientHidden(client.guid, false);
- // There's no particular need to do this, but if you want to see it,
- // let's show it all.
- sState.setClientCollapsed(client.guid, false);
- }
- getLoaderManager().restartLoader(LOADER_ID_REMOTE_TABS, null, mCursorLoaderCallbacks);
- }
-
- @Override
- protected void load() {
- getLoaderManager().initLoader(LOADER_ID_REMOTE_TABS, null, mCursorLoaderCallbacks);
- }
-
- protected abstract void updateUiFromClients(List<RemoteClient> clients, List<RemoteClient> hiddenClients);
-
- private static class RemoteTabsCursorLoader extends SimpleCursorLoader {
- private final GeckoProfile mProfile;
-
- public RemoteTabsCursorLoader(Context context) {
- super(context);
- mProfile = GeckoProfile.get(context);
- }
-
- @Override
- public Cursor loadCursor() {
- return mProfile.getDB().getTabsAccessor().getRemoteTabsCursor(getContext());
- }
- }
-
- protected class CursorLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
- private BrowserDB mDB; // Pseudo-final: set in onCreateLoader.
-
- @Override
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- mDB = GeckoProfile.get(getActivity()).getDB();
- return new RemoteTabsCursorLoader(getActivity());
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
- final List<RemoteClient> clients = mDB.getTabsAccessor().getClientsFromCursor(c);
-
- // Filter the hidden clients out of the clients list. The clients
- // list is updated in place; the hidden clients list is built
- // incrementally.
- mHiddenClients.clear();
- final Iterator<RemoteClient> it = clients.iterator();
- while (it.hasNext()) {
- final RemoteClient client = it.next();
- if (sState.isClientHidden(client.guid)) {
- it.remove();
- mHiddenClients.add(client);
- }
- }
-
- mAdapter.replaceClients(clients);
- updateUiFromClients(clients, mHiddenClients);
- scheduleLastSyncedTime();
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- mAdapter.replaceClients(null);
- }
- }
-
- protected class RemoteTabsRefreshListener implements SwipeRefreshLayout.OnRefreshListener {
- @Override
- public void onRefresh() {
- if (FirefoxAccounts.firefoxAccountsExist(getActivity())) {
- final Account account = FirefoxAccounts.getFirefoxAccount(getActivity());
- FirefoxAccounts.requestImmediateSync(account, STAGES_TO_SYNC_ON_REFRESH, null);
- } else {
- Log.wtf(LOGTAG, "No Firefox Account found; this should never happen. Ignoring.");
- mRefreshLayout.setRefreshing(false);
- }
- }
- }
-
- protected class RemoteTabsSyncListener implements SyncStatusListener {
- @Override
- public Context getContext() {
- return getActivity();
- }
-
- @Override
- public Account getAccount() {
- return FirefoxAccounts.getFirefoxAccount(getContext());
- }
-
- @Override
- public void onSyncStarted() {
- }
-
- @Override
- public void onSyncFinished() {
- mRefreshLayout.setRefreshing(false);
- }
- }
-
- /**
- * Stores information regarding the creation of the context menu for a remote client.
- */
- protected static class RemoteTabsClientContextMenuInfo extends HomeContextMenuInfo {
- protected final RemoteClient client;
-
- public RemoteTabsClientContextMenuInfo(View targetView, int position, long id, RemoteClient client) {
- super(targetView, position, id);
- this.client = client;
- }
- }
-
- /**
- * The Runnable that schedules a future update and updates the last synced time.
- */
- protected class LastSyncTimeUpdateRunnable implements Runnable {
- @Override
- public void run() {
- updateAndScheduleLastSyncedTime();
- }
- }
-
- protected void scheduleLastSyncedTime() {
- // Pushes back any existing schedule callback.
- mHandler.postDelayed(mLastSyncedTimeUpdateRunnable, LAST_SYNCED_TIME_UPDATE_INTERVAL_IN_MILLISECONDS);
- }
-
- protected void updateAndScheduleLastSyncedTime() {
- // This does not hit the database; it just makes consumers update their views. Perfect!
- mAdapter.notifyDataSetChanged();
- scheduleLastSyncedTime();
- }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/home/RemoteTabsExpandableListFragment.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/* -*- 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.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.RemoteClientsDialogFragment;
-import org.mozilla.gecko.RemoteTabsExpandableListAdapter;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.RemoteClient;
-import org.mozilla.gecko.db.RemoteTab;
-import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
-
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.widget.ExpandableListAdapter;
-import android.widget.ExpandableListView;
-import android.widget.ExpandableListView.OnChildClickListener;
-import android.widget.ExpandableListView.OnGroupClickListener;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-/**
- * Fragment that displays tabs from other devices in an <code>ExpandableListView<code>.
- * <p>
- * This is intended to be used on phones, and possibly in portrait mode on tablets.
- */
-public class RemoteTabsExpandableListFragment extends RemoteTabsBaseFragment {
- // Logging tag name.
- private static final String LOGTAG = "GeckoRemoteTabsExpList";
-
- // The view shown by the fragment.
- private HomeExpandableListView mList;
-
- public static RemoteTabsExpandableListFragment newInstance() {
- return new RemoteTabsExpandableListFragment();
- }
-
- public RemoteTabsExpandableListFragment() {
- super();
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.home_remote_tabs_list_panel, container, false);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- mList = (HomeExpandableListView) view.findViewById(R.id.list);
- mList.setTag(HomePager.LIST_TAG_REMOTE_TABS);
-
- mList.setOnChildClickListener(new OnChildClickListener() {
- @Override
- public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
- final ExpandableListAdapter adapter = parent.getExpandableListAdapter();
- final RemoteTab tab = (RemoteTab) adapter.getChild(groupPosition, childPosition);
- if (tab == null) {
- return false;
- }
-
- Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM, "remote_tabs");
-
- // This item is a TwoLinePageRow, so we allow switch-to-tab.
- mUrlOpenListener.onUrlOpen(tab.url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
- return true;
- }
- });
-
- mList.setOnGroupClickListener(new OnGroupClickListener() {
- @Override
- public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
- final ExpandableListAdapter adapter = parent.getExpandableListAdapter();
- final RemoteClient client = (RemoteClient) adapter.getGroup(groupPosition);
- if (client != null) {
- // After we process this click, the group's expanded state will have flipped.
- sState.setClientCollapsed(client.guid, mList.isGroupExpanded(groupPosition));
- }
-
- // We want the system to handle the click, expanding or collapsing as necessary.
- return false;
- }
- });
-
- // Show a context menu only for tabs (not for clients).
- mList.setContextMenuInfoFactory(new HomeContextMenuInfo.ExpandableFactory() {
- @Override
- public HomeContextMenuInfo makeInfoForAdapter(View view, int position, long id, ExpandableListAdapter adapter) {
- long packedPosition = mList.getExpandableListPosition(position);
- final int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
- final int type = ExpandableListView.getPackedPositionType(packedPosition);
- if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
- final int childPosition = ExpandableListView.getPackedPositionChild(packedPosition);
- final RemoteTab tab = (RemoteTab) adapter.getChild(groupPosition, childPosition);
- final HomeContextMenuInfo info = new HomeContextMenuInfo(view, position, id);
- info.url = tab.url;
- info.title = tab.title;
- return info;
- }
-
- if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
- final RemoteClient client = (RemoteClient) adapter.getGroup(groupPosition);
- final RemoteTabsClientContextMenuInfo info = new RemoteTabsClientContextMenuInfo(view, position, id, client);
- return info;
- }
- return null;
- }
- });
-
- registerForContextMenu(mList);
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
-
- // Discard any additional item clicks on the list as the
- // panel is getting destroyed (bug 1210243).
- mList.setOnChildClickListener(null);
- mList.setOnGroupClickListener(null);
-
- mList = null;
- mEmptyView = null;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- // There is an unfortunate interaction between ExpandableListViews and
- // footer onClick handling. The footer view itself appears to not
- // receive click events. Its children, however, do receive click events.
- // Therefore, we attach an onClick handler to a child of the footer view
- // itself.
- mFooterView = LayoutInflater.from(getActivity()).inflate(R.layout.home_remote_tabs_hidden_devices_footer, mList, false);
- final View view = mFooterView.findViewById(R.id.hidden_devices);
- view.setClickable(true);
- view.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final RemoteClientsDialogFragment dialog = RemoteClientsDialogFragment.newInstance(
- getResources().getString(R.string.home_remote_tabs_hidden_devices_title),
- getResources().getString(R.string.home_remote_tabs_unhide_selected_devices),
- RemoteClientsDialogFragment.ChoiceMode.MULTIPLE, new ArrayList<>(mHiddenClients));
- dialog.setTargetFragment(RemoteTabsExpandableListFragment.this, 0);
- dialog.show(getActivity().getSupportFragmentManager(), DIALOG_TAG_REMOTE_TABS);
- }
- });
-
- // There is a delicate interaction, pre-KitKat, between
- // {add,remove}FooterView and setAdapter. setAdapter wraps the adapter
- // in a footer/header-managing adapter, which only happens (pre-KitKat)
- // if a footer/header is present. Therefore, we add our footer before
- // setting the adapter; and then we remove it afterward. From there on,
- // we can add/remove it at will.
- mList.addFooterView(mFooterView, null, true);
-
- // Initialize adapter
- mAdapter = new RemoteTabsExpandableListAdapter(R.layout.home_remote_tabs_group, R.layout.home_remote_tabs_child, null, true);
- mList.setAdapter(mAdapter);
-
- // Now the adapter is wrapped; we can remove our footer view.
- mList.removeFooterView(mFooterView);
-
- // Create callbacks before the initial loader is started
- mCursorLoaderCallbacks = new CursorLoaderCallbacks();
- loadIfVisible();
- }
-
- @Override
- protected void updateUiFromClients(List<RemoteClient> clients, List<RemoteClient> hiddenClients) {
- if (getView() == null) {
- // Early abort. It is possible to get UI updates after the view is
- // destroyed; this can happen due to asynchronous loaders or
- // animations complete.
- return;
- }
-
- // We have three states: no clients (including hidden clients) at all;
- // all clients hidden; some clients hidden. We want to show the empty
- // list view only when we have no clients at all. This flag
- // differentiates the first from the latter two states.
- boolean displayedSomeClients = false;
-
- if (hiddenClients == null || hiddenClients.isEmpty()) {
- mList.removeFooterView(mFooterView);
- } else {
- displayedSomeClients = true;
-
- final TextView textView = (TextView) mFooterView.findViewById(R.id.hidden_devices);
- if (hiddenClients.size() == 1) {
- textView.setText(getResources().getString(R.string.home_remote_tabs_one_hidden_device));
- } else {
- textView.setText(getResources().getString(R.string.home_remote_tabs_many_hidden_devices, hiddenClients.size()));
- }
-
- // This is a simple, if not very future-proof, way to determine if
- // the footer view has already been added to the list view.
- if (mList.getFooterViewsCount() < 1) {
- mList.addFooterView(mFooterView);
- }
- }
-
- if (clients != null && !clients.isEmpty()) {
- displayedSomeClients = true;
-
- // No sense crashing if we've made an error.
- int groupCount = Math.min(mList.getExpandableListAdapter().getGroupCount(), clients.size());
- for (int i = 0; i < groupCount; i++) {
- final RemoteClient client = clients.get(i);
- if (sState.isClientCollapsed(client.guid)) {
- mList.collapseGroup(i);
- } else {
- mList.expandGroup(i);
- }
- }
- }
-
- if (displayedSomeClients) {
- return;
- }
-
- // No clients shown, not even hidden clients. Set the empty view if it
- // hasn't been set already.
- if (mEmptyView == null) {
- // Set empty panel view. We delay this so that the empty view won't flash.
- final ViewStub emptyViewStub = (ViewStub) getView().findViewById(R.id.home_empty_view_stub);
- mEmptyView = emptyViewStub.inflate();
-
- final ImageView emptyIcon = (ImageView) mEmptyView.findViewById(R.id.home_empty_image);
- emptyIcon.setImageResource(R.drawable.icon_remote_tabs_empty);
-
- final TextView emptyText = (TextView) mEmptyView.findViewById(R.id.home_empty_text);
- emptyText.setText(R.string.home_remote_tabs_empty);
-
- mList.setEmptyView(mEmptyView);
- }
- }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/home/RemoteTabsPanel.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/* -*- 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 org.mozilla.gecko.GeckoScreenOrientation;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.fxa.AccountLoader;
-import org.mozilla.gecko.fxa.FirefoxAccounts;
-import org.mozilla.gecko.fxa.FxAccountConstants;
-import org.mozilla.gecko.fxa.login.State;
-import org.mozilla.gecko.fxa.login.State.Action;
-import org.mozilla.gecko.sync.SyncConstants;
-import org.mozilla.gecko.util.HardwareUtils;
-
-import android.accounts.Account;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.LoaderManager.LoaderCallbacks;
-import android.support.v4.content.Loader;
-import android.util.Log;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * A <code>HomeFragment</code> that, depending on the state of accounts on the
- * device:
- * <ul>
- * <li>displays remote tabs from other devices;</li>
- * <li>offers to re-connect a Firefox Account;</li>
- * <li>offers to create a new Firefox Account.</li>
- * </ul>
- */
-public class RemoteTabsPanel extends HomeFragment {
- private static final String LOGTAG = "GeckoRemoteTabsPanel";
-
- // Loader ID for Android Account loader.
- private static final int LOADER_ID_ACCOUNT = 0;
- private static final String FRAGMENT_ACTION = "FRAGMENT_ACTION";
- private static final String FRAGMENT_ORIENTATION = "FRAGMENT_ORIENTATION";
- private static final String FRAGMENT_TAG = "FRAGMENT_TAG";
- private static final String NO_ACCOUNT = "NO_ACCOUNT";
-
- // Callback for loaders.
- private AccountLoaderCallbacks mAccountLoaderCallbacks;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.home_remote_tabs_panel, container, false);
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- // Create callbacks before the initial loader is started.
- mAccountLoaderCallbacks = new AccountLoaderCallbacks();
- loadIfVisible();
- }
-
- @Override
- protected void loadIfVisible() {
- // Force reload fragment only in tablets when there is valid account and the orientation has changed.
- Pair<String, Integer> actionOrientationPair;
- if (canLoad() && HardwareUtils.isTablet() && (actionOrientationPair = getActionAndOrientationForFragmentInBackStack()) != null) {
- if (actionOrientationPair.first.equals(Action.None.name()) && actionOrientationPair.second != GeckoScreenOrientation.getInstance().getAndroidOrientation()) {
- // As the fragment becomes visible only after onStart callback, we can safely remove it from the back-stack.
- // If a portrait fragment is in the back-stack and then a landscape fragment should be shown, there can
- // be a brief flash as the fragment as replaced.
- getChildFragmentManager()
- .beginTransaction()
- .addToBackStack(null)
- .remove(getChildFragmentManager().findFragmentByTag(FRAGMENT_TAG))
- .commitAllowingStateLoss();
- getChildFragmentManager().executePendingTransactions();
-
- load();
- return;
- }
- }
- super.loadIfVisible();
- }
-
- @Override
- public void load() {
- getLoaderManager().initLoader(LOADER_ID_ACCOUNT, null, mAccountLoaderCallbacks);
- }
-
- private void showSubPanel(Account account) {
- final Action actionNeeded = getActionNeeded(account);
- final String actionString = actionNeeded != null ? actionNeeded.name() : NO_ACCOUNT;
- final int orientation = HardwareUtils.isTablet() ? GeckoScreenOrientation.getInstance().getAndroidOrientation()
- : Configuration.ORIENTATION_UNDEFINED;
-
- // Check if fragment for given action and orientation is in the back-stack.
- final Pair<String, Integer> actionOrientationPair = getActionAndOrientationForFragmentInBackStack();
- if (actionOrientationPair != null && actionOrientationPair.first.equals(actionString) && (actionOrientationPair.second == orientation)) {
- return;
- }
-
- // Instantiate the fragment for the action and update the arguments.
- Fragment subPanel = makeFragmentForAction(actionNeeded);
- final Bundle args = new Bundle();
- args.putBoolean(HomePager.CAN_LOAD_ARG, getCanLoadHint());
- args.putString(FRAGMENT_ACTION, actionString);
- args.putInt(FRAGMENT_ORIENTATION, orientation);
- subPanel.setArguments(args);
-
- // Add the fragment to the back-stack.
- getChildFragmentManager()
- .beginTransaction()
- .addToBackStack(null)
- .replace(R.id.remote_tabs_container, subPanel, FRAGMENT_TAG)
- .commitAllowingStateLoss();
- }
-
- private Pair<String, Integer> getActionAndOrientationForFragmentInBackStack() {
- final Fragment currentFragment = getChildFragmentManager().findFragmentByTag(FRAGMENT_TAG);
- if (currentFragment != null && currentFragment.getArguments() != null) {
- final String fragmentAction = currentFragment.getArguments().getString(FRAGMENT_ACTION);
- final int fragmentOrientation = currentFragment.getArguments().getInt(FRAGMENT_ORIENTATION);
- return Pair.create(fragmentAction, fragmentOrientation);
- }
- return null;
- }
-
- /**
- * Get whatever <code>Action</code> is required to continue healthy syncing
- * of Remote Tabs.
- * <p>
- * A Firefox Account can be in many states, from healthy to requiring a
- * Fennec upgrade to continue use. If we have a Firefox Account, but the
- * state seems corrupt, the best we can do is ask for a password, which
- * resets most of the Account state. The health of a Sync account is
- * essentially opaque in this respect.
- * <p>
- * A null Account means there is no Account (Sync or Firefox) on the device.
- *
- * @param account
- * Android Account (Sync or Firefox); may be null.
- */
- private Action getActionNeeded(Account account) {
- if (account == null) {
- return null;
- }
-
- if (!FxAccountConstants.ACCOUNT_TYPE.equals(account.type)) {
- Log.wtf(LOGTAG, "Non Sync, non Firefox Android Account returned by AccountLoader; returning null.");
- return null;
- }
-
- final State state = FirefoxAccounts.getFirefoxAccountState(getActivity());
- if (state == null) {
- Log.wtf(LOGTAG, "Firefox Account with null state found; offering needs password.");
- return Action.NeedsPassword;
- }
-
- final Action actionNeeded = state.getNeededAction();
- if (actionNeeded == null) {
- Log.wtf(LOGTAG, "Firefox Account with non-null state but null action needed; offering needs password.");
- return Action.NeedsPassword;
- }
-
- return actionNeeded;
- }
-
- private Fragment makeFragmentForAction(Action action) {
- if (action == null) {
- // This corresponds to no Account: neither Sync nor Firefox.
- return RemoteTabsStaticFragment.newInstance(R.layout.remote_tabs_setup);
- }
-
- switch (action) {
- case None:
- if (HardwareUtils.isTablet() && GeckoScreenOrientation.getInstance().getAndroidOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
- return new RemoteTabsSplitPlaneFragment();
- } else {
- return new RemoteTabsExpandableListFragment();
- }
- case NeedsVerification:
- return RemoteTabsStaticFragment.newInstance(R.layout.remote_tabs_needs_verification);
- case NeedsPassword:
- return RemoteTabsStaticFragment.newInstance(R.layout.remote_tabs_needs_password);
- case NeedsUpgrade:
- return RemoteTabsStaticFragment.newInstance(R.layout.remote_tabs_needs_upgrade);
- case NeedsFinishMigrating:
- return RemoteTabsStaticFragment.newInstance(R.layout.remote_tabs_needs_finish_migrating);
- default:
- // This should never happen, but we're confident we have a Firefox
- // Account at this point, so let's show the needs password screen.
- // That's our best hope of righting the ship.
- Log.wtf(LOGTAG, "Got unexpected action needed; offering needs password.");
- return RemoteTabsStaticFragment.newInstance(R.layout.remote_tabs_needs_password);
- }
- }
-
- /**
- * Update the UI to reflect the given <code>Account</code> and its state.
- * <p>
- * A null Account means there is no Account (Sync or Firefox) on the device.
- *
- * @param account
- * Android Account (Sync or Firefox); may be null.
- */
- protected void updateUiFromAccount(Account account) {
- if (getView() == null) {
- // Early abort. When the fragment is detached, we get a loader
- // reset, which calls this with a null account parameter. A null
- // account is valid (it means there is no account, either Sync or
- // Firefox), and so we start to offer the setup flow. But this all
- // happens after the view has been destroyed, which means inserting
- // the setup flow fails. In this case, just abort.
- return;
- }
- showSubPanel(account);
- }
-
- private class AccountLoaderCallbacks implements LoaderCallbacks<Account> {
- @Override
- public Loader<Account> onCreateLoader(int id, Bundle args) {
- return new AccountLoader(getActivity());
- }
-
- @Override
- public void onLoadFinished(Loader<Account> loader, Account account) {
- updateUiFromAccount(account);
- }
-
- @Override
- public void onLoaderReset(Loader<Account> loader) {
- updateUiFromAccount(null);
- }
- }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/home/RemoteTabsSplitPlaneFragment.java
+++ /dev/null
@@ -1,408 +0,0 @@
-package org.mozilla.gecko.home;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.widget.AbsListView;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.TextView;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.RemoteClientsDialogFragment;
-import org.mozilla.gecko.RemoteTabsExpandableListAdapter;
-import org.mozilla.gecko.RemoteTabsExpandableListAdapter.GroupViewHolder;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.RemoteClient;
-import org.mozilla.gecko.db.RemoteTab;
-
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-
-/**
- * Fragment that displays other devices and tabs from them in two separate <code>ListView<code> instances.
- * <p/>
- * This is intended to be used in landscape mode on tablets.
- */
-public class RemoteTabsSplitPlaneFragment extends RemoteTabsBaseFragment {
- // Logging tag name.
- private static final String LOGTAG = "GeckoSplitPlaneFragment";
-
- private ArrayAdapter<RemoteTab> mTabsAdapter;
- private ArrayAdapter<RemoteClient> mClientsAdapter;
-
- // DataSetObserver for the expandable list adapter.
- private DataSetObserver mObserver;
-
- // The views shown by the fragment.
- private HomeListView mClientList;
- private HomeListView mTabList;
-
- public static RemoteTabsSplitPlaneFragment newInstance() {
- return new RemoteTabsSplitPlaneFragment();
- }
-
- public RemoteTabsSplitPlaneFragment() {
- super();
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.home_remote_tabs_split_plane_panel, container, false);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- mClientList = (HomeListView) view.findViewById(R.id.clients_list);
- mTabList = (HomeListView) view.findViewById(R.id.tabs_list);
-
- mClientList.setTag(HomePager.LIST_TAG_REMOTE_TABS);
-
- mTabList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
- final RemoteTab tab = (RemoteTab) adapter.getItemAtPosition(position);
- if (tab == null) {
- return;
- }
-
- Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM, "remote_tabs");
-
- // This item is a TwoLinePageRow, so we allow switch-to-tab.
- mUrlOpenListener.onUrlOpen(tab.url, EnumSet.of(HomePager.OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
- }
- });
-
- mClientList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
- final RemoteClient client = (RemoteClient) adapter.getItemAtPosition(position);
- if (client != null) {
- sState.setClientAsSelected(client.guid);
- mTabsAdapter.clear();
- for (RemoteTab tab : client.tabs) {
- mTabsAdapter.add(tab);
- }
-
- // Notify data has changed for both clients and tabs adapter.
- // This will update selected client item background and the tabs list.
- mClientsAdapter.notifyDataSetChanged();
- mTabsAdapter.notifyDataSetChanged();
- }
- }
- });
-
- mTabList.setContextMenuInfoFactory(new HomeContextMenuInfo.ListFactory() {
- @Override
- public HomeContextMenuInfo makeInfoForCursor(View view, int position, long id, Cursor cursor) {
- return null;
- }
-
- @Override
- public HomeContextMenuInfo makeInfoForAdapter(View view, int position, long id, ListAdapter adapter) {
- final RemoteTab tab = (RemoteTab) adapter.getItem(position);
- final HomeContextMenuInfo info = new HomeContextMenuInfo(view, position, id);
- info.url = tab.url;
- info.title = tab.title;
- return info;
- }
- });
-
- mClientList.setContextMenuInfoFactory(new HomeContextMenuInfo.ListFactory() {
- @Override
- public HomeContextMenuInfo makeInfoForCursor(View view, int position, long id, Cursor cursor) {
- return null;
- }
-
- @Override
- public HomeContextMenuInfo makeInfoForAdapter(View view, int position, long id, ListAdapter adapter) {
- final RemoteClient client = (RemoteClient) adapter.getItem(position);
- return new RemoteTabsClientContextMenuInfo(view, position, id, client);
- }
- });
-
- registerForContextMenu(mClientList);
- registerForContextMenu(mTabList);
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
-
- // Discard any additional item clicks on the list as the
- // panel is getting destroyed (bug 1210243).
- mClientList.setOnItemClickListener(null);
- mTabList.setOnItemClickListener(null);
-
- mClientList = null;
- mTabList = null;
- mEmptyView = null;
- mAdapter.unregisterDataSetObserver(mObserver);
- mObserver = null;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- // There is an unfortunate interaction between ListViews and
- // footer onClick handling. The footer view itself appears to not
- // receive click events. Its children, however, do receive click events.
- // Therefore, we attach an onClick handler to a child of the footer view
- // itself.
- mFooterView = LayoutInflater.from(getActivity()).inflate(R.layout.home_remote_tabs_hidden_devices_footer, mClientList, false);
- final View view = mFooterView.findViewById(R.id.hidden_devices);
- view.setClickable(true);
- view.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final RemoteClientsDialogFragment dialog = RemoteClientsDialogFragment.newInstance(
- getResources().getString(R.string.home_remote_tabs_hidden_devices_title),
- getResources().getString(R.string.home_remote_tabs_unhide_selected_devices),
- RemoteClientsDialogFragment.ChoiceMode.MULTIPLE, new ArrayList<>(mHiddenClients));
- dialog.setTargetFragment(RemoteTabsSplitPlaneFragment.this, 0);
- dialog.show(getActivity().getSupportFragmentManager(), DIALOG_TAG_REMOTE_TABS);
- }
- });
-
- // There is a delicate interaction, pre-KitKat, between
- // {add,remove}FooterView and setAdapter. setAdapter wraps the adapter
- // in a footer/header-managing adapter, which only happens (pre-KitKat)
- // if a footer/header is present. Therefore, we add our footer before
- // setting the adapter; and then we remove it afterward. From there on,
- // we can add/remove it at will.
- mClientList.addFooterView(mFooterView, null, true);
-
- // Initialize adapter
- mAdapter = new RemoteTabsExpandableListAdapter(R.layout.home_remote_tabs_group, R.layout.home_remote_tabs_child, null, false);
-
- mTabsAdapter = new RemoteTabsAdapter(getActivity(), R.layout.home_remote_tabs_child);
- mClientsAdapter = new RemoteClientAdapter(getActivity(), R.layout.home_remote_tabs_group, mAdapter);
-
- // ArrayAdapter.addAll() is supported only from API 11. We avoid redundant notifications while each item is added to the adapter here.
- // ArrayAdapter notifyDataSetChanged should be called after all add operations manually.
- mTabsAdapter.setNotifyOnChange(false);
- mClientsAdapter.setNotifyOnChange(false);
-
- mTabList.setAdapter(mTabsAdapter);
- mClientList.setAdapter(mClientsAdapter);
-
- mObserver = new RemoteTabDataSetObserver();
- mAdapter.registerDataSetObserver(mObserver);
-
- // Now the adapter is wrapped; we can remove our footer view.
- mClientList.removeFooterView(mFooterView);
-
- // Register touch handler to conditionally enable swipe refresh layout.
- mClientList.setOnTouchListener(new ListTouchListener(mClientList));
- mTabList.setOnTouchListener(new ListTouchListener(mTabList));
-
- // Create callbacks before the initial loader is started
- mCursorLoaderCallbacks = new CursorLoaderCallbacks();
- loadIfVisible();
- }
-
- @Override
- protected void updateUiFromClients(List<RemoteClient> clients, List<RemoteClient> hiddenClients) {
- if (getView() == null) {
- // Early abort. It is possible to get UI updates after the view is
- // destroyed; this can happen due to asynchronous loaders or
- // animations complete.
- return;
- }
-
- // We have three states: no clients (including hidden clients) at all;
- // all clients hidden; some clients hidden. We want to show the empty
- // list view only when we have no clients at all. This flag
- // differentiates the first from the latter two states.
- boolean displayedSomeClients = false;
-
- if (hiddenClients == null || hiddenClients.isEmpty()) {
- mClientList.removeFooterView(mFooterView);
- } else {
- displayedSomeClients = true;
-
- final TextView textView = (TextView) mFooterView.findViewById(R.id.hidden_devices);
- if (hiddenClients.size() == 1) {
- textView.setText(getResources().getString(R.string.home_remote_tabs_one_hidden_device));
- } else {
- textView.setText(getResources().getString(R.string.home_remote_tabs_many_hidden_devices, hiddenClients.size()));
- }
-
- // This is a simple, if not very future-proof, way to determine if
- // the footer view has already been added to the list view.
- if (mClientList.getFooterViewsCount() < 1) {
- mClientList.addFooterView(mFooterView);
- }
- }
-
- if (clients != null && !clients.isEmpty()) {
- displayedSomeClients = true;
- }
-
- if (displayedSomeClients) {
- return;
- }
-
- // No clients shown, not even hidden clients. Set the empty view if it
- // hasn't been set already.
- if (mEmptyView == null) {
- // Set empty panel view. We delay this so that the empty view won't flash.
- final ViewStub emptyViewStub = (ViewStub) getView().findViewById(R.id.home_empty_view_stub);
- mEmptyView = emptyViewStub.inflate();
-
- final ImageView emptyIcon = (ImageView) mEmptyView.findViewById(R.id.home_empty_image);
- emptyIcon.setImageResource(R.drawable.icon_remote_tabs_empty);
-
- final TextView emptyText = (TextView) mEmptyView.findViewById(R.id.home_empty_text);
- emptyText.setText(R.string.home_remote_tabs_empty);
-
- mClientList.setEmptyView(mEmptyView);
- }
- }
-
- private class RemoteTabDataSetObserver extends DataSetObserver {
- @Override
- public void onChanged() {
- super.onChanged();
- mClientsAdapter.clear();
- mTabsAdapter.clear();
-
- RemoteClient selectedClient = null;
- for (int i = 0; i < mAdapter.getGroupCount(); i++) {
- final RemoteClient client = (RemoteClient) mAdapter.getGroup(i);
- mClientsAdapter.add(client);
-
- if (i == 0) {
- // Fallback to most recent client when selected client guid not found.
- selectedClient = client;
- }
-
- if (client.guid.equals(sState.selectedClient)) {
- selectedClient = client;
- }
- }
-
- final List<RemoteTab> visibleTabs = (selectedClient != null) ? selectedClient.tabs : new ArrayList<RemoteTab>();
- for (RemoteTab tab : visibleTabs) {
- mTabsAdapter.add(tab);
- }
-
- // Update the selected client and notify data has changed both the list views.
- sState.setClientAsSelected(selectedClient != null ? selectedClient.guid : null);
- mTabsAdapter.notifyDataSetChanged();
- mClientsAdapter.notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- super.onInvalidated();
- mClientsAdapter.clear();
- mTabsAdapter.clear();
- mTabsAdapter.notifyDataSetChanged();
- mClientsAdapter.notifyDataSetChanged();
- }
- }
-
- private static class RemoteTabsAdapter extends ArrayAdapter<RemoteTab> {
- private final Context context;
- private final int resource;
-
- public RemoteTabsAdapter(Context context, int resource) {
- super(context, resource);
- this.context = context;
- this.resource = resource;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final TwoLinePageRow view;
- if (convertView != null) {
- view = (TwoLinePageRow) convertView;
- } else {
- final LayoutInflater inflater = LayoutInflater.from(context);
- view = (TwoLinePageRow) inflater.inflate(resource, parent, false);
- }
-
- final RemoteTab tab = getItem(position);
- view.update(tab.title, tab.url);
-
- return view;
- }
- }
-
- private class RemoteClientAdapter extends ArrayAdapter<RemoteClient> {
- private final Context context;
- private final int resource;
- private final RemoteTabsExpandableListAdapter adapter;
-
- public RemoteClientAdapter(Context context, int resource, RemoteTabsExpandableListAdapter adapter) {
- super(context, resource);
- this.context = context;
- this.resource = resource;
- this.adapter = adapter;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final View view;
- if (convertView != null) {
- view = convertView;
- } else {
- final LayoutInflater inflater = LayoutInflater.from(context);
- view = inflater.inflate(resource, parent, false);
- final GroupViewHolder holder = new GroupViewHolder(view);
- view.setTag(holder);
- }
-
- // Update the background based on the state of the selected client.
- final RemoteClient client = getItem(position);
- final boolean isSelected = client.guid.equals(sState.selectedClient);
- adapter.updateClientsItemView(isSelected, context, view, getItem(position));
- return view;
- }
- }
-
- /**
- * OnTouchListener implementation for ListView that enables swipe to refresh on the touch down event iff list cannot scroll up.
- * This implementation does not consume the <code>MotionEvent</code>.
- */
- private class ListTouchListener implements View.OnTouchListener {
- private final AbsListView listView;
-
- public ListTouchListener(AbsListView listView) {
- this.listView = listView;
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // Enable swipe to refresh iff the first item is visible and is at the top.
- mRefreshLayout.setEnabled(listView.getCount() <= 0
- || (listView.getFirstVisiblePosition() <= 0 && listView.getChildAt(0).getTop() >= 0));
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- mRefreshLayout.setEnabled(true);
- break;
- }
-
- // Event is not handled here, it will be consumed in enclosing SwipeRefreshLayout.
- return false;
- }
- }
-}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/home/RemoteTabsStaticFragment.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/* 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 android.content.Intent;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.fxa.FxAccountConstants;
-import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
-
-import java.util.EnumSet;
-
-/**
- * A <code>HomeFragment</code> which displays one of a small set of static views
- * in response to different Firefox Account states. When the Firefox Account is
- * healthy and syncing normally, these views should not be shown.
- * <p>
- * This class exists to handle view-specific actions when buttons and links
- * shown by the different static views are clicked. For example, a static view
- * offers to set up a Firefox Account to a user who has no account (Firefox or
- * Sync) on their device.
- * <p>
- * This could be a vanilla <code>Fragment</code>, except it needs to open URLs.
- * To do so, it expects its containing <code>Activity</code> to implement
- * <code>OnUrlOpenListener<code>; to suggest this invariant at compile time, we
- * inherit from <code>HomeFragment</code>.
- */
-public class RemoteTabsStaticFragment extends HomeFragment implements OnClickListener {
- @SuppressWarnings("unused")
- private static final String LOGTAG = "GeckoRemoteTabsStatic";
-
- protected static final String RESOURCE_ID = "resource_id";
- protected static final int DEFAULT_RESOURCE_ID = R.layout.remote_tabs_setup;
-
- private static final String CONFIRM_ACCOUNT_SUPPORT_URL =
- "https://support.mozilla.org/kb/im-having-problems-confirming-my-firefox-account";
-
- protected int mLayoutId;
-
- public static RemoteTabsStaticFragment newInstance(int resourceId) {
- final RemoteTabsStaticFragment fragment = new RemoteTabsStaticFragment();
-
- final Bundle args = new Bundle();
- args.putInt(RESOURCE_ID, resourceId);
- fragment.setArguments(args);
-
- return fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final Bundle args = getArguments();
- if (args != null) {
- mLayoutId = args.getInt(RESOURCE_ID, DEFAULT_RESOURCE_ID);
- } else {
- mLayoutId = DEFAULT_RESOURCE_ID;
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(mLayoutId, container, false);
- }
-
- protected boolean maybeSetOnClickListener(View view, int resourceId) {
- final View button = view.findViewById(resourceId);
- if (button != null) {
- button.setOnClickListener(this);
- return true;
- }
- return false;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- for (int resourceId : new int[] {
- R.id.remote_tabs_setup_get_started,
- R.id.remote_tabs_needs_verification_resend_email,
- R.id.remote_tabs_needs_verification_help,
- R.id.remote_tabs_needs_password_sign_in,
- R.id.remote_tabs_needs_finish_migrating_sign_in, }) {
- maybeSetOnClickListener(view, resourceId);
- }
- }
-
- @Override
- public void onClick(final View v) {
- final int id = v.getId();
- if (id == R.id.remote_tabs_setup_get_started) {
- // This Activity will redirect to the correct Activity as needed.
- final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
- startActivity(intent);
- } else if (id == R.id.remote_tabs_needs_verification_resend_email) {
- final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_CONFIRM_ACCOUNT);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- } else if (id == R.id.remote_tabs_needs_verification_help) {
- // Don't allow switch-to-tab.
- final EnumSet<OnUrlOpenListener.Flags> flags = EnumSet.noneOf(OnUrlOpenListener.Flags.class);
- mUrlOpenListener.onUrlOpen(CONFIRM_ACCOUNT_SUPPORT_URL, flags);
- } else if (id == R.id.remote_tabs_needs_password_sign_in) {
- final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_UPDATE_CREDENTIALS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- } else if (id == R.id.remote_tabs_needs_finish_migrating_sign_in) {
- final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_FINISH_MIGRATING);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- }
- }
-
- @Override
- protected void load() {
- // We're static, so nothing to do here!
- }
-}
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -540,39 +540,28 @@ size. -->
<!ENTITY home_clear_history_button "Clear browsing history">
<!ENTITY home_clear_history_confirm "Are you sure you want to clear your history?">
<!ENTITY home_bookmarks_empty "Bookmarks you save show up here.">
<!ENTITY home_closed_tabs_title "Recently closed tabs">
<!ENTITY home_last_tabs_title "Tabs from last time">
<!ENTITY home_last_tabs_empty "Your recent tabs show up here.">
<!ENTITY home_open_all "Open all">
<!ENTITY home_most_recent_empty "Websites you visited most recently show up here.">
-<!ENTITY home_selected_empty "Websites you visited in the selected timeframe show up here.">
<!-- Localization note (home_most_recent_emptyhint2): "Psst" is a sound that might be used to attract someone's attention unobtrusively, and intended to hint at Private Browsing to the user.
The placeholders &formatS1; and &formatS2; are used to mark the location of text underlining. -->
<!ENTITY home_most_recent_emptyhint2 "Psst: using a &formatS1;New Private Tab&formatS2; won\'t save your history.">
<!-- Localization note (home_default_empty): This string is used as the default text when there
is no data to show in an about:home panel that was created by an add-on. -->
<!ENTITY home_default_empty "No content could be found for this panel.">
<!-- Localization note (home_back_up_to_filter): The variable is replaced by the name of the
previous location in the navigation, such as the previous folder -->
<!ENTITY home_move_back_to_filter "Back to &formatS;">
-<!ENTITY home_remote_tabs_title "Synced Tabs">
-<!ENTITY home_remote_tabs_empty "Your tabs from other devices show up here.">
-<!ENTITY home_remote_tabs_unable_to_connect "Unable to connect">
-<!ENTITY home_remote_tabs_need_to_sign_in "Please sign in to reconnect your Firefox Account and continue syncing.">
-<!ENTITY home_remote_tabs_need_to_finish_migrating "Your new Firefox Account is ready!">
-
-<!ENTITY home_remote_tabs_trouble_verifying "Trouble verifying your account?">
-<!ENTITY home_remote_tabs_need_to_verify "Please verify your Firefox Account to start syncing.">
-
-<!ENTITY home_remote_tabs_one_hidden_device "1 device hidden">
<!-- Localization note (home_remote_tabs_many_hidden_devices) : The
formatD is replaced with the number of hidden devices. The
number of hidden devices is always more than one. We can't use
Android plural forms, sadly. See Bug #753859. -->
<!ENTITY home_remote_tabs_many_hidden_devices "&formatD; devices hidden">
<!-- Localization note (home_remote_tabs_hidden_devices_title) : This is the
title of a dialog; we expect more than one device. -->
<!ENTITY home_remote_tabs_hidden_devices_title "Hidden devices">
--- a/mobile/android/base/locales/en-US/sync_strings.dtd
+++ b/mobile/android/base/locales/en-US/sync_strings.dtd
@@ -46,24 +46,16 @@
Firefox. -->
<!ENTITY fxaccount_back_to_browsing 'Back to browsing'>
<!ENTITY fxaccount_getting_started_welcome_to_sync 'Welcome to &syncBrand.shortName.label;'>
<!ENTITY fxaccount_getting_started_description2 'Sign in to sync your tabs, bookmarks, logins & more.'>
<!ENTITY fxaccount_getting_started_get_started 'Get started'>
<!ENTITY fxaccount_getting_started_old_firefox 'Using an older version of &syncBrand.shortName.label;?'>
-<!ENTITY fxaccount_confirm_account_header 'Confirm your account'>
-<!ENTITY fxaccount_confirm_account_resend_email 'Resend email'>
-
-<!ENTITY fxaccount_sign_in_button_label 'Sign in'>
-
-<!ENTITY fxaccount_finish_migrating_header 'Sign in to finish upgrading'>
-<!ENTITY fxaccount_finish_migrating_button_label 'Finish upgrading'>
-
<!ENTITY fxaccount_status_signed_in_as 'Signed in as'>
<!ENTITY fxaccount_status_manage_account 'Manage account'>
<!ENTITY fxaccount_status_auth_server 'Account server'>
<!ENTITY fxaccount_status_sync_now 'Sync now'>
<!ENTITY fxaccount_status_syncing2 'Syncing…'>
<!ENTITY fxaccount_status_device_name 'Device name'>
<!ENTITY fxaccount_status_sync_server 'Sync server'>
<!ENTITY fxaccount_status_sync '&syncBrand.shortName.label;'>
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -414,22 +414,17 @@ gbjar.sources += ['java/org/mozilla/geck
'home/PanelRecyclerView.java',
'home/PanelRecyclerViewAdapter.java',
'home/PanelRefreshLayout.java',
'home/PanelViewAdapter.java',
'home/PanelViewItemHandler.java',
'home/PinSiteDialog.java',
'home/ReadingListPanel.java',
'home/RecentTabsPanel.java',
- 'home/RemoteTabsBaseFragment.java',
- 'home/RemoteTabsExpandableListFragment.java',
'home/RemoteTabsExpandableListState.java',
- 'home/RemoteTabsPanel.java',
- 'home/RemoteTabsSplitPlaneFragment.java',
- 'home/RemoteTabsStaticFragment.java',
'home/SearchEngine.java',
'home/SearchEngineAdapter.java',
'home/SearchEngineBar.java',
'home/SearchEngineRow.java',
'home/SearchLoader.java',
'home/SimpleCursorLoader.java',
'home/SpacingDecoration.java',
'home/TabMenuStrip.java',
deleted file mode 100644
--- a/mobile/android/base/resources/layout/home_remote_tabs_child.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-
-<org.mozilla.gecko.home.TwoLinePageRow xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/Widget.RemoteTabsItemView"
- android:layout_width="match_parent"
- android:layout_height="@dimen/page_row_height"
- android:minHeight="@dimen/page_row_height"/>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/home_remote_tabs_hidden_devices_footer.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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/.
--->
-
-<!-- This layout is actually necessary because of an interaction
- between ExpandableListView and onClick handling. We need a child
- to attach a click listener to. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:gecko="http://schemas.android.com/apk/res-auto"
- style="@style/Widget.RemoteTabsClientView"
- android:layout_width="match_parent"
- android:layout_height="@dimen/home_remote_tabs_hidden_footer_height"
- android:gravity="center_vertical" >
-
- <TextView
- android:id="@+id/hidden_devices"
- style="@style/Widget.Home.ActionItem"
- android:background="@drawable/action_bar_button"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:maxLength="1024"
- android:textColor="@color/tabs_tray_icon_grey" />
-
-</LinearLayout>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/home_remote_tabs_list_panel.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <ViewStub android:id="@+id/home_empty_view_stub"
- android:layout="@layout/home_empty_panel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- <android.support.v4.widget.SwipeRefreshLayout
- android:id="@+id/remote_tabs_refresh_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <org.mozilla.gecko.home.HomeExpandableListView
- android:id="@+id/list"
- style="@style/Widget.RemoteTabsListView"
- android:groupIndicator="@android:color/transparent"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- </android.support.v4.widget.SwipeRefreshLayout>
-
-</LinearLayout>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/home_remote_tabs_panel.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <FrameLayout android:id="@+id/remote_tabs_container"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
-</LinearLayout>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/home_remote_tabs_split_plane_panel.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <ViewStub android:id="@id/home_empty_view_stub"
- android:layout="@layout/home_empty_panel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- <android.support.v4.widget.SwipeRefreshLayout
- android:id="@id/remote_tabs_refresh_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
-
- <org.mozilla.gecko.home.HomeListView
- android:id="@+id/clients_list"
- style="@style/Widget.RemoteTabsListView"
- android:layout_weight="0.32"
- android:layout_width="0dp"
- android:layout_height="match_parent"/>
-
- <View
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:background="#D7D9DB" />
-
- <org.mozilla.gecko.home.HomeListView
- android:id="@+id/tabs_list"
- style="@style/Widget.RemoteTabsListView"
- android:layout_weight="0.68"
- android:layout_width="0dp"
- android:layout_height="match_parent"/>
-
- </LinearLayout>
-
- </android.support.v4.widget.SwipeRefreshLayout>
-
-</LinearLayout>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_needs_finish_migrating.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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/.
--->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <LinearLayout style="@style/RemoteTabsPanelFrame" >
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance.Header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/fxaccount_finish_migrating_header" />
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/home_remote_tabs_need_to_finish_migrating" />
-
- <Button
- android:id="@+id/remote_tabs_needs_finish_migrating_sign_in"
- style="@style/RemoteTabsPanelItem.Button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/fxaccount_finish_migrating_button_label" />
- </LinearLayout>
-
-</ScrollView>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_needs_password.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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/.
--->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <LinearLayout style="@style/RemoteTabsPanelFrame" >
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance.Header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/home_remote_tabs_unable_to_connect" />
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/home_remote_tabs_need_to_sign_in" />
-
- <Button
- android:id="@+id/remote_tabs_needs_password_sign_in"
- style="@style/RemoteTabsPanelItem.Button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/fxaccount_sign_in_button_label" />
- </LinearLayout>
-
-</ScrollView>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_needs_upgrade.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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/.
--->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <LinearLayout style="@style/RemoteTabsPanelFrame" >
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance.Header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/home_remote_tabs_unable_to_connect" />
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/fxaccount_status_needs_upgrade" />
- </LinearLayout>
-
-</ScrollView>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_needs_verification.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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/.
--->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <LinearLayout style="@style/RemoteTabsPanelFrame" >
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance.Header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/fxaccount_confirm_account_header" />
-
- <TextView
- style="@style/RemoteTabsPanelItem.TextAppearance"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/home_remote_tabs_need_to_verify" />
-
- <Button
- android:id="@+id/remote_tabs_needs_verification_resend_email"
- style="@style/RemoteTabsPanelItem.Button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/fxaccount_confirm_account_resend_email" />
-
- <TextView
- android:id="@+id/remote_tabs_needs_verification_help"
- style="@style/RemoteTabsPanelItem.TextAppearance.Linkified"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/home_remote_tabs_trouble_verifying" />
- </LinearLayout>
-</ScrollView>
--- a/mobile/android/base/resources/values/dimens.xml
+++ b/mobile/android/base/resources/values/dimens.xml
@@ -205,12 +205,9 @@
<dimen name="progress_bar_scroll_offset">1.5dp</dimen>
<!-- http://blog.danlew.net/2015/01/06/handling-android-resources-with-non-standard-formats/ -->
<item name="match_parent" type="dimen">-1</item>
<item name="wrap_content" type="dimen">-2</item>
<item name="tab_strip_content_start" type="dimen">12dp</item>
<item name="firstrun_tab_strip_content_start" type="dimen">15dp</item>
-
- <item name="split_plane_left_pane_weight" format="float" type="dimen">0.32</item>
- <item name="split_plane_right_pane_weight" format="float" type="dimen">0.68</item>
</resources>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -443,28 +443,19 @@
<string name="home_clear_history_button">&home_clear_history_button;</string>
<string name="home_clear_history_confirm">&home_clear_history_confirm;</string>
<string name="home_bookmarks_empty">&home_bookmarks_empty;</string>
<string name="home_closed_tabs_title">&home_closed_tabs_title;</string>
<string name="home_last_tabs_title">&home_last_tabs_title;</string>
<string name="home_last_tabs_empty">&home_last_tabs_empty;</string>
<string name="home_open_all">&home_open_all;</string>
<string name="home_most_recent_empty">&home_most_recent_empty;</string>
- <string name="home_selected_empty">&home_selected_empty;</string>
<string name="home_most_recent_emptyhint">&home_most_recent_emptyhint2;</string>
<string name="home_default_empty">&home_default_empty;</string>
<string name="home_move_back_to_filter">&home_move_back_to_filter;</string>
- <string name="home_remote_tabs_title">&home_remote_tabs_title;</string>
- <string name="home_remote_tabs_empty">&home_remote_tabs_empty;</string>
- <string name="home_remote_tabs_unable_to_connect">&home_remote_tabs_unable_to_connect;</string>
- <string name="home_remote_tabs_need_to_sign_in">&home_remote_tabs_need_to_sign_in;</string>
- <string name="home_remote_tabs_need_to_finish_migrating">&home_remote_tabs_need_to_finish_migrating;</string>
- <string name="home_remote_tabs_trouble_verifying">&home_remote_tabs_trouble_verifying;</string>
- <string name="home_remote_tabs_need_to_verify">&home_remote_tabs_need_to_verify;</string>
- <string name="home_remote_tabs_one_hidden_device">&home_remote_tabs_one_hidden_device;</string>
<string name="home_remote_tabs_many_hidden_devices">&home_remote_tabs_many_hidden_devices;</string>
<string name="home_remote_tabs_hidden_devices_title">&home_remote_tabs_hidden_devices_title;</string>
<string name="home_remote_tabs_unhide_selected_devices">&home_remote_tabs_unhide_selected_devices;</string>
<string name="pin_site_dialog_hint">&pin_site_dialog_hint;</string>
<string name="remote_tabs_never_synced">&remote_tabs_never_synced;</string>
<string name="filepicker_title">&filepicker_title;</string>
--- a/mobile/android/services/strings.xml.in
+++ b/mobile/android/services/strings.xml.in
@@ -23,24 +23,16 @@
<!-- Firefox Account links. -->
<string name="fxaccount_link_tos">https://accounts.firefox.com/legal/terms</string>
<string name="fxaccount_link_pn">https://accounts.firefox.com/legal/privacy</string>
<string name="fxaccount_getting_started_welcome_to_sync">&fxaccount_getting_started_welcome_to_sync;</string>
<string name="fxaccount_getting_started_description">&fxaccount_getting_started_description2;</string>
<string name="fxaccount_getting_started_get_started">&fxaccount_getting_started_get_started;</string>
-<string name="fxaccount_confirm_account_header">&fxaccount_confirm_account_header;</string>
-<string name="fxaccount_confirm_account_resend_email">&fxaccount_confirm_account_resend_email;</string>
-
-<string name="fxaccount_sign_in_button_label">&fxaccount_sign_in_button_label;</string>
-
-<string name="fxaccount_finish_migrating_header">&fxaccount_finish_migrating_header;</string>
-<string name="fxaccount_finish_migrating_button_label">&fxaccount_finish_migrating_button_label;</string>
-
<string name="fxaccount_status_activity_label">&syncBrand.shortName.label;</string>
<string name="fxaccount_status_signed_in_as">&fxaccount_status_signed_in_as;</string>
<string name="fxaccount_status_manage_account">&fxaccount_status_manage_account;</string>
<string name="fxaccount_status_auth_server">&fxaccount_status_auth_server;</string>
<string name="fxaccount_status_sync_now">&fxaccount_status_sync_now;</string>
<string name="fxaccount_status_syncing">&fxaccount_status_syncing2;</string>
<string name="fxaccount_status_last_synced">&remote_tabs_last_synced;</string>
<string name="fxaccount_status_never_synced">&remote_tabs_never_synced;</string>