package com.borqs.browser; import org.chromium.content.browser.ContentView; import org.chromium.content.browser.ContentSettings; import android.app.ActivityManager; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.preference.PreferenceManager; import android.util.DisplayMetrics; import android.os.Build; import android.content.SharedPreferences.Editor; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.provider.Settings; import android.content.ContentResolver; import android.provider.Browser; import android.webkit.WebIconDatabase; import android.webkit.WebSettings.PluginState; //import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebStorage; import android.webkit.CookieManager; import android.webkit.GeolocationPermissions; import com.borqs.browser.homepages.HomeProvider; import com.borqs.browser.provider.BrowserProvider; import com.borqs.browser.search.SearchEngine; import com.borqs.browser.search.SearchEngines; //import com.borqs.provider.Browser; import java.lang.ref.WeakReference; import java.util.Iterator; import java.util.LinkedList; import java.util.WeakHashMap; import android.util.Log; public class BrowserSettings implements OnSharedPreferenceChangeListener, PreferenceKeys { // TODO: Do something with this UserAgent stuff private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " + "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " + "Chrome/11.0.696.34 Safari/534.24"; private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " + "CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 " + "(KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7"; private static final String IPAD_USERAGENT = "Mozilla/5.0 (iPad; U; " + "CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " + "(KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10"; private static final String FROYO_USERAGENT = "Mozilla/5.0 (Linux; U; " + "Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 " + "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"; private static final String HONEYCOMB_USERAGENT = "Mozilla/5.0 (Linux; U; " + "Android 3.1; en-us; Xoom Build/HMJ25) AppleWebKit/534.13 " + "(KHTML, like Gecko) Version/4.0 Safari/534.13"; private static final String USER_AGENTS[] = { null, DESKTOP_USERAGENT, IPHONE_USERAGENT, IPAD_USERAGENT, FROYO_USERAGENT, HONEYCOMB_USERAGENT, }; // The minimum min font size // Aka, the lower bounds for the min font size range // which is 1:5..24 private static final int MIN_FONT_SIZE_OFFSET = 5; // The initial value in the text zoom range // This is what represents 100% in the SeekBarPreference range private static final int TEXT_ZOOM_START_VAL = 10; // The size of a single step in the text zoom range, in percent private static final int TEXT_ZOOM_STEP = 5; // The initial value in the double tap zoom range // This is what represents 100% in the SeekBarPreference range private static final int DOUBLE_TAP_ZOOM_START_VAL = 5; // The size of a single step in the double tap zoom range, in percent private static final int DOUBLE_TAP_ZOOM_STEP = 5; private static BrowserSettings sInstance; private Context mContext; private SharedPreferences mPrefs; //private LinkedList<WeakReference<WebSettings>> mManagedSettings; private LinkedList<WeakReference<ContentSettings>> mManagedSettings; private Controller mController; //private WebStorageSizeManager mWebStorageSizeManager; //private WeakHashMap<WebSettings, String> mCustomUserAgents; private WeakHashMap<ContentSettings, String> mCustomUserAgents; private static boolean sInitialized = false; private boolean mNeedsSharedSync = true; private float mFontSizeMult = 1.0f; // Current state of network-dependent settings private boolean mLinkPrefetchAllowed = true; // Cached values private int mPageCacheCapacity = 1; private String mAppCachePath; // Cached settings private SearchEngine mSearchEngine; private static String sFactoryResetUrl; public static void initialize(final Context context) { sInstance = new BrowserSettings(context); } public static BrowserSettings getInstance() { return sInstance; } private BrowserSettings(Context context) { mContext = context.getApplicationContext(); mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); mManagedSettings = new LinkedList<WeakReference<ContentSettings>>(); mCustomUserAgents = new WeakHashMap<ContentSettings, String>(); BackgroundHandler.execute(mSetup); } public void setController(Controller controller) { mController = controller; if (sInitialized) { syncSharedSettings(); } } public void startManagingSettings(ContentSettings settings) { Log.i("BrowserSettings", "startManagingSettings"); if (mNeedsSharedSync) { syncSharedSettings(); } synchronized (mManagedSettings) { syncStaticSettings(settings); syncSetting(settings); mManagedSettings.add(new WeakReference<ContentSettings>(settings)); } } public void stopManagingSettings(ContentSettings settings) { Iterator<WeakReference<ContentSettings>> iter = mManagedSettings.iterator(); while (iter.hasNext()) { WeakReference<ContentSettings> ref = iter.next(); if (ref.get() == settings) { iter.remove(); return; } } } private Runnable mSetup = new Runnable() { @Override public void run() { DisplayMetrics metrics = mContext.getResources().getDisplayMetrics(); mFontSizeMult = metrics.scaledDensity / metrics.density; // the cost of one cached page is ~3M (measured using nytimes.com). For // low end devices, we only cache one page. For high end devices, we try // to cache more pages, currently choose 5. /*if (ActivityManager.staticGetMemoryClass() > 16) { mPageCacheCapacity = 5; }*/ /*mWebStorageSizeManager = new WebStorageSizeManager(mContext, new WebStorageSizeManager.StatFsDiskInfo(getAppCachePath()), new WebStorageSizeManager.WebKitAppCacheInfo(getAppCachePath()));*/ // Workaround b/5254577 //CookieManager.getInstance().acceptCookie(); // Workaround b/5254577 mPrefs.registerOnSharedPreferenceChangeListener(BrowserSettings.this); if (Build.VERSION.CODENAME.equals("REL")) { // This is a release build, always startup with debug disabled setDebugEnabled(false); } if (mPrefs.contains(PREF_TEXT_SIZE)) { /* * Update from TextSize enum to zoom percent * SMALLEST is 50% * SMALLER is 75% * NORMAL is 100% * LARGER is 150% * LARGEST is 200% */ /*switch (getTextSize()) { case SMALLEST: setTextZoom(50); break; case SMALLER: setTextZoom(75); break; case LARGER: setTextZoom(150); break; case LARGEST: setTextZoom(200); break; }*/ mPrefs.edit().remove(PREF_TEXT_SIZE).apply(); } sFactoryResetUrl = mContext.getResources().getString(R.string.homepage_base); if (sFactoryResetUrl.indexOf("{CID}") != -1) { sFactoryResetUrl = sFactoryResetUrl.replace("{CID}", BrowserProvider.getClientId(mContext.getContentResolver())); } synchronized (BrowserSettings.class) { sInitialized = true; BrowserSettings.class.notifyAll(); } } }; private static void requireInitialization() { synchronized (BrowserSettings.class) { while (!sInitialized) { try { BrowserSettings.class.wait(); } catch (InterruptedException e) { } } } } /** * Syncs all the settings that have a Preference UI */ private void syncSetting(ContentSettings settings) { Log.i("BrowserSettings", "syncSetting"); settings.setGeolocationEnabled(enableGeolocation()); settings.setJavaScriptEnabled(enableJavascript()); //settings.setLightTouchEnabled(enableLightTouch()); //settings.setNavDump(enableNavDump()); settings.setDefaultTextEncodingName(getDefaultTextEncoding()); //settings.setDefaultZoom(getDefaultZoom()); settings.setMinimumFontSize(getMinimumFontSize()); settings.setMinimumLogicalFontSize(getMinimumFontSize()); settings.setPluginState(getPluginState()); settings.setTextZoom(getTextZoom()); settings.setLayoutAlgorithm(getLayoutAlgorithm()); settings.setJavaScriptCanOpenWindowsAutomatically(!blockPopupWindows()); settings.setLoadsImagesAutomatically(loadImages()); //settings.setLoadWithOverviewMode(loadPageInOverviewMode()); //settings.setSavePassword(rememberPasswords()); //settings.setSaveFormData(saveFormdata()); settings.setUseWideViewPort(isWideViewport()); String ua = mCustomUserAgents.get(settings); if (ua != null) { settings.setUserAgentString(ua); } else { settings.setUserAgentString(USER_AGENTS[getUserAgent()]); } } /** * Syncs all the settings that have no UI * These cannot change, so we only need to set them once per WebSettings */ private void syncStaticSettings(ContentSettings settings) { settings.setDefaultFontSize(16); settings.setDefaultFixedFontSize(13); // WebView inside Browser doesn't want initial focus to be set. settings.setShouldFocusFirstNode(false); // Browser supports multiple windows settings.setSupportMultipleWindows(true); // enable smooth transition for better performance during panning or // zooming //settings.setEnableSmoothTransition(true); // disable content url access settings.setAllowContentAccess(false); // HTML5 API flags settings.setAppCacheEnabled(true); settings.setDatabaseEnabled(true); settings.setDomStorageEnabled(true); // HTML5 configuration parametersettings. //settings.setAppCacheMaxSize(getWebStorageSizeManager().getAppCacheMaxSize()); settings.setAppCachePath(getAppCachePath()); //settings.setDatabasePath(mContext.getDir("databases", 0).getPath()); //settings.setGeolocationDatabasePath(mContext.getDir("geolocation", 0).getPath()); // origin policy for file access settings.setAllowUniversalAccessFromFileURLs(false); settings.setAllowFileAccessFromFileURLs(false); } private String getAppCachePath() { if (mAppCachePath == null) { mAppCachePath = mContext.getDir("appcache", 0).getPath(); } return mAppCachePath; } public boolean isDebugEnabled() { //return false; requireInitialization(); return mPrefs.getBoolean(PREF_DEBUG_MENU, false); } public void setDebugEnabled(boolean value) { Editor edit = mPrefs.edit(); edit.putBoolean(PREF_DEBUG_MENU, value); if (!value) { // Reset to "safe" value edit.putBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false); } edit.apply(); } public void clearCache() { WebIconDatabase.getInstance().removeAllIcons(); if (mController != null) { ContentView current = mController.getCurrentWebView(); if (current != null) { //current.clearCache(true); } } } public void resetDefaultPreferences() { // Preserve autologin setting long gal = mPrefs.getLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, -1); mPrefs.edit() .clear() .putLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, gal) .apply(); resetCachedValues(); Log.i("BrowserSettings", "resetDefaultPreferences"); syncManagedSettings(); } private void resetCachedValues() { updateSearchEngine(false); } /*@Deprecated private TextSize getTextSize() { String textSize = mPrefs.getString(PREF_TEXT_SIZE, "NORMAL"); return TextSize.valueOf(textSize); }*/ private void syncSharedSettings() { Log.i("BrowserSettings", "syncSharedSettings"); mNeedsSharedSync = false; //CookieManager.getInstance().setAcceptCookie(acceptCookies()); if (mController != null) { mController.setShouldShowErrorConsole(enableJavascriptConsole()); } } private void syncManagedSettings() { Log.i("BrowserSettings", "syncManagedSettings"); syncSharedSettings(); synchronized (mManagedSettings) { Log.i("BrowserSettings", "syncManagedSettings:synchronized"); Iterator<WeakReference<ContentSettings>> iter = mManagedSettings.iterator(); Log.i("BrowserSettings", "syncManagedSettings, mManagedSettings.size() : " + mManagedSettings.size()); while (iter.hasNext()) { Log.i("BrowserSettings", "syncManagedSettings:while"); WeakReference<ContentSettings> ref = iter.next(); ContentSettings settings = ref.get(); if (settings == null) { iter.remove(); continue; } syncSetting(settings); } } } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Log.i("BrowserSettings", "onSharedPreferenceChanged"); Log.i("BrowserSettings", "search engine : " + key); syncManagedSettings(); if (PREF_SEARCH_ENGINE.equals(key)) { updateSearchEngine(false); } else if (PREF_FULLSCREEN.equals(key)) { if (mController != null && mController.getUi() != null) { mController.getUi().setFullscreen(useFullscreen()); } } else if (PREF_ENABLE_QUICK_CONTROLS.equals(key)) { if (mController != null && mController.getUi() != null) { //mController.getUi().setUseQuickControls(sharedPreferences.getBoolean(key, false)); } } else if (PREF_LINK_PREFETCH.equals(key)) { updateConnectionType(); } } public static String getFactoryResetHomeUrl(Context context) { requireInitialization(); return sFactoryResetUrl; } public String getHomePage() { //return "http://www.baidu.com"; return mPrefs.getString(PREF_HOMEPAGE, getFactoryResetHomeUrl(mContext)); } public boolean hasDesktopUseragent(ContentView view) { return false; } public boolean enableNavDump() { return false; } /*public boolean isDebugEnabled() { //return false; requireInitialization(); return mPrefs.getBoolean(PREF_DEBUG_MENU, false); }*/ boolean allowAppTabs() { return false; } boolean openInBackground() { return false; } public void setLastRunPaused(boolean b) { // TODO Auto-generated method stub } public boolean enableJavascriptConsole() { if (!isDebugEnabled()) { return false; } return mPrefs.getBoolean(PREF_JAVASCRIPT_CONSOLE, true); } public boolean enableGeolocation() { return mPrefs.getBoolean(PREF_ENABLE_GEOLOCATION, true); } public boolean enableJavascript() { return mPrefs.getBoolean(PREF_ENABLE_JAVASCRIPT, true); } public boolean enableLightTouch() { if (!isDebugEnabled()) { return false; } return mPrefs.getBoolean(PREF_ENABLE_LIGHT_TOUCH, false); } public String getDefaultTextEncoding() { return mPrefs.getString(PREF_DEFAULT_TEXT_ENCODING, null); } public int getMinimumFontSize() { int minFont = mPrefs.getInt(PREF_MIN_FONT_SIZE, 0); return getAdjustedMinimumFontSize(minFont); } public static int getAdjustedMinimumFontSize(int rawValue) { rawValue++; // Preference starts at 0, min font at 1 if (rawValue > 1) { rawValue += (MIN_FONT_SIZE_OFFSET - 2); } return rawValue; } // TODO: Cache public PluginState getPluginState() { String state = mPrefs.getString(PREF_PLUGIN_STATE, "ON"); return PluginState.valueOf(state); } public int getTextZoom() { requireInitialization(); int textZoom = mPrefs.getInt(PREF_TEXT_ZOOM, 10); return getAdjustedTextZoom(textZoom); } public int getAdjustedTextZoom(int rawValue) { rawValue = (rawValue - TEXT_ZOOM_START_VAL) * TEXT_ZOOM_STEP; return (int) ((rawValue + 100) * mFontSizeMult); } public ContentSettings.LayoutAlgorithm getLayoutAlgorithm() { ContentSettings.LayoutAlgorithm layoutAlgorithm = ContentSettings.LayoutAlgorithm.NORMAL; if (autofitPages()) { layoutAlgorithm = ContentSettings.LayoutAlgorithm.NARROW_COLUMNS; } if (isDebugEnabled()) { if (isSmallScreen()) { layoutAlgorithm = ContentSettings.LayoutAlgorithm.SINGLE_COLUMN; } else { if (isNormalLayout()) { layoutAlgorithm = ContentSettings.LayoutAlgorithm.NORMAL; } else { layoutAlgorithm = ContentSettings.LayoutAlgorithm.NARROW_COLUMNS; } } } return layoutAlgorithm; } public boolean autofitPages() { return mPrefs.getBoolean(PREF_AUTOFIT_PAGES, true); } public boolean isSmallScreen() { if (!isDebugEnabled()) { return false; } return mPrefs.getBoolean(PREF_SMALL_SCREEN, false); } public boolean isNormalLayout() { if (!isDebugEnabled()) { return false; } return mPrefs.getBoolean(PREF_NORMAL_LAYOUT, false); } public boolean blockPopupWindows() { return mPrefs.getBoolean(PREF_BLOCK_POPUP_WINDOWS, true); } public boolean loadImages() { return mPrefs.getBoolean(PREF_LOAD_IMAGES, true); } public boolean loadPageInOverviewMode() { return mPrefs.getBoolean(PREF_LOAD_PAGE, true); } public boolean isWideViewport() { if (!isDebugEnabled()) { return true; } return mPrefs.getBoolean(PREF_WIDE_VIEWPORT, true); } public int getUserAgent() { if (!isDebugEnabled()) { return 0; } return Integer.parseInt(mPrefs.getString(PREF_USER_AGENT, "0")); } /*public WebStorageSizeManager getWebStorageSizeManager() { requireInitialization(); return mWebStorageSizeManager; }*/ private void updateSearchEngine(boolean force) { String searchEngineName = getSearchEngineName(); Log.i("BrowserSettings", "updateSearchEngine, searchEngineName: " + searchEngineName); if (force || mSearchEngine == null || !mSearchEngine.getName().equals(searchEngineName)) { if (mSearchEngine != null) { mSearchEngine.close(); } mSearchEngine = SearchEngines.get(mContext, searchEngineName); Log.i("BrowserSettings", "updateSearchEngine, mSearchEngine: " + mSearchEngine); } } public String getSearchEngineName() { return mPrefs.getString(PREF_SEARCH_ENGINE, SearchEngine.GOOGLE); //return ""; } public SharedPreferences getPreferences() { return mPrefs; } // update connectivity-dependent options public void updateConnectionType() { ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); String linkPrefetchPreference = getLinkPrefetchEnabled(); boolean linkPrefetchAllowed = linkPrefetchPreference. equals(getLinkPrefetchAlwaysPreferenceString(mContext)); NetworkInfo ni = cm.getActiveNetworkInfo(); if (ni != null) { switch (ni.getType()) { case ConnectivityManager.TYPE_WIFI: case ConnectivityManager.TYPE_ETHERNET: case ConnectivityManager.TYPE_BLUETOOTH: linkPrefetchAllowed |= linkPrefetchPreference. equals(getLinkPrefetchOnWifiOnlyPreferenceString(mContext)); break; case ConnectivityManager.TYPE_MOBILE: case ConnectivityManager.TYPE_MOBILE_DUN: case ConnectivityManager.TYPE_MOBILE_MMS: case ConnectivityManager.TYPE_MOBILE_SUPL: case ConnectivityManager.TYPE_WIMAX: default: break; } } if (mLinkPrefetchAllowed != linkPrefetchAllowed) { mLinkPrefetchAllowed = linkPrefetchAllowed; Log.i("BrowserSettings", "updateConnectionType"); syncManagedSettings(); } } public String getDefaultLinkPrefetchSetting() { String preload = Settings.Secure.getString(mContext.getContentResolver(), DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY); if (preload == null) { preload = mContext.getResources().getString(R.string.pref_link_prefetch_default_value); } return preload; } public String getLinkPrefetchEnabled() { return mPrefs.getString(PREF_LINK_PREFETCH, getDefaultLinkPrefetchSetting()); } public static String getLinkPrefetchOnWifiOnlyPreferenceString(Context context) { return context.getResources().getString(R.string.pref_link_prefetch_value_wifi_only); } public static String getLinkPrefetchAlwaysPreferenceString(Context context) { return context.getResources().getString(R.string.pref_link_prefetch_value_always); } private static final String DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY = "browser_default_link_prefetch_setting"; public int getDoubleTapZoom() { requireInitialization(); int doubleTapZoom = mPrefs.getInt(PREF_DOUBLE_TAP_ZOOM, 5); return getAdjustedDoubleTapZoom(doubleTapZoom); } public int getAdjustedDoubleTapZoom(int rawValue) { rawValue = (rawValue - DOUBLE_TAP_ZOOM_START_VAL) * DOUBLE_TAP_ZOOM_STEP; return (int) ((rawValue + 100) * mFontSizeMult); } public float getInvertedContrast() { return 1 + (mPrefs.getInt(PREF_INVERTED_CONTRAST, 0) / 10f); } public boolean useMostVisitedHomepage() { return HomeProvider.MOST_VISITED.equals(getHomePage()); } private static final String DEAULT_PRELOAD_SECURE_SETTING_KEY = "browser_default_preload_setting"; public String getDefaultPreloadSetting() { String preload = Settings.Secure.getString(mContext.getContentResolver(), DEAULT_PRELOAD_SECURE_SETTING_KEY); if (preload == null) { preload = mContext.getResources().getString(R.string.pref_data_preload_default_value); } return preload; } public void setHomePage(String value) { mPrefs.edit().putString(PREF_HOMEPAGE, value).apply(); } public boolean useInverteRendering() { return mPrefs.getBoolean(PREF_INVERTED, false); } public SearchEngine getSearchEngine() { if (mSearchEngine == null) { updateSearchEngine(false); } return mSearchEngine; } public boolean useFullscreen() { return mPrefs.getBoolean(PREF_FULLSCREEN, false); } public String getJsEngineFlags() { if (!isDebugEnabled()) { return ""; } return mPrefs.getString(PREF_JS_ENGINE_FLAGS, ""); } public void clearDatabases() { WebStorage.getInstance().deleteAllData(); } public void clearCookies() { CookieManager.getInstance().removeAllCookie(); } public void clearHistory() { ContentResolver resolver = mContext.getContentResolver(); Browser.clearHistory(resolver); Browser.clearSearches(resolver); } public void clearFormData() { /*WebViewDatabase.getInstance(mContext).clearFormData(); if (mController!= null) { WebView currentTopView = mController.getCurrentTopWebView(); if (currentTopView != null) { currentTopView.clearFormData(); } }*/ } public void clearPasswords() { /*WebViewDatabase db = WebViewDatabase.getInstance(mContext); db.clearUsernamePassword(); db.clearHttpAuthUsernamePassword();*/ } public void clearLocationAccess() { GeolocationPermissions.getInstance().clearAll(); } public boolean acceptCookies() { return mPrefs.getBoolean(PREF_ACCEPT_COOKIES, true); } public boolean useInvertedRendering() { return mPrefs.getBoolean(PREF_INVERTED, false); } }