diff options
Diffstat (limited to 'src/src/com/android/browser/preferences')
19 files changed, 3477 insertions, 0 deletions
diff --git a/src/src/com/android/browser/preferences/AboutPreferencesFragment.java b/src/src/com/android/browser/preferences/AboutPreferencesFragment.java new file mode 100644 index 00000000..7d143205 --- /dev/null +++ b/src/src/com/android/browser/preferences/AboutPreferencesFragment.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2014, 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.net.Uri; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.provider.Browser; + +import com.android.browser.BrowserActivity; +import com.android.browser.BrowserPreferencesPage; +import com.android.browser.BrowserSwitches; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; +import com.android.browser.UpdateNotificationService; + +import org.codeaurora.swe.BrowserCommandLine; + +public class AboutPreferencesFragment extends PreferenceFragment + implements OnPreferenceClickListener { + + final String ABOUT_TEXT_VERSION_KEY = "Version:"; + final String ABOUT_TEXT_BUILT_KEY = "Built:"; + final String ABOUT_TEXT_HASH_KEY = "Hash:"; + + String mFeedbackRecipient = ""; + String mHelpURL = ""; + String mVersion = ""; + String mBuilt = ""; + String mHash = ""; + String mTabTitle = ""; + String mTabURL = ""; + + String mAboutText = ""; + PreferenceScreen mHeadPref = null; + + private String findValueFromAboutText(String aboutKey) { + int start = mAboutText.indexOf(aboutKey); + int end = mAboutText.indexOf("\n", start); + String value = ""; + + if (start != -1 && end != -1) { + start += aboutKey.length(); + value = mAboutText.substring(start, end); + } + return value; + } + + private void setPreference(String prefKey, String value) { + Preference pref = findPreference(prefKey); + if (pref == null) { + return; + } + + if (value.isEmpty()) { + if (mHeadPref != null) + mHeadPref.removePreference(pref); + } else { + pref.setSummary(value); + } + } + + private void setOnClickListener(String prefKey, boolean set) { + Preference pref = findPreference(prefKey); + if (pref == null) { + return; + } + + if (set) { + pref.setOnPreferenceClickListener(this); + } else { + if (mHeadPref != null) + mHeadPref.removePreference(pref); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ActionBar bar = getActivity().getActionBar(); + if (bar != null) { + bar.setTitle(R.string.about); + } + + mAboutText = getString(R.string.about_text); + + addPreferencesFromResource(R.xml.about_preferences); + mHeadPref = (PreferenceScreen) findPreference(PreferenceKeys.PREF_ABOUT); + + mVersion = findValueFromAboutText(ABOUT_TEXT_VERSION_KEY); + setPreference(PreferenceKeys.PREF_VERSION, mVersion); + + mBuilt = findValueFromAboutText(ABOUT_TEXT_BUILT_KEY); + setPreference(PreferenceKeys.PREF_BUILD_DATE, mBuilt); + + mHash = findValueFromAboutText(ABOUT_TEXT_HASH_KEY); + setPreference(PreferenceKeys.PREF_BUILD_HASH, mHash); + + final Bundle arguments = getArguments(); + String user_agent = ""; + if (arguments != null) { + user_agent = (String) arguments.getCharSequence("UA", ""); + mTabTitle = (String) arguments.getCharSequence("TabTitle", ""); + mTabURL = (String) arguments.getCharSequence("TabURL", ""); + } + + setPreference(PreferenceKeys.PREF_USER_AGENT, user_agent); + + if (BrowserCommandLine.hasSwitch(BrowserSwitches.CMD_LINE_SWITCH_HELPURL)) { + mHelpURL = BrowserCommandLine.getSwitchValue( + BrowserSwitches.CMD_LINE_SWITCH_HELPURL); + } + + setOnClickListener(PreferenceKeys.PREF_HELP, !mHelpURL.isEmpty()); + + if (BrowserCommandLine.hasSwitch(BrowserSwitches.CMD_LINE_SWITCH_FEEDBACK)) { + mFeedbackRecipient = BrowserCommandLine.getSwitchValue( + BrowserSwitches.CMD_LINE_SWITCH_FEEDBACK); + } + + setOnClickListener(PreferenceKeys.PREF_FEEDBACK, !mFeedbackRecipient.isEmpty()); + + setOnClickListener(PreferenceKeys.PREF_LEGAL, true); + if (BrowserCommandLine.hasSwitch(BrowserSwitches.AUTO_UPDATE_SERVER_CMD)) { + setPreference(PreferenceKeys.PREF_AUTO_UPDATE, + UpdateNotificationService.getLatestVersion(getActivity())); + setOnClickListener(PreferenceKeys.PREF_AUTO_UPDATE, + UpdateNotificationService.getCurrentVersionCode(getActivity()) < + UpdateNotificationService.getLatestVersionCode(getActivity())); + } else { + Preference pref = findPreference(PreferenceKeys.PREF_AUTO_UPDATE); + if (mHeadPref != null) + mHeadPref.removePreference(pref); + } + + } + + @Override + public boolean onPreferenceClick(Preference preference) { + if (preference.getKey().equals(PreferenceKeys.PREF_HELP)) { + Intent intent = new Intent(getActivity(), BrowserActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(mHelpURL)); + getActivity().startActivity(intent); + return true; + } else if(preference.getKey().equals(PreferenceKeys.PREF_LEGAL)) { + Bundle bundle = new Bundle(); + BrowserPreferencesPage.startPreferenceFragmentExtraForResult(getActivity(), + LegalPreferencesFragment.class.getName(), bundle, 0); + return true; + } else if (preference.getKey().equals(PreferenceKeys.PREF_FEEDBACK)) { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("message/rfc822"); + intent.putExtra(Intent.EXTRA_EMAIL, new String[]{mFeedbackRecipient}); + intent.putExtra(Intent.EXTRA_SUBJECT,"Browser Feedback"); + + String message = ""; + if (!mVersion.isEmpty()) { + message += "Version: " + mVersion + "\n"; + } + + if (!mBuilt.isEmpty()) { + message += "Build Date: " + mBuilt + "\n"; + } + + if (!mHash.isEmpty()) { + message += "Build Hash: " + mHash + "\n"; + } + + if (!mTabTitle.isEmpty()) { + message += "Tab Title: " + mTabTitle + "\n"; + } + + if (!mTabURL.isEmpty()) { + message += "Tab URL: " + mTabURL + "\n"; + } + + message += "\nEnter your feedback here..."; + + intent.putExtra(Intent.EXTRA_TEXT, message); + startActivity(Intent.createChooser(intent, "Select email application")); + return true; + } else if (preference.getKey().equals(PreferenceKeys.PREF_AUTO_UPDATE)) { + Intent intent = new Intent(getActivity(), BrowserActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, getActivity().getPackageName()); + intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); + intent.setData(Uri.parse( + UpdateNotificationService.getLatestDownloadUrl(getActivity()))); + getActivity().startActivity(intent); + } + return false; + } +} diff --git a/src/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java b/src/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java new file mode 100644 index 00000000..a505836b --- /dev/null +++ b/src/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.browser.preferences; + +import android.app.ActionBar; +import android.content.Context; +import android.os.Bundle; +import android.preference.Preference; +import android.util.Log; + +import com.android.browser.BrowserSettings; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; + +import java.text.NumberFormat; + +public class AccessibilityPreferencesFragment extends SWEPreferenceFragment + implements Preference.OnPreferenceChangeListener { + + NumberFormat mFormat; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.accessibility_preferences); + BrowserSettings settings = BrowserSettings.getInstance(); + mFormat = NumberFormat.getPercentInstance(); + + Preference e = findPreference(PreferenceKeys.PREF_MIN_FONT_SIZE); + e.setOnPreferenceChangeListener(this); + updateMinFontSummary(e, settings.getMinimumFontSize()); + e = findPreference(PreferenceKeys.PREF_TEXT_ZOOM); + e.setOnPreferenceChangeListener(this); + updateTextZoomSummary(e, settings.getTextZoom()); + + /* SWE: Comment out double tap zoom feature + e = findPreference(PreferenceKeys.PREF_DOUBLE_TAP_ZOOM); + e.setOnPreferenceChangeListener(this); + updateDoubleTapZoomSummary(e, settings.getDoubleTapZoom()); + */ + /* + * SWE_TODO: Commented out functionality for inverted rendering + * (as well as corresponding sections below) + e = findPreference(PreferenceKeys.PREF_INVERTED_CONTRAST); + e.setOnPreferenceChangeListener(this); + updateInvertedContrastSummary(e, (int) (settings.getInvertedContrast() * 100)); + */ + } + + @Override + public void onResume() { + super.onResume(); + ActionBar bar = getActivity().getActionBar(); + if (bar != null) { + bar.setTitle(R.string.pref_accessibility_title); + bar.setDisplayHomeAsUpEnabled(false); + bar.setHomeButtonEnabled(false); + } + } + + void updateMinFontSummary(Preference pref, int minFontSize) { + Context c = getActivity(); + pref.setSummary(c.getString(R.string.pref_min_font_size_value, minFontSize)); + } + + void updateTextZoomSummary(Preference pref, int textZoom) { + pref.setSummary(mFormat.format(textZoom / 100.0)); + } + + void updateDoubleTapZoomSummary(Preference pref, int doubleTapZoom) { + pref.setSummary(mFormat.format(doubleTapZoom / 100.0)); + } + + /* + void updateInvertedContrastSummary(Preference pref, int contrast) { + pref.setSummary(mFormat.format(contrast / 100.0)); + } + */ + + @Override + public boolean onPreferenceChange(Preference pref, Object objValue) { + if (getActivity() == null) { + // We aren't attached, so don't accept preferences changes from the + // invisible UI. + Log.d("AccessibilityPref", "Activity is null"); + return false; + } + Log.d("AccessibilityPref", "User clicked on " + pref.getKey()); + + if (PreferenceKeys.PREF_MIN_FONT_SIZE.equals(pref.getKey())) { + updateMinFontSummary(pref, BrowserSettings + .getAdjustedMinimumFontSize((Integer) objValue)); + } + if (PreferenceKeys.PREF_TEXT_ZOOM.equals(pref.getKey())) { + BrowserSettings settings = BrowserSettings.getInstance(); + updateTextZoomSummary(pref, settings + .getAdjustedTextZoom((Integer) objValue)); + } + if (PreferenceKeys.PREF_DOUBLE_TAP_ZOOM.equals(pref.getKey())) { + BrowserSettings settings = BrowserSettings.getInstance(); + updateDoubleTapZoomSummary(pref, settings + .getAdjustedDoubleTapZoom((Integer) objValue)); + } + /* + if (PreferenceKeys.PREF_INVERTED_CONTRAST.equals(pref.getKey())) { + updateInvertedContrastSummary(pref, + (int) ((10 + (Integer) objValue) * 10)); + } + */ + + return true; + } + +} diff --git a/src/src/com/android/browser/preferences/AdvancedPreferencesFragment.java b/src/src/com/android/browser/preferences/AdvancedPreferencesFragment.java new file mode 100644 index 00000000..3d988947 --- /dev/null +++ b/src/src/com/android/browser/preferences/AdvancedPreferencesFragment.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.browser.preferences; + +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.content.Intent; +import android.content.SharedPreferences.Editor; +import android.net.Uri; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.util.Log; + +import com.android.browser.BaseUi; +import com.android.browser.BrowserActivity; +import com.android.browser.BrowserSettings; +import com.android.browser.BrowserYesNoPreference; +import com.android.browser.DownloadHandler; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; + +public class AdvancedPreferencesFragment + implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener { + + PreferenceFragment mFragment = null; + + AdvancedPreferencesFragment(PreferenceFragment fragment) { + mFragment = fragment; + + Preference e = mFragment.findPreference(PreferenceKeys.PREF_RESET_DEFAULT_PREFERENCES); + e.setOnPreferenceChangeListener(this); + + e = mFragment.findPreference(PreferenceKeys.PREF_SEARCH_ENGINE); + 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"); + category.removePreference(e); + } else { + e.setOnPreferenceClickListener(this); + } + + e = mFragment.findPreference("accessibility_menu"); + e.setOnPreferenceClickListener(this); + + // Below are preferences for carrier specific features + PreferenceScreen contentSettingsPrefScreen = + (PreferenceScreen) mFragment.findPreference("content_settings"); + contentSettingsPrefScreen.setOnPreferenceClickListener(this); + + ListPreference edgeSwipePref = + (ListPreference) mFragment.findPreference("edge_swiping_action"); + edgeSwipePref.setOnPreferenceChangeListener(this); + + if (BaseUi.isUiLowPowerMode()) { + edgeSwipePref.setEnabled(false); + } else { + String[] options = mFragment.getResources().getStringArray( + R.array.pref_edge_swiping_values); + + String value = BrowserSettings.getInstance().getEdgeSwipeAction(); + + if (value.equals(mFragment.getString(R.string.value_unknown_edge_swipe))) { + edgeSwipePref.setSummary(mFragment.getString(R.string.pref_edge_swipe_unknown)); + } else { + for (int i = 0; i < options.length; i++) { + if (value.equals(options[i])) { + edgeSwipePref.setValueIndex(i); + break; + } + } + } + } + } + + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + 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); + String downloadPath = intent.getStringExtra(result_dir_sel); + // Fallback logic to stock browser + if (downloadPath == null) { + Uri uri = intent.getData(); + if(uri != null) + downloadPath = uri.getPath(); + } + if (downloadPath != null) { + PreferenceScreen downloadPathPreset = + (PreferenceScreen) mFragment.findPreference( + PreferenceKeys.PREF_DOWNLOAD_PATH); + Editor editor = downloadPathPreset.getEditor(); + editor.putString(PreferenceKeys.PREF_DOWNLOAD_PATH, downloadPath); + editor.apply(); + String downloadPathForUser = DownloadHandler.getDownloadPathForUser( + mFragment.getActivity(), downloadPath); + downloadPathPreset.setSummary(downloadPathForUser); + } + + return; + } + } + return; + } + + void updateListPreferenceSummary(ListPreference e) { + e.setSummary(e.getEntry()); + } + + /* + * We need to set the PreferenceScreen state in onResume(), as the number of + * origins with active features (WebStorage, Geolocation etc) could have + * changed after calling the WebsiteSettingsActivity. + */ + public void onResume() { + } + + @Override + public boolean onPreferenceChange(Preference pref, Object objValue) { + if (mFragment.getActivity() == null) { + // We aren't attached, so don't accept preferences changes from the + // invisible UI. + Log.w("PageContentPreferencesFragment", "onPreferenceChange called from detached fragment!"); + return false; + } + if(pref.getKey().equals("edge_swiping_action")){ + ListPreference lp = (ListPreference) pref; + lp.setValue((String) objValue); + updateListPreferenceSummary(lp); + return true; + } + + else if (pref.getKey().equals(PreferenceKeys.PREF_RESET_DEFAULT_PREFERENCES)) { + Integer value = (Integer) objValue; + if (value.intValue() != BrowserYesNoPreference.CANCEL_BTN) { + BrowserSettings settings = BrowserSettings.getInstance(); + if (value.intValue() == BrowserYesNoPreference.OTHER_BTN) { + settings.clearCache(); + settings.clearDatabases(); + settings.clearCookies(); + settings.clearHistory(); + settings.clearFormData(); + settings.clearPasswords(); + settings.clearLocationAccess(); + } + + settings.resetDefaultPreferences(); + mFragment.startActivity(new Intent(BrowserActivity.ACTION_RESTART, null, + mFragment.getActivity(), BrowserActivity.class)); + return true; + } + + } else if (pref.getKey().equals(PreferenceKeys.PREF_SEARCH_ENGINE)) { + ListPreference lp = (ListPreference) pref; + lp.setValue((String) objValue); + updateListPreferenceSummary(lp); + return false; + } + return false; + } + + @Override + public boolean onPreferenceClick(Preference preference) { + FragmentManager fragmentManager = mFragment.getFragmentManager(); + + if (preference.getKey().equals(PreferenceKeys.PREF_DEBUG_MENU)) { + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + Fragment newFragment = new DebugPreferencesFragment(); + fragmentTransaction.replace(mFragment.getId(), newFragment); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + return true; + } else if (preference.getKey().equals("accessibility_menu")) { + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + Fragment newFragment = new AccessibilityPreferencesFragment(); + fragmentTransaction.replace(mFragment.getId(), newFragment); + 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/src/com/android/browser/preferences/BandwidthPreferencesFragment.java b/src/src/com/android/browser/preferences/BandwidthPreferencesFragment.java new file mode 100644 index 00000000..0cb064ab --- /dev/null +++ b/src/src/com/android/browser/preferences/BandwidthPreferencesFragment.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.browser.preferences; + +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.ListPreference; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; + +import com.android.browser.BrowserSettings; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; + +public class BandwidthPreferencesFragment extends PreferenceFragment { + + static final String TAG = "BandwidthPreferencesFragment"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Load the XML preferences file + addPreferencesFromResource(R.xml.bandwidth_preferences); + } + + @Override + public void onResume() { + super.onResume(); + PreferenceScreen prefScreen = getPreferenceScreen(); + SharedPreferences sharedPrefs = prefScreen.getSharedPreferences(); + if (!sharedPrefs.contains(PreferenceKeys.PREF_DATA_PRELOAD)) { + // set default value for preload setting + ListPreference preload = (ListPreference) prefScreen.findPreference( + PreferenceKeys.PREF_DATA_PRELOAD); + if (preload != null) { + preload.setValue(BrowserSettings.getInstance().getDefaultPreloadSetting()); + } + } + if (!sharedPrefs.contains(PreferenceKeys.PREF_LINK_PREFETCH)) { + // set default value for link prefetch setting + ListPreference prefetch = (ListPreference) prefScreen.findPreference( + PreferenceKeys.PREF_LINK_PREFETCH); + if (prefetch != null) { + prefetch.setValue(BrowserSettings.getInstance().getDefaultLinkPrefetchSetting()); + } + } + } + +} diff --git a/src/src/com/android/browser/preferences/ContentPreferencesFragment.java b/src/src/com/android/browser/preferences/ContentPreferencesFragment.java new file mode 100644 index 00000000..63bae5b9 --- /dev/null +++ b/src/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/src/com/android/browser/preferences/DebugPreferencesFragment.java b/src/src/com/android/browser/preferences/DebugPreferencesFragment.java new file mode 100644 index 00000000..2283fb6a --- /dev/null +++ b/src/src/com/android/browser/preferences/DebugPreferencesFragment.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.browser.preferences; + +import android.app.ActionBar; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.SwitchPreference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.Preference.OnPreferenceChangeListener; + +import com.android.browser.PreferenceKeys; +import com.android.browser.R; + +import org.codeaurora.swe.PermissionsServiceFactory; + +public class DebugPreferencesFragment extends SWEPreferenceFragment + implements OnPreferenceClickListener, OnPreferenceChangeListener { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Load the XML preferences file + addPreferencesFromResource(R.xml.debug_preferences); + + SwitchPreference pref = (SwitchPreference) findPreference(PreferenceKeys.PREF_DISABLE_PERF); + pref.setOnPreferenceChangeListener(this); + } + + @Override + public boolean onPreferenceChange(Preference pref, Object objValue) { + if (getActivity() == null) { + return false; + } + + if (pref.getKey().equals(PreferenceKeys.PREF_DISABLE_PERF)) { + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.WEBREFINER, (Boolean)objValue); + return true; + } + + return false; + } + + @Override + public boolean onPreferenceClick(Preference preference) { + return false; + } + + @Override + public void onResume() { + super.onResume(); + ActionBar bar = getActivity().getActionBar(); + if (bar != null) { + bar.setTitle(R.string.pref_development_title); + bar.setDisplayHomeAsUpEnabled(false); + bar.setHomeButtonEnabled(false); + } + } +} diff --git a/src/src/com/android/browser/preferences/FontSizePreview.java b/src/src/com/android/browser/preferences/FontSizePreview.java new file mode 100644 index 00000000..67d0bd7b --- /dev/null +++ b/src/src/com/android/browser/preferences/FontSizePreview.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.preferences; + +import android.content.Context; +import android.util.AttributeSet; +import com.android.browser.BrowserSettings; +import com.android.browser.R; + +import org.codeaurora.swe.WebSettings; + +public class FontSizePreview extends WebViewPreview { + + //default size for normal sized preview text + static final int DEFAULT_FONT_PREVIEW_SIZE = 13; + + public FontSizePreview( + Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public FontSizePreview(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FontSizePreview(Context context) { + super(context); + } + + @Override + protected void updatePreview(boolean forceReload) { + if (mWebView == null || mTextView == null) + return; + + WebSettings ws = mWebView.getSettings(); + BrowserSettings bs = BrowserSettings.getInstance(); + ws.setMinimumFontSize(bs.getMinimumFontSize()); + ws.setTextZoom(bs.getTextZoom()); + mTextView.setText(R.string.pref_sample_font_size); + mTextView.setTextSize(DEFAULT_FONT_PREVIEW_SIZE * bs.getTextZoom() / 100); + } +} diff --git a/src/src/com/android/browser/preferences/GeneralPreferencesFragment.java b/src/src/com/android/browser/preferences/GeneralPreferencesFragment.java new file mode 100644 index 00000000..9f610617 --- /dev/null +++ b/src/src/com/android/browser/preferences/GeneralPreferencesFragment.java @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.browser.preferences; + +import android.app.ActionBar; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceScreen; +import android.preference.SwitchPreference; +import android.text.InputType; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; +import android.widget.Toast; + +import com.android.browser.AutoFillSettingsFragment; +import com.android.browser.BrowserPreferencesPage; +import com.android.browser.BrowserSettings; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; +import com.android.browser.UrlUtils; +import com.android.browser.homepages.HomeProvider; +import com.android.browser.mdm.AutoFillRestriction; +import com.android.browser.mdm.SearchEngineRestriction; + +import org.codeaurora.swe.PermissionsServiceFactory; + +public class GeneralPreferencesFragment extends SWEPreferenceFragment + implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener { + + static final String TAG = "GeneralPreferencesFragment"; + + public static final String EXTRA_CURRENT_PAGE = "currentPage"; + + static final String BLANK_URL = "about:blank"; + static final String CURRENT = "current"; + static final String BLANK = "blank"; + static final String DEFAULT = "default"; + static final String MOST_VISITED = "most_visited"; + static final String OTHER = "other"; + + static final String PREF_HOMEPAGE_PICKER = "homepage_picker"; + static final String PREF_POWERSAVE = "powersave_enabled"; + + String[] mChoices, mValues; + String mCurrentPage; + + AdvancedPreferencesFragment mAdvFrag = null; + PrivacySecurityPreferencesFragment mPrivFrag = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Resources res = getActivity().getResources(); + mChoices = res.getStringArray(R.array.pref_homepage_choices); + mValues = res.getStringArray(R.array.pref_homepage_values); + mCurrentPage = getActivity().getIntent().getStringExtra(EXTRA_CURRENT_PAGE); + + // Load the XML preferences file + addPreferencesFromResource(R.xml.general_preferences); + + ListPreference pref = (ListPreference) findPreference(PREF_HOMEPAGE_PICKER); + pref.setSummary(getHomepageSummary()); + pref.setPersistent(false); + pref.setValue(getHomepageValue()); + pref.setOnPreferenceChangeListener(this); + + PreferenceScreen autofill = (PreferenceScreen) findPreference( + PreferenceKeys.PREF_AUTOFILL_PROFILE); + autofill.setOnPreferenceClickListener(this); + + SwitchPreference powersave = (SwitchPreference) findPreference(PREF_POWERSAVE); + powersave.setOnPreferenceChangeListener(this); + + SwitchPreference nightmode = (SwitchPreference) findPreference( + PreferenceKeys.PREF_NIGHTMODE_ENABLED); + nightmode.setOnPreferenceChangeListener(this); + + final Bundle arguments = getArguments(); + if (arguments != null && arguments.getBoolean("LowPower")) { + LowPowerDialogFragment fragment = LowPowerDialogFragment.newInstance(); + fragment.show(getActivity().getFragmentManager(), "setPowersave dialog"); + } + + //Disable set search engine preference if SEARCH_ENGINE restriction is enabled + if (SearchEngineRestriction.getInstance().isEnabled()) { + findPreference("search_engine").setEnabled(false); + } + + // Register Preference objects with their MDM restriction handlers + AutoFillRestriction.getInstance(). + registerPreference(findPreference(PreferenceKeys.PREF_AUTOFILL_ENABLED)); + + mAdvFrag = new AdvancedPreferencesFragment(this); + //mPrivFrag = new PrivacySecurityPreferencesFragment(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + // Un-register Preference objects from their MDM restriction handlers + AutoFillRestriction.getInstance().registerPreference(null); + } + + @Override + public boolean onPreferenceChange(Preference pref, Object objValue) { + if (getActivity() == null) { + // We aren't attached, so don't accept preferences changes from the + // invisible UI. + Log.w("PageContentPreferencesFragment", "onPreferenceChange called from detached fragment!"); + return false; + } + + if (pref.getKey().equals(PREF_HOMEPAGE_PICKER)) { + BrowserSettings settings = BrowserSettings.getInstance(); + if (CURRENT.equals(objValue)) { + settings.setHomePage(mCurrentPage); + } + if (BLANK.equals(objValue)) { + settings.setHomePage(BLANK_URL); + } + if (DEFAULT.equals(objValue)) { + settings.setHomePage(BrowserSettings.getFactoryResetHomeUrl( + getActivity())); + } + if (MOST_VISITED.equals(objValue)) { + settings.setHomePage(HomeProvider.MOST_VISITED); + } + if (OTHER.equals(objValue)) { + promptForHomepage(); + return false; + } + pref.setSummary(getHomepageSummary()); + ((ListPreference)pref).setValue(getHomepageValue()); + return false; + } + + if (pref.getKey().equals(PREF_POWERSAVE)) { + BrowserSettings settings = BrowserSettings.getInstance(); + settings.setPowerSaveModeEnabled((Boolean)objValue); + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.WEBREFINER, !(Boolean)objValue); + showPowerSaveInfo((Boolean) objValue); + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + } + + if (pref.getKey().equals(PreferenceKeys.PREF_NIGHTMODE_ENABLED)) { + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + } + return true; + } + + void promptForHomepage() { + MyAlertDialogFragment fragment = MyAlertDialogFragment.newInstance(); + fragment.setTargetFragment(this, -1); + fragment.show(getActivity().getFragmentManager(), "setHomepage dialog"); + } + + String getHomepageValue() { + BrowserSettings settings = BrowserSettings.getInstance(); + String homepage = settings.getHomePage(); + if (TextUtils.isEmpty(homepage) || BLANK_URL.endsWith(homepage)) { + return BLANK; + } + if (HomeProvider.MOST_VISITED.equals(homepage)) { + return MOST_VISITED; + } + String defaultHomepage = BrowserSettings.getFactoryResetHomeUrl( + getActivity()); + if (TextUtils.equals(defaultHomepage, homepage)) { + return DEFAULT; + } + if (TextUtils.equals(mCurrentPage, homepage)) { + return CURRENT; + } + return OTHER; + } + + String getHomepageSummary() { + BrowserSettings settings = BrowserSettings.getInstance(); + if (settings.useMostVisitedHomepage()) { + return getHomepageLabel(MOST_VISITED); + } + String homepage = settings.getHomePage(); + if (TextUtils.isEmpty(homepage) || BLANK_URL.equals(homepage)) { + return getHomepageLabel(BLANK); + } + return homepage; + } + + String getHomepageLabel(String value) { + for (int i = 0; i < mValues.length; i++) { + if (value.equals(mValues[i])) { + return mChoices[i]; + } + } + return null; + } + + @Override + public void onResume() { + super.onResume(); + + mAdvFrag.onResume(); + refreshUi(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + mAdvFrag.onActivityResult(requestCode,resultCode, data); + } + + void refreshUi() { + ActionBar bar = getActivity().getActionBar(); + if (bar != null) { + bar.setTitle(R.string.menu_preferences); + bar.setDisplayHomeAsUpEnabled(true); + } + + PreferenceScreen autoFillSettings = + (PreferenceScreen)findPreference(PreferenceKeys.PREF_AUTOFILL_PROFILE); + autoFillSettings.setDependency(PreferenceKeys.PREF_AUTOFILL_ENABLED); + } + + @Override + public boolean onPreferenceClick(Preference preference) { + if (preference.getKey().equals(PreferenceKeys.PREF_AUTOFILL_PROFILE)) { + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + Fragment newFragment = new AutoFillSettingsFragment(); + fragmentTransaction.replace(getId(), newFragment); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + return true; + } + return false; + } + + void showPowerSaveInfo(boolean toggle) { + String toastInfo; + if (toggle) + toastInfo = getActivity().getResources().getString(R.string.powersave_dialog_on); + else + toastInfo = getActivity().getResources().getString(R.string.powersave_dialog_off); + + Toast toast = Toast.makeText(getActivity(), toastInfo, Toast.LENGTH_SHORT); + toast.setGravity(Gravity.CENTER, 0, 0); + toast.show(); + } + + /* + Add this class to manage AlertDialog lifecycle. + */ + public static class MyAlertDialogFragment extends DialogFragment { + private final String HOME_PAGE = "homepage"; + private EditText editText = null; + public static MyAlertDialogFragment newInstance() { + MyAlertDialogFragment frag = new MyAlertDialogFragment(); + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final BrowserSettings settings = BrowserSettings.getInstance(); + editText = new EditText(getActivity()); + String homePage = savedInstanceState != null ? + savedInstanceState.getString(HOME_PAGE): settings.getHomePage(); + editText.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_URI); + editText.setText(homePage); + editText.setSelectAllOnFocus(true); + editText.setSingleLine(true); + editText.setImeActionLabel(null, EditorInfo.IME_ACTION_DONE); + final AlertDialog dialog = new AlertDialog.Builder(getActivity()) + .setView(editText) + .setPositiveButton(android.R.string.ok, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String homepage = editText.getText().toString().trim(); + homepage = UrlUtils.smartUrlFilter(homepage); + settings.setHomePage(homepage); + Fragment frag = getTargetFragment(); + if (frag == null || !(frag instanceof GeneralPreferencesFragment)) { + Log.e("MyAlertDialogFragment", "get target fragment error!"); + return; + } + GeneralPreferencesFragment target = (GeneralPreferencesFragment)frag; + ListPreference pref = (ListPreference) target. + findPreference(PREF_HOMEPAGE_PICKER); + pref.setValue(target.getHomepageValue()); + pref.setSummary(target.getHomepageSummary()); + } + }) + .setNegativeButton(android.R.string.cancel, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + } + }) + .setTitle(R.string.pref_set_homepage_to) + .create(); + + editText.setOnEditorActionListener(new OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + dialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); + return true; + } + return false; + } + }); + + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + + return dialog; + } + + @Override + public void onSaveInstanceState(Bundle outState){ + super.onSaveInstanceState(outState); + outState.putString(HOME_PAGE, editText.getText().toString().trim()); + } + } + public static class LowPowerDialogFragment extends DialogFragment { + public static LowPowerDialogFragment newInstance() { + LowPowerDialogFragment frag = new LowPowerDialogFragment(); + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final BrowserSettings settings = BrowserSettings.getInstance(); + final AlertDialog dialog = new AlertDialog.Builder(getActivity()) + .setPositiveButton(android.R.string.ok, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + settings.setPowerSaveModeEnabled(true); + getActivity().finish(); + } + }) + .setNegativeButton(android.R.string.cancel, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + getActivity().finish(); + } + }) + .setTitle(R.string.pref_powersave_enabled_summary) + .create(); + + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + + return dialog; + } + } +} diff --git a/src/src/com/android/browser/preferences/InvertedContrastPreview.java b/src/src/com/android/browser/preferences/InvertedContrastPreview.java new file mode 100644 index 00000000..690a529a --- /dev/null +++ b/src/src/com/android/browser/preferences/InvertedContrastPreview.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.preferences; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import org.codeaurora.swe.WebSettings; +import org.codeaurora.swe.WebView; + +import com.android.browser.BrowserSettings; +import com.android.browser.BrowserWebView; +import com.android.browser.WebViewProperties; + +public class InvertedContrastPreview extends WebViewPreview { + + static final String IMG_ROOT = "content://com.android.browser.home/res/raw/"; + static final String[] THUMBS = new String[] { + "thumb_google", + "thumb_amazon", + "thumb_cnn", + "thumb_espn", + "", // break + "thumb_bbc", + "thumb_nytimes", + "thumb_weatherchannel", + "thumb_picasa", + }; + + String mHtml; + + public InvertedContrastPreview( + Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public InvertedContrastPreview(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public InvertedContrastPreview(Context context) { + super(context); + } + + @Override + protected void init(Context context) { + super.init(context); + StringBuilder builder = new StringBuilder("<html><body style=\"width: 1000px\">"); + for (String thumb : THUMBS) { + if (TextUtils.isEmpty(thumb)) { + builder.append("<br />"); + continue; + } + builder.append("<img src=\""); + builder.append(IMG_ROOT); + builder.append(thumb); + builder.append("\" /> "); + } + builder.append("</body></html>"); + mHtml = builder.toString(); + } + + @Override + protected void updatePreview(boolean forceReload) { + if (mWebView == null) return; + + /* SWE: This class extends WebViewPreview, however, WebViewPreview has + * been modified to use the system webview. Commenting out code for now + * which implements the preview as this class requires refactoring + * regardless & is currently not in use. + + WebSettings ws = mWebView.getSettings(); + BrowserSettings bs = BrowserSettings.getInstance(); + ws.setProperty(WebViewProperties.gfxInvertedScreen, + bs.useInvertedRendering() ? "true" : "false"); + ws.setProperty(WebViewProperties.gfxInvertedScreenContrast, + Float.toString(bs.getInvertedContrast())); + if (forceReload) { + mWebView.loadData(mHtml, "text/html", null); + } + + */ + } + +} diff --git a/src/src/com/android/browser/preferences/LegalPreferencesFragment.java b/src/src/com/android/browser/preferences/LegalPreferencesFragment.java new file mode 100644 index 00000000..ea3fb17b --- /dev/null +++ b/src/src/com/android/browser/preferences/LegalPreferencesFragment.java @@ -0,0 +1,121 @@ +/* + * 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.PreferenceFragment; +import android.preference.PreferenceScreen; + +import com.android.browser.BrowserSwitches; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; + +import org.codeaurora.swe.BrowserCommandLine; + +public class LegalPreferencesFragment extends PreferenceFragment + implements OnPreferenceClickListener { + + private static final String creditsUrl = "chrome://credits"; + PreferenceScreen mHeadPref = null; + String mEulaUrl = ""; + String mPrivacyPolicyUrl = ""; + + private void setOnClickListener(String prefKey, boolean set) { + Preference pref = findPreference(prefKey); + if (pref == null) { + return; + } + + if (set) { + pref.setOnPreferenceClickListener(this); + } else { + if (mHeadPref != null) + mHeadPref.removePreference(pref); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ActionBar bar = getActivity().getActionBar(); + if (bar != null) { + bar.setTitle(R.string.swe_legal); + } + addPreferencesFromResource(R.xml.legal_preferences); + mHeadPref = (PreferenceScreen) findPreference(PreferenceKeys.PREF_LEGAL); + + + setOnClickListener(PreferenceKeys.PREF_LEGAL_CREDITS, true); + + if(BrowserCommandLine.hasSwitch(BrowserSwitches.CMD_LINE_SWITCH_EULA_URL)) { + mEulaUrl = BrowserCommandLine.getSwitchValue(BrowserSwitches.CMD_LINE_SWITCH_EULA_URL); + } else { + mEulaUrl = getResources().getString(R.string.swe_eula_url); + } + setOnClickListener(PreferenceKeys.PREF_LEGAL_EULA, !mEulaUrl.isEmpty()); + + + if(BrowserCommandLine.hasSwitch(BrowserSwitches.CMD_LINE_SWITCH_PRIVACY_POLICY_URL)) { + mPrivacyPolicyUrl = BrowserCommandLine.getSwitchValue( + BrowserSwitches.CMD_LINE_SWITCH_PRIVACY_POLICY_URL); + } else { + mPrivacyPolicyUrl = getResources().getString(R.string.swe_privacy_policy_url); + } + setOnClickListener(PreferenceKeys.PREF_LEGAL_PRIVACY_POLICY, !mPrivacyPolicyUrl.isEmpty()); + } + + @Override + public boolean onPreferenceClick(Preference preference) { + Bundle b = new Bundle(); + if(preference.getKey().equals(PreferenceKeys.PREF_LEGAL_CREDITS)) { + Intent i = new Intent(getActivity(), LegalPreviewActivity.class); + i.putExtra(LegalPreviewActivity.URL_INTENT_EXTRA, creditsUrl); + startActivity(i); + return true; + } else if(preference.getKey().equals(PreferenceKeys.PREF_LEGAL_EULA)) { + Intent i = new Intent(getActivity(), LegalPreviewActivity.class); + i.putExtra(LegalPreviewActivity.URL_INTENT_EXTRA, mEulaUrl); + startActivity(i); + return true; + } else if(preference.getKey().equals(PreferenceKeys.PREF_LEGAL_PRIVACY_POLICY)) { + Intent i = new Intent(getActivity(), LegalPreviewActivity.class); + i.putExtra(LegalPreviewActivity.URL_INTENT_EXTRA, mPrivacyPolicyUrl); + startActivity(i); + return true; + } + return false; + } +} diff --git a/src/src/com/android/browser/preferences/LegalPreviewActivity.java b/src/src/com/android/browser/preferences/LegalPreviewActivity.java new file mode 100644 index 00000000..eeaf5589 --- /dev/null +++ b/src/src/com/android/browser/preferences/LegalPreviewActivity.java @@ -0,0 +1,95 @@ +/* + * 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.Fragment; +import android.app.FragmentTransaction; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.view.KeyEvent; +import android.view.MenuItem; + +import com.android.browser.R; + +public class LegalPreviewActivity extends FragmentActivity { + LegalPreviewFragment mLegalPreviewFragment; + protected static final String URL_INTENT_EXTRA = "url"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.credits_tab); + ActionBar bar = getActionBar(); + if (bar != null) { + bar.setTitle(R.string.swe_open_source_licenses); + bar.setDisplayHomeAsUpEnabled(true); + } + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + mLegalPreviewFragment = new LegalPreviewFragment(); + Bundle args = new Bundle(); + args.putString(URL_INTENT_EXTRA, getIntent().getExtras() + .getString(URL_INTENT_EXTRA)); + mLegalPreviewFragment.setArguments(args); + fragmentTransaction.add(R.id.license_layout, mLegalPreviewFragment, + "LegalPreviewFragmentTag"); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + } + + private boolean back() { + if(!mLegalPreviewFragment.onBackPressed()) { + onBackPressed(); + return true; + } else { + return false; + } + } + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + switch(keyCode) { + case KeyEvent.KEYCODE_BACK: + if (event.isTracking() && !event.isCanceled()) { + return back(); + } + } + return false; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + return back(); + } + return super.onOptionsItemSelected(item); + } +} diff --git a/src/src/com/android/browser/preferences/LegalPreviewFragment.java b/src/src/com/android/browser/preferences/LegalPreviewFragment.java new file mode 100644 index 00000000..ec60e10c --- /dev/null +++ b/src/src/com/android/browser/preferences/LegalPreviewFragment.java @@ -0,0 +1,83 @@ +/* + * 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.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.android.browser.R; + +import org.codeaurora.swe.WebView; + +public class LegalPreviewFragment extends Fragment { + + private WebView mWebView; + private String mUrl; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle args = getArguments(); + mUrl = args.getString(LegalPreviewActivity.URL_INTENT_EXTRA); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + ViewGroup contentContainer = (ViewGroup) inflater.inflate( + R.layout.webview_wrapper, container, false); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT); + mWebView = new WebView(getActivity()); + contentContainer.addView(mWebView.getView(), params); + return contentContainer; + } + + @Override + public void onActivityCreated(Bundle b) { + super.onActivityCreated(b); + if (mWebView == null) return; + mWebView.loadUrl(mUrl); + } + + public boolean onBackPressed() { + if(mWebView != null && mWebView.canGoBack()) { + mWebView.goBack(); + return true; + } + return false; + } +} diff --git a/src/src/com/android/browser/preferences/NonformattingListPreference.java b/src/src/com/android/browser/preferences/NonformattingListPreference.java new file mode 100644 index 00000000..51b3231e --- /dev/null +++ b/src/src/com/android/browser/preferences/NonformattingListPreference.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.browser.preferences; + +import android.content.Context; +import android.preference.ListPreference; +import android.util.AttributeSet; + +public class NonformattingListPreference extends ListPreference { + + private CharSequence mSummary; + + public NonformattingListPreference(Context context) { + super(context); + } + + public NonformattingListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void setSummary(CharSequence summary) { + mSummary = summary; + super.setSummary(summary); + } + + @Override + public CharSequence getSummary() { + if (mSummary != null) { + return mSummary; + } + return super.getSummary(); + } + +} diff --git a/src/src/com/android/browser/preferences/PrivacySecurityPreferencesFragment.java b/src/src/com/android/browser/preferences/PrivacySecurityPreferencesFragment.java new file mode 100644 index 00000000..d038163f --- /dev/null +++ b/src/src/com/android/browser/preferences/PrivacySecurityPreferencesFragment.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.browser.preferences; + +import com.android.browser.BrowserLocationSwitchPreference; +import com.android.browser.BrowserPreferencesPage; +import com.android.browser.BrowserSettings; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; +import com.android.browser.mdm.DoNotTrackRestriction; +import com.android.browser.mdm.ThirdPartyCookiesRestriction; + +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.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.preference.TwoStatePreference; + +import org.codeaurora.swe.PermissionsServiceFactory; +import org.codeaurora.swe.WebRefiner; + +public class PrivacySecurityPreferencesFragment extends SWEPreferenceFragment + implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener { + + private Preference mClearPref; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.privacy_and_security_preferences); + + PreferenceScreen websiteSettings = (PreferenceScreen) findPreference( + PreferenceKeys.PREF_WEBSITE_SETTINGS); + websiteSettings.setFragment(WebsiteSettingsFragment.class.getName()); + websiteSettings.setOnPreferenceClickListener(this); + + mClearPref = findPreference(PreferenceKeys.PREF_CLEAR_SELECTED_DATA); + mClearPref.setOnPreferenceChangeListener(this); + + readAndShowPermission("enable_geolocation", + PermissionsServiceFactory.PermissionType.GEOLOCATION); + + readAndShowPermission("microphone", PermissionsServiceFactory.PermissionType.VOICE); + + readAndShowPermission("camera", PermissionsServiceFactory.PermissionType.VIDEO); + + Preference pref = findPreference("distracting_contents"); + if (!BrowserSettings.getInstance().getPreferences() + .getBoolean(PreferenceKeys.PREF_WEB_REFINER, false)) { + PreferenceCategory category = + (PreferenceCategory) findPreference("default_site_settings"); + if (category != null) { + category.removePreference(pref); + } + } else { + // since webrefiner and distracting_contents are paradoxes + // the value needs to be flipped + pref.setOnPreferenceChangeListener(this); + showPermission(pref, + !PermissionsServiceFactory.getDefaultPermissions( + PermissionsServiceFactory.PermissionType.WEBREFINER)); + } + + readAndShowPermission("popup_windows", PermissionsServiceFactory.PermissionType.POPUP); + + readAndShowPermission("accept_cookies", PermissionsServiceFactory.PermissionType.COOKIE); + + readAndShowPermission("accept_third_cookies", + PermissionsServiceFactory.PermissionType.THIRDPARTYCOOKIES); + + // Register Preference objects with their MDM restriction handlers + DoNotTrackRestriction.getInstance(). + registerPreference(findPreference(PreferenceKeys.PREF_DO_NOT_TRACK)); + ThirdPartyCookiesRestriction.getInstance(). + registerPreference(findPreference("accept_third_cookies")); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + // Un-register Preference objects from their MDM restriction handlers + DoNotTrackRestriction.getInstance().registerPreference(null); + ThirdPartyCookiesRestriction.getInstance().registerPreference(null); + } + + @Override + public void onPause() { + super.onPause(); + PermissionsServiceFactory.flushPendingSettings(); + } + + @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 = true; + if (pref == mClearPref) { + Integer value = (Integer) objValue; + if (value == 0) { + return false; + } + } else { + Boolean bFlag = (Boolean) objValue; + flag = bFlag.booleanValue(); + } + + if (pref.getKey().equals(PreferenceKeys.PREF_CLEAR_SELECTED_DATA)) { + if (pref.getPreferenceManager().getDefaultSharedPreferences( + (Context) getActivity()).getBoolean( + PreferenceKeys.PREF_PRIVACY_CLEAR_HISTORY, false)) { + // Need to tell the browser to remove the parent/child relationship + // between tabs + getActivity().setResult(Activity.RESULT_OK, + (new Intent()).putExtra(Intent.EXTRA_TEXT, pref.getKey())); + } + // return true by default for all preferences + return true; + } + + if (pref.getKey().toString().equalsIgnoreCase("enable_geolocation")) { + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.GEOLOCATION, flag); + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + return true; + } + + if (pref.getKey().toString().equalsIgnoreCase("microphone")) { + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.VOICE, flag); + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + return true; + } + + if (pref.getKey().toString().equalsIgnoreCase("camera")) { + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.VIDEO, flag); + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + return true; + } + + if (pref.getKey().toString().equalsIgnoreCase("distracting_contents")) { + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.WEBREFINER, !flag); + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + return true; + } + + if (pref.getKey().toString().equalsIgnoreCase("popup_windows")) { + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.POPUP, flag); + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + 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); + } + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + return true; + } + + if (pref.getKey().toString().equalsIgnoreCase("accept_third_cookies")) { + PermissionsServiceFactory.setDefaultPermissions( + PermissionsServiceFactory.PermissionType.THIRDPARTYCOOKIES, flag); + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + 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(); + BrowserLocationSwitchPreference pref = + (BrowserLocationSwitchPreference) findPreference(PreferenceKeys.PREF_ENABLE_GEOLOCATION); + if (bar != null) { + bar.setTitle(R.string.pref_privacy_security_title); + bar.setDisplayHomeAsUpEnabled(false); + bar.setHomeButtonEnabled(false); + } + if ( pref != null) pref.setEnabled(PermissionsServiceFactory.isSystemLocationEnabled()); + } +} diff --git a/src/src/com/android/browser/preferences/SWEPreferenceFragment.java b/src/src/com/android/browser/preferences/SWEPreferenceFragment.java new file mode 100644 index 00000000..7bfd0d1e --- /dev/null +++ b/src/src/com/android/browser/preferences/SWEPreferenceFragment.java @@ -0,0 +1,114 @@ +/* + * 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.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.preference.PreferenceFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.Switch; + +import com.android.browser.R; + +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; + } + + @Override + public void onResume() { + super.onResume(); + + /*ActionBar bar = getActivity().getActionBar(); + if (bar != null) { + bar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.accent))); + }*/ + } + + 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/src/com/android/browser/preferences/SeekBarSummaryPreference.java b/src/src/com/android/browser/preferences/SeekBarSummaryPreference.java new file mode 100644 index 00000000..5cb8ae67 --- /dev/null +++ b/src/src/com/android/browser/preferences/SeekBarSummaryPreference.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.preferences; + +import android.content.Context; + +import com.android.browser.platformsupport.SeekBarPreference; + +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; + + +public class SeekBarSummaryPreference extends SeekBarPreference { + + CharSequence mSummary; + TextView mSummaryView; + + public SeekBarSummaryPreference( + Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(); + } + + public SeekBarSummaryPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public SeekBarSummaryPreference(Context context) { + super(context); + init(); + } + + void init() { + setWidgetLayoutResource(com.android.browser.R.layout.font_size_widget); + } + + @Override + public void setSummary(CharSequence summary) { + mSummary = summary; + if (mSummaryView != null) { + mSummaryView.setText(mSummary); + } + } + + @Override + public CharSequence getSummary() { + return null; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + mSummaryView = (TextView) view.findViewById(com.android.browser.R.id.text); + if (TextUtils.isEmpty(mSummary)) { + mSummaryView.setVisibility(View.GONE); + } else { + mSummaryView.setVisibility(View.VISIBLE); + mSummaryView.setText(mSummary); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // Intentionally blank - prevent super.onStartTrackingTouch from running + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // Intentionally blank - prevent onStopTrackingTouch from running + } + +} diff --git a/src/src/com/android/browser/preferences/SiteSpecificPreferencesFragment.java b/src/src/com/android/browser/preferences/SiteSpecificPreferencesFragment.java new file mode 100644 index 00000000..b5d748df --- /dev/null +++ b/src/src/com/android/browser/preferences/SiteSpecificPreferencesFragment.java @@ -0,0 +1,816 @@ +/* + * 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.Context; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.http.SslCertificate; +import android.os.Bundle; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.preference.TwoStatePreference; +import android.text.Html; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.webkit.ValueCallback; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.browser.BrowserLocationListPreference; +import com.android.browser.BrowserPreferencesPage; +import com.android.browser.BrowserSettings; +import com.android.browser.NavigationBarBase; +import com.android.browser.PreferenceKeys; +import com.android.browser.R; +import com.android.browser.reflect.ReflectHelper; + +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.Formatter; +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_SITE_TITLE = "website_title"; + public static final String EXTRA_WEB_REFINER_ADS_INFO = "website_refiner_ads_info"; + public static final String EXTRA_WEB_REFINER_TRACKER_INFO = "website_refiner_tracker_info"; + public static final String EXTRA_WEB_REFINER_MALWARE_INFO = "website_refiner_malware_info"; + public static final String EXTRA_SECURITY_CERT = "website_security_cert"; + public static final String EXTRA_SECURITY_CERT_BAD = "website_security_cert_bad"; + public static final String EXTRA_SECURITY_CERT_MIXED = "website_security_cert_mixed"; + + private PermissionsServiceFactory.PermissionsService.OriginInfo mOriginInfo; + private PermissionsServiceFactory.PermissionsService mPermServ; + private ActionBar mBar; + private List<String> mLocationValues; + + private Preference mSecurityInfoPrefs; + + private boolean mUsingDefaultSettings = true; + private int mOriginalActionBarOptions; + private int mIconColor = 0; + + private SslCertificate mSslCert; + private int mSslState; + + 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(); + } + + boolean empty = true; + for (Map.Entry<ViewType, String> entry: mTexts.entrySet()) { + if (!entry.getValue().isEmpty()) { + empty = false; + } + } + mbEmpty = empty; + } + + 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; + private String mSiteTitle; + + @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); + mSiteTitle = args.getString(EXTRA_SITE_TITLE, 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((mSiteTitle != null) ? + mSiteTitle : + mOriginText); + + try { + URL url = new URL(mOriginText); + pref.setSummary((mSiteTitle != null) ? + mOriginText : + "(" + url.getHost() + ")"); + } catch (MalformedURLException e) { + } + mOriginInfo = mPermServ.getOriginInfo(mOriginText); + setActionBarTitle(PermissionsServiceFactory.getPrettyUrl(mOriginText)); + updatePreferenceInfo(); + } + } + ); + + if (!BrowserSettings.getInstance().getPreferences() + .getBoolean(PreferenceKeys.PREF_WEB_REFINER, false)) { + PreferenceCategory category = (PreferenceCategory) findPreference("site_pref_list"); + if (category != null) { + Preference pref = findPreference("distracting_contents"); + category.removePreference(pref); + } + } + + int ads = args.getInt(EXTRA_WEB_REFINER_ADS_INFO, 0); + String[] strings = new String[3]; + int index = 0; + + if (ads > 0) { + strings[index++] = getResources().getQuantityString( + R.plurals.pref_web_refiner_advertisements, ads, ads); + } + + int trackers = args.getInt(EXTRA_WEB_REFINER_TRACKER_INFO, 0); + if (trackers > 0) { + strings[index++] = getResources().getQuantityString( + R.plurals.pref_web_refiner_trackers, trackers, trackers); + + } + + int malware = args.getInt(EXTRA_WEB_REFINER_MALWARE_INFO, 0); + if (malware > 0) { + strings[index++] = getResources().getQuantityString( + R.plurals.pref_web_refiner_malware, malware, malware); + } + + if (index > 0) { + String[] formats = getResources().getStringArray(R.array.pref_web_refiner_message); + Formatter formatter = new Formatter(); + formatter.format(formats[index - 1], strings[0], strings[1], strings[2]); + mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.INFO, formatter.toString()); + } + + Bundle parcel = args.getParcelable(EXTRA_SECURITY_CERT); + mSslCert = (parcel != null) ? SslCertificate.restoreState(parcel) : null; + + if (mSslCert != null) { + Preference pref = findPreference("site_security_info"); + if (pref != null) { + pref.setSelectable(true); + } + + boolean certBad = args.getBoolean(EXTRA_SECURITY_CERT_BAD, false); + boolean certMix = args.getBoolean(EXTRA_SECURITY_CERT_MIXED, false); + if (!certBad && !certMix) { + final String string = getString(R.string.pref_valid_cert); + mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.INFO, + string); + mSslState = 0; + } else if (certMix) { + mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.WARNING, + getString(R.string.pref_warning_cert)); + mSslState = 1; + } else { + mSecurityViews.appendText(SiteSecurityViewFactory.ViewType.ERROR, + getString(R.string.pref_invalid_cert)); + mSslState = 2; + } + } + + updateSecurityViewVisibility(); + } + + private AlertDialog.Builder createSslCertificateDialog(Context ctx, + SslCertificate certificate) { + Object[] params = {ctx}; + Class[] type = new Class[] {Context.class}; + View certificateView = (View) ReflectHelper.invokeMethod(certificate, + "inflateCertificateView", type, params); + 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(ctx); + int iconId = R.drawable.ic_cert_trusted; + TextView textView; + + switch (mSslState) { + case 0: + iconId = R.drawable.ic_cert_trusted; + LinearLayout table = (LinearLayout)factory.inflate(R.layout.ssl_success, placeholder); + textView = (TextView)table.findViewById(R.id.success); + textView.setText(R.string.ssl_certificate_is_valid); + break; + case 1: + iconId = R.drawable.ic_cert_untrusted; + textView = (TextView) factory.inflate(R.layout.ssl_warning, placeholder, false); + textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_sp_level_warning, + 0, 0, 0); + textView.setText(R.string.ssl_unknown); + placeholder.addView(textView); + break; + case 2: + iconId = R.drawable.ic_cert_avoid; + textView = (TextView) factory.inflate(R.layout.ssl_warning, placeholder, false); + textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_sp_level_severe, + 0, 0, 0); + textView.setText(R.string.ssl_invalid); + placeholder.addView(textView); + break; + } + + return new AlertDialog.Builder(ctx) + .setTitle(R.string.ssl_certificate) + .setIcon(iconId) + .setView(certificateView); + } + + 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 = (mSslState == 1) ? getString(R.string.pref_warning_cert) + " " : + new String(""); + boolean setting_warnings = false; + + 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); + setting_warnings = true; + } + + 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); + setting_warnings = true; + 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() && setting_warnings) { + warningText += ", "; + } + warningText += getString(R.string.pref_security_allow_mic); + setting_warnings = true; + } + + 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() && setting_warnings) { + warningText += ", "; + } + warningText += getString(R.string.pref_security_allow_camera); + setting_warnings = true; + } + + if (!warningText.isEmpty()) { + if (setting_warnings) { + warningText += " "; + warningText += getResources().getString(R.string.pref_security_access_is_allowed); + } + mSecurityViews.setText(SiteSecurityViewFactory.ViewType.WARNING, warningText); + } else { + mSecurityViews.clearText(SiteSecurityViewFactory.ViewType.WARNING); + } + + pref = findPreference("distracting_contents"); + if (pref != null) { + permission = showPermission("distracting_contents", + PermissionsServiceFactory.PermissionType.WEBREFINER, + R.string.pref_security_allowed, R.string.pref_security_not_allowed); + if (permission == PermissionsServiceFactory.Permission.BLOCK) { + ((TwoStatePreference) pref).setChecked(true); + } else { + ((TwoStatePreference) pref).setChecked(false); + } + } + + 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); + } + + updateSecurityViewVisibility(); + } + + private void updateSecurityViewVisibility() { + if (mSecurityViews.mbEmpty) { + PreferenceScreen screen = (PreferenceScreen) + findPreference("site_specific_prefs"); + + if (mSecurityInfoPrefs == null) { + mSecurityInfoPrefs = findPreference("site_security_info_title"); + } + + if (mSecurityInfoPrefs != null && screen != null) { + screen.removePreference(mSecurityInfoPrefs); + } + } else { + PreferenceScreen screen = (PreferenceScreen) + findPreference("site_specific_prefs"); + + Preference pref = findPreference("site_security_info_title"); + if (pref == null && mSecurityInfoPrefs != null) { + screen.addPreference(mSecurityInfoPrefs); + } + } + + } + + @Override + public void onResume() { + super.onResume(); + BrowserLocationListPreference pref = + (BrowserLocationListPreference) findPreference("select_geolocation"); + if ( pref != null) pref.setEnabled(PermissionsServiceFactory.isSystemLocationEnabled()); + 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)); + } + } + } + } + } + + @Override + public void onPause() { + super.onPause(); + if (mBar != null) { + mBar.setDisplayOptions(mOriginalActionBarOptions); + } + + // flush all the settings in pause to assure that writes happen + // as soon the user leaves the activity + PermissionsServiceFactory.flushPendingSettings(); + + } + + 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.ok, + 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.useDefaultPermissionForOrigins(origins); + } + + BrowserPreferencesPage.sResultExtra = + PreferenceKeys.ACTION_RELOAD_PAGE; + BrowserPreferencesPage.onUrlNeedsReload(mOriginText); + finish(); + } + } + }) + .setNegativeButton( + R.string.cancel, 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) { + createSslCertificateDialog(getActivity(), mSslCert) + .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 disable = (boolean) objValue; + String[] origins = new String[1]; + origins[0] = mOriginInfo.getOrigin(); + refiner.setPermissionForOrigins(origins, !disable); + } + // Distracting contents and web refiner complimentary of each other + 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); + } + BrowserPreferencesPage.sResultExtra = PreferenceKeys.ACTION_RELOAD_PAGE; + BrowserPreferencesPage.onUrlNeedsReload(mOriginText); + updatePreferenceInfo(); + 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.ok, + new AlertDialog.OnClickListener() { + public void onClick(DialogInterface dlg, int which) { + if (mOriginInfo != null) { + mOriginInfo.clearAllStoredData(); + Preference e = findPreference("clear_data"); + e.setSummary("(Empty)"); + BrowserPreferencesPage.sResultExtra = + PreferenceKeys.ACTION_RELOAD_PAGE; + BrowserPreferencesPage.onUrlNeedsReload(mOriginText); + } + } + }) + .setNegativeButton(R.string.cancel, null) + .setIconAttribute(android.R.attr.alertDialogIcon) + .show(); + } + return true; + } + +} diff --git a/src/src/com/android/browser/preferences/WebViewPreview.java b/src/src/com/android/browser/preferences/WebViewPreview.java new file mode 100644 index 00000000..03ffcb24 --- /dev/null +++ b/src/src/com/android/browser/preferences/WebViewPreview.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.preferences; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.preference.Preference; +import android.preference.PreferenceManager; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import com.android.browser.BrowserSettings; +import com.android.browser.R; +import org.codeaurora.swe.WebView; + +public abstract class WebViewPreview extends Preference + implements OnSharedPreferenceChangeListener { + + protected TextView mTextView; + protected WebView mWebView; + + public WebViewPreview(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context); + } + + public WebViewPreview(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public WebViewPreview(Context context) { + super(context); + init(context); + } + + protected void init(Context context) { + setLayoutResource(R.layout.webview_preview); + BrowserSettings bs = BrowserSettings.getInstance(); + mWebView = bs.getTopWebView(); + } + + protected abstract void updatePreview(boolean forceReload); + + @Override + protected void onBindView(View view) { + super.onBindView(view); + mTextView = (TextView) view.findViewById(R.id.text_size_preview); + // Ignore all touch events & don't show scrollbars + mTextView.setFocusable(false); + mTextView.setFocusableInTouchMode(false); + mTextView.setClickable(false); + mTextView.setLongClickable(false); + mTextView.setHorizontalScrollBarEnabled(false); + mTextView.setVerticalScrollBarEnabled(false); + updatePreview(true); + } + + @Override + protected void onAttachedToHierarchy(PreferenceManager preferenceManager) { + super.onAttachedToHierarchy(preferenceManager); + getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + } + + @Override + protected void onPrepareForRemoval() { + getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + super.onPrepareForRemoval(); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + updatePreview(false); + } + +} diff --git a/src/src/com/android/browser/preferences/WebsiteSettingsFragment.java b/src/src/com/android/browser/preferences/WebsiteSettingsFragment.java new file mode 100644 index 00000000..c9dd04d3 --- /dev/null +++ b/src/src/com/android/browser/preferences/WebsiteSettingsFragment.java @@ -0,0 +1,388 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.preferences; + +import android.app.ActionBar; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.app.ListFragment; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.ColorDrawable; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +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.SiteTileView; +import com.android.browser.WebStorageSizeManager; + +import java.io.ByteArrayOutputStream; +import java.util.HashMap; +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; + +/** + * Manage the settings for an origin. + * We use it to keep track of the 'HTML5' settings, i.e. database (webstorage) + * and Geolocation. + */ +public class WebsiteSettingsFragment extends ListFragment implements OnClickListener { + private SiteAdapter mAdapter = null; + + private class Site implements OnClickListener { + private String mOrigin; + private String mTitle; + private Bitmap mIcon; + private View mView; + private Bitmap mDefaultIcon = mAdapter.mDefaultIcon; + + public Site(String origin) { + mOrigin = origin; + mTitle = null; + mIcon = null; + fetchFavicon(); + } + + private void fetchFavicon() { + // Fetch favicon and set it + PermissionsServiceFactory.getFavicon(mOrigin, getActivity(), + new ValueCallback<Bitmap>() { + @Override + public void onReceiveValue(Bitmap value) { + setIcon(value); + + } + }); + } + + public void updateView(View view){ + mView = view; + fetchFavicon(); + } + + public String getOrigin() { + return mOrigin; + } + + public void setTitle(String title) { + mTitle = title; + } + + public void setIcon(Bitmap image) { + mIcon = image; + if (mView != null) { + SiteTileView icon = (SiteTileView) mView.findViewById(R.id.icon); + icon.replaceFavicon((image == null) ? mDefaultIcon : image); + icon.setVisibility(View.VISIBLE); + icon.setOnClickListener(this); + } + } + + public Bitmap getIcon() { + return mIcon; + } + + public String getPrettyOrigin() { + return mTitle == null ? null : hideHttp(mOrigin); + } + + public String getPrettyTitle() { + return mTitle == null ? hideHttp(mOrigin) : mTitle; + } + + 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 void onClick(View v) { + clickHandler(this); + } + } + + class SiteAdapter extends ArrayAdapter<Site> + implements AdapterView.OnItemClickListener { + private int mResource; + private LayoutInflater mInflater; + private Bitmap mDefaultIcon; + private PermissionsServiceFactory.PermissionsService mPermServ; + private boolean mReady; + + public SiteAdapter(Context context, int rsc) { + super(context, rsc); + mResource = rsc; + mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mDefaultIcon = BitmapFactory.decodeResource(getResources(), + R.drawable.ic_deco_favicon_normal); + mReady = false; + askForOrigins(); + } + + public void askForOrigins() { + if (mPermServ == null) { + PermissionsServiceFactory.getPermissionsService( + new ValueCallback<PermissionsServiceFactory.PermissionsService>() { + @Override + public void onReceiveValue( + PermissionsServiceFactory.PermissionsService value) { + mPermServ = value; + Map<String, Site> sites = new HashMap<>(); + + Set<String> origins = mPermServ.getOrigins(); + for (String origin : origins) { + if (!TextUtils.isEmpty(origin)) + sites.put(origin, new Site(origin)); + } + + // 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; + } + } + ); + } + } + + 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) { + info.clearAllStoredData(); + } + } + // purge the permissionservice since its not needed + mPermServ.purge(); + mPermServ = null; + + // reset all site settings + PermissionsServiceFactory.resetSiteSettings(); + + WebRefiner refiner = WebRefiner.getInstance(); + if (refiner != null) { + refiner.useDefaultPermissionForOrigins(originArray); + } + } + } + + private void populateOrigins(Map<String, Site> sites) { + clear(); + + // We can now simply populate our array with Site instances + Set<Map.Entry<String, Site>> elements = sites.entrySet(); + Iterator<Map.Entry<String, Site>> entryIterator = elements.iterator(); + while (entryIterator.hasNext()) { + Map.Entry<String, Site> entry = entryIterator.next(); + Site site = entry.getValue(); + add(site); + } + + notifyDataSetChanged(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view; + final TextView title; + final TextView subtitle; + + if (convertView == null) { + view = mInflater.inflate(mResource, parent, false); + } else { + view = convertView; + } + + title = (TextView) view.findViewById(R.id.title); + subtitle = (TextView) view.findViewById(R.id.subtitle); + + Site site = getItem(position); + site.updateView(view); + 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); + } + // We set the site as the view's tag, + // so that we can get it in onItemClick() + view.setTag(site); + + return view; + } + + public void onItemClick(AdapterView<?> parent, + View view, + int position, + long id) { + clickHandler((Site) view.getTag()); + } + } + + private void clickHandler(Site site) { + Activity activity = getActivity(); + if (activity != null) { + Bundle args = new Bundle(); + args.putString(SiteSpecificPreferencesFragment.EXTRA_ORIGIN, site.getOrigin()); + if(site.getIcon() != null) { + ByteArrayOutputStream favicon = new ByteArrayOutputStream(); + site.getIcon().compress(Bitmap.CompressFormat.PNG, 100, favicon); + args.putByteArray(SiteSpecificPreferencesFragment.EXTRA_FAVICON, + favicon.toByteArray()); + } + FragmentManager fragmentManager = activity.getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + Fragment newFragment = new SiteSpecificPreferencesFragment(); + newFragment.setArguments(args); + fragmentTransaction.replace(getId(), newFragment); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.swe_website_settings, container, false); + 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); + mAdapter = new SiteAdapter(getActivity(), R.layout.website_settings_row); + getListView().setAdapter(mAdapter); + getListView().setOnItemClickListener(mAdapter); + } + + @Override + public void onResume() { + super.onResume(); + mAdapter.askForOrigins(); + ActionBar bar = getActivity().getActionBar(); + if (bar != null) { + bar.setTitle(R.string.pref_extras_website_settings); + bar.setDisplayHomeAsUpEnabled(false); + bar.setHomeButtonEnabled(false); + } + } + + private void finish() { + Activity activity = getActivity(); + if (activity != null) { + getActivity().getFragmentManager().popBackStack(); + } + } + + @Override + 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. + new AlertDialog.Builder(getActivity()) + .setMessage(R.string.website_settings_clear_all_dialog_message) + .setPositiveButton(R.string.ok, + new AlertDialog.OnClickListener() { + public void onClick(DialogInterface dlg, int which) { + mAdapter.deleteAllOrigins(); + if (GeolocationPermissions.isIncognitoCreated()) { + GeolocationPermissions.getIncognitoInstance().clearAll(); + } + WebStorageSizeManager.resetLastOutOfSpaceNotificationTime(); + mAdapter.askForOrigins(); + finish(); + } + }) + .setNegativeButton(R.string.cancel, 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 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.cancel, null) + .show(); + + break; + } + } +} |