diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 8e8d988..8f63ed7 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -250,7 +250,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mTabsManager = new TabsManager(); mPresenter = new BrowserPresenter(this, isIncognito()); - initialize(); + initialize(savedInstanceState); KeyboardHelper keyboardHelper = new KeyboardHelper(mRoot); keyboardHelper.registerKeyboardListener(new KeyboardHelper.KeyboardListener() { @@ -265,7 +265,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements }); } - private synchronized void initialize() { + private synchronized void initialize(Bundle savedInstanceState) { mToolbar = (Toolbar) findViewById(R.id.toolbar); initializeToolbarHeight(getResources().getConfiguration()); setSupportActionBar(mToolbar); @@ -406,11 +406,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath()); } - if (isPanicTrigger(getIntent())) { + Intent intent = savedInstanceState == null ? getIntent() : null; + + if (isPanicTrigger(intent)) { setIntent(null); panicClean(); } else { - mPresenter.setupTabs(getIntent()); + mPresenter.setupTabs(intent); setIntent(null); mProxyUtils.checkForProxy(BrowserActivity.this); } diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index d96fd9b..a52e9a8 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -143,7 +143,7 @@ public class TabsManager { private void restoreLostTabs(@Nullable final String url, @NonNull final Activity activity, @NonNull final Subscriber subscriber) { - restoreState().subscribeOn(Schedulers.worker()) + restoreState().subscribeOn(Schedulers.io()) .observeOn(Schedulers.main()).subscribe(new OnSubscribe() { @Override public void onNext(Bundle item) { @@ -282,6 +282,21 @@ public class TabsManager { return mTabList.size() - 1; } + + /** + * The last tab in the tab manager. + * + * @return the last tab, or null if + * there are no tabs. + */ + @Nullable + public synchronized LightningView lastTab() { + if (last() < 0) { + return null; + } + return mTabList.get(last()); + } + /** * Create and return a new tab. The tab is * automatically added to the tabs list. diff --git a/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java b/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java index 39a7534..a152818 100644 --- a/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java +++ b/app/src/main/java/acr/browser/lightning/browser/BrowserPresenter.java @@ -38,7 +38,7 @@ public class BrowserPresenter { @Nullable private LightningView mCurrentTab; private final boolean mIsIncognito; - private boolean mIsNewIntent; + private boolean mShouldClose; public BrowserPresenter(@NonNull BrowserView view, boolean isIncognito) { BrowserApp.getAppComponent().inject(this); @@ -152,8 +152,9 @@ public class BrowserPresenter { if (!UrlUtils.isSpecialUrl(tabToDelete.getUrl()) && !mIsIncognito) { mPreferences.setSavedUrl(tabToDelete.getUrl()); } + final boolean isShown = tabToDelete.isShown(); - boolean shouldClose = mIsNewIntent && isShown; + boolean shouldClose = mShouldClose && isShown && Boolean.TRUE.equals(tabToDelete.getTag()); final LightningView currentTab = mTabsModel.getCurrentTab(); if (mTabsModel.size() == 1 && currentTab != null && (UrlUtils.isSpecialUrl(currentTab.getUrl()) || @@ -186,7 +187,7 @@ public class BrowserPresenter { } if (shouldClose) { - mIsNewIntent = false; + mShouldClose = false; mView.closeActivity(); } @@ -230,7 +231,11 @@ public class BrowserPresenter { } else { newTab(url, true); } - mIsNewIntent = true; + mShouldClose = true; + LightningView tab = mTabsModel.lastTab(); + if (tab != null) { + tab.setTag(true); + } } } }); @@ -303,7 +308,6 @@ public class BrowserPresenter { Log.d(TAG, "New tab, show: " + show); - mIsNewIntent = false; LightningView startingTab = mTabsModel.newTab((Activity) mView, url, mIsIncognito); if (mTabsModel.size() == 1) { startingTab.resumeTimers(); diff --git a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java index 1614508..4560d52 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java @@ -180,7 +180,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, setupNavigationButton(view, R.id.action_reading, R.id.icon_reading); setupNavigationButton(view, R.id.action_toggle_desktop, R.id.icon_desktop); - initBookmarkManager().subscribeOn(Schedulers.worker()) + initBookmarkManager().subscribeOn(Schedulers.io()) .observeOn(Schedulers.main()) .subscribe(new OnSubscribe() { @Override diff --git a/app/src/main/java/acr/browser/lightning/react/Observable.java b/app/src/main/java/acr/browser/lightning/react/Observable.java index 5535b30..1566d64 100644 --- a/app/src/main/java/acr/browser/lightning/react/Observable.java +++ b/app/src/main/java/acr/browser/lightning/react/Observable.java @@ -197,7 +197,7 @@ public class Observable { private static class OnCompleteRunnable implements Runnable { private final OnSubscribe onSubscribe; - public OnCompleteRunnable(OnSubscribe onSubscribe) {this.onSubscribe = onSubscribe;} + public OnCompleteRunnable(@NonNull OnSubscribe onSubscribe) {this.onSubscribe = onSubscribe;} @Override public void run() { @@ -209,7 +209,7 @@ public class Observable { private final OnSubscribe onSubscribe; private final T item; - public OnNextRunnable(OnSubscribe onSubscribe, T item) { + public OnNextRunnable(@NonNull OnSubscribe onSubscribe, T item) { this.onSubscribe = onSubscribe; this.item = item; } @@ -224,7 +224,7 @@ public class Observable { private final OnSubscribe onSubscribe; private final Throwable throwable; - public OnErrorRunnable(OnSubscribe onSubscribe, Throwable throwable) { + public OnErrorRunnable(@NonNull OnSubscribe onSubscribe, @NonNull Throwable throwable) { this.onSubscribe = onSubscribe; this.throwable = throwable; } @@ -238,7 +238,7 @@ public class Observable { private static class OnStartRunnable implements Runnable { private final OnSubscribe onSubscribe; - public OnStartRunnable(OnSubscribe onSubscribe) {this.onSubscribe = onSubscribe;} + public OnStartRunnable(@NonNull OnSubscribe onSubscribe) {this.onSubscribe = onSubscribe;} @Override public void run() { diff --git a/app/src/main/java/acr/browser/lightning/react/Schedulers.java b/app/src/main/java/acr/browser/lightning/react/Schedulers.java index 8f5323e..4368c96 100644 --- a/app/src/main/java/acr/browser/lightning/react/Schedulers.java +++ b/app/src/main/java/acr/browser/lightning/react/Schedulers.java @@ -7,11 +7,14 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class Schedulers { - private static final Executor sWorker = Executors.newCachedThreadPool(); + private static final Executor sWorker = Executors.newFixedThreadPool(4); + private static final Executor sIOWorker = Executors.newSingleThreadExecutor(); private static final Executor sMain = new ThreadExecutor(Looper.getMainLooper()); /** - * The worker thread. + * The worker thread executor, will + * execute work on any one of multiple + * threads. * * @return a non-null executor. */ @@ -29,4 +32,15 @@ public class Schedulers { public static Executor main() { return sMain; } + + /** + * The io thread. + * + * @return a non-null executor that does + * work on a single thread off the main thread. + */ + @NonNull + public static Executor io() { + return sIOWorker; + } } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index cb4b4ba..9a85687 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -67,39 +67,43 @@ import acr.browser.lightning.utils.Utils; */ public class LightningView { + private static final String TAG = LightningView.class.getSimpleName(); + public static final String HEADER_REQUESTED_WITH = "X-Requested-With"; public static final String HEADER_WAP_PROFILE = "X-Wap-Profile"; private static final String HEADER_DNT = "DNT"; - - @NonNull private final LightningViewTitle mTitle; - @Nullable private WebView mWebView; - private final boolean mIsIncognitoTab; - @NonNull private final UIController mUIController; - @NonNull private final GestureDetector mGestureDetector; - @NonNull private final Activity mActivity; - private static String mHomepage; - private static String mDefaultUserAgent; - private final Paint mPaint = new Paint(); - private boolean isForegroundTab; - private boolean mInvertPage = false; - private boolean mToggleDesktop = false; - private static float mMaxFling; private static final int API = android.os.Build.VERSION.SDK_INT; private static final int SCROLL_UP_THRESHOLD = Utils.dpToPx(10); - private static final float[] mNegativeColorArray = { + + private static String sHomepage; + private static String sDefaultUserAgent; + private static float mMaxFling; + private static final float[] sNegativeColorArray = { -1.0f, 0, 0, 0, 255, // red 0, -1.0f, 0, 0, 255, // green 0, 0, -1.0f, 0, 255, // blue 0, 0, 0, 1.0f, 0 // alpha }; - private static final float[] mIncreaseContrastColorArray = { + private static final float[] sIncreaseContrastColorArray = { 2.0f, 0, 0, 0, -160.f, // red 0, 2.0f, 0, 0, -160.f, // green 0, 0, 2.0f, 0, -160.f, // blue 0, 0, 0, 1.0f, 0 // alpha }; - private final WebViewHandler mWebViewHandler = new WebViewHandler(this); - private final Map mRequestHeaders = new ArrayMap<>(); + + @NonNull private final LightningViewTitle mTitle; + @Nullable private WebView mWebView; + @NonNull private final UIController mUIController; + @NonNull private final GestureDetector mGestureDetector; + @NonNull private final Activity mActivity; + @NonNull private final Paint mPaint = new Paint(); + @Nullable private Object mTag; + private final boolean mIsIncognitoTab; + private boolean isForegroundTab; + private boolean mInvertPage = false; + private boolean mToggleDesktop = false; + @NonNull private final WebViewHandler mWebViewHandler = new WebViewHandler(this); + @NonNull private final Map mRequestHeaders = new ArrayMap<>(); @Inject Bus mEventBus; @Inject PreferenceManager mPreferences; @@ -107,7 +111,6 @@ public class LightningView { @Inject ProxyUtils mProxyUtils; @Inject BookmarkManager mBookmarkManager; - @SuppressLint("NewApi") public LightningView(@NonNull Activity activity, @Nullable String url, boolean isIncognito) { BrowserApp.getAppComponent().inject(this); mActivity = activity; @@ -139,7 +142,7 @@ public class LightningView { mWebView.setDownloadListener(new LightningDownloadListener(activity)); mGestureDetector = new GestureDetector(activity, new CustomGestureListener()); mWebView.setOnTouchListener(new TouchListener()); - mDefaultUserAgent = mWebView.getSettings().getUserAgentString(); + sDefaultUserAgent = mWebView.getSettings().getUserAgentString(); initializeSettings(); initializePreferences(activity); @@ -154,6 +157,28 @@ public class LightningView { } } + /** + * Sets the tag on the object, + * a reference to this object is held + * indefinitely. + * + * @param tag the tag to set, may be null. + */ + public void setTag(@Nullable Object tag) { + mTag = tag; + } + + /** + * The tag set on the object. + * + * @return the tag set on the object, + * may be null. + */ + @Nullable + public Object getTag() { + return mTag; + } + /** * This method loads the homepage for the browser. Either * it loads the URL stored as the homepage, or loads the @@ -164,7 +189,7 @@ public class LightningView { if (mWebView == null) { return; } - switch (mHomepage) { + switch (sHomepage) { case "about:home": loadStartpage(); break; @@ -172,7 +197,7 @@ public class LightningView { loadBookmarkpage(); break; default: - mWebView.loadUrl(mHomepage, mRequestHeaders); + mWebView.loadUrl(sHomepage, mRequestHeaders); break; } } @@ -227,7 +252,7 @@ public class LightningView { } settings.setDefaultTextEncodingName(mPreferences.getTextEncoding()); - mHomepage = mPreferences.getHomepage(); + sHomepage = mPreferences.getHomepage(); setColorMode(mPreferences.getRenderingMode()); if (!mIsIncognitoTab) { @@ -286,7 +311,7 @@ public class LightningView { } catch (Exception e) { // This shouldn't be necessary, but there are a number // of KitKat devices that crash trying to set this - Log.e(Constants.TAG, "Problem setting LayoutAlgorithm to TEXT_AUTOSIZING"); + Log.e(TAG, "Problem setting LayoutAlgorithm to TEXT_AUTOSIZING"); } } } else { @@ -376,7 +401,8 @@ public class LightningView { } getPathObservable("appcache") - .subscribeOn(Schedulers.worker()) + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.main()) .subscribe(new OnSubscribe() { @Override public void onNext(File item) { @@ -388,7 +414,8 @@ public class LightningView { }); getPathObservable("geolocation") - .subscribeOn(Schedulers.worker()) + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.main()) .subscribe(new OnSubscribe() { @Override public void onNext(File item) { @@ -400,7 +427,8 @@ public class LightningView { }); getPathObservable("databases") - .subscribeOn(Schedulers.worker()) + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.main()) .subscribe(new OnSubscribe() { @Override public void onNext(File item) { @@ -488,7 +516,7 @@ public class LightningView { if (API >= Build.VERSION_CODES.JELLY_BEAN_MR1) { settings.setUserAgentString(WebSettings.getDefaultUserAgent(context)); } else { - settings.setUserAgentString(mDefaultUserAgent); + settings.setUserAgentString(sDefaultUserAgent); } break; case 2: @@ -498,7 +526,7 @@ public class LightningView { settings.setUserAgentString(Constants.MOBILE_USER_AGENT); break; case 4: - String ua = mPreferences.getUserAgentString(mDefaultUserAgent); + String ua = mPreferences.getUserAgentString(sDefaultUserAgent); if (ua == null || ua.isEmpty()) { ua = " "; } @@ -663,7 +691,7 @@ public class LightningView { break; case 1: ColorMatrixColorFilter filterInvert = new ColorMatrixColorFilter( - mNegativeColorArray); + sNegativeColorArray); mPaint.setColorFilter(filterInvert); setHardwareRendering(); @@ -678,7 +706,7 @@ public class LightningView { break; case 3: ColorMatrix matrix = new ColorMatrix(); - matrix.set(mNegativeColorArray); + matrix.set(sNegativeColorArray); ColorMatrix matrixGray = new ColorMatrix(); matrixGray.setSaturation(0); ColorMatrix concat = new ColorMatrix(); @@ -692,7 +720,7 @@ public class LightningView { case 4: ColorMatrixColorFilter IncreaseHighContrast = new ColorMatrixColorFilter( - mIncreaseContrastColorArray); + sIncreaseContrastColorArray); mPaint.setColorFilter(IncreaseHighContrast); setHardwareRendering(); break; @@ -800,7 +828,7 @@ public class LightningView { // before calling destroy() so that a memory leak is not created ViewGroup parent = (ViewGroup) mWebView.getParent(); if (parent != null) { - Log.e(Constants.TAG, "WebView was not detached from window before onDestroy"); + Log.e(TAG, "WebView was not detached from window before onDestroy"); parent.removeView(mWebView); } mWebView.stopLoading();