Security and Privacy UI

- new panel for site specific settings
- hooked up favicon to site settings
- new images for security icons
- revamped settings panels to match the new
  ui layouts

Change-Id: I1e872ce353e66f78e2b0530901fcbb7de69e28b4
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index 2d7c0b3..c12b581 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -733,7 +733,7 @@
             // See http://b/5403800
             d = getLockIconMixed();
         }
-        mNavigationBar.setLock(d);
+        mNavigationBar.setLock(d, securityState);
     }
 
     protected void setUrlTitle(Tab tab) {
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 4a138c1..eb36023 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -26,11 +26,9 @@
 import android.os.Build;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
-import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.webkit.WebStorage;
 
-import com.android.browser.R;
 import com.android.browser.homepages.HomeProvider;
 import com.android.browser.mdm.DoNotTrackRestriction;
 import com.android.browser.mdm.ProxyRestriction;
@@ -43,16 +41,14 @@
 import java.lang.ref.WeakReference;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.WeakHashMap;
 
 import org.codeaurora.swe.AutoFillProfile;
 import org.codeaurora.swe.CookieManager;
 import org.codeaurora.swe.GeolocationPermissions;
+import org.codeaurora.swe.PermissionsServiceFactory;
 import org.codeaurora.swe.WebRefiner;
 import org.codeaurora.swe.WebSettings.LayoutAlgorithm;
-import org.codeaurora.swe.WebSettings.PluginState;
 import org.codeaurora.swe.WebSettings.TextSize;
-import org.codeaurora.swe.WebSettings.ZoomDensity;
 import org.codeaurora.swe.WebSettings;
 import org.codeaurora.swe.WebView;
 import org.codeaurora.swe.WebViewDatabase;
@@ -385,9 +381,6 @@
             }
         } else if (PREF_LINK_PREFETCH.equals(key)) {
             updateConnectionType();
-        } else if (PREF_WEB_REFINER_ENABLED.equals(key)) {
-            if (WebRefiner.isInitialized())
-                WebRefiner.getInstance().setRulesEnabled(WebRefiner.CATEGORY_ALL, isWebRefinerEnabled());
         }
     }
 
@@ -755,7 +748,7 @@
     }
 
     public boolean blockPopupWindows() {
-        return mPrefs.getBoolean(PREF_BLOCK_POPUP_WINDOWS, true);
+        return !mPrefs.getBoolean(PREF_POPUP_WINDOWS, false);
     }
 
     public boolean loadImages() {
@@ -814,14 +807,6 @@
         mPrefs.edit().putBoolean(PREF_POWERSAVE_ENABLED, value).apply();
     }
 
-    public boolean isWebRefinerEnabled() {
-        return mPrefs.getBoolean(PREF_WEB_REFINER_ENABLED, true);
-    }
-
-    public void setWebRefinerEnabled(boolean value) {
-        mPrefs.edit().putBoolean(PREF_WEB_REFINER_ENABLED, value).apply();
-    }
-
     public boolean isNightModeEnabled() {
         return mPrefs.getBoolean(PREF_NIGHTMODE_ENABLED, false);
     }
@@ -955,7 +940,8 @@
     }
 
     public boolean acceptCookies() {
-        return mPrefs.getBoolean(PREF_ACCEPT_COOKIES, true);
+        return PermissionsServiceFactory.getDefaultPermissions(
+                PermissionsServiceFactory.PermissionType.COOKIE);
     }
 
     public boolean saveFormdata() {
diff --git a/src/com/android/browser/BrowserYesNoPreference.java b/src/com/android/browser/BrowserYesNoPreference.java
index 6fdde2c..f47ff3d 100644
--- a/src/com/android/browser/BrowserYesNoPreference.java
+++ b/src/com/android/browser/BrowserYesNoPreference.java
@@ -25,6 +25,8 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
 
 class BrowserYesNoPreference extends DialogPreference {
     private SharedPreferences mPrefs;
@@ -38,6 +40,31 @@
     }
 
     @Override
+    protected View onCreateView(ViewGroup group) {
+        View child = super.onCreateView(group);
+        View titleView = child.findViewById(android.R.id.title);
+        if (titleView instanceof Button) {
+            Button btn = (Button) titleView;
+            final BrowserYesNoPreference pref = this;
+            btn.setOnClickListener(
+                    new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            pref.onClick();
+                        }
+                    }
+            );
+        }
+
+        return child;
+    }
+
+    @Override
+    protected void onClick() {
+        super.onClick();
+    }
+
+    @Override
     protected View onCreateDialogView() {
         if (PreferenceKeys.PREF_CLEAR_SELECTED_DATA.equals(getKey())) {
             String dialogMessage = mContext.getString(R.string.pref_privacy_clear_selected_dlg);
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 2f8db52..3f5319a 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -88,14 +88,14 @@
 import org.codeaurora.swe.CookieSyncManager;
 import org.codeaurora.swe.Engine;
 import org.codeaurora.swe.HttpAuthHandler;
+import org.codeaurora.swe.PermissionsServiceFactory;
 import org.codeaurora.swe.SslErrorHandler;
+import org.codeaurora.swe.WebRefiner;
 import org.codeaurora.swe.WebSettings;
 import org.codeaurora.swe.WebView;
 import org.codeaurora.swe.WebBackForwardList;
 import org.codeaurora.swe.WebHistoryItem;
 
-import com.android.browser.AppAdapter;
-import com.android.browser.R;
 import com.android.browser.IntentHandler.UrlData;
 import com.android.browser.UI.ComboViews;
 import com.android.browser.mdm.EditBookmarksRestriction;
@@ -127,6 +127,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Controller for browser
@@ -296,6 +297,45 @@
         mNetworkHandler = new NetworkStateHandler(mActivity, this);
         mHomepageHandler = new HomepageHandler(browser, this);
         mAppMenuHandler = new AppMenuHandler(browser, this, R.menu.browser);
+
+        final WebRefiner refiner = WebRefiner.getInstance();
+        if (refiner != null) {
+            refiner.setRulesEnabled(WebRefiner.CATEGORY_ALL,
+                    !PermissionsServiceFactory.getDefaultPermissions(
+                            PermissionsServiceFactory.PermissionType.WEBREFINER));
+
+            PermissionsServiceFactory.getPermissionsService(
+                    new ValueCallback<PermissionsServiceFactory.PermissionsService>() {
+                        @Override
+                        public void onReceiveValue(
+                                PermissionsServiceFactory.PermissionsService value) {
+                            Set<String> origins = value.getOrigins();
+                            ArrayList<String> allowList = new ArrayList<>();
+                            ArrayList<String> blockList = new ArrayList<>();
+                            for (String origin : origins) {
+                                PermissionsServiceFactory.PermissionsService.OriginInfo
+                                        info = value.getOriginInfo(origin);
+                                int perm = info.getPermission(
+                                        PermissionsServiceFactory.PermissionType.WEBREFINER);
+                                if (perm == PermissionsServiceFactory.Permission.ALLOW) {
+                                    allowList.add(origin);
+                                } else if (perm == PermissionsServiceFactory.Permission.BLOCK) {
+                                    blockList.add(origin);
+                                }
+                            }
+                            if (!allowList.isEmpty()) {
+                                refiner.enableRulesForDomains(WebRefiner.CATEGORY_ALL,
+                                        allowList.toArray(new String[allowList.size()]));
+                            }
+
+                            if (!blockList.isEmpty()) {
+                                refiner.disableRulesForDomains(WebRefiner.CATEGORY_ALL,
+                                        blockList.toArray(new String[blockList.size()]));
+                            }
+                        }
+                    }
+            );
+        }
     }
 
     @Override
diff --git a/src/com/android/browser/NavigationBarBase.java b/src/com/android/browser/NavigationBarBase.java
index ebeae65..753e362 100644
--- a/src/com/android/browser/NavigationBarBase.java
+++ b/src/com/android/browser/NavigationBarBase.java
@@ -15,14 +15,21 @@
  */
 package com.android.browser;
 
+import android.animation.ArgbEvaluator;
+import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.app.SearchManager;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.net.http.SslCertificate;
+import android.net.http.SslError;
+import android.os.Build;
 import android.os.Bundle;
 import android.text.Editable;
 import android.text.TextWatcher;
@@ -40,14 +47,19 @@
 import android.widget.PopupMenu;
 import android.widget.Toast;
 
-import com.android.browser.R;
 import com.android.browser.UrlInputView.UrlInputListener;
+import com.android.browser.preferences.SiteSpecificPreferencesFragment;
 
+import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
 import java.net.URISyntaxException;
+import java.net.URL;
 
 import org.codeaurora.swe.Engine;
+import org.codeaurora.swe.WebRefiner;
 import org.codeaurora.swe.WebView;
+import org.codeaurora.swe.util.ColorUtils;
 
 public class NavigationBarBase extends LinearLayout implements
         OnClickListener, UrlInputListener, OnFocusChangeListener,
@@ -61,6 +73,8 @@
     protected UiController mUiController;
     protected UrlInputView mUrlInput;
 
+    protected ImageView mFaviconBadge;
+
     private ImageView mFavicon;
     private ImageView mLockIcon;
 
@@ -69,6 +83,11 @@
     private boolean mOverflowMenuShowing;
     private boolean mNeedsMenu;
 
+    private int mStatusBarColor;
+    private static int mDefaultStatusBarColor = -1;
+
+    private Tab.SecurityState mSecurityState = Tab.SecurityState.SECURITY_STATE_NOT_SECURE;
+
     public NavigationBarBase(Context context) {
         super(context);
     }
@@ -94,6 +113,7 @@
         mMore = findViewById(R.id.more_browser_settings);
         mMore.setOnClickListener(this);
         mNeedsMenu = !ViewConfiguration.get(getContext()).hasPermanentMenuKey();
+        mFaviconBadge = (ImageView) findViewById(R.id.favicon_badge);
     }
 
     public void setTitleBar(TitleBar titleBar) {
@@ -103,7 +123,22 @@
         mUrlInput.setController(mUiController);
     }
 
-    public void setLock(Drawable d) {
+    public void setLock(Drawable d, Tab.SecurityState securityState) {
+        mSecurityState = securityState;
+        switch (mSecurityState) {
+            case SECURITY_STATE_SECURE:
+                mFaviconBadge.setImageResource(R.drawable.ic_fav_overlay_good);
+                break;
+            case SECURITY_STATE_MIXED:
+                mFaviconBadge.setImageResource(R.drawable.ic_fav_overlay_warning);
+                break;
+            case SECURITY_STATE_BAD_CERTIFICATE:
+                mFaviconBadge.setImageResource(R.drawable.ic_fav_overlay_severe);
+                break;
+            case SECURITY_STATE_NOT_SECURE:
+            default:
+                mFaviconBadge.setImageResource(R.drawable.ic_fav_overlay_normal);
+        }
         if (mLockIcon == null) return;
         if (d == null) {
             mLockIcon.setVisibility(View.GONE);
@@ -113,11 +148,157 @@
         }
     }
 
+    public static int adjustColor(int color, float hueMultiplier,
+                                   float saturationMultiplier, float valueMultiplier) {
+        float[] hsv = new float[3];
+        Color.colorToHSV(color, hsv);
+        hsv[0] *= hueMultiplier;
+        hsv[1] *= saturationMultiplier;
+        hsv[2] *= valueMultiplier;
+        return Color.HSVToColor(Color.alpha(color), hsv);
+    }
+
+    public static void setStatusAndNavigationBarColor(final Activity activity, int color) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            int currentColor = activity.getWindow().getStatusBarColor();
+            Integer from = currentColor;
+            Integer to = color;
+            ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
+
+            if (mDefaultStatusBarColor == -1) {
+                mDefaultStatusBarColor = activity.getWindow().getStatusBarColor();
+            }
+
+            animator.addUpdateListener(
+                    new ValueAnimator.AnimatorUpdateListener() {
+                        @Override
+                        public void onAnimationUpdate(ValueAnimator animation) {
+                            Integer value = (Integer) animation.getAnimatedValue();
+                            activity.getWindow().setStatusBarColor(value.intValue());
+                            //activity.getWindow().setNavigationBarColor(value.intValue());
+                        }
+                    }
+            );
+            animator.start();
+        }
+    }
+
+    private void updateSiteIconColor(String urlString, int color) {
+        try {
+            URL url = new URL(urlString);
+            String host = url.getHost();
+            SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
+            int currentColor = prefs.getInt(host + ":color", 0);
+            if (currentColor != color) {
+                SharedPreferences.Editor editor = prefs.edit();
+                editor.remove(host + ":color");
+                editor.putInt(host + ":color", color);
+                editor.commit();
+            }
+        } catch (MalformedURLException e) {
+        }
+    }
+
+    public static int getSiteIconColor(String urlString) {
+        try {
+            URL url = new URL(urlString);
+            String host = url.getHost();
+            SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
+            return prefs.getInt(host + ":color", 0);
+        } catch (MalformedURLException e) {
+            return 0;
+        }
+    }
+
+    public static int getDefaultStatusBarColor() {
+        return mDefaultStatusBarColor;
+    }
+
     public void setFavicon(Bitmap icon) {
+        int color = ColorUtils.getDominantColorForBitmap(icon);
+        Tab tab = mUiController.getCurrentTab();
+
+        if (tab != null) {
+            if (tab.hasFavicon()) {
+                updateSiteIconColor(tab.getUrl(), color);
+                setStatusAndNavigationBarColor(mUiController.getActivity(),
+                        adjustColor(color, 1, 1, 0.7f));
+            } else {
+                color = getSiteIconColor(tab.getUrl());
+                if (color != 0) {
+                    setStatusAndNavigationBarColor(mUiController.getActivity(),
+                            adjustColor(color, 1, 1, 0.7f));
+                } else {
+                    setStatusAndNavigationBarColor(mUiController.getActivity(),
+                            mDefaultStatusBarColor);
+                }
+            }
+        } else {
+            setStatusAndNavigationBarColor(mUiController.getActivity(), mDefaultStatusBarColor);
+        }
+
         if (mFavicon == null) return;
         mFavicon.setImageDrawable(mBaseUi.getFaviconDrawable(icon));
     }
 
+    protected void showSiteSpecificSettings() {
+        WebView wv = mUiController.getCurrentTopWebView();
+        int count = 0;
+
+        if (wv != null && WebRefiner.getInstance() != null) {
+            count = WebRefiner.getInstance().getBlockedURLCount(wv);
+        }
+
+        Bundle bundle = new Bundle();
+        bundle.putCharSequence(SiteSpecificPreferencesFragment.EXTRA_SITE,
+                mUiController.getCurrentTab().getUrl());
+        bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_INFO, count);
+
+        bundle.putParcelable(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT,
+                SslCertificate.saveState(wv.getCertificate()));
+
+        SslError error = mUiController.getCurrentTab().getSslCertificateError();
+        if (error != null) {
+            int certError = 0;
+            if (error.hasError(SslError.SSL_DATE_INVALID)) {
+                certError |= (1 << SslError.SSL_DATE_INVALID);
+            }
+
+            if (error.hasError(SslError.SSL_EXPIRED)) {
+                certError |= (1 << SslError.SSL_EXPIRED);
+            }
+
+            if (error.hasError(SslError.SSL_IDMISMATCH)) {
+                certError |= (1 << SslError.SSL_IDMISMATCH);
+            }
+
+            if (error.hasError(SslError.SSL_INVALID)) {
+                certError |= (1 << SslError.SSL_INVALID);
+            }
+
+            if (error.hasError(SslError.SSL_NOTYETVALID)) {
+                certError |= (1 << SslError.SSL_NOTYETVALID);
+            }
+
+            if (error.hasError(SslError.SSL_UNTRUSTED)) {
+                certError |= (1 << SslError.SSL_UNTRUSTED);
+            }
+
+            bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_ERR, certError);
+        }
+
+        Bitmap favicon = mUiController.getCurrentTab().getFavicon();
+        if (favicon != null) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            favicon.compress(Bitmap.CompressFormat.PNG, 50, baos);
+            bundle.putByteArray(SiteSpecificPreferencesFragment.EXTRA_FAVICON,
+                    baos.toByteArray());
+        }
+        BrowserPreferencesPage.startPreferenceFragmentExtraForResult(
+                mUiController.getActivity(),
+                SiteSpecificPreferencesFragment.class.getName(), bundle, 0);
+    }
+
     @Override
     public void onClick(View v) {
         if (mMore == v) {
@@ -422,6 +603,8 @@
     }
 
     public void onProgressStarted() {
+        mFaviconBadge.setImageResource(R.drawable.ic_fav_overlay_normal);
+        mSecurityState = Tab.SecurityState.SECURITY_STATE_NOT_SECURE;
     }
 
     public void onProgressStopped() {
diff --git a/src/com/android/browser/NavigationBarPhone.java b/src/com/android/browser/NavigationBarPhone.java
index cb6f7fc..e5f76ff 100644
--- a/src/com/android/browser/NavigationBarPhone.java
+++ b/src/com/android/browser/NavigationBarPhone.java
@@ -17,13 +17,16 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.View;
 
+import org.codeaurora.swe.Engine;
 import org.codeaurora.swe.WebRefiner;
 import org.codeaurora.swe.WebView;
 import org.codeaurora.swe.util.Activator;
@@ -32,6 +35,10 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.browser.UrlInputView.StateListener;
+import com.android.browser.preferences.AboutPreferencesFragment;
+import com.android.browser.preferences.SiteSpecificPreferencesFragment;
+
+import java.io.ByteArrayOutputStream;
 
 public class NavigationBarPhone extends NavigationBarBase implements
         StateListener {
@@ -149,6 +156,7 @@
                 mStopButton.setVisibility(View.VISIBLE);
             }
         }*/
+        mFaviconBadge.setImageResource(R.drawable.ic_fav_overlay_normal);
         mNotificationCounter.setVisibility(View.INVISIBLE);
         mHandler.removeMessages(MSG_UPDATE_NOTIFICATION_COUNTER);
         mHandler.sendEmptyMessageDelayed(MSG_UPDATE_NOTIFICATION_COUNTER, NOTIFICATION_COUNTER_UPDATE_DELAY);
@@ -207,7 +215,7 @@
         } else if (mClearButton == v) {
             mUrlInput.setText("");
         } else if (mComboIcon == v) {
-            mUiController.showPageInfo();
+            showSiteSpecificSettings();
         } else if (mVoiceButton == v) {
             mUiController.startVoiceRecognizer();
         } else {
diff --git a/src/com/android/browser/NavigationBarTablet.java b/src/com/android/browser/NavigationBarTablet.java
index 31edce9..c6c88cd 100644
--- a/src/com/android/browser/NavigationBarTablet.java
+++ b/src/com/android/browser/NavigationBarTablet.java
@@ -25,6 +25,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
@@ -33,6 +34,12 @@
 
 import com.android.browser.UI.ComboViews;
 import com.android.browser.UrlInputView.StateListener;
+import com.android.browser.preferences.SiteSpecificPreferencesFragment;
+
+import org.codeaurora.swe.WebRefiner;
+import org.codeaurora.swe.WebView;
+
+import java.io.ByteArrayOutputStream;
 
 public class NavigationBarTablet extends NavigationBarBase implements StateListener {
 
@@ -105,6 +112,7 @@
         mVoiceButton.setOnClickListener(this);
         mUrlInput.setContainer(mUrlContainer);
         mUrlInput.setStateListener(this);
+        mUrlIcon.setOnClickListener(this);
     }
 
     public void onConfigurationChanged(Configuration config) {
@@ -171,6 +179,8 @@
             clearOrClose();
         } else if (mVoiceButton == v) {
             mUiController.startVoiceRecognizer();
+        } else if (mUrlIcon == v) {
+            showSiteSpecificSettings();
         } else {
             super.onClick(v);
         }
@@ -188,6 +198,7 @@
 
     @Override
     public void setFavicon(Bitmap icon) {
+        super.setFavicon(icon);
         mFaviconDrawable = mBaseUi.getFaviconDrawable(icon);
         updateUrlIcon();
     }
diff --git a/src/com/android/browser/PageDialogsHandler.java b/src/com/android/browser/PageDialogsHandler.java
index b92add9..af54000 100644
--- a/src/com/android/browser/PageDialogsHandler.java
+++ b/src/com/android/browser/PageDialogsHandler.java
@@ -353,23 +353,17 @@
         return (View)ReflectHelper.invokeMethod(certificate, "inflateCertificateView",type, params);
     }
 
-    /*
-     * Creates an AlertDialog to display the given certificate. If error is
-     * null, text is added to state that the certificae is valid and the icon
-     * is set accordingly. If error is non-null, it must relate to the supplied
-     * certificate. In this case, error is used to add text describing the
-     * problems with the certificate and a different icon is used.
-     */
-    private AlertDialog.Builder createSslCertificateDialog(SslCertificate certificate,
-            SslError error) {
-        View certificateView = inflateCertificateView(certificate, mContext);
+    public static AlertDialog.Builder createSslCertificateDialog(Context ctx,
+                                                                 SslCertificate certificate,
+                                                                 SslError error) {
+        View certificateView = inflateCertificateView(certificate, ctx);
         Resources res = Resources.getSystem();
         // load 'android.R.placeholder' via introspection, since it's not a public resource ID
         int placeholder_id = res.getIdentifier("placeholder", "id", "android");
         final LinearLayout placeholder =
                 (LinearLayout)certificateView.findViewById(placeholder_id);
 
-        LayoutInflater factory = LayoutInflater.from(mContext);
+        LayoutInflater factory = LayoutInflater.from(ctx);
         int iconId;
 
         if (error == null) {
@@ -407,13 +401,25 @@
             }
         }
 
-        return new AlertDialog.Builder(mContext)
+        return new AlertDialog.Builder(ctx)
                 .setTitle(R.string.ssl_certificate)
                 .setIcon(iconId)
                 .setView(certificateView);
     }
 
-    private void addError(LayoutInflater inflater, LinearLayout parent, int error) {
+    /*
+     * Creates an AlertDialog to display the given certificate. If error is
+     * null, text is added to state that the certificae is valid and the icon
+     * is set accordingly. If error is non-null, it must relate to the supplied
+     * certificate. In this case, error is used to add text describing the
+     * problems with the certificate and a different icon is used.
+     */
+    private AlertDialog.Builder createSslCertificateDialog(SslCertificate certificate,
+            SslError error) {
+        return createSslCertificateDialog(mContext, certificate, error);
+    }
+
+    private static void addError(LayoutInflater inflater, LinearLayout parent, int error) {
         TextView textView = (TextView) inflater.inflate(R.layout.ssl_warning,
                 parent, false);
         textView.setText(error);
diff --git a/src/com/android/browser/PreferenceKeys.java b/src/com/android/browser/PreferenceKeys.java
index 951a658..7c7c286 100644
--- a/src/com/android/browser/PreferenceKeys.java
+++ b/src/com/android/browser/PreferenceKeys.java
@@ -36,7 +36,7 @@
     // Keys for advanced_preferences.xml
     // ----------------------
     static final String PREF_AUTOFIT_PAGES = "autofit_pages";
-    static final String PREF_BLOCK_POPUP_WINDOWS = "block_popup_windows";
+    static final String PREF_POPUP_WINDOWS = "popup_windows";
     static final String PREF_DEFAULT_TEXT_ENCODING = "default_text_encoding";
     static final String PREF_ENABLE_JAVASCRIPT = "enable_javascript";
     static final String PREF_ENABLE_MEMORY_MONITOR = "enable_memory_monitor";
@@ -59,7 +59,6 @@
     // ----------------------
     static final String PREF_AUTOFILL_ENABLED = "autofill_enabled";
     static final String PREF_AUTOFILL_PROFILE = "autofill_profile";
-    static final String PREF_WEB_REFINER_ENABLED = "web_refiner_enabled";
     static final String PREF_HOMEPAGE = "homepage";
     static final String PREF_POWERSAVE_ENABLED = "powersave_enabled";
     static final String PREF_NIGHTMODE_ENABLED = "nightmode_enabled";
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 99d57a8..a7157d0 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -1726,6 +1726,10 @@
         return getDefaultFavicon(mContext);
     }
 
+    public boolean hasFavicon() {
+        return mCurrentState.mFavicon != null;
+    }
+
     public boolean isBookmarkedSite() {
         return mCurrentState.mIsBookmarkedSite;
     }
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index ec62a23..addbf72 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.graphics.drawable.PaintDrawable;
@@ -36,6 +37,7 @@
 import android.webkit.WebChromeClient;
 
 import org.codeaurora.swe.WebView;
+import org.codeaurora.swe.util.ColorUtils;
 
 import com.android.browser.R;
 
@@ -266,6 +268,13 @@
     public void setFavicon(Tab tab) {
         super.setFavicon(tab);
         mTabBar.onFavicon(tab, tab.getFavicon());
+        if (mActiveTab == tab) {
+            int color = NavigationBarBase.getSiteIconColor(tab.getUrl());
+            if (tab.hasFavicon()) {
+                color = ColorUtils.getDominantColorForBitmap(tab.getFavicon());
+            }
+            mActionBar.setBackgroundDrawable(new ColorDrawable(color));
+        }
     }
 
     @Override
diff --git a/src/com/android/browser/mdm/MdmCheckBoxPreference.java b/src/com/android/browser/mdm/MdmCheckBoxPreference.java
index c235d52..91f9e03 100644
--- a/src/com/android/browser/mdm/MdmCheckBoxPreference.java
+++ b/src/com/android/browser/mdm/MdmCheckBoxPreference.java
@@ -32,6 +32,7 @@
 import android.content.Context;
 import android.preference.CheckBoxPreference;
 import android.preference.Preference;
+import android.preference.SwitchPreference;
 import android.util.AttributeSet;
 //import android.util.Log;
 import android.view.View;
@@ -39,7 +40,7 @@
 
 import com.android.browser.R;
 
-public class MdmCheckBoxPreference extends CheckBoxPreference {
+public class MdmCheckBoxPreference extends SwitchPreference {
 
     View mView = null;
     OnPreferenceClickListener mOrigClickListener = null;
diff --git a/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java b/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java
index 46fdd42..a505836 100644
--- a/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java
+++ b/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java
@@ -18,10 +18,8 @@
 
 import android.app.ActionBar;
 import android.content.Context;
-import android.content.res.Resources;
 import android.os.Bundle;
 import android.preference.Preference;
-import android.preference.PreferenceFragment;
 import android.util.Log;
 
 import com.android.browser.BrowserSettings;
@@ -30,7 +28,7 @@
 
 import java.text.NumberFormat;
 
-public class AccessibilityPreferencesFragment extends PreferenceFragment
+public class AccessibilityPreferencesFragment extends SWEPreferenceFragment
         implements Preference.OnPreferenceChangeListener {
 
     NumberFormat mFormat;
diff --git a/src/com/android/browser/preferences/AdvancedPreferencesFragment.java b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
index 9853128..3641380 100644
--- a/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
+++ b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
@@ -21,7 +21,6 @@
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.content.Intent;
-import android.content.res.Resources;
 import android.content.SharedPreferences.Editor;
 import android.net.Uri;
 import android.preference.ListPreference;
@@ -30,38 +29,21 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 import android.util.Log;
-import android.webkit.ValueCallback;
-import android.widget.Toast;
-import android.text.TextUtils;
 
 import com.android.browser.BrowserActivity;
-import com.android.browser.BrowserConfig;
 import com.android.browser.BrowserSettings;
 import com.android.browser.DownloadHandler;
 import com.android.browser.PreferenceKeys;
 import com.android.browser.R;
 
-import java.util.Map;
-import java.util.Set;
-import org.codeaurora.swe.GeolocationPermissions;
-import org.codeaurora.swe.WebStorage;
-
 public class AdvancedPreferencesFragment
         implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
 
-    private static final int DOWNLOAD_PATH_RESULT_CODE = 1;
-    private final static String LOGTAG = "AdvancedPreferencesFragment";
-
     PreferenceFragment mFragment = null;
 
     AdvancedPreferencesFragment(PreferenceFragment fragment) {
         mFragment = fragment;
 
-        PreferenceScreen websiteSettings = (PreferenceScreen) mFragment.findPreference(
-                PreferenceKeys.PREF_WEBSITE_SETTINGS);
-        websiteSettings.setFragment(WebsiteSettingsFragment.class.getName());
-        websiteSettings.setOnPreferenceClickListener(this);
-
         Preference e = mFragment.findPreference(PreferenceKeys.PREF_RESET_DEFAULT_PREFERENCES);
         e.setOnPreferenceChangeListener(this);
 
@@ -69,6 +51,9 @@
         e.setOnPreferenceChangeListener(this);
         updateListPreferenceSummary((ListPreference) e);
 
+        e = mFragment.findPreference("privacy_security");
+        e.setOnPreferenceClickListener(this);
+
         e = mFragment.findPreference(PreferenceKeys.PREF_DEBUG_MENU);
         if (!BrowserSettings.getInstance().isDebugEnabled()) {
             PreferenceCategory category = (PreferenceCategory) mFragment.findPreference("advanced");
@@ -83,23 +68,7 @@
         // Below are preferences for carrier specific features
         PreferenceScreen contentSettingsPrefScreen =
                 (PreferenceScreen) mFragment.findPreference("content_settings");
-
-        if (!BrowserConfig.getInstance(mFragment.getActivity().getApplicationContext())
-                .hasFeature(BrowserConfig.Feature.CUSTOM_DOWNLOAD_PATH)) {
-            contentSettingsPrefScreen.removePreference(contentSettingsPrefScreen
-                    .findPreference(PreferenceKeys.PREF_DOWNLOAD_PATH));
-        } else {
-            PreferenceScreen downloadPathPreset =
-                    (PreferenceScreen) mFragment.findPreference(PreferenceKeys.PREF_DOWNLOAD_PATH);
-            downloadPathPreset.setOnPreferenceClickListener(onClickDownloadPathSettings());
-
-            String downloadPath = downloadPathPreset.getSharedPreferences().
-                    getString(PreferenceKeys.PREF_DOWNLOAD_PATH,
-                            BrowserSettings.getInstance().getDownloadPath());
-            String downloadPathForUser = DownloadHandler.getDownloadPathForUser(mFragment.getActivity(),
-                    downloadPath);
-            downloadPathPreset.setSummary(downloadPathForUser);
-        }
+        contentSettingsPrefScreen.setOnPreferenceClickListener(this);
 
         ListPreference edgeSwipePref =
                 (ListPreference) mFragment.findPreference("edge_swiping_action");
@@ -117,33 +86,8 @@
         }
     }
 
-    private Preference.OnPreferenceClickListener onClickDownloadPathSettings() {
-        return new Preference.OnPreferenceClickListener() {
-            public boolean onPreferenceClick(Preference preference) {
-                final String filemanagerIntent =
-                        mFragment.getResources().getString(R.string.def_intent_file_manager);
-                if (!TextUtils.isEmpty(filemanagerIntent)) {
-                    try {
-                        Intent i = new Intent(filemanagerIntent);
-                        mFragment.startActivityForResult(i,
-                                DOWNLOAD_PATH_RESULT_CODE);
-                    } catch (Exception e) {
-                        String err_msg = mFragment.getResources().getString(
-                                R.string.activity_not_found,
-                                filemanagerIntent);
-                        Toast.makeText(mFragment.getActivity(), err_msg, Toast.LENGTH_LONG).show();
-                    }
-                    return true;
-                } else {
-                    Log.e(LOGTAG, "File Manager intent not defined !!");
-                    return true;
-                }
-            }
-        };
-    }
-
     public void onActivityResult(int requestCode, int resultCode, Intent intent) {
-        if (requestCode == DOWNLOAD_PATH_RESULT_CODE) {
+        if (requestCode == ContentPreferencesFragment.DOWNLOAD_PATH_RESULT_CODE) {
             if ( resultCode == Activity.RESULT_OK && intent != null) {
                 final String result_dir_sel =
                     mFragment.getResources().getString(R.string.def_file_manager_result_dir);
@@ -182,25 +126,6 @@
      * changed after calling the WebsiteSettingsActivity.
      */
     public void onResume() {
-        final PreferenceScreen websiteSettings = (PreferenceScreen) mFragment.findPreference(
-                PreferenceKeys.PREF_WEBSITE_SETTINGS);
-        websiteSettings.setEnabled(false);
-        WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
-            @Override
-            public void onReceiveValue(Map webStorageOrigins) {
-                if ((webStorageOrigins != null) && !webStorageOrigins.isEmpty()) {
-                    websiteSettings.setEnabled(true);
-                }
-            }
-        });
-        GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() {
-            @Override
-            public void onReceiveValue(Set<String> geolocationOrigins) {
-                if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) {
-                    websiteSettings.setEnabled(true);
-                }
-            }
-        });
     }
 
     @Override
@@ -232,15 +157,7 @@
     public boolean onPreferenceClick(Preference preference) {
         FragmentManager fragmentManager = mFragment.getFragmentManager();
 
-        if (preference.getKey().equals(PreferenceKeys.PREF_WEBSITE_SETTINGS)) {
-            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
-
-            Fragment newFragment = new WebsiteSettingsFragment();
-            fragmentTransaction.replace(mFragment.getId(), newFragment);
-            fragmentTransaction.addToBackStack(null);
-            fragmentTransaction.commit();
-            return true;
-        } else if (preference.getKey().equals(PreferenceKeys.PREF_DEBUG_MENU)) {
+        if (preference.getKey().equals(PreferenceKeys.PREF_DEBUG_MENU)) {
             FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
 
             Fragment newFragment = new DebugPreferencesFragment();
@@ -256,8 +173,23 @@
             fragmentTransaction.addToBackStack(null);
             fragmentTransaction.commit();
             return true;
-        }
+        } else if (preference.getKey().equals("privacy_security")) {
+            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
 
+            Fragment newFragment = new PrivacySecurityPreferencesFragment();
+            fragmentTransaction.replace(mFragment.getId(), newFragment);
+            fragmentTransaction.addToBackStack(null);
+            fragmentTransaction.commit();
+            return true;
+        } else if (preference.getKey().equals("content_settings")) {
+            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+            Fragment newFragment = new ContentPreferencesFragment();
+            fragmentTransaction.replace(mFragment.getId(), newFragment);
+            fragmentTransaction.addToBackStack(null);
+            fragmentTransaction.commit();
+            return true;
+        }
         return false;
     }
 }
diff --git a/src/com/android/browser/preferences/ContentPreferencesFragment.java b/src/com/android/browser/preferences/ContentPreferencesFragment.java
new file mode 100644
index 0000000..63bae5b
--- /dev/null
+++ b/src/com/android/browser/preferences/ContentPreferencesFragment.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.android.browser.preferences;
+
+import android.app.ActionBar;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.browser.BrowserConfig;
+import com.android.browser.BrowserSettings;
+import com.android.browser.DownloadHandler;
+import com.android.browser.PreferenceKeys;
+import com.android.browser.R;
+
+public class ContentPreferencesFragment extends SWEPreferenceFragment {
+    public static final int DOWNLOAD_PATH_RESULT_CODE = 1;
+    private final static String LOGTAG = "ContentPreferences";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Load the XML preferences file
+        addPreferencesFromResource(R.xml.content_preferences);
+
+        PreferenceScreen screen = (PreferenceScreen) findPreference("content_settings");
+
+        if (!BrowserConfig.getInstance(getActivity().getApplicationContext())
+                .hasFeature(BrowserConfig.Feature.CUSTOM_DOWNLOAD_PATH)) {
+            screen.removePreference(findPreference(PreferenceKeys.PREF_DOWNLOAD_PATH));
+        } else {
+            PreferenceScreen downloadPathPreset =
+                    (PreferenceScreen) findPreference(PreferenceKeys.PREF_DOWNLOAD_PATH);
+            downloadPathPreset.setOnPreferenceClickListener(onClickDownloadPathSettings());
+
+            String downloadPath = downloadPathPreset.getSharedPreferences().
+                    getString(PreferenceKeys.PREF_DOWNLOAD_PATH,
+                            BrowserSettings.getInstance().getDownloadPath());
+            String downloadPathForUser = DownloadHandler.getDownloadPathForUser(getActivity(),
+                    downloadPath);
+            downloadPathPreset.setSummary(downloadPathForUser);
+        }
+    }
+
+    private Preference.OnPreferenceClickListener onClickDownloadPathSettings() {
+        return new Preference.OnPreferenceClickListener() {
+            public boolean onPreferenceClick(Preference preference) {
+                final String filemanagerIntent =
+                        getResources().getString(R.string.def_intent_file_manager);
+                if (!TextUtils.isEmpty(filemanagerIntent)) {
+                    try {
+                        Intent i = new Intent(filemanagerIntent);
+                        startActivityForResult(i,
+                                DOWNLOAD_PATH_RESULT_CODE);
+                    } catch (Exception e) {
+                        String err_msg = getResources().getString(
+                                R.string.activity_not_found,
+                                filemanagerIntent);
+                        Toast.makeText(getActivity(), err_msg, Toast.LENGTH_LONG).show();
+                    }
+                    return true;
+                } else {
+                    Log.e(LOGTAG, "File Manager intent not defined !!");
+                    return true;
+                }
+            }
+        };
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        ActionBar bar = getActivity().getActionBar();
+        if (bar != null) {
+            bar.setTitle(R.string.pref_content_title);
+            bar.setDisplayHomeAsUpEnabled(false);
+            bar.setHomeButtonEnabled(false);
+        }
+    }
+}
diff --git a/src/com/android/browser/preferences/DebugPreferencesFragment.java b/src/com/android/browser/preferences/DebugPreferencesFragment.java
index 09f19ef..21e3080 100644
--- a/src/com/android/browser/preferences/DebugPreferencesFragment.java
+++ b/src/com/android/browser/preferences/DebugPreferencesFragment.java
@@ -20,13 +20,10 @@
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceFragment;
 
-import com.android.browser.BrowserSettings;
-import com.android.browser.PreferenceKeys;
 import com.android.browser.R;
 
-public class DebugPreferencesFragment extends PreferenceFragment
+public class DebugPreferencesFragment extends SWEPreferenceFragment
         implements OnPreferenceClickListener {
     @Override
     public void onCreate(Bundle savedInstanceState) {
diff --git a/src/com/android/browser/preferences/GeneralPreferencesFragment.java b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
index 0629115..07d53b1 100644
--- a/src/com/android/browser/preferences/GeneralPreferencesFragment.java
+++ b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
@@ -30,7 +30,6 @@
 import android.os.Bundle;
 import android.preference.ListPreference;
 import android.preference.Preference;
-import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 import android.text.InputType;
 import android.text.TextUtils;
@@ -52,7 +51,7 @@
 import com.android.browser.mdm.MdmCheckBoxPreference;
 import com.android.browser.mdm.SearchEngineRestriction;
 
-public class GeneralPreferencesFragment extends PreferenceFragment
+public class GeneralPreferencesFragment extends SWEPreferenceFragment
         implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
 
     static final String TAG = "GeneralPreferencesFragment";
@@ -112,7 +111,7 @@
         DoNotTrackRestriction.getInstance().registerPreference(dntPref);
 
         mAdvFrag = new AdvancedPreferencesFragment(this);
-        mPrivFrag = new PrivacySecurityPreferencesFragment(this);
+        //mPrivFrag = new PrivacySecurityPreferencesFragment(this);
     }
 
     @Override
diff --git a/src/com/android/browser/preferences/PrivacySecurityPreferencesFragment.java b/src/com/android/browser/preferences/PrivacySecurityPreferencesFragment.java
index bddcdec..f7aa217 100644
--- a/src/com/android/browser/preferences/PrivacySecurityPreferencesFragment.java
+++ b/src/com/android/browser/preferences/PrivacySecurityPreferencesFragment.java
@@ -19,42 +19,172 @@
 import com.android.browser.PreferenceKeys;
 import com.android.browser.R;
 
+import android.app.ActionBar;
 import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.preference.Preference;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.preference.TwoStatePreference;
 
-public class PrivacySecurityPreferencesFragment
-        implements Preference.OnPreferenceChangeListener {
+import org.codeaurora.swe.PermissionsServiceFactory;
+import org.codeaurora.swe.WebRefiner;
 
-    PreferenceFragment mFragment;
+public class PrivacySecurityPreferencesFragment extends SWEPreferenceFragment
+        implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
 
-    PrivacySecurityPreferencesFragment(PreferenceFragment fragment) {
-        mFragment = fragment;
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.privacy_and_security_preferences);
 
-        Preference e = mFragment.findPreference(PreferenceKeys.PREF_CLEAR_SELECTED_DATA);
+        PreferenceScreen websiteSettings = (PreferenceScreen) findPreference(
+                PreferenceKeys.PREF_WEBSITE_SETTINGS);
+        websiteSettings.setFragment(WebsiteSettingsFragment.class.getName());
+        websiteSettings.setOnPreferenceClickListener(this);
+
+        Preference e = findPreference(PreferenceKeys.PREF_CLEAR_SELECTED_DATA);
         e.setOnPreferenceChangeListener(this);
+
+        readAndShowPermission("enable_geolocation",
+                PermissionsServiceFactory.PermissionType.GEOLOCATION);
+
+        readAndShowPermission("microphone", PermissionsServiceFactory.PermissionType.VOICE);
+
+        readAndShowPermission("camera", PermissionsServiceFactory.PermissionType.VIDEO);
+
+        readAndShowPermission("distracting_contents",
+                PermissionsServiceFactory.PermissionType.WEBREFINER);
+
+        readAndShowPermission("popup_windows", PermissionsServiceFactory.PermissionType.POPUP);
+
+        readAndShowPermission("accept_cookies", PermissionsServiceFactory.PermissionType.COOKIE);
+
+        readAndShowPermission("accept_third_cookies",
+                PermissionsServiceFactory.PermissionType.THIRDPARTYCOOKIES);
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        FragmentManager fragmentManager = getFragmentManager();
+
+        if (preference.getKey().equals(PreferenceKeys.PREF_WEBSITE_SETTINGS)) {
+            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+            Fragment newFragment = new WebsiteSettingsFragment();
+            fragmentTransaction.replace(getId(), newFragment);
+            fragmentTransaction.addToBackStack(null);
+            fragmentTransaction.commit();
+            return true;
+        }
+        return false;
     }
 
     @Override
     public boolean onPreferenceChange(Preference pref, Object objValue) {
+        boolean flag = (boolean) objValue;
         if (pref.getKey().equals(PreferenceKeys.PREF_CLEAR_SELECTED_DATA)) {
             if (pref.getPreferenceManager().getDefaultSharedPreferences(
-                    (Context)mFragment.getActivity()).getBoolean(
+                    (Context) getActivity()).getBoolean(
                     PreferenceKeys.PREF_PRIVACY_CLEAR_HISTORY, false)) {
                 // Need to tell the browser to remove the parent/child relationship
                 // between tabs
-                mFragment.getActivity().setResult(Activity.RESULT_OK,
-                        (new Intent()).putExtra(Intent.EXTRA_TEXT,
-                                pref.getKey()));
+                getActivity().setResult(Activity.RESULT_OK,
+                        (new Intent()).putExtra(Intent.EXTRA_TEXT, pref.getKey()));
                 return true;
             }
         }
 
-        return true;
+        if (pref.getKey().toString().equalsIgnoreCase("enable_geolocation")) {
+            PermissionsServiceFactory.setDefaultPermissions(
+                    PermissionsServiceFactory.PermissionType.GEOLOCATION, flag);
+            return true;
+        }
+
+        if (pref.getKey().toString().equalsIgnoreCase("microphone")) {
+            PermissionsServiceFactory.setDefaultPermissions(
+                    PermissionsServiceFactory.PermissionType.VOICE, flag);
+            return true;
+        }
+
+        if (pref.getKey().toString().equalsIgnoreCase("camera")) {
+            PermissionsServiceFactory.setDefaultPermissions(
+                    PermissionsServiceFactory.PermissionType.VIDEO, flag);
+            return true;
+        }
+
+        if (pref.getKey().toString().equalsIgnoreCase("distracting_contents")) {
+            WebRefiner refiner = WebRefiner.getInstance();
+            PermissionsServiceFactory.setDefaultPermissions(
+                    PermissionsServiceFactory.PermissionType.WEBREFINER, flag);
+            if (refiner != null) {
+                refiner.setRulesEnabled(WebRefiner.CATEGORY_ALL, !flag);
+            }
+            return true;
+        }
+
+        if (pref.getKey().toString().equalsIgnoreCase("popup_windows")) {
+            PermissionsServiceFactory.setDefaultPermissions(
+                    PermissionsServiceFactory.PermissionType.POPUP, flag);
+            return true;
+        }
+
+        if (pref.getKey().toString().equalsIgnoreCase("accept_cookies")) {
+            PermissionsServiceFactory.setDefaultPermissions(
+                    PermissionsServiceFactory.PermissionType.COOKIE, flag);
+
+            if (!flag) {
+                // Disable third party cookies as well
+                PermissionsServiceFactory.setDefaultPermissions(
+                        PermissionsServiceFactory.PermissionType.THIRDPARTYCOOKIES, flag);
+                showPermission(findPreference("accept_third_cookies"), flag);
+            }
+            return true;
+        }
+
+        if (pref.getKey().toString().equalsIgnoreCase("accept_third_cookies")) {
+            PermissionsServiceFactory.setDefaultPermissions(
+                    PermissionsServiceFactory.PermissionType.THIRDPARTYCOOKIES, flag);
+            return true;
+        }
+
+        return false;
     }
 
+    private void readAndShowPermission(CharSequence key,
+                                       PermissionsServiceFactory.PermissionType type) {
+        Preference pref = findPreference(key);
+        pref.setOnPreferenceChangeListener(this);
+        showPermission(pref, PermissionsServiceFactory.getDefaultPermissions(type));
+    }
+
+    private void showPermission(Preference pref, boolean perm) {
+        if (pref instanceof TwoStatePreference) {
+            TwoStatePreference twoStatePreference = (TwoStatePreference) pref;
+            if (twoStatePreference.isChecked() != perm) {
+                twoStatePreference.setChecked(perm);
+            }
+        } else {
+            if (!perm) {
+                pref.setSummary(R.string.pref_security_not_allowed);
+            } else {
+                pref.setSummary(R.string.pref_security_ask_before_using);
+            }
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        ActionBar bar = getActivity().getActionBar();
+        if (bar != null) {
+            bar.setTitle(R.string.pref_privacy_security_title);
+            bar.setDisplayHomeAsUpEnabled(false);
+            bar.setHomeButtonEnabled(false);
+        }
+    }
 }
diff --git a/src/com/android/browser/preferences/SWEPreferenceFragment.java b/src/com/android/browser/preferences/SWEPreferenceFragment.java
new file mode 100644
index 0000000..79781da
--- /dev/null
+++ b/src/com/android/browser/preferences/SWEPreferenceFragment.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.android.browser.preferences;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.Switch;
+
+public abstract class SWEPreferenceFragment extends PreferenceFragment  {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
+        View view = super.onCreateView(inflater, container, bundle);
+
+        ListView list = (ListView) view.findViewById(android.R.id.list);
+
+        if (list == null) {
+            return view;
+        }
+
+        ViewGroup.LayoutParams params = list.getLayoutParams();
+        params.width = ViewGroup.LayoutParams.MATCH_PARENT;
+        list.setLayoutParams(params);
+        list.setPadding(0, list.getPaddingTop(), 0, list.getPaddingBottom());
+        list.setDivider(null);
+        list.setDividerHeight(0);
+
+        list.setOnHierarchyChangeListener(
+                new ViewGroup.OnHierarchyChangeListener() {
+                    @Override
+                    public void onChildViewAdded(View parent, View child) {
+                        onChildViewAddedToHierarchy(parent, child);
+                        findAndResizeSwitchPreferenceWidget(child);
+                    }
+
+                    @Override
+                    public void onChildViewRemoved(View parent, View child) {
+                        onChildViewRemovedFromHierarchy(parent, child);
+                    }
+                }
+        );
+
+        return view;
+    }
+
+    private final void findAndResizeSwitchPreferenceWidget(View parent) {
+        LinearLayout layout = (LinearLayout) parent.findViewById(android.R.id.widget_frame);
+        if (layout != null) {
+            for (int i = 0; i < layout.getChildCount(); i++) {
+                View view = layout.getChildAt(i);
+                if (view instanceof Switch) {
+                    Switch switchView = (Switch) view;
+                    switchView.setThumbTextPadding(0);
+                    int width = switchView.getSwitchMinWidth();
+                    switchView.setSwitchMinWidth(width/2);
+                }
+            }
+        }
+    }
+
+    public void onChildViewAddedToHierarchy(View parent, View child) {
+
+    }
+
+    public void onChildViewRemovedFromHierarchy(View parent, View child) {
+
+    }
+}
diff --git a/src/com/android/browser/preferences/SiteSpecificPreferencesFragment.java b/src/com/android/browser/preferences/SiteSpecificPreferencesFragment.java
new file mode 100644
index 0000000..68c3ebc
--- /dev/null
+++ b/src/com/android/browser/preferences/SiteSpecificPreferencesFragment.java
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.android.browser.preferences;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.net.http.SslCertificate;
+import android.net.http.SslError;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+import android.preference.TwoStatePreference;
+import android.text.TextUtils;
+import android.view.View;
+import android.webkit.ValueCallback;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.browser.NavigationBarBase;
+import com.android.browser.PageDialogsHandler;
+import com.android.browser.R;
+
+import org.codeaurora.swe.PermissionsServiceFactory;
+import org.codeaurora.swe.WebRefiner;
+import org.codeaurora.swe.util.ColorUtils;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+public class SiteSpecificPreferencesFragment extends SWEPreferenceFragment
+        implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
+        View.OnClickListener {
+    public static final String EXTRA_SITE = "website";
+    public static final String EXTRA_ORIGIN = "website_origin";
+    public static final String EXTRA_FAVICON = "website_favicon";
+    public static final String EXTRA_WEB_REFINER_INFO = "website_refiner_info";
+    public static final String EXTRA_SECURITY_CERT = "website_security_cert";
+    public static final String EXTRA_SECURITY_CERT_ERR = "website_security_cert_err";
+
+    private PermissionsServiceFactory.PermissionsService.OriginInfo mOriginInfo;
+    private PermissionsServiceFactory.PermissionsService mPermServ;
+    private ActionBar mBar;
+    private List<String> mLocationValues;
+
+    private boolean mUsingDefaultSettings = true;
+    private int mOriginalActionBarOptions;
+    private int mIconColor = 0;
+
+    private SslCertificate mSslCert;
+    private SslError mSslError;
+
+    private static class SiteSecurityViewFactory {
+        private class SiteSecurityView {
+            private TextView mTextView;
+            private View mContainer;
+            private String mDisplayText;
+
+            public SiteSecurityView(View parent, int resId, String text) {
+                mContainer = parent.findViewById(resId);
+                mTextView = (TextView) mContainer.findViewById(R.id.security_view_text);
+                mTextView.setText(text);
+                mDisplayText = text;
+                updateVisibility();
+            }
+
+            private void updateVisibility() {
+                if (TextUtils.isEmpty(mDisplayText)) {
+                    mContainer.setVisibility(View.GONE);
+                } else {
+                    mContainer.setVisibility(View.VISIBLE);
+                }
+            }
+
+            public void setText(String text) {
+                mDisplayText = text;
+                mTextView.setText(mDisplayText);
+                updateVisibility();
+            }
+
+            public void clearText() {
+                mDisplayText = null;
+                updateVisibility();
+            }
+        }
+
+        public enum ViewType{
+            ERROR,
+            WARNING,
+            INFO
+        };
+
+        private Map<ViewType, SiteSecurityView> mViews =
+                new EnumMap<ViewType, SiteSecurityView>(ViewType.class);
+        private Map<ViewType, String> mTexts = new EnumMap<ViewType, String>(ViewType.class);
+
+        private boolean mbEmpty = true;
+
+        public void setText(ViewType type, String text) {
+            mTexts.put(type, text);
+
+            SiteSecurityView view = mViews.get(type);
+            if (view != null) {
+                view.setText(text);
+            }
+
+            mbEmpty = false;
+        }
+
+        public void appendText(ViewType type, String text) {
+            String new_text = mTexts.get(type);
+            if (new_text != null)
+                new_text += text;
+            else
+                new_text = text;
+
+            mTexts.put(type, new_text);
+
+            SiteSecurityView view = mViews.get(type);
+            if (view != null) {
+                view.setText(new_text);
+            }
+
+            mbEmpty = false;
+        }
+
+        public void clearText(ViewType type) {
+            mTexts.remove(type);
+
+            SiteSecurityView view = mViews.get(type);
+            if (view != null) {
+                view.clearText();
+            }
+        }
+
+        public void setResource(ViewType type, View parent, int resId) {
+            String text = mTexts.get(type);
+            mViews.remove(type);
+            mViews.put(type, new SiteSecurityView(parent, resId, text));
+        }
+    }
+
+    private SiteSecurityViewFactory mSecurityViews;
+
+    private String mOriginText;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.site_specific_preferences);
+
+        mBar = getActivity().getActionBar();
+
+        mLocationValues = Arrays.asList(
+                getResources().getStringArray(R.array.geolocation_settings_choices));
+
+        mSecurityViews = new SiteSecurityViewFactory();
+
+        Bundle args = getArguments();
+        if (args != null) {
+            mOriginText = args.getString(EXTRA_ORIGIN, null);
+
+            if (mOriginText == null) {
+                mOriginText = args.getString(EXTRA_SITE);
+            }
+        }
+
+        mIconColor = NavigationBarBase.getSiteIconColor(mOriginText);
+
+        PermissionsServiceFactory.getPermissionsService(
+            new ValueCallback<PermissionsServiceFactory.PermissionsService>() {
+                @Override
+                public void onReceiveValue(PermissionsServiceFactory.PermissionsService value) {
+                    mPermServ = value;
+                    Preference pref = findPreference("site_name");
+
+                    pref.setTitle(mOriginText);
+                    try {
+                        URL url = new URL(mOriginText);
+                        pref.setSummary("(" + url.getHost() + ")");
+                    } catch (MalformedURLException e) {
+                    }
+                    mOriginInfo = mPermServ.getOriginInfo(mOriginText);
+                    setActionBarTitle(PermissionsServiceFactory.getPrettyUrl(mOriginText));
+                    updatePreferenceInfo();
+                }
+            }
+        );
+
+        Bundle parcel = args.getParcelable(EXTRA_SECURITY_CERT);
+        mSslCert = (parcel != null) ? SslCertificate.restoreState(parcel) : null;
+
+        if (mSslCert != null) {
+            int certErrors = args.getInt(EXTRA_SECURITY_CERT_ERR, 0);
+
+            if (certErrors == 0) {
+                mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.INFO,
+                        "Valid SSL Certificate. ");
+            } else {
+                mSslError = new SslError(-1, mSslCert, mOriginText);
+
+                if ((certErrors & (1 << SslError.SSL_DATE_INVALID)) != 0) {
+                    mSslError.addError(SslError.SSL_DATE_INVALID);
+                    mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.ERROR,
+                            "Invalid SSL Certificate. ");
+                }
+
+                if ((certErrors & (1 << SslError.SSL_EXPIRED)) != 0) {
+                    mSslError.addError(SslError.SSL_EXPIRED);
+                    mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.ERROR,
+                            "Invalid SSL Certificate. ");
+                }
+
+                if ((certErrors & (1 << SslError.SSL_IDMISMATCH)) != 0) {
+                    mSslError.addError(SslError.SSL_IDMISMATCH);
+                    mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.ERROR,
+                            "Invalid SSL Certificate. ");
+                }
+
+                if ((certErrors & (1 << SslError.SSL_INVALID)) != 0) {
+                    mSslError.addError(SslError.SSL_INVALID);
+                    mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.ERROR,
+                            "Invalid SSL Certificate. ");
+                }
+
+                if ((certErrors & (1 << SslError.SSL_NOTYETVALID)) != 0) {
+                    mSslError.addError(SslError.SSL_NOTYETVALID);
+                    mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.WARNING,
+                            "SSL Certificate warnings. ");
+                }
+
+                if ((certErrors & (1 << SslError.SSL_UNTRUSTED)) != 0) {
+                    mSslError.addError(SslError.SSL_UNTRUSTED);
+                    mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.WARNING,
+                            "SSL Certificate warnings. ");
+                }
+            }
+        }
+
+        int adBlocks = args.getInt(EXTRA_WEB_REFINER_INFO, 0);
+        if (adBlocks > 0) {
+            mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.INFO,
+                     getString(R.string.pref_web_refiner_blocked) + " " + adBlocks + " " +
+                            getString(R.string.pref_web_refiner_advertisements));
+        }
+    }
+
+    private void setActionBarTitle(String url) {
+        if (mBar != null) {
+            mBar.setTitle("  " + url);
+        }
+    }
+
+    private String getStorage() {
+        if (mOriginInfo == null) {
+            return new String("");
+        }
+
+        long value = mOriginInfo.getStoredData();
+        if (value == 0) {
+            return "Empty";
+        }
+
+        if (value < (1 << 10)) {
+            return value + "B";
+        } else if (value < (1 << 20)) {
+            return (value >> 10) + "KB";
+        } else if (value < (1 << 30)) {
+            return (value >> 20) + "MB";
+        }
+
+        return (value >> 30) + "GB";
+    }
+
+    private long showPermission(CharSequence key, PermissionsServiceFactory.PermissionType type,
+                                int defaultOnSummary, int defaultOffSummary) {
+        Preference pref = findPreference(key);
+        long permission = (mOriginInfo != null) ? mOriginInfo.getPermission(type) :
+                PermissionsServiceFactory.Permission.NOTSET;
+
+        pref.setOnPreferenceChangeListener(this);
+
+        if (permission == PermissionsServiceFactory.Permission.ALLOW) {
+            if (pref instanceof TwoStatePreference) {
+                ((TwoStatePreference) pref).setChecked(true);
+                ((TwoStatePreference) pref).setSummaryOn(R.string.pref_security_allowed);
+            } else {
+                pref.setSummary(R.string.pref_security_allowed);
+            }
+            mUsingDefaultSettings = false;
+        } else if (permission == PermissionsServiceFactory.Permission.BLOCK) {
+            if (pref instanceof TwoStatePreference) {
+                ((TwoStatePreference) pref).setChecked(false);
+            } else {
+                pref.setSummary(R.string.pref_security_not_allowed);
+            }
+            mUsingDefaultSettings = false;
+        } else if (permission == PermissionsServiceFactory.Permission.ASK) {
+            if (pref instanceof TwoStatePreference) {
+                ((TwoStatePreference) pref).setChecked(true);
+                ((TwoStatePreference) pref).setSummaryOn(R.string.pref_security_ask_before_using);
+            } else {
+                pref.setSummary(R.string.pref_security_ask_before_using);
+            }
+            mUsingDefaultSettings = false;
+        } else if (permission == PermissionsServiceFactory.Permission.NOTSET) {
+            boolean defaultPerm = PermissionsServiceFactory.getDefaultPermissions(type);
+            if (pref instanceof TwoStatePreference) {
+                if (!defaultPerm) {
+                    ((TwoStatePreference) pref).setChecked(false);
+                    ((TwoStatePreference) pref).setSummaryOff(defaultOffSummary);
+                    return PermissionsServiceFactory.Permission.BLOCK;
+                } else {
+                    ((TwoStatePreference) pref).setChecked(true);
+                    ((TwoStatePreference) pref).setSummaryOn(defaultOnSummary);
+                    return PermissionsServiceFactory.Permission.ASK;
+                }
+            } else {
+                if (!defaultPerm) {
+                    pref.setSummary(defaultOffSummary);
+                    return PermissionsServiceFactory.Permission.BLOCK;
+                } else {
+                    pref.setSummary(defaultOnSummary);
+                    return PermissionsServiceFactory.Permission.ASK;
+                }
+            }
+        }
+        return permission;
+    }
+
+    private void updateStorageInfo(Preference pref) {
+        if (mOriginInfo != null) {
+            pref.setTitle(R.string.webstorage_clear_data_title);
+            pref.setSummary("(" + getStorage() + ")");
+        }
+    }
+
+    private void updatePreferenceInfo() {
+        Preference pref = findPreference("clear_data");
+        updateStorageInfo(pref);
+        pref.setOnPreferenceClickListener(this);
+        String warningText = new String("");
+
+        long permission = showPermission("select_geolocation",
+                PermissionsServiceFactory.PermissionType.GEOLOCATION,
+                R.string.pref_security_ask_before_using, R.string.pref_security_not_allowed);
+
+        if (PermissionsServiceFactory.Permission.ALLOW == permission) {
+            warningText = getString(R.string.pref_privacy_enable_geolocation);
+        }
+
+        ListPreference geolocation_pref = (ListPreference) findPreference("select_geolocation");
+        geolocation_pref.setValueIndex(0);
+        if (permission == PermissionsServiceFactory.Permission.CUSTOM) {
+            pref = findPreference("select_geolocation");
+            long custom = mOriginInfo.getPermissionCustomValue(
+                    PermissionsServiceFactory.PermissionType.GEOLOCATION);
+            float customHrs = ((float) custom) / (60 * 60);
+            String customSummary = "Allowed for " + String.format("%.02f", customHrs) + " hours";
+            if (pref instanceof TwoStatePreference) {
+                ((TwoStatePreference) pref).setChecked(true);
+                ((TwoStatePreference) pref).setSummaryOn(customSummary);
+            } else {
+                pref.setSummary(customSummary);
+            }
+            mUsingDefaultSettings = false;
+            warningText = getString(R.string.pref_privacy_enable_geolocation);
+            geolocation_pref.setValueIndex(1);
+        } else if (permission == PermissionsServiceFactory.Permission.ALLOW) {
+            geolocation_pref.setValueIndex(2);
+        }
+
+        permission = showPermission("microphone", PermissionsServiceFactory.PermissionType.VOICE,
+                R.string.pref_security_ask_before_using, R.string.pref_security_not_allowed);
+
+        if (PermissionsServiceFactory.Permission.ALLOW == permission) {
+            if (!warningText.isEmpty()) {
+                warningText += ", ";
+            }
+            warningText += getString(R.string.pref_security_allow_mic);
+        }
+
+        permission = showPermission("camera", PermissionsServiceFactory.PermissionType.VIDEO,
+                R.string.pref_security_ask_before_using, R.string.pref_security_not_allowed);
+        if (PermissionsServiceFactory.Permission.ALLOW == permission) {
+            if (!warningText.isEmpty()) {
+                warningText += ", ";
+            }
+            warningText += getString(R.string.pref_security_allow_camera);
+        }
+
+        if (!warningText.isEmpty()) {
+            warningText += " ";
+            warningText += getResources().getString(R.string.pref_security_access_is_allowed);
+            mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.WARNING, warningText);
+        }
+
+        showPermission("distracting_contents", PermissionsServiceFactory.PermissionType.WEBREFINER,
+                R.string.pref_security_allowed, R.string.pref_security_not_allowed);
+
+        showPermission("popup_windows", PermissionsServiceFactory.PermissionType.POPUP,
+                R.string.pref_security_allowed, R.string.pref_security_not_allowed);
+
+        showPermission("accept_cookies", PermissionsServiceFactory.PermissionType.COOKIE,
+                R.string.pref_security_allowed, R.string.pref_security_not_allowed);
+
+        if (!mUsingDefaultSettings && mBar != null) {
+            mBar.getCustomView().setVisibility(View.VISIBLE);
+        }
+
+        if (mSecurityViews.mbEmpty) {
+            PreferenceScreen screen = (PreferenceScreen)
+                    findPreference("site_specific_prefs");
+
+            pref = findPreference("site_security_info_title");
+            screen.removePreference(pref);
+        }
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mBar != null) {
+            mOriginalActionBarOptions = mBar.getDisplayOptions();
+            mBar.setDisplayHomeAsUpEnabled(false);
+            mBar.setHomeButtonEnabled(false);
+
+            assignResetButton();
+
+            Bundle args = getArguments();
+            if (args != null) {
+                byte[] data = args.getByteArray(EXTRA_FAVICON);
+                if (data != null) {
+                    Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
+                    if (bm != null) {
+                        Bitmap bitmap = Bitmap.createScaledBitmap(bm, 150, 150, true);
+                        int color = ColorUtils.getDominantColorForBitmap(bitmap);
+
+                        appendActionBarDisplayOptions(ActionBar.DISPLAY_SHOW_HOME |
+                                ActionBar.DISPLAY_SHOW_TITLE);
+                        mBar.setHomeButtonEnabled(true);
+                        mBar.setIcon(new BitmapDrawable(getResources(), bitmap));
+                        mBar.setBackgroundDrawable(new ColorDrawable(color));
+                        NavigationBarBase.setStatusAndNavigationBarColor(getActivity(),
+                                NavigationBarBase.adjustColor(color, 1, 1, 0.7f));
+                    }
+                } else {
+                    if (mIconColor != 0) {
+                        mBar.setBackgroundDrawable(new ColorDrawable(mIconColor));
+                        NavigationBarBase.setStatusAndNavigationBarColor(getActivity(),
+                                NavigationBarBase.adjustColor(mIconColor, 1, 1, 0.7f));
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mBar != null) {
+            mBar.setDisplayOptions(mOriginalActionBarOptions);
+            NavigationBarBase.setStatusAndNavigationBarColor(getActivity(),
+                    NavigationBarBase.getDefaultStatusBarColor());
+        }
+    }
+
+    private void appendActionBarDisplayOptions(int extraOptions) {
+        int options = mBar.getDisplayOptions();
+        options |= extraOptions;
+        mBar.setDisplayOptions(options);
+    }
+
+    private void assignResetButton() {
+        appendActionBarDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+        mBar.setCustomView(R.layout.swe_preference_custom_actionbar);
+        //mBar.getCustomView().setVisibility(View.GONE);
+        Button btn = (Button) mBar.getCustomView().findViewById(R.id.reset);
+        if (btn == null) {
+            return;
+        }
+
+        btn.setOnClickListener(
+            new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    new AlertDialog.Builder(getActivity())
+                        .setMessage(R.string.pref_extras_reset_default_dlg)
+                        .setPositiveButton(
+                            R.string.website_settings_clear_all_dialog_ok_button,
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dlg, int which) {
+                                    if (mOriginInfo != null) {
+                                        mOriginInfo.resetSitePermission();
+                                        Preference e = findPreference("clear_data");
+                                        e.setSummary("(Empty)");
+                                        updatePreferenceInfo();
+
+                                        WebRefiner refiner = WebRefiner.getInstance();
+                                        if (refiner != null) {
+                                            String[] origins = new String[1];
+                                            origins[0] = mOriginInfo.getOrigin();
+                                            refiner.useGlobalRulesForDomains(origins);
+                                        }
+
+                                        finish();
+                                    }
+                                }
+                            })
+                        .setNegativeButton(
+                                R.string.website_settings_clear_all_dialog_cancel_button, null)
+                        .setIconAttribute(android.R.attr.alertDialogIcon)
+                        .show();
+                }
+            }
+        );
+    }
+
+    private void finish() {
+        Activity activity = getActivity();
+        if (activity != null) {
+            getActivity().getFragmentManager().popBackStack();
+        }
+    }
+
+    @Override
+    public void onChildViewAddedToHierarchy(View parent, View child) {
+        if (child.getId() == R.id.site_security_info) {
+            mSecurityViews.setResource(SiteSecurityViewFactory.ViewType.ERROR,
+                    child, R.id.site_security_error);
+            mSecurityViews.setResource(SiteSecurityViewFactory.ViewType.WARNING,
+                    child, R.id.site_security_warning);
+            mSecurityViews.setResource(SiteSecurityViewFactory.ViewType.INFO,
+                    child, R.id.site_security_verbose);
+
+            if (mSslCert != null) {
+                child.setOnClickListener(this);
+            }
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.site_security_info) {
+            PageDialogsHandler.createSslCertificateDialog(getActivity(),mSslCert, mSslError)
+                    .setPositiveButton(R.string.ok, null)
+                    .show();
+        }
+    }
+
+    private void updateTwoStatePreference(Preference pref,
+                                          PermissionsServiceFactory.PermissionType type,
+                                          boolean state) {
+        if (state) {
+            mOriginInfo.setPermission(type, PermissionsServiceFactory.Permission.ALLOW);
+            ((TwoStatePreference)pref).setSummaryOn(R.string.pref_security_allowed);
+        } else {
+            mOriginInfo.setPermission(type, PermissionsServiceFactory.Permission.BLOCK);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference pref, Object objValue) {
+        if (mOriginInfo == null) {
+            if (mOriginText != null) {
+                mOriginInfo = mPermServ.addOriginInfo(mOriginText);
+                if (mOriginInfo == null) {
+                    mOriginInfo = mPermServ.getOriginInfo(mOriginText);
+                    if (mOriginInfo == null) {
+                        return false;
+                    }
+                }
+            } else {
+                return false;
+            }
+        }
+        if (pref.getKey().toString().equalsIgnoreCase("select_geolocation")) {
+            int index = mLocationValues.indexOf(objValue.toString());
+            switch (index) {
+                case 0:
+                    mOriginInfo.setPermission(PermissionsServiceFactory.PermissionType.GEOLOCATION,
+                            PermissionsServiceFactory.Permission.BLOCK);
+                    pref.setSummary(R.string.pref_security_not_allowed);
+                    break;
+                case 1:
+                    mOriginInfo.setPermission(PermissionsServiceFactory.PermissionType.GEOLOCATION,
+                            PermissionsServiceFactory.Permission.CUSTOM);
+                    pref.setSummary(R.string.geolocation_permissions_prompt_share_for_limited_time);
+                    break;
+                case 2:
+                    mOriginInfo.setPermission(PermissionsServiceFactory.PermissionType.GEOLOCATION,
+                            PermissionsServiceFactory.Permission.ALLOW);
+                    pref.setSummary(R.string.pref_security_allowed);
+                    break;
+                default:
+                    break;
+            }
+        } else if (pref.getKey().toString().equalsIgnoreCase("microphone")) {
+            updateTwoStatePreference(pref,
+                    PermissionsServiceFactory.PermissionType.VOICE, (boolean)objValue);
+        } else if (pref.getKey().toString().equalsIgnoreCase("camera")) {
+            updateTwoStatePreference(pref,
+                    PermissionsServiceFactory.PermissionType.VIDEO, (boolean)objValue);
+        } else if (pref.getKey().toString().equalsIgnoreCase("distracting_contents")) {
+            WebRefiner refiner = WebRefiner.getInstance();
+            if (refiner != null) {
+                boolean enable = (boolean) objValue;
+                String[] origins = new String[1];
+                origins[0] = mOriginInfo.getOrigin();
+                if (enable) {
+                    refiner.enableRulesForDomains(WebRefiner.CATEGORY_ALL, origins);
+                } else {
+                    refiner.disableRulesForDomains(WebRefiner.CATEGORY_ALL, origins);
+                }
+            }
+            updateTwoStatePreference(pref,
+                    PermissionsServiceFactory.PermissionType.WEBREFINER, (boolean)objValue);
+        } else if (pref.getKey().toString().equalsIgnoreCase("popup_windows")) {
+            updateTwoStatePreference(pref,
+                    PermissionsServiceFactory.PermissionType.POPUP, (boolean)objValue);
+        } else if (pref.getKey().toString().equalsIgnoreCase("accept_cookies")) {
+            updateTwoStatePreference(pref,
+                    PermissionsServiceFactory.PermissionType.COOKIE, (boolean)objValue);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference pref) {
+        if (pref.getKey().toString().equalsIgnoreCase("clear_data")) {
+            new AlertDialog.Builder(getActivity())
+                .setMessage(R.string.website_settings_clear_all_dialog_message)
+                .setPositiveButton(R.string.website_settings_clear_all_dialog_ok_button,
+                        new AlertDialog.OnClickListener() {
+                            public void onClick(DialogInterface dlg, int which) {
+                                if (mOriginInfo != null) {
+                                    mOriginInfo.clearAllStoredData();
+                                    Preference e = findPreference("clear_data");
+                                    e.setSummary("(Empty)");
+                                }
+                            }
+                        })
+                .setNegativeButton(R.string.website_settings_clear_all_dialog_cancel_button, null)
+                .setIconAttribute(android.R.attr.alertDialogIcon)
+                .show();
+        }
+        return true;
+    }
+
+}
diff --git a/src/com/android/browser/preferences/WebsiteSettingsFragment.java b/src/com/android/browser/preferences/WebsiteSettingsFragment.java
index ad16635..7ffb5c1 100644
--- a/src/com/android/browser/preferences/WebsiteSettingsFragment.java
+++ b/src/com/android/browser/preferences/WebsiteSettingsFragment.java
@@ -25,18 +25,12 @@
 import android.app.ListFragment;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ColorDrawable;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.preference.PreferenceActivity;
-import android.util.Log;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -44,20 +38,21 @@
 import android.webkit.ValueCallback;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
+import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.android.browser.R;
 import com.android.browser.WebStorageSizeManager;
-import com.android.browser.platformsupport.BrowserContract.Bookmarks;
 
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
 import org.codeaurora.swe.GeolocationPermissions;
+import org.codeaurora.swe.PermissionsServiceFactory;
+import org.codeaurora.swe.WebRefiner;
 import org.codeaurora.swe.WebStorage;
 
 /**
@@ -66,78 +61,24 @@
  * and Geolocation.
  */
 public class WebsiteSettingsFragment extends ListFragment implements OnClickListener {
-
-    private static final String EXTRA_SITE = "site";
-    private static final long MILLIS_PER_DAY = 86400000;
-    private String LOGTAG = "WebsiteSettingsActivity";
-    private static String sMBStored = null;
     private SiteAdapter mAdapter = null;
-    private Site mSite = null;
 
-    protected long geolocationPolicyExpiration;
-    protected boolean geolocationPolicyOriginAllowed;
-
-    static class Site implements Parcelable {
+    private class Site {
         private String mOrigin;
         private String mTitle;
         private Bitmap mIcon;
-        private int mFeatures;
-
-        // These constants provide the set of features that a site may support
-        // They must be consecutive. To add a new feature, add a new FEATURE_XXX
-        // variable with value equal to the current value of FEATURE_COUNT, then
-        // increment FEATURE_COUNT.
-        final static int FEATURE_WEB_STORAGE = 0;
-        final static int FEATURE_GEOLOCATION = 1;
-        // The number of features available.
-        final static int FEATURE_COUNT = 2;
 
         public Site(String origin) {
             mOrigin = origin;
             mTitle = null;
             mIcon = null;
-            mFeatures = 0;
-        }
-
-        public void addFeature(int feature) {
-            mFeatures |= (1 << feature);
-        }
-
-        public void removeFeature(int feature) {
-            mFeatures &= ~(1 << feature);
-        }
-
-        public boolean hasFeature(int feature) {
-            return (mFeatures & (1 << feature)) != 0;
-        }
-
-        /**
-         * Gets the number of features supported by this site.
-         */
-        public int getFeatureCount() {
-            int count = 0;
-            for (int i = 0; i < FEATURE_COUNT; ++i) {
-                count += hasFeature(i) ? 1 : 0;
-            }
-            return count;
-        }
-
-        /**
-         * Gets the ID of the nth (zero-based) feature supported by this site.
-         * The return value is a feature ID - one of the FEATURE_XXX values.
-         * This is required to determine which feature is displayed at a given
-         * position in the list of features for this site. This is used both
-         * when populating the view and when responding to clicks on the list.
-         */
-        public int getFeatureByIndex(int n) {
-            int j = -1;
-            for (int i = 0; i < FEATURE_COUNT; ++i) {
-                j += hasFeature(i) ? 1 : 0;
-                if (j == n) {
-                    return i;
-                }
-            }
-            return -1;
+            PermissionsServiceFactory.getFavicon(origin, getActivity(),
+                    new ValueCallback<Bitmap>() {
+                        @Override
+                        public void onReceiveValue(Bitmap value) {
+                            mIcon = value;
+                        }
+                    });
         }
 
         public String getOrigin() {
@@ -165,41 +106,11 @@
         }
 
         private String hideHttp(String str) {
+            if (str == null)
+                return null;
             Uri uri = Uri.parse(str);
             return "http".equals(uri.getScheme()) ?  str.substring(7) : str;
         }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(mOrigin);
-            dest.writeString(mTitle);
-            dest.writeInt(mFeatures);
-            dest.writeParcelable(mIcon, flags);
-        }
-
-        private Site(Parcel in) {
-            mOrigin = in.readString();
-            mTitle = in.readString();
-            mFeatures = in.readInt();
-            mIcon = in.readParcelable(null);
-        }
-
-        public static final Parcelable.Creator<Site> CREATOR
-                = new Parcelable.Creator<Site>() {
-            public Site createFromParcel(Parcel in) {
-                return new Site(in);
-            }
-
-            public Site[] newArray(int size) {
-                return new Site[size];
-            }
-        };
-
     }
 
     class SiteAdapter extends ArrayAdapter<Site>
@@ -207,188 +118,69 @@
         private int mResource;
         private LayoutInflater mInflater;
         private Bitmap mDefaultIcon;
-        private Bitmap mUsageEmptyIcon;
-        private Bitmap mUsageLowIcon;
-        private Bitmap mUsageHighIcon;
-        private Bitmap mLocationAllowedIcon;
-        private Bitmap mLocationDisallowedIcon;
-        private Site mCurrentSite;
+        private PermissionsServiceFactory.PermissionsService mPermServ;
+        private boolean mReady;
 
         public SiteAdapter(Context context, int rsc) {
-            this(context, rsc, null);
-        }
-
-        public SiteAdapter(Context context, int rsc, Site site) {
             super(context, rsc);
             mResource = rsc;
             mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             mDefaultIcon = BitmapFactory.decodeResource(getResources(),
                     R.drawable.ic_deco_favicon_normal);
-            mUsageEmptyIcon = BitmapFactory.decodeResource(getResources(),
-                    R.drawable.ic_list_data_off);
-            mUsageLowIcon = BitmapFactory.decodeResource(getResources(),
-                    R.drawable.ic_list_data_small);
-            mUsageHighIcon = BitmapFactory.decodeResource(getResources(),
-                    R.drawable.ic_list_data_large);
-            mLocationAllowedIcon = BitmapFactory.decodeResource(getResources(),
-                    R.drawable.ic_action_gps_on);
-            mLocationDisallowedIcon = BitmapFactory.decodeResource(getResources(),
-                    R.drawable.ic_action_gps_off);
-            mCurrentSite = site;
-            if (mCurrentSite == null) {
-                askForOrigins();
-            }
-        }
 
-        /**
-         * Adds the specified feature to the site corresponding to supplied
-         * origin in the map. Creates the site if it does not already exist.
-         */
-        private void addFeatureToSite(Map<String, Site> sites, String origin, int feature) {
-            Site site = null;
-            if (sites.containsKey(origin)) {
-                site = (Site) sites.get(origin);
-            } else {
-                site = new Site(origin);
-                sites.put(origin, site);
-            }
-            site.addFeature(feature);
+            mReady = false;
+            askForOrigins();
         }
 
         public void askForOrigins() {
-            // Get the list of origins we want to display.
-            // All 'HTML 5 modules' (Database, Geolocation etc) form these
-            // origin strings using WebCore::SecurityOrigin::toString(), so it's
-            // safe to group origins here. Note that WebCore::SecurityOrigin
-            // uses 0 (which is not printed) for the port if the port is the
-            // default for the protocol. Eg http://www.google.com and
-            // http://www.google.com:80 both record a port of 0 and hence
-            // toString() == 'http://www.google.com' for both.
+            if (mPermServ == null) {
+                PermissionsServiceFactory.getPermissionsService(
+                        new ValueCallback<PermissionsServiceFactory.PermissionsService>() {
+                            @Override
+                            public void onReceiveValue(
+                                    PermissionsServiceFactory.PermissionsService value) {
+                                mPermServ = value;
+                                Map<String, Site> sites = new HashMap<>();
 
-            WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
-                public void onReceiveValue(Map origins) {
-                    Map<String, Site> sites = new HashMap<String, Site>();
-                    if (origins != null) {
-                        Iterator<String> iter = origins.keySet().iterator();
-                        while (iter.hasNext()) {
-                            addFeatureToSite(sites, iter.next(), Site.FEATURE_WEB_STORAGE);
-                        }
-                    }
-                    askForGeolocation(sites);
-                }
-            });
-        }
-
-        public void askForGeolocation(final Map<String, Site> sites) {
-            GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() {
-                public void onReceiveValue(Set<String> origins) {
-                    if (origins != null) {
-                        Iterator<String> iter = origins.iterator();
-                        while (iter.hasNext()) {
-                            addFeatureToSite(sites, iter.next(), Site.FEATURE_GEOLOCATION);
-                        }
-                    }
-                    populateIcons(sites);
-                    populateOrigins(sites);
-                }
-            });
-        }
-
-        public void populateIcons(Map<String, Site> sites) {
-            // Create a map from host to origin. This is used to add metadata
-            // (title, icon) for this origin from the bookmarks DB. We must do
-            // the DB access on a background thread.
-            new UpdateFromBookmarksDbTask(this.getContext(), sites).execute();
-        }
-
-        private class UpdateFromBookmarksDbTask extends AsyncTask<Void, Void, Void> {
-
-            private Context mContext;
-            private boolean mDataSetChanged;
-            private Map<String, Site> mSites;
-
-            public UpdateFromBookmarksDbTask(Context ctx, Map<String, Site> sites) {
-                mContext = ctx.getApplicationContext();
-                mSites = sites;
-            }
-
-            protected Void doInBackground(Void... unused) {
-                HashMap<String, Set<Site>> hosts = new HashMap<String, Set<Site>>();
-                Set<Map.Entry<String, Site>> elements = mSites.entrySet();
-                Iterator<Map.Entry<String, Site>> originIter = elements.iterator();
-                while (originIter.hasNext()) {
-                    Map.Entry<String, Site> entry = originIter.next();
-                    Site site = entry.getValue();
-                    String host = Uri.parse(entry.getKey()).getHost();
-                    Set<Site> hostSites = null;
-                    if (hosts.containsKey(host)) {
-                        hostSites = (Set<Site>)hosts.get(host);
-                    } else {
-                        hostSites = new HashSet<Site>();
-                        hosts.put(host, hostSites);
-                    }
-                    hostSites.add(site);
-                }
-
-                // Check the bookmark DB. If we have data for a host used by any of
-                // our origins, use it to set their title and favicon
-                Cursor c = mContext.getContentResolver().query(Bookmarks.CONTENT_URI,
-                        new String[] { Bookmarks.URL, Bookmarks.TITLE, Bookmarks.FAVICON },
-                        Bookmarks.IS_FOLDER + " == 0", null, null);
-
-                if (c != null) {
-                    if (c.moveToFirst()) {
-                        int urlIndex = c.getColumnIndex(Bookmarks.URL);
-                        int titleIndex = c.getColumnIndex(Bookmarks.TITLE);
-                        int faviconIndex = c.getColumnIndex(Bookmarks.FAVICON);
-                        do {
-                            String url = c.getString(urlIndex);
-                            String host = Uri.parse(url).getHost();
-                            if (hosts.containsKey(host)) {
-                                String title = c.getString(titleIndex);
-                                Bitmap bmp = null;
-                                byte[] data = c.getBlob(faviconIndex);
-                                if (data != null) {
-                                    bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
+                                Set<String> origins = mPermServ.getOrigins();
+                                for (String origin : origins) {
+                                    if (!TextUtils.isEmpty(origin))
+                                        sites.put(origin, new Site(origin));
                                 }
-                                Set matchingSites = (Set) hosts.get(host);
-                                Iterator<Site> sitesIter = matchingSites.iterator();
-                                while (sitesIter.hasNext()) {
-                                    Site site = sitesIter.next();
-                                    // We should only set the title if the bookmark is for the root
-                                    // (i.e. www.google.com), as website settings act on the origin
-                                    // as a whole rather than a single page under that origin. If the
-                                    // user has bookmarked a page under the root but *not* the root,
-                                    // then we risk displaying the title of that page which may or
-                                    // may not have any relevance to the origin.
-                                    if (url.equals(site.getOrigin()) ||
-                                            (new String(site.getOrigin()+"/")).equals(url)) {
-                                        mDataSetChanged = true;
-                                        site.setTitle(title);
-                                    }
 
-                                    if (bmp != null) {
-                                        mDataSetChanged = true;
-                                        site.setIcon(bmp);
-                                    }
-                                }
+                                // Create a map from host to origin. This is used to add metadata
+                                // (title, icon) for this origin from the bookmarks DB. We must do
+                                // the DB access on a background thread.
+                                //new UpdateFromBookmarksDbTask(ctx, sites).execute();
+
+                                populateOrigins(sites);
+                                mReady = true;
                             }
-                        } while (c.moveToNext());
-                    }
-                    c.close();
-                }
-            return null;
+                        }
+                );
             }
+        }
 
-            protected void onPostExecute(Void unused) {
-                if (mDataSetChanged) {
-                    notifyDataSetChanged();
+        public void deleteAllOrigins() {
+            if (mPermServ != null) {
+                Set<String> origins = mPermServ.getOrigins();
+                String[] originArray = origins.toArray(new String[origins.size()]);
+                for (String origin : originArray) {
+                    PermissionsServiceFactory.PermissionsService.OriginInfo info =
+                            mPermServ.getOriginInfo(origin);
+                    if (info != null) {
+                        mPermServ.deleteOriginInfo(info);
+                    }
+                }
+
+                WebRefiner refiner = WebRefiner.getInstance();
+                if (refiner != null) {
+                    refiner.useGlobalRulesForDomains(originArray);
                 }
             }
         }
 
-
-        public void populateOrigins(Map<String, Site> sites) {
+        private void populateOrigins(Map<String, Site> sites) {
             clear();
 
             // We can now simply populate our array with Site instances
@@ -407,70 +199,12 @@
             }
         }
 
-        public int getCount() {
-            if (mCurrentSite == null) {
-                return super.getCount();
-            }
-            return mCurrentSite.getFeatureCount();
-        }
-
-        public String sizeValueToString(long bytes) {
-            // We display the size in MB, to 1dp, rounding up to the next 0.1MB.
-            // bytes should always be greater than zero.
-            if (bytes <= 0) {
-                Log.e(LOGTAG, "sizeValueToString called with non-positive value: " + bytes);
-                return "0";
-            }
-            float megabytes = (float) bytes / (1024.0F * 1024.0F);
-            int truncated = (int) Math.ceil(megabytes * 10.0F);
-            float result = (float) (truncated / 10.0F);
-            return String.valueOf(result);
-        }
-
-        /*
-         * If we receive the back event and are displaying
-         * site's settings, we want to go back to the main
-         * list view. If not, we just do nothing (see
-         * dispatchKeyEvent() below).
-         */
-        public boolean backKeyPressed() {
-            if (mCurrentSite != null) {
-                mCurrentSite = null;
-                askForOrigins();
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * @hide
-         * Utility function
-         * Set the icon according to the usage
-         */
-        public void setIconForUsage(ImageView usageIcon, long usageInBytes) {
-            float usageInMegabytes = (float) usageInBytes / (1024.0F * 1024.0F);
-            // We set the correct icon:
-            // 0 < empty < 0.1MB
-            // 0.1MB < low < 5MB
-            // 5MB < high
-            if (usageInMegabytes <= 0.1) {
-                usageIcon.setImageBitmap(mUsageEmptyIcon);
-            } else if (usageInMegabytes > 0.1 && usageInMegabytes <= 5) {
-                usageIcon.setImageBitmap(mUsageLowIcon);
-            } else if (usageInMegabytes > 5) {
-                usageIcon.setImageBitmap(mUsageHighIcon);
-            }
-        }
-
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             View view;
             final TextView title;
             final TextView subtitle;
             final ImageView icon;
-            final ImageView usageIcon;
-            final ImageView locationIcon;
-            final ImageView featureIcon;
 
             if (convertView == null) {
                 view = mInflater.inflate(mResource, parent, false);
@@ -481,107 +215,31 @@
             title = (TextView) view.findViewById(R.id.title);
             subtitle = (TextView) view.findViewById(R.id.subtitle);
             icon = (ImageView) view.findViewById(R.id.icon);
-            featureIcon = (ImageView) view.findViewById(R.id.feature_icon);
-            usageIcon = (ImageView) view.findViewById(R.id.usage_icon);
-            locationIcon = (ImageView) view.findViewById(R.id.location_icon);
-            usageIcon.setVisibility(View.GONE);
-            locationIcon.setVisibility(View.GONE);
 
-            if (mCurrentSite == null) {
-
-                Site site = getItem(position);
-                title.setText(site.getPrettyTitle());
-                String subtitleText = site.getPrettyOrigin();
-                if (subtitleText != null) {
-                    title.setMaxLines(1);
-                    title.setSingleLine(true);
-                    subtitle.setVisibility(View.VISIBLE);
-                    subtitle.setText(subtitleText);
-                } else {
-                    subtitle.setVisibility(View.GONE);
-                    title.setMaxLines(2);
-                    title.setSingleLine(false);
-                }
-
-                icon.setVisibility(View.VISIBLE);
-                usageIcon.setVisibility(View.INVISIBLE);
-                locationIcon.setVisibility(View.INVISIBLE);
-                featureIcon.setVisibility(View.GONE);
-                Bitmap bmp = site.getIcon();
-                if (bmp == null) {
-                    bmp = mDefaultIcon;
-                }
-                icon.setImageBitmap(bmp);
-                // We set the site as the view's tag,
-                // so that we can get it in onItemClick()
-                view.setTag(site);
-
-                String origin = site.getOrigin();
-                if (site.hasFeature(Site.FEATURE_WEB_STORAGE)) {
-                    WebStorage.getInstance().getUsageForOrigin(origin, new ValueCallback<Long>() {
-                        public void onReceiveValue(Long value) {
-                            if (value != null) {
-                                setIconForUsage(usageIcon, value.longValue());
-                                usageIcon.setVisibility(View.VISIBLE);
-                            }
-                        }
-                    });
-                }
-
-                if (site.hasFeature(Site.FEATURE_GEOLOCATION)) {
-                    locationIcon.setVisibility(View.VISIBLE);
-                    GeolocationPermissions.getInstance().getAllowed(origin, new ValueCallback<Boolean>() {
-                        public void onReceiveValue(Boolean allowed) {
-                            if (allowed != null) {
-                                if (allowed.booleanValue()) {
-                                    locationIcon.setImageBitmap(mLocationAllowedIcon);
-                                } else {
-                                    locationIcon.setImageBitmap(mLocationDisallowedIcon);
-                                }
-                            }
-                        }
-                    });
-                }
+            Site site = getItem(position);
+            title.setText(site.getPrettyTitle());
+            String subtitleText = site.getPrettyOrigin();
+            if (subtitleText != null) {
+                title.setMaxLines(1);
+                title.setSingleLine(true);
+                subtitle.setVisibility(View.VISIBLE);
+                subtitle.setText(subtitleText);
             } else {
-                icon.setVisibility(View.GONE);
-                locationIcon.setVisibility(View.GONE);
-                usageIcon.setVisibility(View.GONE);
-                featureIcon.setVisibility(View.VISIBLE);
-                String origin = mCurrentSite.getOrigin();
-                switch (mCurrentSite.getFeatureByIndex(position)) {
-                    case Site.FEATURE_WEB_STORAGE:
-                        WebStorage.getInstance().getUsageForOrigin(origin, new ValueCallback<Long>() {
-                            public void onReceiveValue(Long value) {
-                                if (value != null) {
-                                    String usage = sizeValueToString(value.longValue()) + " " + sMBStored;
-                                    title.setText(R.string.webstorage_clear_data_title);
-                                    subtitle.setText(usage);
-                                    subtitle.setVisibility(View.VISIBLE);
-                                    setIconForUsage(featureIcon, value.longValue());
-                                }
-                            }
-                        });
-                        break;
-                    case Site.FEATURE_GEOLOCATION:
-                        title.setText(R.string.geolocation_settings_page_title);
-                        GeolocationPermissions.getInstance().getAllowed(origin, new ValueCallback<Boolean>() {
-                            public void onReceiveValue(Boolean allowed) {
-                                if (allowed != null) {
-                                    if (allowed.booleanValue()) {
-                                        subtitle.setText(R.string.geolocation_settings_page_summary_allowed);
-                                        featureIcon.setImageBitmap(mLocationAllowedIcon);
-                                    } else {
-                                        subtitle.setText(R.string.geolocation_settings_page_summary_not_allowed);
-                                        featureIcon.setImageBitmap(mLocationDisallowedIcon);
-                                    }
-                                    subtitle.setVisibility(View.VISIBLE);
-                                }
-                            }
-                        });
-                        break;
-                }
+                subtitle.setVisibility(View.GONE);
+                title.setMaxLines(2);
+                title.setSingleLine(false);
             }
 
+            icon.setVisibility(View.VISIBLE);
+            Bitmap bmp = site.getIcon();
+            if (bmp == null) {
+                bmp = mDefaultIcon;
+            }
+            icon.setImageBitmap(bmp);
+            // We set the site as the view's tag,
+            // so that we can get it in onItemClick()
+            view.setTag(site);
+
             return view;
         }
 
@@ -589,142 +247,41 @@
                                 View view,
                                 int position,
                                 long id) {
-            if (mCurrentSite != null) {
-                switch (mCurrentSite.getFeatureByIndex(position)) {
-                    case Site.FEATURE_WEB_STORAGE:
-                        new AlertDialog.Builder(getContext())
-                            .setMessage(R.string.webstorage_clear_data_dialog_message)
-                            .setPositiveButton(R.string.webstorage_clear_data_dialog_ok_button,
-                                               new AlertDialog.OnClickListener() {
-                                public void onClick(DialogInterface dlg, int which) {
-                                    WebStorage.getInstance().deleteOrigin(mCurrentSite.getOrigin());
-                                    // If this site has no more features, then go back to the
-                                    // origins list.
-                                    mCurrentSite.removeFeature(Site.FEATURE_WEB_STORAGE);
-                                    if (mCurrentSite.getFeatureCount() == 0) {
-                                        finish();
-                                    }
-                                    askForOrigins();
-                                    notifyDataSetChanged();
-                                }})
-                            .setNegativeButton(R.string.webstorage_clear_data_dialog_cancel_button, null)
-                            .setIconAttribute(android.R.attr.alertDialogIcon)
-                            .show();
-                        break;
-                    case Site.FEATURE_GEOLOCATION:
-                        final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
-                        final String origin = mCurrentSite.getOrigin();
-                        final GeolocationPermissions geolocationPermissions
-                            = GeolocationPermissions.getInstance();
+            Site site = (Site) view.getTag();
+            Activity activity = getActivity();
+            if (activity != null) {
+                Bundle args = new Bundle();
+                args.putString(SiteSpecificPreferencesFragment.EXTRA_ORIGIN, site.getOrigin());
 
-                        DialogInterface.OnClickListener alertDialogListener =
-                                new AlertDialog.OnClickListener() {
-                            public void onClick(DialogInterface dlg, int which) {
-                                GeolocationPermissions geolocationPermissions =
-                                        GeolocationPermissions.getInstance();
-                                String origin = mCurrentSite.getOrigin();
-                                int selectedPosition = ((AlertDialog)dlg)
-                                        .getListView().getCheckedItemPosition();
-                                switch (selectedPosition) {
-                                    case 0: // Deny forever
-                                        geolocationPermissions.deny(origin);
-                                        break;
-                                    case 1:
-                                        // Allow for 24 hours
-                                        geolocationPermissions.allow(origin,
-                                                System.currentTimeMillis() + MILLIS_PER_DAY);
-                                        break;
-                                    case 2: // Allow forever
-                                        geolocationPermissions.allow(origin);
-                                        break;
-                                    case 3: // Always ask
-                                        geolocationPermissions.clear(origin);
-                                        mCurrentSite.removeFeature(Site.FEATURE_GEOLOCATION);
-                                        if (mCurrentSite.getFeatureCount() == 0) {
-                                            finish();
-                                        }
-                                        break;
-                                    default:
-                                        break;
-                                }
-                                askForOrigins();
-                                notifyDataSetChanged();
-                            }};
+                FragmentManager fragmentManager = activity.getFragmentManager();
+                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
 
-                        builder.setTitle(String.format(getResources()
-                                .getString(R.string.geolocation_settings_page_dialog_title),
-                                    "http".equals(Uri.parse(mCurrentSite.getOrigin()).getScheme()) ?
-                                            origin.substring(7) : origin ))
-                            .setPositiveButton(R.string.geolocation_settings_page_dialog_ok_button,
-                                               alertDialogListener)
-                            .setNegativeButton(R.string.geolocation_settings_page_dialog_cancel_button, null);
-
-                        switch(geolocationPermissions.getContentSetting(origin)) {
-                            case BLOCK:
-                                builder.setSingleChoiceItems(R.array.geolocation_settings_choices,
-                                        0, null);
-                                break;
-                            case ALLOW_24H:
-                                builder.setSingleChoiceItems(R.array.geolocation_settings_choices,
-                                        1, null);
-                                break;
-                            case ALLOW:
-                                builder.setSingleChoiceItems(R.array.geolocation_settings_choices,
-                                        2, null);
-                                break;
-                        }
-                        builder.show();
-                }
-            } else {
-                Site site = (Site) view.getTag();
-                Activity activity = getActivity();
-                if (activity != null) {
-                    Bundle args = new Bundle();
-                    args.putParcelable(EXTRA_SITE, site);
-
-                    FragmentManager fragmentManager = activity.getFragmentManager();
-                    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
-
-                    Fragment newFragment = new WebsiteSettingsFragment();
-                    newFragment.setArguments(args);
-                    fragmentTransaction.replace(getId(), newFragment);
-                    fragmentTransaction.addToBackStack(null);
-                    fragmentTransaction.commit();
-                }
+                Fragment newFragment = new SiteSpecificPreferencesFragment();
+                newFragment.setArguments(args);
+                fragmentTransaction.replace(getId(), newFragment);
+                fragmentTransaction.addToBackStack(null);
+                fragmentTransaction.commit();
             }
         }
-
-        public Site currentSite() {
-            return mCurrentSite;
-        }
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         View view = inflater.inflate(R.layout.swe_website_settings, container, false);
-        Bundle args = getArguments();
-        if (args != null) {
-            mSite = (Site) args.getParcelable(EXTRA_SITE);
-        }
-        if (mSite == null) {
-            View clear = view.findViewById(R.id.clear_all_button);
-            clear.setVisibility(View.VISIBLE);
-            clear.setOnClickListener(this);
-        }
+        View new_site = view.findViewById(R.id.add_new_site);
+        new_site.setVisibility(View.VISIBLE);
+        new_site.setOnClickListener(this);
+        View clear = view.findViewById(R.id.clear_all_button);
+        clear.setVisibility(View.VISIBLE);
+        clear.setOnClickListener(this);
         return view;
     }
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        if (sMBStored == null) {
-            sMBStored = getString(R.string.webstorage_origin_summary_mb_stored);
-        }
         mAdapter = new SiteAdapter(getActivity(), R.layout.website_settings_row);
-        if (mSite != null) {
-            mAdapter.mCurrentSite = mSite;
-        }
         getListView().setAdapter(mAdapter);
         getListView().setOnItemClickListener(mAdapter);
     }
@@ -738,6 +295,7 @@
             bar.setTitle(R.string.pref_extras_website_settings);
             bar.setDisplayHomeAsUpEnabled(false);
             bar.setHomeButtonEnabled(false);
+            bar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.accent)));
         }
     }
 
@@ -752,24 +310,53 @@
     public void onClick(View v) {
         switch (v.getId()) {
         case R.id.clear_all_button:
-         // Show the prompt to clear all origins of their data and geolocation permissions.
+            // Show the prompt to clear all origins of their data and geolocation permissions.
             new AlertDialog.Builder(getActivity())
-                    .setMessage(R.string.website_settings_clear_all_dialog_message)
-                    .setPositiveButton(R.string.website_settings_clear_all_dialog_ok_button,
+                .setMessage(R.string.website_settings_clear_all_dialog_message)
+                .setPositiveButton(R.string.website_settings_clear_all_dialog_ok_button,
+                        new AlertDialog.OnClickListener() {
+                            public void onClick(DialogInterface dlg, int which) {
+                                mAdapter.deleteAllOrigins();
+                                WebStorage.getInstance().deleteAllData();
+                                GeolocationPermissions.getInstance().clearAll();
+                                if (GeolocationPermissions.isIncognitoCreated()) {
+                                    GeolocationPermissions.getIncognitoInstance().clearAll();
+                                }
+                                WebStorageSizeManager.resetLastOutOfSpaceNotificationTime();
+                                mAdapter.askForOrigins();
+                                finish();
+                            }
+                        })
+                .setNegativeButton(R.string.website_settings_clear_all_dialog_cancel_button, null)
+                .setIconAttribute(android.R.attr.alertDialogIcon)
+                .show();
+            break;
+        case R.id.add_new_site:
+            final EditText input = new EditText(getActivity());
+            new AlertDialog.Builder(getActivity())
+                    .setTitle(R.string.website_settings_add_origin)
+                    .setMessage(R.string.pref_security_origin_name)
+                    .setView(input)
+                    .setPositiveButton(R.string.pref_security_add,
                             new AlertDialog.OnClickListener() {
-                                public void onClick(DialogInterface dlg, int which) {
-                                    WebStorage.getInstance().deleteAllData();
-                                    GeolocationPermissions.getInstance().clearAll();
-                                    if (GeolocationPermissions.isIncognitoCreated()) {
-                                        GeolocationPermissions.getIncognitoInstance().clearAll();
-                                    }
-                                    WebStorageSizeManager.resetLastOutOfSpaceNotificationTime();
-                                    mAdapter.askForOrigins();
-                                    finish();
+                                public void onClick(DialogInterface dialog, int whichButton) {
+                                    String origin = input.getText().toString();
+                                    Bundle args = new Bundle();
+                                    args.putString(SiteSpecificPreferencesFragment.EXTRA_SITE,
+                                            origin);
+
+                                    FragmentTransaction fragmentTransaction =
+                                            getActivity().getFragmentManager().beginTransaction();
+
+                                    Fragment newFragment = new SiteSpecificPreferencesFragment();
+                                    newFragment.setArguments(args);
+                                    fragmentTransaction.replace(getId(), newFragment);
+                                    fragmentTransaction.addToBackStack(null);
+                                    fragmentTransaction.commit();
                                 }})
-                    .setNegativeButton(R.string.website_settings_clear_all_dialog_cancel_button, null)
-                    .setIconAttribute(android.R.attr.alertDialogIcon)
+                    .setNegativeButton(R.string.pref_security_cancel, null)
                     .show();
+
             break;
         }
     }