Merge pull request #296 from stefano-cliqz/experimental_tabs

Experimental tabs
This commit is contained in:
Anthony Restaino 2015-10-09 19:47:50 -04:00
commit 5d55e480c9
48 changed files with 4520 additions and 1831 deletions

2
.gitignore vendored
View File

@ -50,3 +50,5 @@ out
# Source: # Source:
# https://raw.githubusercontent.com/github/gitignore/master/Android.gitignore # https://raw.githubusercontent.com/github/gitignore/master/Android.gitignore
# https://gitlab.com/fdroid/fdroidclient/raw/master/.gitignore # https://gitlab.com/fdroid/fdroidclient/raw/master/.gitignore
*.iml

View File

@ -1,139 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="Lightning-Browser" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="lightningPlusDebug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleLightningPlusDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileLightningPlusDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleLightningPlusDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileLightningPlusDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateLightningPlusDebugAndroidTestSources</task>
<task>generateLightningPlusDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/lightningPlus/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/lightningPlus/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/lightningPlus/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/lightningPlus/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/lightningPlus/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/lightningPlus/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/lightningPlus/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/lightningPlus/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/lightningPlus/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlusDebug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlusDebug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlusDebug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlusDebug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlusDebug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlusDebug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlusDebug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/lightningPlus/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/lightningPlus/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/lightningPlus/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/lightningPlus/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/lightningPlus/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/lightningPlus/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/palette-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.squareup.leakcanary/leakcanary-android/1.3.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/net.i2p.android/client/0.7/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="client-0.7" level="project" />
<orderEntry type="library" exported="" name="leakcanary-analyzer-1.3.1" level="project" />
<orderEntry type="library" exported="" name="jsr250-api-1.0" level="project" />
<orderEntry type="library" exported="" name="butterknife-7.0.1" level="project" />
<orderEntry type="library" exported="" name="dagger-2.0.1" level="project" />
<orderEntry type="library" exported="" name="leakcanary-watcher-1.3.1" level="project" />
<orderEntry type="library" exported="" name="otto-1.3.8" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="haha-1.3" level="project" />
<orderEntry type="library" exported="" name="palette-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="design-23.0.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="javax.inject-1" level="project" />
<orderEntry type="library" exported="" name="jsoup-1.8.3" level="project" />
<orderEntry type="library" exported="" name="leakcanary-android-1.3.1" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
<orderEntry type="module" module-name="libnetcipher" exported="" />
</component>
</module>

View File

@ -6,10 +6,13 @@ import android.content.DialogInterface;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
import com.squareup.otto.Bus;
import net.i2p.android.ui.I2PAndroidHelper; import net.i2p.android.ui.I2PAndroidHelper;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import info.guardianproject.netcipher.proxy.OrbotHelper; import info.guardianproject.netcipher.proxy.OrbotHelper;
@ -26,8 +29,11 @@ public class ProxyUtils {
private final PreferenceManager mPreferences; private final PreferenceManager mPreferences;
private static ProxyUtils mInstance; private static ProxyUtils mInstance;
private final Bus mEventBus;
private ProxyUtils(Context context) { private ProxyUtils(Context context) {
mPreferences = PreferenceManager.getInstance(); mPreferences = BrowserApp.getAppComponent().getPreferenceManager();
mEventBus = BrowserApp.getAppComponent().getBus();
mI2PHelper = new I2PAndroidHelper(context.getApplicationContext()); mI2PHelper = new I2PAndroidHelper(context.getApplicationContext());
} }
@ -143,13 +149,13 @@ public class ProxyUtils {
} }
public boolean isProxyReady(Activity activity) { public boolean isProxyReady() {
if (mPreferences.getProxyChoice() == Constants.PROXY_I2P) { if (mPreferences.getProxyChoice() == Constants.PROXY_I2P) {
if (!mI2PHelper.isI2PAndroidRunning()) { if (!mI2PHelper.isI2PAndroidRunning()) {
Utils.showSnackbar(activity, R.string.i2p_not_running); mEventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.i2p_not_running));
return false; return false;
} else if (!mI2PHelper.areTunnelsActive()) { } else if (!mI2PHelper.areTunnelsActive()) {
Utils.showSnackbar(activity, R.string.i2p_tunnels_not_ready); mEventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.i2p_tunnels_not_ready));
return false; return false;
} }
} }

View File

@ -10,6 +10,7 @@ import net.i2p.android.ui.I2PAndroidHelper;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import info.guardianproject.netcipher.proxy.OrbotHelper; import info.guardianproject.netcipher.proxy.OrbotHelper;
@ -27,7 +28,7 @@ public class ProxyUtils {
private static ProxyUtils mInstance; private static ProxyUtils mInstance;
private ProxyUtils(Context context) { private ProxyUtils(Context context) {
mPreferences = PreferenceManager.getInstance(); mPreferences = BrowserApp.getAppComponent().getPreferenceManager();
mI2PHelper = new I2PAndroidHelper(context.getApplicationContext()); mI2PHelper = new I2PAndroidHelper(context.getApplicationContext());
} }
@ -143,13 +144,15 @@ public class ProxyUtils {
} }
public boolean isProxyReady(Activity activity) { public boolean isProxyReady() {
if (mPreferences.getProxyChoice() == Constants.PROXY_I2P) { if (mPreferences.getProxyChoice() == Constants.PROXY_I2P) {
if (!mI2PHelper.isI2PAndroidRunning()) { if (!mI2PHelper.isI2PAndroidRunning()) {
Utils.showSnackbar(activity, R.string.i2p_not_running); BrowserApp.getAppComponent().getBus()
.post(new BrowserEvents.ShowSnackBarMessage(R.string.i2p_not_running));
return false; return false;
} else if (!mI2PHelper.areTunnelsActive()) { } else if (!mI2PHelper.areTunnelsActive()) {
Utils.showSnackbar(activity, R.string.i2p_tunnels_not_ready); BrowserApp.getAppComponent().getBus()
.post(new BrowserEvents.ShowSnackBarMessage(R.string.i2p_tunnels_not_ready));
return false; return false;
} }
} }
@ -200,7 +203,7 @@ public class ProxyUtils {
break; break;
case Constants.PROXY_I2P: case Constants.PROXY_I2P:
I2PAndroidHelper ih = new I2PAndroidHelper(activity.getApplicationContext()); I2PAndroidHelper ih = new I2PAndroidHelper(BrowserApp.getAppContext());
if (!ih.isI2PAndroidInstalled()) { if (!ih.isI2PAndroidInstalled()) {
choice = Constants.NO_PROXY; choice = Constants.NO_PROXY;
ih.promptToInstall(activity); ih.promptToInstall(activity);

File diff suppressed because it is too large Load Diff

View File

@ -18,13 +18,13 @@ public class IncognitoActivity extends BrowserActivity {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this); CookieSyncManager.createInstance(this);
} }
cookieManager.setAcceptCookie(PreferenceManager.getInstance().getIncognitoCookiesEnabled()); cookieManager.setAcceptCookie(mPreferences.getIncognitoCookiesEnabled());
} }
@Override // @Override
public synchronized void initializeTabs() { // public synchronized void initializeTabs() {
newTab(null, true); // newTab(null, true);
} // }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {

View File

@ -18,14 +18,14 @@ public class MainActivity extends BrowserActivity {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this); CookieSyncManager.createInstance(this);
} }
cookieManager.setAcceptCookie(PreferenceManager.getInstance().getCookiesEnabled()); cookieManager.setAcceptCookie(mPreferences.getCookiesEnabled());
} }
@Override // @Override
public synchronized void initializeTabs() { // public synchronized void initializeTabs() {
restoreOrNewTab(); // // restoreOrNewTab();
// if incognito mode use newTab(null, true); instead // // if incognito mode use newTab(null, true); instead
} // }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {

View File

@ -22,6 +22,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView; import android.widget.TextView;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.reading.HtmlFetcher; import acr.browser.lightning.reading.HtmlFetcher;
@ -49,7 +50,7 @@ public class ReadingActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
overridePendingTransition(R.anim.slide_in_from_right, R.anim.fade_out_scale); overridePendingTransition(R.anim.slide_in_from_right, R.anim.fade_out_scale);
mPreferences = PreferenceManager.getInstance(); mPreferences = BrowserApp.getAppComponent().getPreferenceManager();
mInvert = mPreferences.getInvertColors(); mInvert = mPreferences.getInvertColors();
final int color; final int color;
if (mInvert) { if (mInvert) {

View File

@ -0,0 +1,222 @@
package acr.browser.lightning.activity;
import android.app.Activity;
import android.content.Context;
import android.support.annotation.Nullable;
import android.webkit.WebView;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import acr.browser.lightning.controller.BrowserController;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.Utils;
import acr.browser.lightning.view.LightningView;
/**
* @author Stefano Pacifici
* @date 2015/09/14
*/
@Singleton
public class TabsManager {
private final List<LightningView> mWebViewList = new ArrayList<>();
private LightningView mCurrentTab;
@Inject
PreferenceManager mPreferenceManager;
@Inject
public TabsManager() {
}
public void restoreTabs(BrowserActivity activity, boolean darkTheme, boolean incognito) {
mWebViewList.clear();
mCurrentTab = null;
if (!incognito && mPreferenceManager.getRestoreLostTabsEnabled()) {
final String mem = mPreferenceManager.getMemoryUrl();
mPreferenceManager.setMemoryUrl("");
String[] array = Utils.getArray(mem);
int count = 0;
for (String urlString : array) {
if (!urlString.isEmpty()) {
newTab(activity, urlString, darkTheme, incognito);
}
}
}
if (mWebViewList.size() == 0) {
newTab(activity, null, darkTheme, incognito);
}
// mCurrentTab = mWebViewList.get(0);
}
/**
* Return a clone of the current tabs list. The list will not be updated, the user has to fetch
* a new copy when notified.
*
* @return a copy of the current tabs list
*/
public List<LightningView> getTabsList() {
return new ArrayList<>(mWebViewList);
}
/**
* Return the tab at the given position in tabs list, or null if position is not in tabs list
* range.
*
* @param position the index in tabs list
* @return the corespondent {@link LightningView}, or null if the index is invalid
*/
@Nullable
public LightningView getTabAtPosition(final int position) {
if (position < 0 || position >= mWebViewList.size()) {
return null;
}
return mWebViewList.get(position);
}
/**
* Try to low memory pressure
*/
public void freeMemory() {
for (LightningView tab: mWebViewList) {
tab.freeMemory();
}
}
/**
* Shutdown the manager
*/
public synchronized void shutdown() {
for (LightningView tab: mWebViewList) {
tab.onDestroy();
}
mWebViewList.clear();
}
/**
* Resume the tabs
*
* @param context
*/
public synchronized void resume(final Context context) {
for (LightningView tab: mWebViewList) {
tab.initializePreferences(null, context);
}
}
/**
* Forward network connection status to the webviews.
*
* @param isConnected
*/
public synchronized void notifyConnectioneStatus(final boolean isConnected) {
for (LightningView tab: mWebViewList) {
final WebView webView = tab.getWebView();
if (webView != null) {
webView.setNetworkAvailable(isConnected);
}
}
}
/**
* @return The number of currently opened tabs
*/
public int size() {
return mWebViewList.size();
}
/**
* Create and return a new tab. The tab is automatically added to the tabs list.
*
* @param activity
* @param url
* @param darkTheme
* @param isIncognito
* @return
*/
public synchronized LightningView newTab(final BrowserActivity activity,
final String url, final boolean darkTheme,
final boolean isIncognito) {
final LightningView tab = new LightningView(activity, url, darkTheme, isIncognito);
mWebViewList.add(tab);
return tab;
}
/**
* Remove a tab and return its reference or null if the position is not in tabs range
*
* @param position The position of the tab to remove
* @return The removed tab reference or null
*/
@Nullable
public synchronized LightningView deleteTab(final int position) {
if (position >= mWebViewList.size()) {
return null;
}
final LightningView tab = mWebViewList.remove(position);
tab.onDestroy();
return tab;
}
/**
* Return the position of the given tab
* @param tab
* @return
*/
public int positionOf(final LightningView tab) {
return mWebViewList.indexOf(tab);
}
/**
* @return A string representation of the currently opened tabs
*/
public String tabsString() {
final StringBuilder builder = new StringBuilder();
for (LightningView tab: mWebViewList) {
final String url = tab.getUrl();
if (url != null && !url.isEmpty()) {
builder.append(url).append("|$|SEPARATOR|$|");
}
}
return builder.toString();
}
/**
* Return the {@link WebView} associated to the current tab, or null if there is no current tab
* @return a {@link WebView} or null
*/
@Nullable
public WebView getCurrentWebView() {
return mCurrentTab != null ? mCurrentTab.getWebView() : null;
}
/**
* TODO We should remove also this, but probably not
* @return
*/
public LightningView getCurrentTab() {
return mCurrentTab;
}
/**
* Switch the current tab to the one at the given position. It returns the selected. After this
* call {@link TabsManager#getCurrentTab()} return the same reference returned by this method if
* position is valid.
*
* @return the selected tab or null if position is out of tabs range
*/
@Nullable
public LightningView switchToTab(final int position) {
if (position < 0 || position >= mWebViewList.size()) {
return null;
} else {
final LightningView tab = mWebViewList.get(position);
mCurrentTab = tab;
return tab;
}
}
}

View File

@ -5,18 +5,25 @@ import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import javax.inject.Inject;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
public abstract class ThemableBrowserActivity extends AppCompatActivity { public abstract class ThemableBrowserActivity extends AppCompatActivity {
@Inject
PreferenceManager mPreferences;
private int mTheme; private int mTheme;
private boolean mShowTabsInDrawer; private boolean mShowTabsInDrawer;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
mTheme = PreferenceManager.getInstance().getUseTheme(); BrowserApp.getAppComponent().inject(this);
mShowTabsInDrawer = PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); mTheme = mPreferences.getUseTheme();
mShowTabsInDrawer = mPreferences.getShowTabsInDrawer(!isTablet());
// set the theme // set the theme
if (mTheme == 1) { if (mTheme == 1) {
@ -30,8 +37,8 @@ public abstract class ThemableBrowserActivity extends AppCompatActivity {
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
int theme = PreferenceManager.getInstance().getUseTheme(); int theme = mPreferences.getUseTheme();
boolean drawerTabs = PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); boolean drawerTabs = mPreferences.getShowTabsInDrawer(!isTablet());
if (theme != mTheme || mShowTabsInDrawer != drawerTabs) { if (theme != mTheme || mShowTabsInDrawer != drawerTabs) {
restart(); restart();
} }

View File

@ -4,6 +4,7 @@ import android.graphics.drawable.ColorDrawable;
import android.os.Bundle; import android.os.Bundle;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.ThemeUtils; import acr.browser.lightning.utils.ThemeUtils;
@ -13,7 +14,7 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
mTheme = PreferenceManager.getInstance().getUseTheme(); mTheme = BrowserApp.getAppComponent().getPreferenceManager().getUseTheme();
// set the theme // set the theme
if (mTheme == 0) { if (mTheme == 0) {
@ -32,7 +33,7 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
if (PreferenceManager.getInstance().getUseTheme() != mTheme) { if (BrowserApp.getAppComponent().getPreferenceManager().getUseTheme() != mTheme) {
restart(); restart();
} }
} }

View File

@ -1,13 +1,23 @@
package acr.browser.lightning.app; package acr.browser.lightning.app;
import android.content.Context;
import com.squareup.otto.Bus;
import javax.inject.Singleton; import javax.inject.Singleton;
import acr.browser.lightning.activity.BrowserActivity; import acr.browser.lightning.activity.BrowserActivity;
import acr.browser.lightning.activity.ThemableBrowserActivity;
import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.constant.BookmarkPage;
import acr.browser.lightning.dialog.BookmarksDialogBuilder; import acr.browser.lightning.database.HistoryDatabase;
import acr.browser.lightning.dialog.LightningDialogBuilder;
import acr.browser.lightning.fragment.BookmarkSettingsFragment; import acr.browser.lightning.fragment.BookmarkSettingsFragment;
import acr.browser.lightning.fragment.BookmarksFragment; import acr.browser.lightning.fragment.BookmarksFragment;
import acr.browser.lightning.fragment.LightningPreferenceFragment;
import acr.browser.lightning.fragment.TabsFragment;
import acr.browser.lightning.object.SearchAdapter; import acr.browser.lightning.object.SearchAdapter;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.view.LightningView;
import dagger.Component; import dagger.Component;
/** /**
@ -25,7 +35,25 @@ public interface AppComponent {
void inject(SearchAdapter adapter); void inject(SearchAdapter adapter);
void inject(BookmarksDialogBuilder builder); void inject(LightningDialogBuilder builder);
void inject(BookmarkPage bookmarkPage); void inject(BookmarkPage bookmarkPage);
void inject(TabsFragment fragment);
PreferenceManager getPreferenceManager();
void inject(LightningPreferenceFragment fragment);
BookmarkPage getBookmarkPage();
Bus getBus();
HistoryDatabase getHistoryDatabase();
Context getApplicationContext();
void inject(LightningView lightningView);
void inject(ThemableBrowserActivity activity);
} }

View File

@ -11,28 +11,6 @@ public final class BookmarkEvents {
// No instances // No instances
} }
/**
* A bookmark was clicked
*/
public final static class Clicked {
public final HistoryItem bookmark;
public Clicked(final HistoryItem bookmark) {
this.bookmark = bookmark;
}
}
/**
* The user ask to open the bookmark as new tab
*/
public final static class AsNewTab {
public final HistoryItem bookmark;
public AsNewTab(final HistoryItem bookmark) {
this.bookmark = bookmark;
}
}
/** /**
* The user ask to delete the selected bookmark * The user ask to delete the selected bookmark
*/ */
@ -61,13 +39,6 @@ public final class BookmarkEvents {
} }
} }
/**
* The {@link acr.browser.lightning.fragment.BookmarksFragment} want to know the url (and title)
* of the currently shown web page.
*/
// public static class WantInfoAboutCurrentPage {
// }
/** /**
* Sended by the {@link acr.browser.lightning.fragment.BookmarksFragment} when it wants to close * Sended by the {@link acr.browser.lightning.fragment.BookmarksFragment} when it wants to close
* itself (generally in reply to a {@link acr.browser.lightning.bus.BrowserEvents.UserPressedBack} * itself (generally in reply to a {@link acr.browser.lightning.bus.BrowserEvents.UserPressedBack}

View File

@ -1,5 +1,7 @@
package acr.browser.lightning.bus; package acr.browser.lightning.bus;
import android.support.annotation.StringRes;
/** /**
* Created by Stefano Pacifici on 26/08/15. * Created by Stefano Pacifici on 26/08/15.
*/ */
@ -24,9 +26,8 @@ public final class BrowserEvents {
} }
/** /**
* Used to reply to {@link acr.browser.lightning.fragment.BookmarksFragment} message * Notify the current page has a new url. This is generally used to update the
* {@link acr.browser.lightning.bus.BookmarkEvents.WantInfoAboutCurrentPage}. This is generally * {@link acr.browser.lightning.fragment.BookmarksFragment} interface.
* used to update the {@link acr.browser.lightning.fragment.BookmarksFragment} interface.
*/ */
public static class CurrentPageUrl { public static class CurrentPageUrl {
public final String url; public final String url;
@ -41,4 +42,55 @@ public final class BrowserEvents {
*/ */
public static class UserPressedBack { public static class UserPressedBack {
} }
/**
* Notify that the user closed or opened a tab
*/
public static class TabsChanged {
}
/**
*
*/
/**
* Notify the Browser to display a SnackBar in the main activity
*/
public static class ShowSnackBarMessage {
public final String message;
@StringRes
public final int stringRes;
public ShowSnackBarMessage(final String message) {
this.message = message;
this.stringRes = -1;
}
public ShowSnackBarMessage(@StringRes final int stringRes) {
this.message = null;
this.stringRes = stringRes;
}
}
/**
* The user want to open the given url in the current tab
*/
public final static class OpenUrlInCurrentTab {
public final String url;
public OpenUrlInCurrentTab(final String url) {
this.url = url;
}
}
/**
* The user ask to open the given url as new tab
*/
public final static class OpenUrlInNewTab {
public final String url;
public OpenUrlInNewTab(final String url) {
this.url = url;
}
}
} }

View File

@ -0,0 +1,34 @@
package acr.browser.lightning.bus;
/**
* Collections of navigation events, like go back or go forward
*
* @author Stefano Pacifici
* @date 2015/09/15
*/
public class NavigationEvents {
private NavigationEvents() {
// No instances please
}
/**
* Fired by {@link acr.browser.lightning.fragment.TabsFragment} when the user presses back
* button.
*/
public static class GoBack {
}
/**
* Fired by {@link acr.browser.lightning.fragment.TabsFragment} when the user presses forward
* button.
*/
public static class GoForward {
}
/**
* Fired by {@link acr.browser.lightning.fragment.TabsFragment} when the user presses the home
* button.
*/
public static class GoHome {
}
}

View File

@ -0,0 +1,65 @@
package acr.browser.lightning.bus;
/**
* A collection of events been sent by {@link acr.browser.lightning.fragment.TabsFragment}
*
* @author Stefano Pacifici
* @date 2015/09/14
*/
public final class TabEvents {
private TabEvents() {
// No instances
}
/**
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user click on the
* tab exit button
*/
public static class CloseTab {
public final int position;
public CloseTab(int position) {
this.position = position;
}
}
/**
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user click on the
* tab itself.
*/
public static class ShowTab {
public final int position;
public ShowTab(int position) {
this.position = position;
}
}
/**
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user long press on the
* tab itself.
*/
public static class ShowCloseDialog {
public final int position;
public ShowCloseDialog(int position) {
this.position = position;
}
}
/**
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user want to create a
* new tab.
*/
public static class NewTab {
}
/**
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user long presses on
* new tab button.
*/
public static class NewTabLongPress {
}
}

View File

@ -62,7 +62,8 @@ public final class BookmarkPage {
CACHE_DIR = context.getCacheDir(); CACHE_DIR = context.getCacheDir();
} }
public void buildBookmarkPage(final String folder, final List<HistoryItem> list) { public void buildBookmarkPage(final String folder) {
final List<HistoryItem> list = manager.getBookmarksFromFolder(folder, true);
final File bookmarkWebPage; final File bookmarkWebPage;
if (folder == null || folder.isEmpty()) { if (folder == null || folder.isEmpty()) {
bookmarkWebPage = new File(FILES_DIR, Constants.BOOKMARKS_FILENAME); bookmarkWebPage = new File(FILES_DIR, Constants.BOOKMARKS_FILENAME);
@ -83,7 +84,7 @@ public final class BookmarkPage {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
buildBookmarkPage(item.getTitle(), manager.getBookmarksFromFolder(item.getTitle(), true)); buildBookmarkPage(item.getTitle());
} }
}).run(); }).run();
} else { } else {

View File

@ -66,7 +66,7 @@ public class HistoryPage {
} }
private static List<HistoryItem> getWebHistory(Context context) { private static List<HistoryItem> getWebHistory(Context context) {
HistoryDatabase databaseHandler = HistoryDatabase.getInstance(); HistoryDatabase databaseHandler = BrowserApp.getAppComponent().getHistoryDatabase();
return databaseHandler.getLastHundredItems(); return databaseHandler.getLastHundredItems();
} }
} }

View File

@ -57,11 +57,12 @@ public class StartPage {
StringBuilder homepageBuilder = new StringBuilder(StartPage.HEAD); StringBuilder homepageBuilder = new StringBuilder(StartPage.HEAD);
String icon; String icon;
String searchUrl; String searchUrl;
switch (PreferenceManager.getInstance().getSearchChoice()) { final PreferenceManager preferenceManager = BrowserApp.getAppComponent().getPreferenceManager();
switch (preferenceManager.getSearchChoice()) {
case 0: case 0:
// CUSTOM SEARCH // CUSTOM SEARCH
icon = "file:///android_asset/lightning.png"; icon = "file:///android_asset/lightning.png";
searchUrl = PreferenceManager.getInstance().getSearchUrl(); searchUrl = preferenceManager.getSearchUrl();
break; break;
case 1: case 1:
// GOOGLE_SEARCH; // GOOGLE_SEARCH;

View File

@ -23,18 +23,12 @@ public interface BrowserController {
void openFileChooser(ValueCallback<Uri> uploadMsg); void openFileChooser(ValueCallback<Uri> uploadMsg);
void updateTabs(); // void onLongPress();
void onLongPress();
void onShowCustomView(View view, CustomViewCallback callback); void onShowCustomView(View view, CustomViewCallback callback);
void onHideCustomView(); void onHideCustomView();
Bitmap getDefaultVideoPoster();
View getVideoLoadingProgressView();
void onCreateWindow(Message resultMsg); void onCreateWindow(Message resultMsg);
void onCloseWindow(LightningView view); void onCloseWindow(LightningView view);
@ -43,16 +37,12 @@ public interface BrowserController {
void showActionBar(); void showActionBar();
void longClickPage(String url); // void longClickPage(String url);
void openBookmarkPage(WebView view);
void showFileChooser(ValueCallback<Uri[]> filePathCallback); void showFileChooser(ValueCallback<Uri[]> filePathCallback);
void closeEmptyTab(); void closeEmptyTab();
boolean proxyIsNotReady();
// void updateBookmarkIndicator(String url); // void updateBookmarkIndicator(String url);
} }

View File

@ -12,9 +12,13 @@ import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.app.BrowserApp;
@Singleton
public class HistoryDatabase extends SQLiteOpenHelper { public class HistoryDatabase extends SQLiteOpenHelper {
// All Static variables // All Static variables
@ -39,14 +43,8 @@ public class HistoryDatabase extends SQLiteOpenHelper {
private boolean mLock; private boolean mLock;
public static HistoryDatabase getInstance() { @Inject
if (mInstance == null || mInstance.isClosed()) { public HistoryDatabase(Context context) {
mInstance = new HistoryDatabase(BrowserApp.getAppContext());
}
return mInstance;
}
private HistoryDatabase(Context context) {
super(context.getApplicationContext(), DATABASE_NAME, null, DATABASE_VERSION); super(context.getApplicationContext(), DATABASE_NAME, null, DATABASE_VERSION);
mDatabase = this.getWritableDatabase(); mDatabase = this.getWritableDatabase();
} }
@ -91,7 +89,7 @@ public class HistoryDatabase extends SQLiteOpenHelper {
} }
private void openIfNecessary() { private void openIfNecessary() {
if (mDatabase == null) { if (isClosed()) {
mDatabase = this.getWritableDatabase(); mDatabase = this.getWritableDatabase();
} }
} }

View File

@ -1,8 +1,13 @@
package acr.browser.lightning.dialog; package acr.browser.lightning.dialog;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
@ -19,24 +24,32 @@ import javax.inject.Inject;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BookmarkEvents; import acr.browser.lightning.bus.BookmarkEvents;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.constant.HistoryPage;
import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.BookmarkManager;
import acr.browser.lightning.database.HistoryDatabase;
import acr.browser.lightning.database.HistoryItem; import acr.browser.lightning.database.HistoryItem;
import acr.browser.lightning.utils.Utils; import acr.browser.lightning.utils.Utils;
/** /**
* TODO Rename this class it doesn't build dialogs only for bookmarks
*
* Created by Stefano Pacifici on 02/09/15, based on Anthony C. Restaino's code. * Created by Stefano Pacifici on 02/09/15, based on Anthony C. Restaino's code.
*/ */
public class BookmarksDialogBuilder { public class LightningDialogBuilder {
@Inject @Inject
BookmarkManager bookmarkManager; BookmarkManager bookmarkManager;
@Inject
HistoryDatabase mHistoryDatabase;
@Inject @Inject
Bus eventBus; Bus eventBus;
@Inject @Inject
public BookmarksDialogBuilder() { public LightningDialogBuilder() {
BrowserApp.getAppComponent().inject(this); BrowserApp.getAppComponent().inject(this);
} }
@ -46,7 +59,7 @@ public class BookmarksDialogBuilder {
* @param context used to show the dialog * @param context used to show the dialog
* @param url the long pressed url * @param url the long pressed url
*/ */
public void showLongPressedDialogForUrl(final Context context, final String url) { public void showLongPressedDialogForBookmarkUrl(final Context context, final String url) {
final HistoryItem item; final HistoryItem item;
if (url.startsWith(Constants.FILE) && url.endsWith(Constants.BOOKMARKS_FILENAME)) { if (url.startsWith(Constants.FILE) && url.endsWith(Constants.BOOKMARKS_FILENAME)) {
// TODO hacky, make a better bookmark mechanism in the future // TODO hacky, make a better bookmark mechanism in the future
@ -65,19 +78,19 @@ public class BookmarksDialogBuilder {
if (item.isFolder()) { if (item.isFolder()) {
showBookmarkFolderLongPressedDialog(context, item); showBookmarkFolderLongPressedDialog(context, item);
} else { } else {
showLongPressedDialogForUrl(context, item); showLongPressedDialogForBookmarkUrl(context, item);
} }
} }
} }
public void showLongPressedDialogForUrl(final Context context, final HistoryItem item) { public void showLongPressedDialogForBookmarkUrl(final Context context, final HistoryItem item) {
final DialogInterface.OnClickListener dialogClickListener = final DialogInterface.OnClickListener dialogClickListener =
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch (which) { switch (which) {
case DialogInterface.BUTTON_POSITIVE: case DialogInterface.BUTTON_POSITIVE:
eventBus.post(new BookmarkEvents.AsNewTab(item)); eventBus.post(new BrowserEvents.OpenUrlInNewTab(item.getUrl()));
break; break;
case DialogInterface.BUTTON_NEGATIVE: case DialogInterface.BUTTON_NEGATIVE:
if (bookmarkManager.deleteBookmark(item)) { if (bookmarkManager.deleteBookmark(item)) {
@ -197,4 +210,103 @@ public class BookmarksDialogBuilder {
}); });
editFolderDialog.show(); editFolderDialog.show();
} }
public void showLongPressedHistoryLinkDialog(final Context context, final String url) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
eventBus.post(new BrowserEvents.OpenUrlInNewTab(url));
break;
case DialogInterface.BUTTON_NEGATIVE:
mHistoryDatabase.deleteHistoryItem(url);
// openHistory();
eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(HistoryPage.getHistoryPage(context)));
break;
case DialogInterface.BUTTON_NEUTRAL:
eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(url));
break;
default:
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.action_history)
.setMessage(R.string.dialog_history_long_press)
.setCancelable(true)
.setPositiveButton(R.string.action_new_tab, dialogClickListener)
.setNegativeButton(R.string.action_delete, dialogClickListener)
.setNeutralButton(R.string.action_open, dialogClickListener)
.show();
}
// TODO There should be a way in which we do not need an activity reference to dowload a file
public void showLongPressImageDialog(@NonNull final Activity activity, @NonNull final String url,
@NonNull final String userAgent) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
eventBus.post(new BrowserEvents.OpenUrlInNewTab(url));
break;
case DialogInterface.BUTTON_NEGATIVE:
eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(url));
break;
case DialogInterface.BUTTON_NEUTRAL:
if (Build.VERSION.SDK_INT > 8) {
// Should be better to send an event on the bus here
Utils.downloadFile(activity, url,
userAgent, "attachment");
}
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(url.replace(Constants.HTTP, ""))
.setCancelable(true)
.setMessage(R.string.dialog_image)
.setPositiveButton(R.string.action_new_tab, dialogClickListener)
.setNegativeButton(R.string.action_open, dialogClickListener)
.setNeutralButton(R.string.action_download, dialogClickListener)
.show();
}
public void showLongPressLinkDialog(final Context context, final String url) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
eventBus.post(new BrowserEvents.OpenUrlInNewTab(url));
break;
case DialogInterface.BUTTON_NEGATIVE:
eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(url));
break;
case DialogInterface.BUTTON_NEUTRAL:
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label", url);
clipboard.setPrimaryClip(clip);
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(context); // dialog
builder.setTitle(url)
.setCancelable(true)
.setMessage(R.string.dialog_link)
.setPositiveButton(R.string.action_new_tab, dialogClickListener)
.setNegativeButton(R.string.action_open, dialogClickListener)
.setNeutralButton(R.string.action_copy, dialogClickListener)
.show();
}
} }

View File

@ -3,10 +3,8 @@
*/ */
package acr.browser.lightning.download; package acr.browser.lightning.download;
import android.app.Activity;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -19,13 +17,17 @@ import android.util.Log;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.URLUtil; import android.webkit.URLUtil;
import com.squareup.otto.Bus;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import acr.browser.lightning.BuildConfig;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.activity.MainActivity;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.Utils;
/** /**
* Handle download requests * Handle download requests
@ -44,13 +46,13 @@ public class DownloadHandler {
* Notify the host application a download should be done, or that the data * Notify the host application a download should be done, or that the data
* should be streamed if a streaming viewer is available. * should be streamed if a streaming viewer is available.
* *
* @param activity Activity requesting the download. * @param context The context in which the download was requested.
* @param url The full url to the content that should be downloaded * @param url The full url to the content that should be downloaded
* @param userAgent User agent of the downloading application. * @param userAgent User agent of the downloading application.
* @param contentDisposition Content-disposition http header, if present. * @param contentDisposition Content-disposition http header, if present.
* @param mimetype The mimetype of the content reported by the server * @param mimetype The mimetype of the content reported by the server
*/ */
public static void onDownloadStart(Activity activity, String url, String userAgent, public static void onDownloadStart(Context context, String url, String userAgent,
String contentDisposition, String mimetype) { String contentDisposition, String mimetype) {
// if we're dealing wih A/V content that's not explicitly marked // if we're dealing wih A/V content that's not explicitly marked
// for download, check if it's streamable. // for download, check if it's streamable.
@ -61,18 +63,17 @@ public class DownloadHandler {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), mimetype); intent.setDataAndType(Uri.parse(url), mimetype);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ResolveInfo info = activity.getPackageManager().resolveActivity(intent, ResolveInfo info = context.getPackageManager().resolveActivity(intent,
PackageManager.MATCH_DEFAULT_ONLY); PackageManager.MATCH_DEFAULT_ONLY);
if (info != null) { if (info != null) {
ComponentName myName = activity.getComponentName();
// If we resolved to ourselves, we don't want to attempt to // If we resolved to ourselves, we don't want to attempt to
// load the url only to try and download it again. // load the url only to try and download it again.
if (!myName.getPackageName().equals(info.activityInfo.packageName) if (BuildConfig.APPLICATION_ID.equals(info.activityInfo.packageName)
|| !myName.getClassName().equals(info.activityInfo.name)) { || MainActivity.class.getName().equals(info.activityInfo.name)) {
// someone (other than us) knows how to handle this mime // someone (other than us) knows how to handle this mime
// type with this scheme, don't download. // type with this scheme, don't download.
try { try {
activity.startActivity(intent); context.startActivity(intent);
return; return;
} catch (ActivityNotFoundException ex) { } catch (ActivityNotFoundException ex) {
// Best behavior is to fall back to a download in this // Best behavior is to fall back to a download in this
@ -81,8 +82,7 @@ public class DownloadHandler {
} }
} }
} }
onDownloadStartNoStream(activity, url, userAgent, contentDisposition, mimetype onDownloadStartNoStream(context, url, userAgent, contentDisposition, mimetype);
);
} }
// This is to work around the fact that java.net.URI throws Exceptions // This is to work around the fact that java.net.URI throws Exceptions
@ -119,17 +119,17 @@ public class DownloadHandler {
* Notify the host application a download should be done, even if there is a * Notify the host application a download should be done, even if there is a
* streaming viewer available for thise type. * streaming viewer available for thise type.
* *
* @param activity Activity requesting the download. * @param context The context in which the download is requested.
* @param url The full url to the content that should be downloaded * @param url The full url to the content that should be downloaded
* @param userAgent User agent of the downloading application. * @param userAgent User agent of the downloading application.
* @param contentDisposition Content-disposition http header, if present. * @param contentDisposition Content-disposition http header, if present.
* @param mimetype The mimetype of the content reported by the server * @param mimetype The mimetype of the content reported by the server
*/ */
/* package */ /* package */
private static void onDownloadStartNoStream(final Activity activity, String url, String userAgent, private static void onDownloadStartNoStream(final Context context, String url, String userAgent,
String contentDisposition, String mimetype) { String contentDisposition, String mimetype) {
final Bus eventBus = BrowserApp.getAppComponent().getBus();
String filename = URLUtil.guessFileName(url, contentDisposition, mimetype); final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
// Check to see if we have an SDCard // Check to see if we have an SDCard
String status = Environment.getExternalStorageState(); String status = Environment.getExternalStorageState();
@ -139,14 +139,14 @@ public class DownloadHandler {
// Check to see if the SDCard is busy, same as the music app // Check to see if the SDCard is busy, same as the music app
if (status.equals(Environment.MEDIA_SHARED)) { if (status.equals(Environment.MEDIA_SHARED)) {
msg = activity.getString(R.string.download_sdcard_busy_dlg_msg); msg = context.getString(R.string.download_sdcard_busy_dlg_msg);
title = R.string.download_sdcard_busy_dlg_title; title = R.string.download_sdcard_busy_dlg_title;
} else { } else {
msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename); msg = context.getString(R.string.download_no_sdcard_dlg_msg, filename);
title = R.string.download_no_sdcard_dlg_title; title = R.string.download_no_sdcard_dlg_title;
} }
new AlertDialog.Builder(activity).setTitle(title) new AlertDialog.Builder(context).setTitle(title)
.setIcon(android.R.drawable.ic_dialog_alert).setMessage(msg) .setIcon(android.R.drawable.ic_dialog_alert).setMessage(msg)
.setPositiveButton(R.string.action_ok, null).show(); .setPositiveButton(R.string.action_ok, null).show();
return; return;
@ -162,7 +162,7 @@ public class DownloadHandler {
// This only happens for very bad urls, we want to catch the // This only happens for very bad urls, we want to catch the
// exception here // exception here
Log.e(TAG, "Exception while trying to parse url '" + url + '\'', e); Log.e(TAG, "Exception while trying to parse url '" + url + '\'', e);
Utils.showSnackbar(activity, R.string.problem_download); eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_download));
return; return;
} }
@ -172,7 +172,7 @@ public class DownloadHandler {
try { try {
request = new DownloadManager.Request(uri); request = new DownloadManager.Request(uri);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Utils.showSnackbar(activity, R.string.cannot_download); eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.cannot_download));
return; return;
} }
request.setMimeType(mimetype); request.setMimeType(mimetype);
@ -180,7 +180,7 @@ public class DownloadHandler {
// or, should it be set to one of several Environment.DIRECTORY* dirs // or, should it be set to one of several Environment.DIRECTORY* dirs
// depending on mimetype? // depending on mimetype?
String location = PreferenceManager.getInstance().getDownloadDirectory(); String location = BrowserApp.getAppComponent().getPreferenceManager().getDownloadDirectory();
Uri downloadFolder; Uri downloadFolder;
if (location != null) { if (location != null) {
location = addNecessarySlashes(location); location = addNecessarySlashes(location);
@ -188,18 +188,18 @@ public class DownloadHandler {
} else { } else {
location = addNecessarySlashes(DEFAULT_DOWNLOAD_PATH); location = addNecessarySlashes(DEFAULT_DOWNLOAD_PATH);
downloadFolder = Uri.parse(location); downloadFolder = Uri.parse(location);
PreferenceManager.getInstance().setDownloadDirectory(location); BrowserApp.getAppComponent().getPreferenceManager().setDownloadDirectory(location);
} }
File dir = new File(downloadFolder.getPath()); File dir = new File(downloadFolder.getPath());
if (!dir.isDirectory() && !dir.mkdirs()) { if (!dir.isDirectory() && !dir.mkdirs()) {
// Cannot make the directory // Cannot make the directory
Utils.showSnackbar(activity, R.string.problem_location_download); eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_location_download));
return; return;
} }
if (!isWriteAccessAvailable(downloadFolder)) { if (!isWriteAccessAvailable(downloadFolder)) {
Utils.showSnackbar(activity, R.string.problem_location_download); eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_location_download));
return; return;
} }
request.setDestinationUri(Uri.parse(Constants.FILE + location + filename)); request.setDestinationUri(Uri.parse(Constants.FILE + location + filename));
@ -219,9 +219,9 @@ public class DownloadHandler {
} }
// We must have long pressed on a link or image to download it. We // We must have long pressed on a link or image to download it. We
// are not sure of the mimetype in this case, so do a head request // are not sure of the mimetype in this case, so do a head request
new FetchUrlMimeType(activity, request, addressString, cookies, userAgent).start(); new FetchUrlMimeType(context, request, addressString, cookies, userAgent).start();
} else { } else {
final DownloadManager manager = (DownloadManager) activity final DownloadManager manager = (DownloadManager) context
.getSystemService(Context.DOWNLOAD_SERVICE); .getSystemService(Context.DOWNLOAD_SERVICE);
new Thread() { new Thread() {
@Override @Override
@ -231,15 +231,16 @@ public class DownloadHandler {
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Probably got a bad URL or something // Probably got a bad URL or something
e.printStackTrace(); e.printStackTrace();
Utils.showSnackbar(activity, R.string.cannot_download); eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.cannot_download));
} catch (SecurityException e) { } catch (SecurityException e) {
// TODO write a download utility that downloads files rather than rely on the system // TODO write a download utility that downloads files rather than rely on the system
// because the system can only handle Environment.getExternal... as a path // because the system can only handle Environment.getExternal... as a path
Utils.showSnackbar(activity, R.string.problem_location_download); eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_location_download));
} }
} }
}.start(); }.start();
Utils.showSnackbar(activity, activity.getString(R.string.download_pending) + ' ' + filename); eventBus.post(new BrowserEvents.ShowSnackBarMessage(
context.getString(R.string.download_pending) + ' ' + filename));
} }
} }
@ -320,12 +321,12 @@ public class DownloadHandler {
} catch (IOException ignored) { } catch (IOException ignored) {
return false; return false;
} }
} }
public static String addNecessarySlashes(String originalPath) { public static String addNecessarySlashes(String originalPath) {
if (originalPath == null || originalPath.length() == 0) { if (originalPath == null || originalPath.length() == 0) {
return "/"; return "/";
} }
if (originalPath.charAt(originalPath.length() - 1) != '/') { if (originalPath.charAt(originalPath.length() - 1) != '/') {
originalPath = originalPath + '/'; originalPath = originalPath + '/';
} }

View File

@ -3,18 +3,21 @@
*/ */
package acr.browser.lightning.download; package acr.browser.lightning.download;
import android.app.Activity;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.content.Context; import android.content.Context;
import android.os.Environment; import android.os.Environment;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.webkit.URLUtil; import android.webkit.URLUtil;
import com.squareup.otto.Bus;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.utils.Utils; import acr.browser.lightning.utils.Utils;
/** /**
@ -27,7 +30,7 @@ import acr.browser.lightning.utils.Utils;
*/ */
class FetchUrlMimeType extends Thread { class FetchUrlMimeType extends Thread {
private final Activity mActivity; private final Context mContext;
private final DownloadManager.Request mRequest; private final DownloadManager.Request mRequest;
@ -37,9 +40,9 @@ class FetchUrlMimeType extends Thread {
private final String mUserAgent; private final String mUserAgent;
public FetchUrlMimeType(Activity activity, DownloadManager.Request request, String uri, public FetchUrlMimeType(Context context, DownloadManager.Request request, String uri,
String cookies, String userAgent) { String cookies, String userAgent) {
mActivity = activity; mContext = context;
mRequest = request; mRequest = request;
mUri = uri; mUri = uri;
mCookies = cookies; mCookies = cookies;
@ -50,6 +53,7 @@ class FetchUrlMimeType extends Thread {
public void run() { public void run() {
// User agent is likely to be null, though the AndroidHttpClient // User agent is likely to be null, though the AndroidHttpClient
// seems ok with that. // seems ok with that.
final Bus evenBus = BrowserApp.getAppComponent().getBus();
String mimeType = null; String mimeType = null;
String contentDisposition = null; String contentDisposition = null;
HttpURLConnection connection = null; HttpURLConnection connection = null;
@ -101,9 +105,9 @@ class FetchUrlMimeType extends Thread {
} }
// Start the download // Start the download
DownloadManager manager = (DownloadManager) mActivity DownloadManager manager = (DownloadManager) mContext
.getSystemService(Context.DOWNLOAD_SERVICE); .getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(mRequest); manager.enqueue(mRequest);
Utils.showSnackbar(mActivity, mActivity.getString(R.string.download_pending) + ' ' + filename); evenBus.post(new BrowserEvents.ShowSnackBarMessage(mContext.getString(R.string.download_pending) + ' ' + filename));
} }
} }

View File

@ -3,7 +3,7 @@
*/ */
package acr.browser.lightning.download; package acr.browser.lightning.download;
import android.app.Activity; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
@ -15,10 +15,10 @@ import acr.browser.lightning.constant.Constants;
public class LightningDownloadListener implements DownloadListener { public class LightningDownloadListener implements DownloadListener {
private final Activity mActivity; private final Context mContext;
public LightningDownloadListener(Activity activity) { public LightningDownloadListener(Context context) {
mActivity = activity; mContext = context;
} }
@Override @Override
@ -30,7 +30,7 @@ public class LightningDownloadListener implements DownloadListener {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch (which) { switch (which) {
case DialogInterface.BUTTON_POSITIVE: case DialogInterface.BUTTON_POSITIVE:
DownloadHandler.onDownloadStart(mActivity, url, userAgent, DownloadHandler.onDownloadStart(mContext, url, userAgent,
contentDisposition, mimetype); contentDisposition, mimetype);
break; break;
@ -40,12 +40,12 @@ public class LightningDownloadListener implements DownloadListener {
} }
}; };
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); // dialog AlertDialog.Builder builder = new AlertDialog.Builder(mContext); // dialog
builder.setTitle(fileName) builder.setTitle(fileName)
.setMessage(mActivity.getResources().getString(R.string.dialog_download)) .setMessage(mContext.getResources().getString(R.string.dialog_download))
.setPositiveButton(mActivity.getResources().getString(R.string.action_download), .setPositiveButton(mContext.getResources().getString(R.string.action_download),
dialogClickListener) dialogClickListener)
.setNegativeButton(mActivity.getResources().getString(R.string.action_cancel), .setNegativeButton(mContext.getResources().getString(R.string.action_cancel),
dialogClickListener).show(); dialogClickListener).show();
Log.i(Constants.TAG, "Downloading" + fileName); Log.i(Constants.TAG, "Downloading" + fileName);

View File

@ -8,7 +8,6 @@ import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import java.util.Arrays; import java.util.Arrays;
@ -16,9 +15,8 @@ import java.util.List;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.preference.PreferenceManager;
public class AdvancedSettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { public class AdvancedSettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
private static final String SETTINGS_NEWWINDOW = "allow_new_window"; private static final String SETTINGS_NEWWINDOW = "allow_new_window";
private static final String SETTINGS_ENABLECOOKIES = "allow_cookies"; private static final String SETTINGS_ENABLECOOKIES = "allow_cookies";
@ -29,7 +27,6 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
private static final String SETTINGS_TEXTENCODING = "text_encoding"; private static final String SETTINGS_TEXTENCODING = "text_encoding";
private Activity mActivity; private Activity mActivity;
private PreferenceManager mPreferences;
private CheckBoxPreference cbAllowPopups, cbenablecookies, cbcookiesInkognito, cbrestoreTabs; private CheckBoxPreference cbAllowPopups, cbenablecookies, cbcookiesInkognito, cbrestoreTabs;
private Preference renderingmode, urlcontent, textEncoding; private Preference renderingmode, urlcontent, textEncoding;
private CharSequence[] mUrlOptions; private CharSequence[] mUrlOptions;
@ -46,8 +43,6 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
} }
private void initPrefs() { private void initPrefs() {
// mPreferences storage
mPreferences = PreferenceManager.getInstance();
renderingmode = findPreference(SETTINGS_RENDERINGMODE); renderingmode = findPreference(SETTINGS_RENDERINGMODE);
textEncoding = findPreference(SETTINGS_TEXTENCODING); textEncoding = findPreference(SETTINGS_TEXTENCODING);
@ -65,7 +60,7 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
cbcookiesInkognito.setOnPreferenceChangeListener(this); cbcookiesInkognito.setOnPreferenceChangeListener(this);
cbrestoreTabs.setOnPreferenceChangeListener(this); cbrestoreTabs.setOnPreferenceChangeListener(this);
switch (mPreferences.getRenderingMode()) { switch (mPreferenceManager.getRenderingMode()) {
case 0: case 0:
renderingmode.setSummary(getString(R.string.name_normal)); renderingmode.setSummary(getString(R.string.name_normal));
break; break;
@ -80,16 +75,16 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
break; break;
} }
textEncoding.setSummary(mPreferences.getTextEncoding()); textEncoding.setSummary(mPreferenceManager.getTextEncoding());
mUrlOptions = getResources().getStringArray(R.array.url_content_array); mUrlOptions = getResources().getStringArray(R.array.url_content_array);
int option = mPreferences.getUrlBoxContentChoice(); int option = mPreferenceManager.getUrlBoxContentChoice();
urlcontent.setSummary(mUrlOptions[option]); urlcontent.setSummary(mUrlOptions[option]);
cbAllowPopups.setChecked(mPreferences.getPopupsEnabled()); cbAllowPopups.setChecked(mPreferenceManager.getPopupsEnabled());
cbenablecookies.setChecked(mPreferences.getCookiesEnabled()); cbenablecookies.setChecked(mPreferenceManager.getCookiesEnabled());
cbcookiesInkognito.setChecked(mPreferences.getIncognitoCookiesEnabled()); cbcookiesInkognito.setChecked(mPreferenceManager.getIncognitoCookiesEnabled());
cbrestoreTabs.setChecked(mPreferences.getRestoreLostTabsEnabled()); cbrestoreTabs.setChecked(mPreferenceManager.getRestoreLostTabsEnabled());
} }
@Override @Override
@ -114,19 +109,19 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
// switch preferences // switch preferences
switch (preference.getKey()) { switch (preference.getKey()) {
case SETTINGS_NEWWINDOW: case SETTINGS_NEWWINDOW:
mPreferences.setPopupsEnabled((Boolean) newValue); mPreferenceManager.setPopupsEnabled((Boolean) newValue);
cbAllowPopups.setChecked((Boolean) newValue); cbAllowPopups.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_ENABLECOOKIES: case SETTINGS_ENABLECOOKIES:
mPreferences.setCookiesEnabled((Boolean) newValue); mPreferenceManager.setCookiesEnabled((Boolean) newValue);
cbenablecookies.setChecked((Boolean) newValue); cbenablecookies.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_COOKIESINKOGNITO: case SETTINGS_COOKIESINKOGNITO:
mPreferences.setIncognitoCookiesEnabled((Boolean) newValue); mPreferenceManager.setIncognitoCookiesEnabled((Boolean) newValue);
cbcookiesInkognito.setChecked((Boolean) newValue); cbcookiesInkognito.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_RESTORETABS: case SETTINGS_RESTORETABS:
mPreferences.setRestoreLostTabsEnabled((Boolean) newValue); mPreferenceManager.setRestoreLostTabsEnabled((Boolean) newValue);
cbrestoreTabs.setChecked((Boolean) newValue); cbrestoreTabs.setChecked((Boolean) newValue);
return true; return true;
default: default:
@ -142,12 +137,12 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
mActivity.getString(R.string.name_grayscale), mActivity.getString(R.string.name_grayscale),
mActivity.getString(R.string.name_inverted_grayscale)}; mActivity.getString(R.string.name_inverted_grayscale)};
int n = mPreferences.getRenderingMode(); int n = mPreferenceManager.getRenderingMode();
picker.setSingleChoiceItems(chars, n, new DialogInterface.OnClickListener() { picker.setSingleChoiceItems(chars, n, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mPreferences.setRenderingMode(which); mPreferenceManager.setRenderingMode(which);
switch (which) { switch (which) {
case 0: case 0:
renderingmode.setSummary(getString(R.string.name_normal)); renderingmode.setSummary(getString(R.string.name_normal));
@ -172,12 +167,12 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); AlertDialog.Builder picker = new AlertDialog.Builder(mActivity);
picker.setTitle(getResources().getString(R.string.text_encoding)); picker.setTitle(getResources().getString(R.string.text_encoding));
final List<String> textEncodingList = Arrays.asList(Constants.TEXT_ENCODINGS); final List<String> textEncodingList = Arrays.asList(Constants.TEXT_ENCODINGS);
int n = textEncodingList.indexOf(mPreferences.getTextEncoding()); int n = textEncodingList.indexOf(mPreferenceManager.getTextEncoding());
picker.setSingleChoiceItems(Constants.TEXT_ENCODINGS, n, new DialogInterface.OnClickListener() { picker.setSingleChoiceItems(Constants.TEXT_ENCODINGS, n, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mPreferences.setTextEncoding(Constants.TEXT_ENCODINGS[which]); mPreferenceManager.setTextEncoding(Constants.TEXT_ENCODINGS[which]);
textEncoding.setSummary(Constants.TEXT_ENCODINGS[which]); textEncoding.setSummary(Constants.TEXT_ENCODINGS[which]);
} }
}); });
@ -189,12 +184,12 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref
AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); AlertDialog.Builder picker = new AlertDialog.Builder(mActivity);
picker.setTitle(getResources().getString(R.string.url_contents)); picker.setTitle(getResources().getString(R.string.url_contents));
int n = mPreferences.getUrlBoxContentChoice(); int n = mPreferenceManager.getUrlBoxContentChoice();
picker.setSingleChoiceItems(mUrlOptions, n, new DialogInterface.OnClickListener() { picker.setSingleChoiceItems(mUrlOptions, n, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mPreferences.setUrlBoxContentChoice(which); mPreferenceManager.setUrlBoxContentChoice(which);
if (which < mUrlOptions.length) { if (which < mUrlOptions.length) {
urlcontent.setSummary(mUrlOptions[which]); urlcontent.setSummary(mUrlOptions[which]);
} }

View File

@ -1,6 +1,5 @@
package acr.browser.lightning.fragment; package acr.browser.lightning.fragment;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
@ -43,7 +42,7 @@ import acr.browser.lightning.bus.BookmarkEvents;
import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.BookmarkManager;
import acr.browser.lightning.database.HistoryItem; import acr.browser.lightning.database.HistoryItem;
import acr.browser.lightning.dialog.BookmarksDialogBuilder; import acr.browser.lightning.dialog.LightningDialogBuilder;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.async.ImageDownloadTask; import acr.browser.lightning.async.ImageDownloadTask;
import acr.browser.lightning.utils.ThemeUtils; import acr.browser.lightning.utils.ThemeUtils;
@ -53,6 +52,10 @@ import acr.browser.lightning.utils.ThemeUtils;
*/ */
public class BookmarksFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener { public class BookmarksFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener {
private final static String TAG = BookmarksFragment.class.getSimpleName();
public final static String INCOGNITO_MODE = TAG + ".INCOGNITO_MODE";
// Managers // Managers
@Inject @Inject
BookmarkManager mBookmarkManager; BookmarkManager mBookmarkManager;
@ -63,7 +66,10 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
// Dialog builder // Dialog builder
@Inject @Inject
BookmarksDialogBuilder mBookmarksDialogBuilder; LightningDialogBuilder mBookmarksDialogBuilder;
@Inject
PreferenceManager mPreferenceManager;
// Adapter // Adapter
private BookmarkViewAdapter mBookmarkAdapter; private BookmarkViewAdapter mBookmarkAdapter;
@ -81,6 +87,8 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
// Colors // Colors
private int mIconColor, mScrollIndex; private int mIconColor, mScrollIndex;
private boolean mIsIncognito;
// Init asynchronously the bookmark manager // Init asynchronously the bookmark manager
private final Runnable mInitBookmarkManager = new Runnable() { private final Runnable mInitBookmarkManager = new Runnable() {
@Override @Override
@ -96,6 +104,14 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
BrowserApp.getAppComponent().inject(this); BrowserApp.getAppComponent().inject(this);
final Bundle arguments = getArguments();
final Context context = getContext();
mIsIncognito = arguments.getBoolean(INCOGNITO_MODE, false);
boolean darkTheme = mPreferenceManager.getUseTheme() != 0 || mIsIncognito;
mWebpageBitmap = ThemeUtils.getThemedBitmap(context, R.drawable.ic_webpage, darkTheme);
mFolderBitmap = ThemeUtils.getThemedBitmap(context, R.drawable.ic_folder, darkTheme);
mIconColor = darkTheme ? ThemeUtils.getIconDarkThemeColor(context) :
ThemeUtils.getIconLightThemeColor(context);
} }
// Handle bookmark click // Handle bookmark click
@ -107,7 +123,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
mScrollIndex = mBookmarksListView.getFirstVisiblePosition(); mScrollIndex = mBookmarksListView.getFirstVisiblePosition();
setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(item.getTitle(), true), true); setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(item.getTitle(), true), true);
} else { } else {
mEventBus.post(new BookmarkEvents.Clicked(item)); mEventBus.post(new BrowserEvents.OpenUrlInCurrentTab(item.getUrl()));
} }
} }
}; };
@ -135,6 +151,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
mBookmarksListView.setOnItemClickListener(mItemClickListener); mBookmarksListView.setOnItemClickListener(mItemClickListener);
mBookmarksListView.setOnItemLongClickListener(mItemLongClickListener); mBookmarksListView.setOnItemLongClickListener(mItemLongClickListener);
mBookmarkTitleImage = (ImageView) view.findViewById(R.id.starIcon); mBookmarkTitleImage = (ImageView) view.findViewById(R.id.starIcon);
mBookmarkTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
mBookmarkImage = (ImageView) view.findViewById(R.id.icon_star); mBookmarkImage = (ImageView) view.findViewById(R.id.icon_star);
final View backView = view.findViewById(R.id.bookmark_back_button); final View backView = view.findViewById(R.id.bookmark_back_button);
backView.setOnClickListener(new View.OnClickListener() { backView.setOnClickListener(new View.OnClickListener() {
@ -154,20 +171,6 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
return view; return view;
} }
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
// TODO remove dependency on BrowserActivity
super.onActivityCreated(savedInstanceState);
final Activity activity = getActivity();
final PreferenceManager preferenceManager = PreferenceManager.getInstance();
boolean darkTheme = preferenceManager.getUseTheme() != 0 || ((BrowserActivity) activity).isIncognito();
mWebpageBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_webpage, darkTheme);
mFolderBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_folder, darkTheme);
mIconColor = darkTheme ? ThemeUtils.getIconDarkThemeColor(activity) :
ThemeUtils.getIconLightThemeColor(activity);
mBookmarkTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
}
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
@ -229,8 +232,8 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
if (event.item.isFolder()) { if (event.item.isFolder()) {
setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false);
} else { } else {
mBookmarkAdapter.notifyDataSetChanged(); mBookmarkAdapter.notifyDataSetChanged();
} }
} }
private void setBookmarkDataSet(List<HistoryItem> items, boolean animate) { private void setBookmarkDataSet(List<HistoryItem> items, boolean animate) {
@ -295,7 +298,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
if (item.isFolder()) { if (item.isFolder()) {
mBookmarksDialogBuilder.showBookmarkFolderLongPressedDialog(getContext(), item); mBookmarksDialogBuilder.showBookmarkFolderLongPressedDialog(getContext(), item);
} else { } else {
mBookmarksDialogBuilder.showLongPressedDialogForUrl(getContext(), item); mBookmarksDialogBuilder.showLongPressLinkDialog(getContext(), item.getUrl());
} }
} }

View File

@ -8,7 +8,6 @@ import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -19,9 +18,8 @@ import android.widget.SeekBar;
import android.widget.TextView; import android.widget.TextView;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.preference.PreferenceManager;
public class DisplaySettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { public class DisplaySettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
private static final String SETTINGS_HIDESTATUSBAR = "fullScreenOption"; private static final String SETTINGS_HIDESTATUSBAR = "fullScreenOption";
private static final String SETTINGS_FULLSCREEN = "fullscreen"; private static final String SETTINGS_FULLSCREEN = "fullscreen";
@ -38,7 +36,6 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
private static final float XSMALL = 10.0f; private static final float XSMALL = 10.0f;
private Activity mActivity; private Activity mActivity;
private PreferenceManager mPreferences;
private CheckBoxPreference cbstatus, cbfullscreen, cbviewport, cboverview, cbreflow; private CheckBoxPreference cbstatus, cbfullscreen, cbviewport, cboverview, cbreflow;
private Preference theme; private Preference theme;
private String[] mThemeOptions; private String[] mThemeOptions;
@ -57,9 +54,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
private void initPrefs() { private void initPrefs() {
// mPreferences storage // mPreferences storage
mPreferences = PreferenceManager.getInstance();
mThemeOptions = this.getResources().getStringArray(R.array.themes); mThemeOptions = this.getResources().getStringArray(R.array.themes);
mCurrentTheme = mPreferences.getUseTheme(); mCurrentTheme = mPreferenceManager.getUseTheme();
theme = findPreference(SETTINGS_THEME); theme = findPreference(SETTINGS_THEME);
Preference textsize = findPreference(SETTINGS_TEXTSIZE); Preference textsize = findPreference(SETTINGS_TEXTSIZE);
@ -77,13 +73,13 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
cboverview.setOnPreferenceChangeListener(this); cboverview.setOnPreferenceChangeListener(this);
cbreflow.setOnPreferenceChangeListener(this); cbreflow.setOnPreferenceChangeListener(this);
cbstatus.setChecked(mPreferences.getHideStatusBarEnabled()); cbstatus.setChecked(mPreferenceManager.getHideStatusBarEnabled());
cbfullscreen.setChecked(mPreferences.getFullScreenEnabled()); cbfullscreen.setChecked(mPreferenceManager.getFullScreenEnabled());
cbviewport.setChecked(mPreferences.getUseWideViewportEnabled()); cbviewport.setChecked(mPreferenceManager.getUseWideViewportEnabled());
cboverview.setChecked(mPreferences.getOverviewModeEnabled()); cboverview.setChecked(mPreferenceManager.getOverviewModeEnabled());
cbreflow.setChecked(mPreferences.getTextReflowEnabled()); cbreflow.setChecked(mPreferenceManager.getTextReflowEnabled());
theme.setSummary(mThemeOptions[mPreferences.getUseTheme()]); theme.setSummary(mThemeOptions[mPreferenceManager.getUseTheme()]);
} }
@Override @Override
@ -105,23 +101,23 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
// switch preferences // switch preferences
switch (preference.getKey()) { switch (preference.getKey()) {
case SETTINGS_HIDESTATUSBAR: case SETTINGS_HIDESTATUSBAR:
mPreferences.setHideStatusBarEnabled((Boolean) newValue); mPreferenceManager.setHideStatusBarEnabled((Boolean) newValue);
cbstatus.setChecked((Boolean) newValue); cbstatus.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_FULLSCREEN: case SETTINGS_FULLSCREEN:
mPreferences.setFullScreenEnabled((Boolean) newValue); mPreferenceManager.setFullScreenEnabled((Boolean) newValue);
cbfullscreen.setChecked((Boolean) newValue); cbfullscreen.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_VIEWPORT: case SETTINGS_VIEWPORT:
mPreferences.setUseWideViewportEnabled((Boolean) newValue); mPreferenceManager.setUseWideViewportEnabled((Boolean) newValue);
cbviewport.setChecked((Boolean) newValue); cbviewport.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_OVERVIEWMODE: case SETTINGS_OVERVIEWMODE:
mPreferences.setOverviewModeEnabled((Boolean) newValue); mPreferenceManager.setOverviewModeEnabled((Boolean) newValue);
cboverview.setChecked((Boolean) newValue); cboverview.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_REFLOW: case SETTINGS_REFLOW:
mPreferences.setTextReflowEnabled((Boolean) newValue); mPreferenceManager.setTextReflowEnabled((Boolean) newValue);
cbreflow.setChecked((Boolean) newValue); cbreflow.setChecked((Boolean) newValue);
return true; return true;
default: default:
@ -142,14 +138,14 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
bar.setOnSeekBarChangeListener(new TextSeekBarListener(sample)); bar.setOnSeekBarChangeListener(new TextSeekBarListener(sample));
final int MAX = 5; final int MAX = 5;
bar.setMax(MAX); bar.setMax(MAX);
bar.setProgress(MAX - mPreferences.getTextSize()); bar.setProgress(MAX - mPreferenceManager.getTextSize());
builder.setView(view); builder.setView(view);
builder.setTitle(R.string.title_text_size); builder.setTitle(R.string.title_text_size);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface arg0, int arg1) { public void onClick(DialogInterface arg0, int arg1) {
mPreferences.setTextSize(MAX - bar.getProgress()); mPreferenceManager.setTextSize(MAX - bar.getProgress());
} }
}); });
@ -179,12 +175,12 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); AlertDialog.Builder picker = new AlertDialog.Builder(mActivity);
picker.setTitle(getResources().getString(R.string.theme)); picker.setTitle(getResources().getString(R.string.theme));
int n = mPreferences.getUseTheme(); int n = mPreferenceManager.getUseTheme();
picker.setSingleChoiceItems(mThemeOptions, n, new DialogInterface.OnClickListener() { picker.setSingleChoiceItems(mThemeOptions, n, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mPreferences.setUseTheme(which); mPreferenceManager.setUseTheme(which);
if (which < mThemeOptions.length) { if (which < mThemeOptions.length) {
theme.setSummary(mThemeOptions[which]); theme.setSummary(mThemeOptions[which]);
} }
@ -195,7 +191,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (mCurrentTheme != mPreferences.getUseTheme()) { if (mCurrentTheme != mPreferenceManager.getUseTheme()) {
getActivity().onBackPressed(); getActivity().onBackPressed();
} }
} }
@ -203,7 +199,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
picker.setOnCancelListener(new DialogInterface.OnCancelListener() { picker.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
if (mCurrentTheme != mPreferences.getUseTheme()) { if (mCurrentTheme != mPreferenceManager.getUseTheme()) {
getActivity().onBackPressed(); getActivity().onBackPressed();
} }
} }

View File

@ -9,7 +9,6 @@ import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
@ -28,7 +27,7 @@ import acr.browser.lightning.utils.ProxyUtils;
import acr.browser.lightning.utils.ThemeUtils; import acr.browser.lightning.utils.ThemeUtils;
import acr.browser.lightning.utils.Utils; import acr.browser.lightning.utils.Utils;
public class GeneralSettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { public class GeneralSettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
private static final String SETTINGS_PROXY = "proxy"; private static final String SETTINGS_PROXY = "proxy";
private static final String SETTINGS_FLASH = "cb_flash"; private static final String SETTINGS_FLASH = "cb_flash";
@ -45,7 +44,6 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
private Activity mActivity; private Activity mActivity;
private static final int API = android.os.Build.VERSION.SDK_INT; private static final int API = android.os.Build.VERSION.SDK_INT;
private PreferenceManager mPreferences;
private CharSequence[] mProxyChoices; private CharSequence[] mProxyChoices;
private Preference proxy, useragent, downloadloc, home, searchengine; private Preference proxy, useragent, downloadloc, home, searchengine;
private String mDownloadLocation; private String mDownloadLocation;
@ -65,9 +63,6 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
} }
private void initPrefs() { private void initPrefs() {
// mPreferences storage
mPreferences = PreferenceManager.getInstance();
proxy = findPreference(SETTINGS_PROXY); proxy = findPreference(SETTINGS_PROXY);
useragent = findPreference(SETTINGS_USERAGENT); useragent = findPreference(SETTINGS_USERAGENT);
downloadloc = findPreference(SETTINGS_DOWNLOAD); downloadloc = findPreference(SETTINGS_DOWNLOAD);
@ -95,23 +90,23 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
cbgooglesuggest.setOnPreferenceChangeListener(this); cbgooglesuggest.setOnPreferenceChangeListener(this);
cbDrawerTabs.setOnPreferenceChangeListener(this); cbDrawerTabs.setOnPreferenceChangeListener(this);
mAgentChoice = mPreferences.getUserAgentChoice(); mAgentChoice = mPreferenceManager.getUserAgentChoice();
mHomepage = mPreferences.getHomepage(); mHomepage = mPreferenceManager.getHomepage();
mDownloadLocation = mPreferences.getDownloadDirectory(); mDownloadLocation = mPreferenceManager.getDownloadDirectory();
mProxyChoices = getResources().getStringArray(R.array.proxy_choices_array); mProxyChoices = getResources().getStringArray(R.array.proxy_choices_array);
int choice = mPreferences.getProxyChoice(); int choice = mPreferenceManager.getProxyChoice();
if (choice == Constants.PROXY_MANUAL) { if (choice == Constants.PROXY_MANUAL) {
proxy.setSummary(mPreferences.getProxyHost() + ':' + mPreferences.getProxyPort()); proxy.setSummary(mPreferenceManager.getProxyHost() + ':' + mPreferenceManager.getProxyPort());
} else { } else {
proxy.setSummary(mProxyChoices[choice]); proxy.setSummary(mProxyChoices[choice]);
} }
if (API >= 19) { if (API >= 19) {
mPreferences.setFlashSupport(0); mPreferenceManager.setFlashSupport(0);
} }
setSearchEngineSummary(mPreferences.getSearchChoice()); setSearchEngineSummary(mPreferenceManager.getSearchChoice());
downloadloc.setSummary(mDownloadLocation); downloadloc.setSummary(mDownloadLocation);
@ -139,9 +134,9 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
useragent.setSummary(getResources().getString(R.string.agent_custom)); useragent.setSummary(getResources().getString(R.string.agent_custom));
} }
int flashNum = mPreferences.getFlashSupport(); int flashNum = mPreferenceManager.getFlashSupport();
boolean imagesBool = mPreferences.getBlockImagesEnabled(); boolean imagesBool = mPreferenceManager.getBlockImagesEnabled();
boolean enableJSBool = mPreferences.getJavaScriptEnabled(); boolean enableJSBool = mPreferenceManager.getJavaScriptEnabled();
cbAds.setEnabled(Constants.FULL_VERSION); cbAds.setEnabled(Constants.FULL_VERSION);
cbFlash.setEnabled(API < 19); cbFlash.setEnabled(API < 19);
@ -149,17 +144,17 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
cbImages.setChecked(imagesBool); cbImages.setChecked(imagesBool);
cbJsScript.setChecked(enableJSBool); cbJsScript.setChecked(enableJSBool);
cbFlash.setChecked(flashNum > 0); cbFlash.setChecked(flashNum > 0);
cbAds.setChecked(Constants.FULL_VERSION && mPreferences.getAdBlockEnabled()); cbAds.setChecked(Constants.FULL_VERSION && mPreferenceManager.getAdBlockEnabled());
cbColorMode.setChecked(mPreferences.getColorModeEnabled()); cbColorMode.setChecked(mPreferenceManager.getColorModeEnabled());
cbgooglesuggest.setChecked(mPreferences.getGoogleSearchSuggestionsEnabled()); cbgooglesuggest.setChecked(mPreferenceManager.getGoogleSearchSuggestionsEnabled());
cbDrawerTabs.setChecked(mPreferences.getShowTabsInDrawer(true)); cbDrawerTabs.setChecked(mPreferenceManager.getShowTabsInDrawer(true));
} }
private void searchUrlPicker() { private void searchUrlPicker() {
final AlertDialog.Builder urlPicker = new AlertDialog.Builder(mActivity); final AlertDialog.Builder urlPicker = new AlertDialog.Builder(mActivity);
urlPicker.setTitle(getResources().getString(R.string.custom_url)); urlPicker.setTitle(getResources().getString(R.string.custom_url));
final EditText getSearchUrl = new EditText(mActivity); final EditText getSearchUrl = new EditText(mActivity);
String mSearchUrl = mPreferences.getSearchUrl(); String mSearchUrl = mPreferenceManager.getSearchUrl();
getSearchUrl.setText(mSearchUrl); getSearchUrl.setText(mSearchUrl);
urlPicker.setView(getSearchUrl); urlPicker.setView(getSearchUrl);
urlPicker.setPositiveButton(getResources().getString(R.string.action_ok), urlPicker.setPositiveButton(getResources().getString(R.string.action_ok),
@ -167,7 +162,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String text = getSearchUrl.getText().toString(); String text = getSearchUrl.getText().toString();
mPreferences.setSearchUrl(text); mPreferenceManager.setSearchUrl(text);
searchengine.setSummary(getResources().getString(R.string.custom_url) + ": " searchengine.setSummary(getResources().getString(R.string.custom_url) + ": "
+ text); + text);
} }
@ -184,7 +179,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
mPreferences.setFlashSupport(1); mPreferenceManager.setFlashSupport(1);
} }
}) })
.setNegativeButton(getResources().getString(R.string.action_auto), .setNegativeButton(getResources().getString(R.string.action_auto),
@ -192,13 +187,13 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mPreferences.setFlashSupport(2); mPreferenceManager.setFlashSupport(2);
} }
}).setOnCancelListener(new DialogInterface.OnCancelListener() { }).setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
mPreferences.setFlashSupport(0); mPreferenceManager.setFlashSupport(0);
} }
}); });
@ -209,7 +204,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
private void proxyChoicePicker() { private void proxyChoicePicker() {
AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); AlertDialog.Builder picker = new AlertDialog.Builder(mActivity);
picker.setTitle(getResources().getString(R.string.http_proxy)); picker.setTitle(getResources().getString(R.string.http_proxy));
picker.setSingleChoiceItems(mProxyChoices, mPreferences.getProxyChoice(), picker.setSingleChoiceItems(mProxyChoices, mPreferenceManager.getProxyChoice(),
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
@ -234,7 +229,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
break; break;
} }
mPreferences.setProxyChoice(choice); mPreferenceManager.setProxyChoice(choice);
if (choice < mProxyChoices.length) if (choice < mProxyChoices.length)
proxy.setSummary(mProxyChoices[choice]); proxy.setSummary(mProxyChoices[choice]);
} }
@ -252,8 +247,8 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
filterArray[0] = new InputFilter.LengthFilter(maxCharacters - 1); filterArray[0] = new InputFilter.LengthFilter(maxCharacters - 1);
eProxyPort.setFilters(filterArray); eProxyPort.setFilters(filterArray);
eProxyHost.setText(mPreferences.getProxyHost()); eProxyHost.setText(mPreferenceManager.getProxyHost());
eProxyPort.setText(Integer.toString(mPreferences.getProxyPort())); eProxyPort.setText(Integer.toString(mPreferenceManager.getProxyPort()));
new AlertDialog.Builder(mActivity) new AlertDialog.Builder(mActivity)
.setTitle(R.string.manual_proxy) .setTitle(R.string.manual_proxy)
@ -268,10 +263,10 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
// larger than max integer // larger than max integer
proxyPort = Integer.parseInt(eProxyPort.getText().toString()); proxyPort = Integer.parseInt(eProxyPort.getText().toString());
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
proxyPort = mPreferences.getProxyPort(); proxyPort = mPreferenceManager.getProxyPort();
} }
mPreferences.setProxyHost(proxyHost); mPreferenceManager.setProxyHost(proxyHost);
mPreferences.setProxyPort(proxyPort); mPreferenceManager.setProxyPort(proxyPort);
proxy.setSummary(proxyHost + ':' + proxyPort); proxy.setSummary(proxyHost + ':' + proxyPort);
} }
}).show(); }).show();
@ -285,13 +280,13 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
"DuckDuckGo (Privacy)", "DuckDuckGo Lite (Privacy)", "Baidu (Chinese)", "DuckDuckGo (Privacy)", "DuckDuckGo Lite (Privacy)", "Baidu (Chinese)",
"Yandex (Russian)"}; "Yandex (Russian)"};
int n = mPreferences.getSearchChoice(); int n = mPreferenceManager.getSearchChoice();
picker.setSingleChoiceItems(chars, n, new DialogInterface.OnClickListener() { picker.setSingleChoiceItems(chars, n, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mPreferences.setSearchChoice(which); mPreferenceManager.setSearchChoice(which);
setSearchEngineSummary(which); setSearchEngineSummary(which);
} }
}); });
@ -302,7 +297,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
private void homepageDialog() { private void homepageDialog() {
AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); AlertDialog.Builder picker = new AlertDialog.Builder(mActivity);
picker.setTitle(getResources().getString(R.string.home)); picker.setTitle(getResources().getString(R.string.home));
mHomepage = mPreferences.getHomepage(); mHomepage = mPreferenceManager.getHomepage();
int n; int n;
if (mHomepage.contains("about:home")) { if (mHomepage.contains("about:home")) {
n = 1; n = 1;
@ -320,15 +315,15 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch (which + 1) { switch (which + 1) {
case 1: case 1:
mPreferences.setHomepage("about:home"); mPreferenceManager.setHomepage("about:home");
home.setSummary(getResources().getString(R.string.action_homepage)); home.setSummary(getResources().getString(R.string.action_homepage));
break; break;
case 2: case 2:
mPreferences.setHomepage("about:blank"); mPreferenceManager.setHomepage("about:blank");
home.setSummary(getResources().getString(R.string.action_blank)); home.setSummary(getResources().getString(R.string.action_blank));
break; break;
case 3: case 3:
mPreferences.setHomepage("about:bookmarks"); mPreferenceManager.setHomepage("about:bookmarks");
home.setSummary(getResources().getString(R.string.action_bookmarks)); home.setSummary(getResources().getString(R.string.action_bookmarks));
break; break;
case 4: case 4:
@ -345,7 +340,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
final AlertDialog.Builder homePicker = new AlertDialog.Builder(mActivity); final AlertDialog.Builder homePicker = new AlertDialog.Builder(mActivity);
homePicker.setTitle(getResources().getString(R.string.title_custom_homepage)); homePicker.setTitle(getResources().getString(R.string.title_custom_homepage));
final EditText getHome = new EditText(mActivity); final EditText getHome = new EditText(mActivity);
mHomepage = mPreferences.getHomepage(); mHomepage = mPreferenceManager.getHomepage();
if (!mHomepage.startsWith("about:")) { if (!mHomepage.startsWith("about:")) {
getHome.setText(mHomepage); getHome.setText(mHomepage);
} else { } else {
@ -357,7 +352,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String text = getHome.getText().toString(); String text = getHome.getText().toString();
mPreferences.setHomepage(text); mPreferenceManager.setHomepage(text);
home.setSummary(text); home.setSummary(text);
} }
}); });
@ -367,7 +362,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
private void downloadLocDialog() { private void downloadLocDialog() {
AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); AlertDialog.Builder picker = new AlertDialog.Builder(mActivity);
picker.setTitle(getResources().getString(R.string.title_download_location)); picker.setTitle(getResources().getString(R.string.title_download_location));
mDownloadLocation = mPreferences.getDownloadDirectory(); mDownloadLocation = mPreferenceManager.getDownloadDirectory();
int n; int n;
if (mDownloadLocation.contains(Environment.DIRECTORY_DOWNLOADS)) { if (mDownloadLocation.contains(Environment.DIRECTORY_DOWNLOADS)) {
n = 0; n = 0;
@ -381,7 +376,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch (which) { switch (which) {
case 0: case 0:
mPreferences.setDownloadDirectory(DownloadHandler.DEFAULT_DOWNLOAD_PATH); mPreferenceManager.setDownloadDirectory(DownloadHandler.DEFAULT_DOWNLOAD_PATH);
downloadloc.setSummary(DownloadHandler.DEFAULT_DOWNLOAD_PATH); downloadloc.setSummary(DownloadHandler.DEFAULT_DOWNLOAD_PATH);
break; break;
case 1: case 1:
@ -397,12 +392,12 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
private void agentDialog() { private void agentDialog() {
AlertDialog.Builder agentPicker = new AlertDialog.Builder(mActivity); AlertDialog.Builder agentPicker = new AlertDialog.Builder(mActivity);
agentPicker.setTitle(getResources().getString(R.string.title_user_agent)); agentPicker.setTitle(getResources().getString(R.string.title_user_agent));
mAgentChoice = mPreferences.getUserAgentChoice(); mAgentChoice = mPreferenceManager.getUserAgentChoice();
agentPicker.setSingleChoiceItems(R.array.user_agent, mAgentChoice - 1, agentPicker.setSingleChoiceItems(R.array.user_agent, mAgentChoice - 1,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mPreferences.setUserAgentChoice(which + 1); mPreferenceManager.setUserAgentChoice(which + 1);
switch (which + 1) { switch (which + 1) {
case 1: case 1:
useragent.setSummary(getResources().getString(R.string.agent_default)); useragent.setSummary(getResources().getString(R.string.agent_default));
@ -434,7 +429,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String text = getAgent.getText().toString(); String text = getAgent.getText().toString();
mPreferences.setUserAgentString(text); mPreferenceManager.setUserAgentString(text);
useragent.setSummary(getResources().getString(R.string.agent_custom)); useragent.setSummary(getResources().getString(R.string.agent_custom));
} }
}); });
@ -448,12 +443,12 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
final EditText getDownload = new EditText(mActivity); final EditText getDownload = new EditText(mActivity);
getDownload.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDownload.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); ViewGroup.LayoutParams.WRAP_CONTENT));
getDownload.setText(PreferenceManager.getInstance().getDownloadDirectory()); getDownload.setText(mPreferenceManager.getDownloadDirectory());
final int errorColor = ContextCompat.getColor(getActivity(), R.color.error_red); final int errorColor = ContextCompat.getColor(getActivity(), R.color.error_red);
final int regularColor = ThemeUtils.getTextColor(getActivity()); final int regularColor = ThemeUtils.getTextColor(getActivity());
getDownload.setTextColor(regularColor); getDownload.setTextColor(regularColor);
getDownload.addTextChangedListener(new DownloadLocationTextWatcher(getDownload, errorColor, regularColor)); getDownload.addTextChangedListener(new DownloadLocationTextWatcher(getDownload, errorColor, regularColor));
getDownload.setText(mPreferences.getDownloadDirectory()); getDownload.setText(mPreferenceManager.getDownloadDirectory());
layout.addView(getDownload); layout.addView(getDownload);
downLocationPicker.setView(layout); downLocationPicker.setView(layout);
@ -463,7 +458,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String text = getDownload.getText().toString(); String text = getDownload.getText().toString();
text = DownloadHandler.addNecessarySlashes(text); text = DownloadHandler.addNecessarySlashes(text);
mPreferences.setDownloadDirectory(text); mPreferenceManager.setDownloadDirectory(text);
downloadloc.setSummary(text); downloadloc.setSummary(text);
} }
}); });
@ -538,37 +533,37 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
if (cbFlash.isChecked()) { if (cbFlash.isChecked()) {
getFlashChoice(); getFlashChoice();
} else { } else {
mPreferences.setFlashSupport(0); mPreferenceManager.setFlashSupport(0);
} }
if (!Utils.isFlashInstalled(mActivity) && cbFlash.isChecked()) { if (!Utils.isFlashInstalled(mActivity) && cbFlash.isChecked()) {
Utils.createInformativeDialog(mActivity, R.string.title_warning, R.string.dialog_adobe_not_installed); Utils.createInformativeDialog(mActivity, R.string.title_warning, R.string.dialog_adobe_not_installed);
cbFlash.setEnabled(false); cbFlash.setEnabled(false);
mPreferences.setFlashSupport(0); mPreferenceManager.setFlashSupport(0);
} }
cbFlash.setChecked((Boolean) newValue); cbFlash.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_ADS: case SETTINGS_ADS:
mPreferences.setAdBlockEnabled((Boolean) newValue); mPreferenceManager.setAdBlockEnabled((Boolean) newValue);
cbAds.setChecked((Boolean) newValue); cbAds.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_IMAGES: case SETTINGS_IMAGES:
mPreferences.setBlockImagesEnabled((Boolean) newValue); mPreferenceManager.setBlockImagesEnabled((Boolean) newValue);
cbImages.setChecked((Boolean) newValue); cbImages.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_JAVASCRIPT: case SETTINGS_JAVASCRIPT:
mPreferences.setJavaScriptEnabled((Boolean) newValue); mPreferenceManager.setJavaScriptEnabled((Boolean) newValue);
cbJsScript.setChecked((Boolean) newValue); cbJsScript.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_COLORMODE: case SETTINGS_COLORMODE:
mPreferences.setColorModeEnabled((Boolean) newValue); mPreferenceManager.setColorModeEnabled((Boolean) newValue);
cbColorMode.setChecked((Boolean) newValue); cbColorMode.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_GOOGLESUGGESTIONS: case SETTINGS_GOOGLESUGGESTIONS:
mPreferences.setGoogleSearchSuggestionsEnabled((Boolean) newValue); mPreferenceManager.setGoogleSearchSuggestionsEnabled((Boolean) newValue);
cbgooglesuggest.setChecked((Boolean) newValue); cbgooglesuggest.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_DRAWERTABS: case SETTINGS_DRAWERTABS:
mPreferences.setShowTabsInDrawer((Boolean) newValue); mPreferenceManager.setShowTabsInDrawer((Boolean) newValue);
cbDrawerTabs.setChecked((Boolean) newValue); cbDrawerTabs.setChecked((Boolean) newValue);
default: default:
return false; return false;

View File

@ -0,0 +1,27 @@
package acr.browser.lightning.fragment;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import javax.inject.Inject;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.preference.PreferenceManager;
/**
* Simplify {@link PreferenceManager} inject in all the PreferenceFragments
*
* @author Stefano Pacifici
* @date 2015/09/16
*/
public class LightningPreferenceFragment extends PreferenceFragment {
@Inject
PreferenceManager mPreferenceManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BrowserApp.getAppComponent().inject(this);
}
}

View File

@ -11,16 +11,14 @@ import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.webkit.WebView; import android.webkit.WebView;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.Utils; import acr.browser.lightning.utils.Utils;
import acr.browser.lightning.utils.WebUtils; import acr.browser.lightning.utils.WebUtils;
public class PrivacySettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { public class PrivacySettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
private static final String SETTINGS_LOCATION = "location"; private static final String SETTINGS_LOCATION = "location";
private static final String SETTINGS_THIRDPCOOKIES = "third_party"; private static final String SETTINGS_THIRDPCOOKIES = "third_party";
@ -35,7 +33,6 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe
private static final String SETTINGS_WEBSTORAGEEXIT = "clear_webstorage_exit"; private static final String SETTINGS_WEBSTORAGEEXIT = "clear_webstorage_exit";
private Activity mActivity; private Activity mActivity;
private PreferenceManager mPreferences;
private CheckBoxPreference cblocation, cb3cookies, cbsavepasswords, cbcacheexit, cbhistoryexit, private CheckBoxPreference cblocation, cb3cookies, cbsavepasswords, cbcacheexit, cbhistoryexit,
cbcookiesexit, cbwebstorageexit; cbcookiesexit, cbwebstorageexit;
private Handler messageHandler; private Handler messageHandler;
@ -52,9 +49,6 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe
} }
private void initPrefs() { private void initPrefs() {
// mPreferences storage
mPreferences = PreferenceManager.getInstance();
Preference clearcache = findPreference(SETTINGS_CLEARCACHE); Preference clearcache = findPreference(SETTINGS_CLEARCACHE);
Preference clearhistory = findPreference(SETTINGS_CLEARHISTORY); Preference clearhistory = findPreference(SETTINGS_CLEARHISTORY);
Preference clearcookies = findPreference(SETTINGS_CLEARCOOKIES); Preference clearcookies = findPreference(SETTINGS_CLEARCOOKIES);
@ -81,13 +75,13 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe
cbcookiesexit.setOnPreferenceChangeListener(this); cbcookiesexit.setOnPreferenceChangeListener(this);
cbwebstorageexit.setOnPreferenceChangeListener(this); cbwebstorageexit.setOnPreferenceChangeListener(this);
cblocation.setChecked(mPreferences.getLocationEnabled()); cblocation.setChecked(mPreferenceManager.getLocationEnabled());
cbsavepasswords.setChecked(mPreferences.getSavePasswordsEnabled()); cbsavepasswords.setChecked(mPreferenceManager.getSavePasswordsEnabled());
cbcacheexit.setChecked(mPreferences.getClearCacheExit()); cbcacheexit.setChecked(mPreferenceManager.getClearCacheExit());
cbhistoryexit.setChecked(mPreferences.getClearHistoryExitEnabled()); cbhistoryexit.setChecked(mPreferenceManager.getClearHistoryExitEnabled());
cbcookiesexit.setChecked(mPreferences.getClearCookiesExitEnabled()); cbcookiesexit.setChecked(mPreferenceManager.getClearCookiesExitEnabled());
cb3cookies.setChecked(mPreferences.getBlockThirdPartyCookiesEnabled()); cb3cookies.setChecked(mPreferenceManager.getBlockThirdPartyCookiesEnabled());
cbwebstorageexit.setChecked(mPreferences.getClearWebStorageExitEnabled()); cbwebstorageexit.setChecked(mPreferenceManager.getClearWebStorageExitEnabled());
cb3cookies.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP); cb3cookies.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
@ -203,31 +197,31 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe
// switch preferences // switch preferences
switch (preference.getKey()) { switch (preference.getKey()) {
case SETTINGS_LOCATION: case SETTINGS_LOCATION:
mPreferences.setLocationEnabled((Boolean) newValue); mPreferenceManager.setLocationEnabled((Boolean) newValue);
cblocation.setChecked((Boolean) newValue); cblocation.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_THIRDPCOOKIES: case SETTINGS_THIRDPCOOKIES:
mPreferences.setBlockThirdPartyCookiesEnabled((Boolean) newValue); mPreferenceManager.setBlockThirdPartyCookiesEnabled((Boolean) newValue);
cb3cookies.setChecked((Boolean) newValue); cb3cookies.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_SAVEPASSWORD: case SETTINGS_SAVEPASSWORD:
mPreferences.setSavePasswordsEnabled((Boolean) newValue); mPreferenceManager.setSavePasswordsEnabled((Boolean) newValue);
cbsavepasswords.setChecked((Boolean) newValue); cbsavepasswords.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_CACHEEXIT: case SETTINGS_CACHEEXIT:
mPreferences.setClearCacheExit((Boolean) newValue); mPreferenceManager.setClearCacheExit((Boolean) newValue);
cbcacheexit.setChecked((Boolean) newValue); cbcacheexit.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_HISTORYEXIT: case SETTINGS_HISTORYEXIT:
mPreferences.setClearHistoryExitEnabled((Boolean) newValue); mPreferenceManager.setClearHistoryExitEnabled((Boolean) newValue);
cbhistoryexit.setChecked((Boolean) newValue); cbhistoryexit.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_COOKIEEXIT: case SETTINGS_COOKIEEXIT:
mPreferences.setClearCookiesExitEnabled((Boolean) newValue); mPreferenceManager.setClearCookiesExitEnabled((Boolean) newValue);
cbcookiesexit.setChecked((Boolean) newValue); cbcookiesexit.setChecked((Boolean) newValue);
return true; return true;
case SETTINGS_WEBSTORAGEEXIT: case SETTINGS_WEBSTORAGEEXIT:
mPreferences.setClearWebStorageExitEnabled((Boolean) newValue); mPreferenceManager.setClearWebStorageExitEnabled((Boolean) newValue);
cbwebstorageexit.setChecked((Boolean) newValue); cbwebstorageexit.setChecked((Boolean) newValue);
return true; return true;
default: default:

View File

@ -0,0 +1,417 @@
package acr.browser.lightning.fragment;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewCompat;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import java.util.List;
import javax.inject.Inject;
import acr.browser.lightning.R;
import acr.browser.lightning.activity.TabsManager;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.bus.NavigationEvents;
import acr.browser.lightning.bus.TabEvents;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.ThemeUtils;
import acr.browser.lightning.utils.Utils;
import acr.browser.lightning.view.LightningView;
/**
* @author Stefano Pacifici based on Anthony C. Restaino's code
* @date 2015/09/14
*/
public class TabsFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener {
private static final String TAG = TabsFragment.class.getSimpleName();
/**
* Arguments boolean to tell the fragment it is displayed in the drawner or on the tab strip
* If true, the fragment is in the left drawner in the strip otherwise.
*/
public static final String VERTICAL_MODE = TAG + ".VERTICAL_MODE";
public static final String IS_INCOGNITO = TAG + ".IS_INCOGNITO";
private boolean mIsIncognito, mDarkTheme;
private int mIconColor;
private boolean mColorMode = true;
private boolean mShowInNavigationDrawer;
private int mCurrentUiColor = Color.BLACK; // TODO Only temporary
private RecyclerView mRecyclerView;
private LightningViewAdapter mTabsAdapter;
@Inject
TabsManager tabsManager;
@Inject
Bus bus;
@Inject
PreferenceManager mPreferences;
public TabsFragment() {
BrowserApp.getAppComponent().inject(this);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle arguments = getArguments();
final Context context = getContext();
mIsIncognito = arguments.getBoolean(IS_INCOGNITO, false);
mShowInNavigationDrawer = arguments.getBoolean(VERTICAL_MODE, true);
mDarkTheme = mPreferences.getUseTheme() != 0 || mIsIncognito;
mColorMode = mPreferences.getColorModeEnabled();
mColorMode &= !mDarkTheme;
mIconColor = mDarkTheme ?
ThemeUtils.getIconDarkThemeColor(context) :
ThemeUtils.getIconLightThemeColor(context);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final Bundle arguments = getArguments();
final View view;
final LayoutManager layoutManager;
if (mShowInNavigationDrawer) {
view = inflater.inflate(R.layout.tab_drawer, container, false);
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
setupFrameLayoutButton(view, R.id.new_tab_button, R.id.icon_plus);
setupFrameLayoutButton(view, R.id.action_back, R.id.icon_back);
setupFrameLayoutButton(view, R.id.action_forward, R.id.icon_forward);
setupFrameLayoutButton(view, R.id.action_home, R.id.icon_home);
} else {
view = inflater.inflate(R.layout.tab_strip, container, false);
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
}
mRecyclerView = (RecyclerView) view.findViewById(R.id.tabs_list);
mRecyclerView.setLayoutManager(layoutManager);
mTabsAdapter = new LightningViewAdapter(mShowInNavigationDrawer);
mRecyclerView.setAdapter(mTabsAdapter);
mRecyclerView.setHasFixedSize(true);
return view;
}
private void setupFrameLayoutButton(@NonNull final View root, @IdRes final int buttonId,
@IdRes final int imageId) {
final View frameButton = root.findViewById(buttonId);
final ImageView buttonImage = (ImageView) root.findViewById(imageId);
frameButton.setOnClickListener(this);
frameButton.setOnLongClickListener(this);
buttonImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void onDestroyView() {
super.onDestroyView();
mRecyclerView = null;
mTabsAdapter = null;
}
@Override
public void onStart() {
super.onStart();
bus.register(this);
}
@Override
public void onResume() {
super.onResume();
// Force adapter refresh
mTabsAdapter.notifyDataSetChanged();
}
@Override
public void onStop() {
super.onStop();
bus.unregister(this);
}
@Subscribe
public void tabsChanged(final BrowserEvents.TabsChanged event) {
if (mTabsAdapter != null) {
mTabsAdapter.notifyDataSetChanged();
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.new_tab_button:
bus.post(new TabEvents.NewTab());
break;
case R.id.action_back:
bus.post(new NavigationEvents.GoBack());
break;
case R.id.action_forward:
bus.post(new NavigationEvents.GoForward());
break;
case R.id.action_home:
bus.post(new NavigationEvents.GoHome());
default:
break;
}
}
@Override
public boolean onLongClick(View v) {
switch (v.getId()) {
case R.id.action_new_tab:
bus.post(new TabEvents.NewTabLongPress());
break;
default:
break;
}
return true;
}
public class LightningViewAdapter extends RecyclerView.Adapter<LightningViewAdapter.LightningViewHolder> {
private final int layoutResourceId;
private final Drawable mBackgroundTabDrawable;
private final Drawable mForegroundTabDrawable;
private final Bitmap mForegroundTabBitmap;
private ColorMatrix mColorMatrix;
private Paint mPaint;
private ColorFilter mFilter;
private static final float DESATURATED = 0.5f;
private final boolean vertical;
public LightningViewAdapter(final boolean vertical) {
this.layoutResourceId = vertical ? R.layout.tab_list_item : R.layout.tab_list_item_horizontal;
this.vertical = vertical;
if (vertical) {
mBackgroundTabDrawable = null;
mForegroundTabBitmap = null;
mForegroundTabDrawable = ThemeUtils.getSelectedBackground(getContext(), mDarkTheme);
} else {
int backgroundColor = Utils.mixTwoColors(ThemeUtils.getPrimaryColor(getContext()), Color.BLACK, 0.75f);
Bitmap backgroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888);
Utils.drawTrapezoid(new Canvas(backgroundTabBitmap), backgroundColor, true);
mBackgroundTabDrawable = new BitmapDrawable(getResources(), backgroundTabBitmap);
int foregroundColor = ThemeUtils.getPrimaryColor(getContext());
mForegroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888);
Utils.drawTrapezoid(new Canvas(mForegroundTabBitmap), foregroundColor, false);
mForegroundTabDrawable = null;
}
}
@Override
public LightningViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View view = inflater.inflate(layoutResourceId, viewGroup, false);
return new LightningViewHolder(view);
}
@Override
public void onBindViewHolder(final LightningViewHolder holder, int position) {
holder.exitButton.setTag(position);
ViewCompat.jumpDrawablesToCurrentState(holder.exitButton);
LightningView web = tabsManager.getTabAtPosition(position);
holder.txtTitle.setText(web.getTitle());
final Bitmap favicon = web.getFavicon();
if (web.isForegroundTab()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.txtTitle.setTextAppearance(R.style.boldText);
} else {
holder.txtTitle.setTextAppearance(getContext(), R.style.boldText);
}
Drawable foregroundDrawable;
if (!vertical) {
foregroundDrawable = new BitmapDrawable(getResources(), mForegroundTabBitmap);
if (!mIsIncognito && mColorMode) {
foregroundDrawable.setColorFilter(mCurrentUiColor, PorterDuff.Mode.SRC_IN);
}
} else {
foregroundDrawable = mForegroundTabDrawable;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
holder.layout.setBackground(foregroundDrawable);
} else {
holder.layout.setBackgroundDrawable(foregroundDrawable);
}
if (!mIsIncognito && mColorMode) {
changeToolbarBackground(favicon, foregroundDrawable);
}
holder.favicon.setImageBitmap(favicon);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.txtTitle.setTextAppearance(R.style.normalText);
} else {
holder.txtTitle.setTextAppearance(getContext(), R.style.normalText);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
holder.layout.setBackground(mBackgroundTabDrawable);
} else {
holder.layout.setBackgroundDrawable(mBackgroundTabDrawable);
}
holder.favicon.setImageBitmap(getDesaturatedBitmap(favicon));
}
}
@Override
public int getItemCount() {
return tabsManager.size();
}
public Bitmap getDesaturatedBitmap(Bitmap favicon) {
Bitmap grayscaleBitmap = Bitmap.createBitmap(favicon.getWidth(),
favicon.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(grayscaleBitmap);
if (mColorMatrix == null || mFilter == null || mPaint == null) {
mPaint = new Paint();
mColorMatrix = new ColorMatrix();
mColorMatrix.setSaturation(DESATURATED);
mFilter = new ColorMatrixColorFilter(mColorMatrix);
mPaint.setColorFilter(mFilter);
}
c.drawBitmap(favicon, 0, 0, mPaint);
return grayscaleBitmap;
}
/**
* Animates the color of the toolbar from one color to another. Optionally animates
* the color of the tab background, for use when the tabs are displayed on the top
* of the screen.
*
* @param favicon the Bitmap to extract the color from
* @param tabBackground the optional LinearLayout to color
*/
private void changeToolbarBackground(@NonNull Bitmap favicon, @Nullable final Drawable tabBackground) {
if (mShowInNavigationDrawer) {
return;
}
final int defaultColor;
final Resources resources = getResources();
final ColorDrawable mBackground = new ColorDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
defaultColor = resources.getColor(R.color.primary_color, null);
} else {
defaultColor = resources.getColor(R.color.primary_color);
}
if (mCurrentUiColor == Color.BLACK) {
mCurrentUiColor = defaultColor;
}
Palette.from(favicon).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// OR with opaque black to remove transparency glitches
int color = 0xff000000 | palette.getVibrantColor(defaultColor);
int finalColor = Utils.mixTwoColors(defaultColor, color, 0.25f);
ValueAnimator anim = ValueAnimator.ofInt(mCurrentUiColor, finalColor);
anim.setEvaluator(new ArgbEvaluator());
// final Window window = getWindow();
// TODO Check this
// if (!mShowInNavigationDrawer) {
// window.setBackgroundDrawable(new ColorDrawable(Color.BLACK));
// }
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final int color = (Integer) animation.getAnimatedValue();
if (tabBackground != null) {
tabBackground.setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
mCurrentUiColor = color;
}
});
anim.setDuration(300);
anim.start();
}
});
}
public class LightningViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public LightningViewHolder(View view) {
super(view);
txtTitle = (TextView) view.findViewById(R.id.textTab);
favicon = (ImageView) view.findViewById(R.id.faviconTab);
exit = (ImageView) view.findViewById(R.id.deleteButton);
layout = (LinearLayout) view.findViewById(R.id.tab_item_background);
exitButton = (FrameLayout) view.findViewById(R.id.deleteAction);
exit.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
exitButton.setOnClickListener(this);
layout.setOnClickListener(this);
layout.setOnLongClickListener(this);
}
final TextView txtTitle;
final ImageView favicon;
final ImageView exit;
final FrameLayout exitButton;
final LinearLayout layout;
@Override
public void onClick(View v) {
if (v == exitButton) {
// Close tab
bus.post(new TabEvents.CloseTab(getAdapterPosition()));
}
if (v == layout) {
bus.post(new TabEvents.ShowTab(getAdapterPosition()));
}
}
@Override
public boolean onLongClick(View v) {
// Show close dialog
bus.post(new TabEvents.ShowCloseDialog(getAdapterPosition()));
return true;
}
}
}
}

View File

@ -1,30 +0,0 @@
/*
* Copyright 2014 A.C.R. Development
*/
package acr.browser.lightning.object;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import acr.browser.lightning.controller.BrowserController;
public class ClickHandler extends Handler {
private BrowserController mBrowserController;
public ClickHandler(Context context) {
try {
mBrowserController = (BrowserController) context;
} catch (ClassCastException e) {
throw new ClassCastException(context + " must implement BrowserController");
}
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String url = msg.getData().getString("url");
mBrowserController.longClickPage(url);
}
}

View File

@ -56,14 +56,11 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
private final List<HistoryItem> mFilteredList = new ArrayList<>(5); private final List<HistoryItem> mFilteredList = new ArrayList<>(5);
private final List<HistoryItem> mAllBookmarks = new ArrayList<>(5); private final List<HistoryItem> mAllBookmarks = new ArrayList<>(5);
private final Object mLock = new Object(); private final Object mLock = new Object();
private HistoryDatabase mDatabaseHandler;
private final Context mContext; private final Context mContext;
private boolean mUseGoogle = true; private boolean mUseGoogle = true;
private boolean mIsExecuting = false; private boolean mIsExecuting = false;
private final boolean mDarkTheme; private final boolean mDarkTheme;
private final boolean mIncognito; private final boolean mIncognito;
@Inject
BookmarkManager mBookmarkManager;
private static final String CACHE_FILE_TYPE = ".sgg"; private static final String CACHE_FILE_TYPE = ".sgg";
private static final String ENCODING = "ISO-8859-1"; private static final String ENCODING = "ISO-8859-1";
private static final long INTERVAL_DAY = 86400000; private static final long INTERVAL_DAY = 86400000;
@ -75,11 +72,19 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
private final Drawable mHistoryDrawable; private final Drawable mHistoryDrawable;
private final Drawable mBookmarkDrawable; private final Drawable mBookmarkDrawable;
@Inject
HistoryDatabase mDatabaseHandler;
@Inject
BookmarkManager mBookmarkManager;
@Inject
PreferenceManager mPreferenceManager;
public SearchAdapter(Context context, boolean dark, boolean incognito) { public SearchAdapter(Context context, boolean dark, boolean incognito) {
BrowserApp.getAppComponent().inject(this); BrowserApp.getAppComponent().inject(this);
mDatabaseHandler = HistoryDatabase.getInstance();
mAllBookmarks.addAll(mBookmarkManager.getAllBookmarks(true)); mAllBookmarks.addAll(mBookmarkManager.getAllBookmarks(true));
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled(); mUseGoogle = mPreferenceManager.getGoogleSearchSuggestionsEnabled();
mContext = context; mContext = context;
mSearchSubtitle = mContext.getString(R.string.suggestion); mSearchSubtitle = mContext.getString(R.string.suggestion);
mDarkTheme = dark || incognito; mDarkTheme = dark || incognito;
@ -114,13 +119,12 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
} }
public void refreshPreferences() { public void refreshPreferences() {
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled(); mUseGoogle = mPreferenceManager.getGoogleSearchSuggestionsEnabled();
if (!mUseGoogle) { if (!mUseGoogle) {
synchronized (mSuggestions) { synchronized (mSuggestions) {
mSuggestions.clear(); mSuggestions.clear();
} }
} }
mDatabaseHandler = HistoryDatabase.getInstance();
} }
public void refreshBookmarks() { public void refreshBookmarks() {
@ -244,13 +248,10 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
mBookmarks.add(mAllBookmarks.get(n)); mBookmarks.add(mAllBookmarks.get(n));
counter++; counter++;
} }
} }
} }
} }
if (mDatabaseHandler == null || mDatabaseHandler.isClosed()) {
mDatabaseHandler = HistoryDatabase.getInstance();
}
List<HistoryItem> historyList = mDatabaseHandler.findItemsContaining(constraint.toString()); List<HistoryItem> historyList = mDatabaseHandler.findItemsContaining(constraint.toString());
synchronized (mHistory) { synchronized (mHistory) {
mHistory.clear(); mHistory.clear();

View File

@ -1,11 +1,16 @@
package acr.browser.lightning.preference; package acr.browser.lightning.preference;
import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import javax.inject.Inject;
import javax.inject.Singleton;
import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.download.DownloadHandler; import acr.browser.lightning.download.DownloadHandler;
@Singleton
public class PreferenceManager { public class PreferenceManager {
private static class Name { private static class Name {
@ -56,20 +61,13 @@ public class PreferenceManager {
public static final String INITIAL_CHECK_FOR_I2P = "checkForI2P"; public static final String INITIAL_CHECK_FOR_I2P = "checkForI2P";
} }
private static PreferenceManager mInstance;
private final SharedPreferences mPrefs; private final SharedPreferences mPrefs;
private static final String PREFERENCES = "settings"; private static final String PREFERENCES = "settings";
public static PreferenceManager getInstance() { @Inject
if (mInstance == null) { PreferenceManager(final Context context) {
mInstance = new PreferenceManager(); mPrefs = context.getSharedPreferences(PREFERENCES, 0);
}
return mInstance;
}
private PreferenceManager() {
mPrefs = BrowserApp.getAppContext().getSharedPreferences(PREFERENCES, 0);
} }
public boolean getAdBlockEnabled() { public boolean getAdBlockEnabled() {

View File

@ -13,6 +13,7 @@ import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
@ -44,11 +45,11 @@ public class AdBlock {
if (mBlockedDomainsList.isEmpty() && Constants.FULL_VERSION) { if (mBlockedDomainsList.isEmpty() && Constants.FULL_VERSION) {
loadHostsFile(context); loadHostsFile(context);
} }
mBlockAds = PreferenceManager.getInstance().getAdBlockEnabled(); mBlockAds = BrowserApp.getAppComponent().getPreferenceManager().getAdBlockEnabled();
} }
public void updatePreference() { public void updatePreference() {
mBlockAds = PreferenceManager.getInstance().getAdBlockEnabled(); mBlockAds = BrowserApp.getAppComponent().getPreferenceManager().getAdBlockEnabled();
} }
private void loadBlockedDomainsList(final Context context) { private void loadBlockedDomainsList(final Context context) {

View File

@ -2,6 +2,7 @@ package acr.browser.lightning.utils;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;

View File

@ -10,6 +10,7 @@ import android.webkit.WebStorage;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewDatabase; import android.webkit.WebViewDatabase;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.database.HistoryDatabase; import acr.browser.lightning.database.HistoryDatabase;
/** /**
@ -34,7 +35,7 @@ public class WebUtils {
} }
public static void clearHistory(@NonNull Context context) { public static void clearHistory(@NonNull Context context) {
HistoryDatabase.getInstance().deleteHistory(); BrowserApp.getAppComponent().getHistoryDatabase().deleteHistory();
WebViewDatabase m = WebViewDatabase.getInstance(context); WebViewDatabase m = WebViewDatabase.getInstance(context);
m.clearFormData(); m.clearFormData();
m.clearHttpAuthUsernamePassword(); m.clearHttpAuthUsernamePassword();

View File

@ -0,0 +1,44 @@
package acr.browser.lightning.view;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.utils.Utils;
/**
* @author Anthony C. Restaino
* @date 2015/09/29
*/
class IconCacheTask implements Runnable{
private final Uri uri;
private final Bitmap icon;
public IconCacheTask(Uri uri, Bitmap icon) {
this.uri = uri;
this.icon = icon;
}
@Override
public void run() {
String hash = String.valueOf(uri.getHost().hashCode());
Log.d(Constants.TAG, "Caching icon for " + uri.getHost());
FileOutputStream fos = null;
try {
File image = new File(BrowserApp.getAppContext().getCacheDir(), hash + ".png");
fos = new FileOutputStream(image);
icon.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
Utils.close(fos);
}
}
}

View File

@ -0,0 +1,250 @@
package acr.browser.lightning.view;
import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Message;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.GeolocationPermissions;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import com.squareup.otto.Bus;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import acr.browser.lightning.R;
import acr.browser.lightning.activity.BrowserActivity;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.utils.PermissionsManager;
import acr.browser.lightning.utils.Utils;
/**
* @author Stefano Pacifici based on Anthony C. Restaino code
* @date 2015/09/21
*/
class LightningChromeClient extends WebChromeClient {
private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
private final BrowserActivity mActivity;
private final LightningView mLightningView;
private final Bus eventBus;
LightningChromeClient(BrowserActivity activity, LightningView lightningView) {
mActivity = activity;
mLightningView = lightningView;
eventBus = BrowserApp.getAppComponent().getBus();
}
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (mLightningView.isShown()) {
mActivity.updateProgress(newProgress);
}
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
if (icon == null)
return;
mLightningView.mTitle.setFavicon(icon);
eventBus.post(new BrowserEvents.TabsChanged()); ;
cacheFavicon(view.getUrl(), icon);
}
/**
* Naive caching of the favicon according to the domain name of the URL
* @param icon the icon to cache
*/
private void cacheFavicon(final String url, final Bitmap icon) {
if (icon == null) return;
final Uri uri = Uri.parse(url);
if (uri.getHost() == null) {
return;
}
new Thread(new Runnable() {
@Override
public void run() {
String hash = String.valueOf(uri.getHost().hashCode());
Log.d(Constants.TAG, "Caching icon for " + uri.getHost());
FileOutputStream fos = null;
try {
File image = new File(BrowserApp.getAppContext().getCacheDir(), hash + ".png");
fos = new FileOutputStream(image);
icon.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
Utils.close(fos);
}
}
}).start();
}
@Override
public void onReceivedTitle(WebView view, String title) {
if (title != null && !title.isEmpty()) {
mLightningView.mTitle.setTitle(title);
} else {
mLightningView.mTitle.setTitle(mActivity.getString(R.string.untitled));
}
eventBus.post(new BrowserEvents.TabsChanged());
if (view != null) {
mActivity.updateHistory(title, view.getUrl());
}
}
@Override
public void onGeolocationPermissionsShowPrompt(final String origin,
final GeolocationPermissions.Callback callback) {
PermissionsManager.getInstance().requestPermissionsIfNecessary(mActivity, PERMISSIONS);
final boolean remember = true;
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(mActivity.getString(R.string.location));
String org;
if (origin.length() > 50) {
org = origin.subSequence(0, 50) + "...";
} else {
org = origin;
}
builder.setMessage(org + mActivity.getString(R.string.message_location))
.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.action_allow),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
callback.invoke(origin, true, remember);
}
})
.setNegativeButton(mActivity.getString(R.string.action_dont_allow),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
callback.invoke(origin, false, remember);
}
});
AlertDialog alert = builder.create();
alert.show();
}
@Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture,
Message resultMsg) {
mActivity.onCreateWindow(resultMsg);
return true;
}
@Override
public void onCloseWindow(WebView window) {
mActivity.onCloseWindow(mLightningView);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mActivity.openFileChooser(uploadMsg);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
mActivity.openFileChooser(uploadMsg);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
mActivity.openFileChooser(uploadMsg);
}
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
mActivity.showFileChooser(filePathCallback);
return true;
}
/**
* Obtain an image that is displayed as a placeholder on a video until the video has initialized
* and can begin loading.
*
* @return a Bitmap that can be used as a place holder for videos.
*/
@Override
public Bitmap getDefaultVideoPoster() {
final Resources resources = mActivity.getResources();
return BitmapFactory.decodeResource(resources, android.R.drawable.spinner_background);
}
/**
* Inflate a view to send to a LightningView when it needs to display a video and has to
* show a loading dialog. Inflates a progress view and returns it.
*
* @return A view that should be used to display the state
* of a video's loading progress.
*/
@Override
public View getVideoLoadingProgressView() {
LayoutInflater inflater = LayoutInflater.from(mActivity);
return inflater.inflate(R.layout.video_loading_progress, null);
}
@Override
public void onHideCustomView() {
mActivity.onHideCustomView();
super.onHideCustomView();
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
// While these lines might look like they work, in practice,
// Full-screen videos won't work correctly. I may test this out some
// more
// if (view instanceof FrameLayout) {
// FrameLayout frame = (FrameLayout) view;
// if (frame.getFocusedChild() instanceof VideoView) {
// VideoView video = (VideoView) frame.getFocusedChild();
// video.stopPlayback();
// frame.removeView(video);
// video.setVisibility(View.GONE);
// }
// } else {
mActivity.onShowCustomView(view, callback);
// }
super.onShowCustomView(view, callback);
}
@Override
@Deprecated
public void onShowCustomView(View view, int requestedOrientation,
CustomViewCallback callback) {
// While these lines might look like they work, in practice,
// Full-screen videos won't work correctly. I may test this out some
// more
// if (view instanceof FrameLayout) {
// FrameLayout frame = (FrameLayout) view;
// if (frame.getFocusedChild() instanceof VideoView) {
// VideoView video = (VideoView) frame.getFocusedChild();
// video.stopPlayback();
// frame.removeView(video);
// video.setVisibility(View.GONE);
// }
// } else {
mActivity.onShowCustomView(view, callback);
// }
super.onShowCustomView(view, requestedOrientation, callback);
}
}

View File

@ -6,26 +6,18 @@ package acr.browser.lightning.view;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.ColorMatrix; import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter; import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint; import android.graphics.Paint;
import android.net.MailTo;
import android.net.Uri; import android.net.Uri;
import android.net.http.SslError;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.util.Log; import android.util.Log;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener; import android.view.GestureDetector.SimpleOnGestureListener;
@ -34,60 +26,48 @@ import android.view.View;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.GeolocationPermissions;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebSettings.PluginState; import android.webkit.WebSettings.PluginState;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.LinearLayout;
import java.io.ByteArrayInputStream; import com.squareup.otto.Bus;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException;
import javax.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.activity.BrowserActivity;
import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.constant.HistoryPage;
import acr.browser.lightning.constant.StartPage; import acr.browser.lightning.constant.StartPage;
import acr.browser.lightning.controller.BrowserController; import acr.browser.lightning.dialog.LightningDialogBuilder;
import acr.browser.lightning.download.LightningDownloadListener; import acr.browser.lightning.download.LightningDownloadListener;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.AdBlock;
import acr.browser.lightning.utils.IntentUtils;
import acr.browser.lightning.utils.PermissionsManager; import acr.browser.lightning.utils.PermissionsManager;
import acr.browser.lightning.utils.ProxyUtils;
import acr.browser.lightning.utils.ThemeUtils; import acr.browser.lightning.utils.ThemeUtils;
import acr.browser.lightning.utils.Utils; import acr.browser.lightning.utils.Utils;
public class LightningView { public class LightningView {
private final Title mTitle; final LightningViewTitle mTitle;
private WebView mWebView; private WebView mWebView;
private final boolean mIsIncognitoTab; final boolean mIsIncognitoTab;
private final BrowserController mBrowserController;
private final GestureDetector mGestureDetector; private final GestureDetector mGestureDetector;
private final Activity mActivity; private final BrowserActivity mActivity;
private static String mHomepage; private static String mHomepage;
private static String mDefaultUserAgent; private static String mDefaultUserAgent;
// TODO fix so that mWebpageBitmap can be static - static changes the icon when switching from light to dark and then back to light
private final Bitmap mWebpageBitmap;
private static PreferenceManager mPreferences;
private final AdBlock mAdBlock;
private final IntentUtils mIntentUtils;
private final Paint mPaint = new Paint(); private final Paint mPaint = new Paint();
private boolean isForegroundTab; private boolean isForegroundTab;
private boolean mTextReflow = false;
private boolean mInvertPage = false; private boolean mInvertPage = false;
private boolean mToggleDesktop = false; private boolean mToggleDesktop = false;
private static float mMaxFling; private static float mMaxFling;
@ -101,24 +81,28 @@ public class LightningView {
}; };
private final PermissionsManager mPermissionsManager; private final PermissionsManager mPermissionsManager;
private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
private final WebViewHandler webViewHandler = new WebViewHandler();
@Inject
Bus eventBus;
@Inject
PreferenceManager mPreferences;
@Inject
LightningDialogBuilder bookmarksDialogBuilder;
@SuppressLint("NewApi") @SuppressLint("NewApi")
public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito, BrowserController controller) { public LightningView(BrowserActivity activity, String url, boolean darkTheme, boolean isIncognito) {
BrowserApp.getAppComponent().inject(this);
mActivity = activity; mActivity = activity;
mWebView = new WebView(activity); mWebView = new WebView(activity);
mIsIncognitoTab = isIncognito; mIsIncognitoTab = isIncognito;
mTitle = new Title(activity, darkTheme); mTitle = new LightningViewTitle(activity, darkTheme);
mAdBlock = AdBlock.getInstance(activity.getApplicationContext());
mPermissionsManager = PermissionsManager.getInstance(); mPermissionsManager = PermissionsManager.getInstance();
mWebpageBitmap = mTitle.mDefaultIcon;
mMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity(); mMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity();
mBrowserController = controller;
mIntentUtils = new IntentUtils(mActivity);
mWebView.setDrawingCacheBackgroundColor(Color.WHITE); mWebView.setDrawingCacheBackgroundColor(Color.WHITE);
mWebView.setFocusableInTouchMode(true); mWebView.setFocusableInTouchMode(true);
mWebView.setFocusable(true); mWebView.setFocusable(true);
@ -135,8 +119,8 @@ public class LightningView {
mWebView.setScrollbarFadingEnabled(true); mWebView.setScrollbarFadingEnabled(true);
mWebView.setSaveEnabled(true); mWebView.setSaveEnabled(true);
mWebView.setNetworkAvailable(true); mWebView.setNetworkAvailable(true);
mWebView.setWebChromeClient(new LightningChromeClient(activity)); mWebView.setWebChromeClient(new LightningChromeClient(activity, this));
mWebView.setWebViewClient(new LightningWebClient(activity)); mWebView.setWebViewClient(new LightningWebClient(activity, this));
mWebView.setDownloadListener(new LightningDownloadListener(activity)); mWebView.setDownloadListener(new LightningDownloadListener(activity));
mGestureDetector = new GestureDetector(activity, new CustomGestureListener()); mGestureDetector = new GestureDetector(activity, new CustomGestureListener());
mWebView.setOnTouchListener(new TouchListener()); mWebView.setOnTouchListener(new TouchListener());
@ -162,12 +146,37 @@ public class LightningView {
if (mHomepage.startsWith("about:home")) { if (mHomepage.startsWith("about:home")) {
mWebView.loadUrl(StartPage.getHomepage(mActivity)); mWebView.loadUrl(StartPage.getHomepage(mActivity));
} else if (mHomepage.startsWith("about:bookmarks")) { } else if (mHomepage.startsWith("about:bookmarks")) {
mBrowserController.openBookmarkPage(mWebView); loadBookmarkpage();
} else { } else {
mWebView.loadUrl(mHomepage); mWebView.loadUrl(mHomepage);
} }
} }
/**
* Load the HTML bookmarks page in this view
*/
public void loadBookmarkpage() {
if (mWebView == null)
return;
Bitmap folderIcon = ThemeUtils.getThemedBitmap(mActivity, R.drawable.ic_folder, false);
FileOutputStream outputStream = null;
File image = new File(mActivity.getCacheDir(), "folder.png");
try {
outputStream = new FileOutputStream(image);
folderIcon.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
folderIcon.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
Utils.close(outputStream);
}
File bookmarkWebPage = new File(mActivity.getFilesDir(), Constants.BOOKMARKS_FILENAME);
BrowserApp.getAppComponent().getBookmarkPage().buildBookmarkPage(null);
mWebView.loadUrl(Constants.FILE + bookmarkWebPage);
}
/** /**
* Initialize the preference driven settings of the WebView * Initialize the preference driven settings of the WebView
* *
@ -182,12 +191,9 @@ public class LightningView {
} else if (settings == null) { } else if (settings == null) {
settings = mWebView.getSettings(); settings = mWebView.getSettings();
} }
mPreferences = PreferenceManager.getInstance();
settings.setDefaultTextEncodingName(mPreferences.getTextEncoding()); settings.setDefaultTextEncodingName(mPreferences.getTextEncoding());
mHomepage = mPreferences.getHomepage(); mHomepage = mPreferences.getHomepage();
mAdBlock.updatePreference();
setColorMode(mPreferences.getRenderingMode()); setColorMode(mPreferences.getRenderingMode());
if (!mIsIncognitoTab) { if (!mIsIncognitoTab) {
@ -242,7 +248,6 @@ public class LightningView {
} }
if (mPreferences.getTextReflowEnabled()) { if (mPreferences.getTextReflowEnabled()) {
mTextReflow = true;
settings.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS); settings.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
if (API >= android.os.Build.VERSION_CODES.KITKAT) { if (API >= android.os.Build.VERSION_CODES.KITKAT) {
try { try {
@ -254,7 +259,6 @@ public class LightningView {
} }
} }
} else { } else {
mTextReflow = false;
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL); settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
} }
@ -408,7 +412,7 @@ public class LightningView {
public void setForegroundTab(boolean isForeground) { public void setForegroundTab(boolean isForeground) {
isForegroundTab = isForeground; isForegroundTab = isForeground;
mBrowserController.updateTabs(); eventBus.post(new BrowserEvents.TabsChanged());
} }
public boolean isForegroundTab() { public boolean isForegroundTab() {
@ -511,7 +515,7 @@ public class LightningView {
public synchronized void reload() { public synchronized void reload() {
// Check if configured proxy is available // Check if configured proxy is available
if (mBrowserController.proxyIsNotReady()) { if (!ProxyUtils.getInstance().isProxyReady()) {
// User has been notified // User has been notified
return; return;
} }
@ -579,6 +583,60 @@ public class LightningView {
} }
} }
/**
* Used by {@link LightningWebClient}
*
* @return true if the page is in inverted mode, false otherwise
*/
public boolean getInvertePage() {
return mInvertPage;
}
/**
* handles a long click on the page, parameter String url
* is the url that should have been obtained from the WebView touch node
* thingy, if it is null, this method tries to deal with it and find a workaround
*/
private void longClickPage(final String url) {
final WebView.HitTestResult result = mWebView.getHitTestResult();
String currentUrl = mWebView.getUrl();
if (currentUrl != null && currentUrl.startsWith(Constants.FILE)) {
if (currentUrl.endsWith(HistoryPage.FILENAME)) {
if (url != null) {
bookmarksDialogBuilder.showLongPressedHistoryLinkDialog(mActivity, url);
} else if (result != null && result.getExtra() != null) {
final String newUrl = result.getExtra();
bookmarksDialogBuilder.showLongPressedHistoryLinkDialog(mActivity, newUrl);
}
} else if (currentUrl.endsWith(Constants.BOOKMARKS_FILENAME)) {
if (url != null) {
bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, url);
} else if (result != null && result.getExtra() != null) {
final String newUrl = result.getExtra();
bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, newUrl);
}
}
} else {
if (url != null) {
if (result != null) {
if (result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == WebView.HitTestResult.IMAGE_TYPE) {
bookmarksDialogBuilder.showLongPressImageDialog(mActivity, url, getUserAgent());
} else {
bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, url);
}
} else {
bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, url);
}
} else if (result != null && result.getExtra() != null) {
final String newUrl = result.getExtra();
if (result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == WebView.HitTestResult.IMAGE_TYPE) {
bookmarksDialogBuilder.showLongPressImageDialog(mActivity, newUrl, getUserAgent());
} else {
bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, newUrl);
}
}
}
}
public boolean canGoBack() { public boolean canGoBack() {
return mWebView != null && mWebView.canGoBack(); return mWebView != null && mWebView.canGoBack();
} }
@ -598,8 +656,7 @@ public class LightningView {
public synchronized void loadUrl(String url) { public synchronized void loadUrl(String url) {
// Check if configured proxy is available // Check if configured proxy is available
if (mBrowserController.proxyIsNotReady()) { if (!ProxyUtils.getInstance().isProxyReady()) {
// User has been notified
return; return;
} }
@ -621,500 +678,6 @@ public class LightningView {
} }
} }
private static class IconCacheTask implements Runnable {
private final Uri uri;
private final Bitmap icon;
public IconCacheTask(Uri uri, Bitmap icon) {
this.uri = uri;
this.icon = icon;
}
@Override
public void run() {
String hash = String.valueOf(uri.getHost().hashCode());
Log.d(Constants.TAG, "Caching icon for " + uri.getHost());
FileOutputStream fos = null;
try {
File image = new File(BrowserApp.getAppContext().getCacheDir(), hash + ".png");
fos = new FileOutputStream(image);
icon.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
Utils.close(fos);
}
}
}
public class LightningWebClient extends WebViewClient {
final Activity mActivity;
LightningWebClient(Activity activity) {
mActivity = activity;
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mAdBlock.isAd(request.getUrl().toString())) {
ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
return new WebResourceResponse("text/plain", "utf-8", EMPTY);
}
}
return super.shouldInterceptRequest(view, request);
}
@SuppressWarnings("deprecation")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (mAdBlock.isAd(url)) {
ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
return new WebResourceResponse("text/plain", "utf-8", EMPTY);
}
return null;
}
@SuppressLint("NewApi")
@Override
public void onPageFinished(WebView view, String url) {
if (view.isShown()) {
mBrowserController.updateUrl(url, true);
view.postInvalidate();
}
if (view.getTitle() == null || view.getTitle().isEmpty()) {
mTitle.setTitle(mActivity.getString(R.string.untitled));
} else {
mTitle.setTitle(view.getTitle());
}
if (API >= android.os.Build.VERSION_CODES.KITKAT && mInvertPage) {
view.evaluateJavascript(Constants.JAVASCRIPT_INVERT_PAGE, null);
}
mBrowserController.updateTabs();
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (isShown()) {
mBrowserController.updateUrl(url, false);
mBrowserController.showActionBar();
}
mTitle.setFavicon(mWebpageBitmap);
mBrowserController.updateTabs();
}
@Override
public void onReceivedHttpAuthRequest(final WebView view, @NonNull final HttpAuthHandler handler,
final String host, final String realm) {
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
final EditText name = new EditText(mActivity);
final EditText password = new EditText(mActivity);
LinearLayout passLayout = new LinearLayout(mActivity);
passLayout.setOrientation(LinearLayout.VERTICAL);
passLayout.addView(name);
passLayout.addView(password);
name.setHint(mActivity.getString(R.string.hint_username));
name.setSingleLine();
password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
password.setSingleLine();
password.setTransformationMethod(new PasswordTransformationMethod());
password.setHint(mActivity.getString(R.string.hint_password));
builder.setTitle(mActivity.getString(R.string.title_sign_in));
builder.setView(passLayout);
builder.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.title_sign_in),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
String user = name.getText().toString();
String pass = password.getText().toString();
handler.proceed(user.trim(), pass.trim());
Log.d(Constants.TAG, "Request Login");
}
})
.setNegativeButton(mActivity.getString(R.string.action_cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
handler.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
private boolean mIsRunning = false;
private float mZoomScale = 0.0f;
@SuppressLint("NewApi")
@Override
public void onScaleChanged(final WebView view, final float oldScale, final float newScale) {
if (view.isShown() && mTextReflow && API >= android.os.Build.VERSION_CODES.KITKAT) {
if (mIsRunning)
return;
if (Math.abs(mZoomScale - newScale) > 0.01f) {
mIsRunning = view.postDelayed(new Runnable() {
@Override
public void run() {
mZoomScale = newScale;
view.evaluateJavascript(Constants.JAVASCRIPT_TEXT_REFLOW, null);
mIsRunning = false;
}
}, 100);
}
}
}
private List<Integer> getAllSslErrorMessageCodes(SslError error) {
List<Integer> errorCodeMessageCodes = new ArrayList<>();
if (error.hasError(SslError.SSL_DATE_INVALID)) {
errorCodeMessageCodes.add(R.string.message_certificate_date_invalid);
}
if (error.hasError(SslError.SSL_EXPIRED)) {
errorCodeMessageCodes.add(R.string.message_certificate_expired);
}
if (error.hasError(SslError.SSL_IDMISMATCH)) {
errorCodeMessageCodes.add(R.string.message_certificate_domain_mismatch);
}
if (error.hasError(SslError.SSL_NOTYETVALID)) {
errorCodeMessageCodes.add(R.string.message_certificate_not_yet_valid);
}
if (error.hasError(SslError.SSL_UNTRUSTED)) {
errorCodeMessageCodes.add(R.string.message_certificate_untrusted);
}
if (error.hasError(SslError.SSL_INVALID)) {
errorCodeMessageCodes.add(R.string.message_certificate_invalid);
}
return errorCodeMessageCodes;
}
@Override
public void onReceivedSslError(WebView view, @NonNull final SslErrorHandler handler, SslError error) {
List<Integer> errorCodeMessageCodes = getAllSslErrorMessageCodes(error);
StringBuilder stringBuilder = new StringBuilder();
for (Integer messageCode : errorCodeMessageCodes) {
stringBuilder.append(" - ").append(mActivity.getString(messageCode)).append('\n');
}
String alertMessage =
mActivity.getString(R.string.message_insecure_connection, stringBuilder.toString());
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(mActivity.getString(R.string.title_warning));
builder.setMessage(alertMessage)
.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.action_yes),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
handler.proceed();
}
})
.setNegativeButton(mActivity.getString(R.string.action_no),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
handler.cancel();
}
});
builder.create().show();
}
@Override
public void onFormResubmission(WebView view, @NonNull final Message dontResend, final Message resend) {
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(mActivity.getString(R.string.title_form_resubmission));
builder.setMessage(mActivity.getString(R.string.message_form_resubmission))
.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.action_yes),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
resend.sendToTarget();
}
})
.setNegativeButton(mActivity.getString(R.string.action_no),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dontResend.sendToTarget();
}
});
AlertDialog alert = builder.create();
alert.show();
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Check if configured proxy is available
if (mBrowserController.proxyIsNotReady()) {
// User has been notified
return true;
}
if (mIsIncognitoTab) {
return super.shouldOverrideUrlLoading(view, url);
}
if (url.startsWith("about:")) {
return super.shouldOverrideUrlLoading(view, url);
}
if (url.contains("mailto:")) {
MailTo mailTo = MailTo.parse(url);
Intent i = Utils.newEmailIntent(mailTo.getTo(), mailTo.getSubject(),
mailTo.getBody(), mailTo.getCc());
mActivity.startActivity(i);
view.reload();
return true;
} else if (url.startsWith("intent://")) {
Intent intent;
try {
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
} catch (URISyntaxException ex) {
return false;
}
if (intent != null) {
try {
mActivity.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.e(Constants.TAG, "ActivityNotFoundException");
}
return true;
}
}
return mIntentUtils.startActivityForUrl(mWebView, url);
}
}
public class LightningChromeClient extends WebChromeClient {
final Activity mActivity;
LightningChromeClient(Activity activity) {
mActivity = activity;
}
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (isShown()) {
mBrowserController.updateProgress(newProgress);
}
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
if (icon == null)
return;
mTitle.setFavicon(icon);
mBrowserController.updateTabs();
cacheFavicon(icon);
}
@Override
public void onReceivedTitle(WebView view, String title) {
if (title != null && !title.isEmpty()) {
mTitle.setTitle(title);
} else {
mTitle.setTitle(mActivity.getString(R.string.untitled));
}
mBrowserController.updateTabs();
if (view != null)
mBrowserController.updateHistory(title, view.getUrl());
}
@Override
public void onGeolocationPermissionsShowPrompt(final String origin,
final GeolocationPermissions.Callback callback) {
mPermissionsManager.requestPermissionsIfNecessary(mActivity, PERMISSIONS);
final boolean remember = true;
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(mActivity.getString(R.string.location));
String org;
if (origin.length() > 50) {
org = origin.subSequence(0, 50) + "...";
} else {
org = origin;
}
builder.setMessage(org + mActivity.getString(R.string.message_location))
.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.action_allow),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
callback.invoke(origin, true, remember);
}
})
.setNegativeButton(mActivity.getString(R.string.action_dont_allow),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
callback.invoke(origin, false, remember);
}
});
AlertDialog alert = builder.create();
alert.show();
}
@Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture,
Message resultMsg) {
mBrowserController.onCreateWindow(resultMsg);
return true;
}
@Override
public void onCloseWindow(WebView window) {
mBrowserController.onCloseWindow(LightningView.this);
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mBrowserController.openFileChooser(uploadMsg);
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
mBrowserController.openFileChooser(uploadMsg);
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
mBrowserController.openFileChooser(uploadMsg);
}
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
mBrowserController.showFileChooser(filePathCallback);
return true;
}
@Override
public Bitmap getDefaultVideoPoster() {
return mBrowserController.getDefaultVideoPoster();
}
@Override
public View getVideoLoadingProgressView() {
return mBrowserController.getVideoLoadingProgressView();
}
@Override
public void onHideCustomView() {
mBrowserController.onHideCustomView();
super.onHideCustomView();
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
// While these lines might look like they work, in practice,
// Full-screen videos won't work correctly. I may test this out some
// more
// if (view instanceof FrameLayout) {
// FrameLayout frame = (FrameLayout) view;
// if (frame.getFocusedChild() instanceof VideoView) {
// VideoView video = (VideoView) frame.getFocusedChild();
// video.stopPlayback();
// frame.removeView(video);
// video.setVisibility(View.GONE);
// }
// } else {
mBrowserController.onShowCustomView(view, callback);
// }
super.onShowCustomView(view, callback);
}
@SuppressWarnings("deprecation")
@Override
@Deprecated
public void onShowCustomView(View view, int requestedOrientation,
CustomViewCallback callback) {
// While these lines might look like they work, in practice,
// Full-screen videos won't work correctly. I may test this out some
// more
// if (view instanceof FrameLayout) {
// FrameLayout frame = (FrameLayout) view;
// if (frame.getFocusedChild() instanceof VideoView) {
// VideoView video = (VideoView) frame.getFocusedChild();
// video.stopPlayback();
// frame.removeView(video);
// video.setVisibility(View.GONE);
// }
// } else {
mBrowserController.onShowCustomView(view, callback);
// }
super.onShowCustomView(view, requestedOrientation, callback);
}
}
public class Title {
private Bitmap mFavicon;
private String mTitle;
private final Bitmap mDefaultIcon;
public Title(Context context, boolean darkTheme) {
mDefaultIcon = ThemeUtils.getThemedBitmap(context, R.drawable.ic_webpage, darkTheme);
mFavicon = mDefaultIcon;
mTitle = mActivity.getString(R.string.action_new_tab);
}
public void setFavicon(Bitmap favicon) {
if (favicon == null) {
mFavicon = mDefaultIcon;
} else {
mFavicon = Utils.padFavicon(favicon);
}
}
public void setTitle(String title) {
if (title == null) {
mTitle = "";
} else {
mTitle = title;
}
}
public void setTitleAndFavicon(String title, Bitmap favicon) {
mTitle = title;
if (favicon == null) {
mFavicon = mDefaultIcon;
} else {
mFavicon = Utils.padFavicon(favicon);
}
}
public String getTitle() {
return mTitle;
}
public Bitmap getFavicon() {
return mFavicon;
}
}
private class TouchListener implements OnTouchListener { private class TouchListener implements OnTouchListener {
float mLocation; float mLocation;
@ -1137,9 +700,9 @@ public class LightningView {
} else if (mAction == MotionEvent.ACTION_UP) { } else if (mAction == MotionEvent.ACTION_UP) {
final float distance = (mY - mLocation); final float distance = (mY - mLocation);
if (distance > SCROLL_UP_THRESHOLD && view.getScrollY() < SCROLL_UP_THRESHOLD) { if (distance > SCROLL_UP_THRESHOLD && view.getScrollY() < SCROLL_UP_THRESHOLD) {
mBrowserController.showActionBar(); mActivity.showActionBar();
} else if (distance < -SCROLL_UP_THRESHOLD) { } else if (distance < -SCROLL_UP_THRESHOLD) {
mBrowserController.hideActionBar(); mActivity.hideActionBar();
} }
mLocation = 0; mLocation = 0;
} }
@ -1154,9 +717,9 @@ public class LightningView {
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int power = (int) (velocityY * 100 / mMaxFling); int power = (int) (velocityY * 100 / mMaxFling);
if (power < -10) { if (power < -10) {
mBrowserController.hideActionBar(); mActivity.hideActionBar();
} else if (power > 15) { } else if (power > 15) {
mBrowserController.showActionBar(); mActivity.showActionBar();
} }
return super.onFling(e1, e2, velocityX, velocityY); return super.onFling(e1, e2, velocityX, velocityY);
} }
@ -1172,8 +735,13 @@ public class LightningView {
@Override @Override
public void onLongPress(MotionEvent e) { public void onLongPress(MotionEvent e) {
if (mCanTriggerLongPress) if (mCanTriggerLongPress) {
mBrowserController.onLongPress(); Message msg = webViewHandler.obtainMessage();
if (msg != null) {
msg.setTarget(webViewHandler);
mWebView.requestFocusNodeHref(msg);
}
}
} }
/** /**
@ -1195,4 +763,13 @@ public class LightningView {
mCanTriggerLongPress = true; mCanTriggerLongPress = true;
} }
} }
private class WebViewHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
final String url = msg.getData().getString("url");
longClickPage(url);
}
}
} }

View File

@ -0,0 +1,66 @@
package acr.browser.lightning.view;
import android.content.Context;
import android.graphics.Bitmap;
import acr.browser.lightning.R;
import acr.browser.lightning.utils.ThemeUtils;
import acr.browser.lightning.utils.Utils;
/**
* @author Stefano Pacifici base on Anthony C. Restaino's code
* @date 2015/09/21
*/
class LightningViewTitle {
private static Bitmap DEFAULT_ICON = null;
private Bitmap mFavicon;
private String mTitle;
public LightningViewTitle(Context context, boolean darkTheme) {
if (DEFAULT_ICON == null) {
DEFAULT_ICON = ThemeUtils.getThemedBitmap(context, R.drawable.ic_webpage, darkTheme);
}
mFavicon = DEFAULT_ICON;
mTitle = context.getString(R.string.action_new_tab);
}
public void setFavicon(Bitmap favicon) {
if (favicon == null) {
mFavicon = DEFAULT_ICON;
} else {
mFavicon = Utils.padFavicon(favicon);
}
}
public void setTitle(String title) {
if (title == null) {
mTitle = "";
} else {
mTitle = title;
}
}
public void setTitleAndFavicon(String title, Bitmap favicon) {
mTitle = title;
if (favicon == null) {
mFavicon = DEFAULT_ICON;
} else {
mFavicon = Utils.padFavicon(favicon);
}
}
public String getTitle() {
return mTitle;
}
public Bitmap getFavicon() {
return mFavicon;
}
public Bitmap getDefaultIcon() {
return DEFAULT_ICON;
}
}

View File

@ -0,0 +1,276 @@
package acr.browser.lightning.view;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.MailTo;
import android.net.http.SslError;
import android.os.Build;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.squareup.otto.Bus;
import java.io.ByteArrayInputStream;
import java.net.URISyntaxException;
import acr.browser.lightning.R;
import acr.browser.lightning.activity.BrowserActivity;
import acr.browser.lightning.app.BrowserApp;
import acr.browser.lightning.bus.BrowserEvents;
import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.utils.AdBlock;
import acr.browser.lightning.utils.IntentUtils;
import acr.browser.lightning.utils.ProxyUtils;
import acr.browser.lightning.utils.Utils;
/**
* @author Stefano Pacifici based on Anthony C. Restaino's code
* @date 2015/09/22
*/
public class LightningWebClient extends WebViewClient {
private final BrowserActivity mActivity;
private final LightningView mLightningView;
private final AdBlock mAdBlock;
private final Bus mEventBus;
private final IntentUtils mIntentUtils;
LightningWebClient(BrowserActivity activity, LightningView lightningView) {
mActivity = activity;
mLightningView = lightningView;
mAdBlock = AdBlock.getInstance(activity);
mAdBlock.updatePreference();
mEventBus = BrowserApp.getAppComponent().getBus();
mIntentUtils = new IntentUtils(activity);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mAdBlock.isAd(request.getUrl().toString())) {
ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
return new WebResourceResponse("text/plain", "utf-8", EMPTY);
}
}
return super.shouldInterceptRequest(view, request);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (mAdBlock.isAd(url)) {
ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
return new WebResourceResponse("text/plain", "utf-8", EMPTY);
}
return null;
}
@SuppressLint("NewApi")
@Override
public void onPageFinished(WebView view, String url) {
if (view.isShown()) {
mActivity.updateUrl(url, true);
view.postInvalidate();
}
if (view.getTitle() == null || view.getTitle().isEmpty()) {
mLightningView.mTitle.setTitle(mActivity.getString(R.string.untitled));
} else {
mLightningView.mTitle.setTitle(view.getTitle());
}
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT &&
mLightningView.getInvertePage()) {
view.evaluateJavascript(Constants.JAVASCRIPT_INVERT_PAGE, null);
}
mEventBus.post(new BrowserEvents.TabsChanged());
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (mLightningView.isShown()) {
mActivity.updateUrl(url, false);
mActivity.showActionBar();
}
mEventBus.post(new BrowserEvents.TabsChanged());
}
@Override
public void onReceivedHttpAuthRequest(final WebView view, @NonNull final HttpAuthHandler handler,
final String host, final String realm) {
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
final EditText name = new EditText(mActivity);
final EditText password = new EditText(mActivity);
LinearLayout passLayout = new LinearLayout(mActivity);
passLayout.setOrientation(LinearLayout.VERTICAL);
passLayout.addView(name);
passLayout.addView(password);
name.setHint(mActivity.getString(R.string.hint_username));
name.setSingleLine();
password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
password.setSingleLine();
password.setTransformationMethod(new PasswordTransformationMethod());
password.setHint(mActivity.getString(R.string.hint_password));
builder.setTitle(mActivity.getString(R.string.title_sign_in));
builder.setView(passLayout);
builder.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.title_sign_in),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
String user = name.getText().toString();
String pass = password.getText().toString();
handler.proceed(user.trim(), pass.trim());
Log.d(Constants.TAG, "Request Login");
}
})
.setNegativeButton(mActivity.getString(R.string.action_cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
handler.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
private boolean mIsRunning = false;
private float mZoomScale = 0.0f;
@SuppressLint("NewApi")
@Override
public void onScaleChanged(final WebView view, final float oldScale, final float newScale) {
if (view.isShown() && mLightningView.mPreferences.getTextReflowEnabled() &&
Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
if (mIsRunning)
return;
if (Math.abs(mZoomScale - newScale) > 0.01f) {
mIsRunning = view.postDelayed(new Runnable() {
@Override
public void run() {
mZoomScale = newScale;
view.evaluateJavascript(Constants.JAVASCRIPT_TEXT_REFLOW, null);
mIsRunning = false;
}
}, 100);
}
}
}
@Override
public void onReceivedSslError(WebView view, @NonNull final SslErrorHandler handler, SslError error) {
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(mActivity.getString(R.string.title_warning));
builder.setMessage(mActivity.getString(R.string.message_untrusted_certificate))
.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.action_yes),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
handler.proceed();
}
})
.setNegativeButton(mActivity.getString(R.string.action_no),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
handler.cancel();
}
});
AlertDialog alert = builder.create();
if (error.getPrimaryError() == SslError.SSL_UNTRUSTED) {
alert.show();
} else {
handler.proceed();
}
}
@Override
public void onFormResubmission(WebView view, @NonNull final Message dontResend, final Message resend) {
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(mActivity.getString(R.string.title_form_resubmission));
builder.setMessage(mActivity.getString(R.string.message_form_resubmission))
.setCancelable(true)
.setPositiveButton(mActivity.getString(R.string.action_yes),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
resend.sendToTarget();
}
})
.setNegativeButton(mActivity.getString(R.string.action_no),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dontResend.sendToTarget();
}
});
AlertDialog alert = builder.create();
alert.show();
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Check if configured proxy is available
if (!ProxyUtils.getInstance().isProxyReady()) {
// User has been notified
return true;
}
if (mLightningView.mIsIncognitoTab) {
return super.shouldOverrideUrlLoading(view, url);
}
if (url.startsWith("about:")) {
return super.shouldOverrideUrlLoading(view, url);
}
if (url.contains("mailto:")) {
MailTo mailTo = MailTo.parse(url);
Intent i = Utils.newEmailIntent(mailTo.getTo(), mailTo.getSubject(),
mailTo.getBody(), mailTo.getCc());
mActivity.startActivity(i);
view.reload();
return true;
} else if (url.startsWith("intent://")) {
Intent intent;
try {
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
} catch (URISyntaxException ex) {
return false;
}
if (intent != null) {
try {
mActivity.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.e(Constants.TAG, "ActivityNotFoundException");
}
return true;
}
}
return mIntentUtils.startActivityForUrl(view, url);
}
}

View File

@ -25,7 +25,14 @@
<include layout="@layout/search_interface" /> <include layout="@layout/search_interface" />
</LinearLayout> </LinearLayout>
<include layout="@layout/tab_drawer" /> <FrameLayout
android:layout_width="@dimen/navigation_width"
android:layout_height="match_parent"
android:background="?attr/drawerBackground"
android:id="@+id/left_drawer"
android:fitsSystemWindows="true"
android:layout_gravity="start"
android:weightSum="1" />
<FrameLayout <FrameLayout
android:weightSum="1" android:weightSum="1"
@ -34,14 +41,8 @@
android:id="@+id/right_drawer" android:id="@+id/right_drawer"
android:background="?attr/drawerBackground" android:background="?attr/drawerBackground"
android:layout_width="@dimen/navigation_width" android:layout_width="@dimen/navigation_width"
android:layout_height="match_parent"> android:layout_height="match_parent" />
<fragment
android:id="@+id/bookmark_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="acr.browser.lightning.fragment.BookmarksFragment" />
</FrameLayout>
<!-- include layout="@layout/bookmark_drawer" / -->
</android.support.v4.widget.DrawerLayout> </android.support.v4.widget.DrawerLayout>
</LinearLayout> </LinearLayout>

View File

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/left_drawer" android:layout_width="match_parent"
android:layout_width="@dimen/navigation_width"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="start"
android:background="?attr/drawerBackground" android:background="?attr/drawerBackground"
android:clickable="true" android:clickable="true"
android:fitsSystemWindows="true"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
@ -45,12 +42,13 @@
</LinearLayout> </LinearLayout>
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/left_drawer_list" android:id="@+id/tabs_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:divider="@null" android:divider="@null"
android:dividerHeight="0dp" /> android:dividerHeight="0dp"
android:overScrollMode="ifContentScrolls" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@color/black"
android:overScrollMode="never"
android:scrollbars="none"
android:id="@+id/tabs_list" />

View File

@ -8,13 +8,10 @@
android:elevation="2dp" android:elevation="2dp"
android:orientation="vertical"> android:orientation="vertical">
<android.support.v7.widget.RecyclerView <FrameLayout
android:id="@+id/twv_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="30dp" android:layout_height="30dp"
android:background="@color/black" android:id="@+id/tabs_toolbar_container"/>
android:overScrollMode="never"
android:scrollbars="none" />
<android.support.v7.widget.Toolbar <android.support.v7.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"