Bug 942281 - Create a PanelAuthCache to keep track of whether or not panel is authenciated (r=lucasr)

This commit is contained in:
Margaret Leibovic 2014-03-27 09:25:04 -07:00
Родитель b11cb7dcd0
Коммит 4e76284655
5 изменённых файлов: 210 добавлений и 30 удалений

Просмотреть файл

@ -17,6 +17,7 @@ import org.mozilla.gecko.home.PanelLayout.DatasetHandler;
import org.mozilla.gecko.home.PanelLayout.DatasetRequest;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UiAsyncTask;
import android.app.Activity;
import android.content.ContentResolver;
@ -68,6 +69,13 @@ public class DynamicPanel extends HomeFragment
// The layout used to show authentication UI for this panel
private PanelAuthLayout mPanelAuthLayout;
// Cache used to keep track of whether or not the user has been authenticated.
private PanelAuthCache mPanelAuthCache;
// Hold a reference to the UiAsyncTask we use to check the state of the
// PanelAuthCache, so that we can cancel it if necessary.
private UiAsyncTask<Void, Void, Boolean> mAuthStateTask;
// The configuration associated with this panel
private PanelConfig mPanelConfig;
@ -77,6 +85,17 @@ public class DynamicPanel extends HomeFragment
// On URL open listener
private OnUrlOpenListener mUrlOpenListener;
/*
* Different UI modes to display depending on the authentication state.
*
* PANEL: Layout to display panel data.
* AUTH: Authentication UI.
*/
private enum UIMode {
PANEL,
AUTH
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
@ -108,31 +127,21 @@ public class DynamicPanel extends HomeFragment
if (mPanelConfig == null) {
throw new IllegalStateException("Can't create a DynamicPanel without a PanelConfig");
}
mPanelAuthCache = new PanelAuthCache(getActivity());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
switch(mPanelConfig.getLayoutType()) {
case FRAME:
final PanelDatasetHandler datasetHandler = new PanelDatasetHandler();
mPanelLayout = new FramePanelLayout(getActivity(), mPanelConfig, datasetHandler, mUrlOpenListener);
break;
default:
throw new IllegalStateException("Unrecognized layout type in DynamicPanel");
}
Log.d(LOGTAG, "Created layout of type: " + mPanelConfig.getLayoutType());
mView = new FrameLayout(getActivity());
mView.addView(mPanelLayout);
return mView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mPanelAuthCache.setOnChangeListener(new PanelAuthChangeListener());
GeckoAppShell.registerEventListener("HomePanels:RefreshDataset", this);
}
@ -143,7 +152,13 @@ public class DynamicPanel extends HomeFragment
mPanelLayout = null;
mPanelAuthLayout = null;
mPanelAuthCache.setOnChangeListener(null);
GeckoAppShell.unregisterEventListener("HomePanels:RefreshDataset", this);
if (mAuthStateTask != null) {
mAuthStateTask.cancel(true);
mAuthStateTask = null;
}
}
@Override
@ -173,10 +188,21 @@ public class DynamicPanel extends HomeFragment
Log.d(LOGTAG, "Loading layout");
if (requiresAuth()) {
// TODO: check to see if the panel isn't already authenticated
setAuthVisible(true);
mAuthStateTask = new UiAsyncTask<Void, Void, Boolean>(ThreadUtils.getBackgroundHandler()) {
@Override
public synchronized Boolean doInBackground(Void... params) {
return mPanelAuthCache.isAuthenticated(mPanelConfig.getId());
}
@Override
public void onPostExecute(Boolean isAuthenticated) {
mAuthStateTask = null;
setUIMode(isAuthenticated ? UIMode.PANEL : UIMode.AUTH);
}
};
mAuthStateTask.execute();
} else {
mPanelLayout.load();
setUIMode(UIMode.PANEL);
}
}
@ -187,15 +213,61 @@ public class DynamicPanel extends HomeFragment
return mPanelConfig.getAuthConfig() != null;
}
private void setAuthVisible(boolean visible) {
// Lazily create PanelAuthLayout.
if (visible && mPanelAuthLayout == null) {
/**
* Lazily creates layout for panel data.
*/
private void createPanelLayout() {
switch(mPanelConfig.getLayoutType()) {
case FRAME:
final PanelDatasetHandler datasetHandler = new PanelDatasetHandler();
mPanelLayout = new FramePanelLayout(getActivity(), mPanelConfig, datasetHandler, mUrlOpenListener);
break;
default:
throw new IllegalStateException("Unrecognized layout type in DynamicPanel");
}
Log.d(LOGTAG, "Created layout of type: " + mPanelConfig.getLayoutType());
mView.addView(mPanelLayout);
}
/**
* Lazily creates layout for authentication UI.
*/
private void createPanelAuthLayout() {
mPanelAuthLayout = new PanelAuthLayout(getActivity(), mPanelConfig);
mView.addView(mPanelAuthLayout, 0);
}
mPanelAuthLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
mPanelLayout.setVisibility(visible ? View.GONE : View.VISIBLE);
private void setUIMode(UIMode mode) {
switch(mode) {
case PANEL:
if (mPanelAuthLayout != null) {
mPanelAuthLayout.setVisibility(View.GONE);
}
if (mPanelLayout == null) {
createPanelLayout();
}
mPanelLayout.setVisibility(View.VISIBLE);
if (canLoad()) {
mPanelLayout.load();
}
break;
case AUTH:
if (mPanelLayout != null) {
mPanelLayout.setVisibility(View.GONE);
}
if (mPanelAuthLayout == null) {
createPanelAuthLayout();
}
mPanelAuthLayout.setVisibility(View.VISIBLE);
break;
default:
throw new IllegalStateException("Unrecognized UIMode in DynamicPanel");
}
}
@Override
@ -348,8 +420,10 @@ public class DynamicPanel extends HomeFragment
final DatasetRequest request = getRequestFromLoader(loader);
Log.d(LOGTAG, "Finished loader for request: " + request);
if (mPanelLayout != null) {
mPanelLayout.deliverDataset(request, cursor);
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
@ -365,4 +439,15 @@ public class DynamicPanel extends HomeFragment
return datasetLoader.getRequest();
}
}
private class PanelAuthChangeListener implements PanelAuthCache.OnChangeListener {
@Override
public void onChange(String panelId, boolean isAuthenticated) {
if (!mPanelConfig.getId().equals(panelId)) {
return;
}
setUIMode(isAuthenticated ? UIMode.PANEL : UIMode.AUTH);
}
}
}

Просмотреть файл

@ -221,16 +221,18 @@ abstract class HomeFragment extends Fragment {
protected abstract void load();
protected boolean canLoad() {
return (mCanLoadHint && isVisible() && getUserVisibleHint());
}
protected void loadIfVisible() {
if (!mCanLoadHint || !isVisible() || !getUserVisibleHint()) {
if (!canLoad() || mIsLoaded) {
return;
}
if (!mIsLoaded) {
load();
mIsLoaded = true;
}
}
private static class RemoveBookmarkTask extends UiAsyncTask<Void, Void, Void> {
private final Context mContext;

Просмотреть файл

@ -0,0 +1,81 @@
/* -*- 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.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.util.Log;
/**
* Cache used to store authentication state of dynamic panels. The values
* in this cache are set in JS through the Home.panels API.
*
* {@code DynamicPanel} uses this cache to determine whether or not to
* show authentication UI for dynamic panels, including listening for
* changes in authentication state.
*/
class PanelAuthCache {
private static final String LOGTAG = "GeckoPanelAuthCache";
// Keep this in sync with the constant defined in Home.jsm
private static final String PREFS_PANEL_AUTH_PREFIX = "home_panels_auth_";
private final Context mContext;
private SharedPrefsListener mSharedPrefsListener;
private OnChangeListener mChangeListener;
public interface OnChangeListener {
public void onChange(String panelId, boolean isAuthenticated);
}
public PanelAuthCache(Context context) {
mContext = context;
}
private SharedPreferences getSharedPreferences() {
return PreferenceManager.getDefaultSharedPreferences(mContext);
}
private String getPanelAuthKey(String panelId) {
return PREFS_PANEL_AUTH_PREFIX + panelId;
}
public boolean isAuthenticated(String panelId) {
final SharedPreferences prefs = getSharedPreferences();
return prefs.getBoolean(getPanelAuthKey(panelId), false);
}
public void setOnChangeListener(OnChangeListener listener) {
final SharedPreferences prefs = getSharedPreferences();
if (mChangeListener != null) {
prefs.unregisterOnSharedPreferenceChangeListener(mSharedPrefsListener);
mSharedPrefsListener = null;
}
mChangeListener = listener;
if (mChangeListener != null) {
mSharedPrefsListener = new SharedPrefsListener();
prefs.registerOnSharedPreferenceChangeListener(mSharedPrefsListener);
}
}
private class SharedPrefsListener implements OnSharedPreferenceChangeListener {
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.startsWith(PREFS_PANEL_AUTH_PREFIX)) {
final String panelId = key.substring(PREFS_PANEL_AUTH_PREFIX.length());
final boolean isAuthenticated = prefs.getBoolean(key, false);
Log.d(LOGTAG, "Auth state changed: panelId=" + panelId + ", isAuthenticated=" + isAuthenticated);
mChangeListener.onChange(panelId, isAuthenticated);
}
}
}
}

Просмотреть файл

@ -248,6 +248,7 @@ gbjar.sources += [
'home/LastTabsPanel.java',
'home/MostRecentPanel.java',
'home/MultiTypeCursorAdapter.java',
'home/PanelAuthCache.java',
'home/PanelAuthLayout.java',
'home/PanelBackItemView.java',
'home/PanelGridView.java',

Просмотреть файл

@ -13,6 +13,9 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/SharedPreferences.jsm");
Cu.import("resource://gre/modules/Messaging.jsm");
// Keep this in sync with the constant defined in PanelAuthCache.java
const PREFS_PANEL_AUTH_PREFIX = "home_panels_auth_";
// See bug 915424
function resolveGeckoURI(aURI) {
if (!aURI)
@ -363,6 +366,14 @@ let HomePanels = (function () {
type: "HomePanels:Update",
panel: _generatePanel(id)
});
},
setAuthenticated: function(id, isAuthenticated) {
_assertPanelExists(id);
let authKey = PREFS_PANEL_AUTH_PREFIX + id;
let sharedPrefs = new SharedPreferences();
sharedPrefs.setBoolPref(authKey, isAuthenticated);
}
});
})();