/* -*- 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.support.v4.util.Pair;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A HomeFragment that, depending on the state of accounts on the
* device:
*
Action is required to continue healthy syncing
* of Remote Tabs.
* * 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. *
* 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 (SyncConstants.ACCOUNTTYPE_SYNC.equals(account.type)) {
return Action.None;
}
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 Account and its state.
*
* 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