<commit_before>/*
 * Copyright (C) 2017-2019 Hazuki
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jp.hazuki.yuzubrowser.browser

import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.gesture.GestureOverlayView
import android.media.AudioManager
import android.os.*
import android.text.TextUtils
import android.view.*
import android.webkit.*
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.appbar.AppBarLayout
import com.squareup.moshi.Moshi
import jp.hazuki.asyncpermissions.AsyncPermissions
import jp.hazuki.yuzubrowser.browser.behavior.BottomBarBehavior
import jp.hazuki.yuzubrowser.browser.behavior.WebViewBehavior
import jp.hazuki.yuzubrowser.browser.manager.UserActionManager
import jp.hazuki.yuzubrowser.browser.tab.TabManagerFactory
import jp.hazuki.yuzubrowser.browser.view.Toolbar
import jp.hazuki.yuzubrowser.core.utility.extensions.appCacheFilePath
import jp.hazuki.yuzubrowser.core.utility.log.ErrorReport
import jp.hazuki.yuzubrowser.core.utility.log.Logger
import jp.hazuki.yuzubrowser.core.utility.utils.ui
import jp.hazuki.yuzubrowser.favicon.FaviconManager
import jp.hazuki.yuzubrowser.legacy.BrowserApplication
import jp.hazuki.yuzubrowser.legacy.BrowserState
import jp.hazuki.yuzubrowser.legacy.Constants
import jp.hazuki.yuzubrowser.legacy.action.Action
import jp.hazuki.yuzubrowser.legacy.action.ActionNameArray
import jp.hazuki.yuzubrowser.legacy.action.item.AutoPageScrollAction
import jp.hazuki.yuzubrowser.legacy.action.item.OpenOptionsMenuAction
import jp.hazuki.yuzubrowser.legacy.action.item.TabListSingleAction
import jp.hazuki.yuzubrowser.legacy.action.manager.ActionExecutor
import jp.hazuki.yuzubrowser.legacy.action.manager.ActionIconManager
import jp.hazuki.yuzubrowser.legacy.action.manager.MenuActionManager
import jp.hazuki.yuzubrowser.legacy.action.view.ActionActivity
import jp.hazuki.yuzubrowser.legacy.adblock.AddAdBlockDialog
import jp.hazuki.yuzubrowser.legacy.bookmark.view.showAddBookmarkDialog
import jp.hazuki.yuzubrowser.legacy.browser.*
import jp.hazuki.yuzubrowser.legacy.browser.openable.BrowserOpenable
import jp.hazuki.yuzubrowser.legacy.download.service.DownloadFile
import jp.hazuki.yuzubrowser.legacy.download.ui.FastDownloadActivity
import jp.hazuki.yuzubrowser.legacy.download.ui.fragment.SaveWebArchiveDialog
import jp.hazuki.yuzubrowser.legacy.gesture.GestureManager
import jp.hazuki.yuzubrowser.legacy.history.BrowserHistoryManager
import jp.hazuki.yuzubrowser.legacy.menuwindow.MenuWindow
import jp.hazuki.yuzubrowser.legacy.readitlater.readItLater
import jp.hazuki.yuzubrowser.legacy.search.SearchActivity
import jp.hazuki.yuzubrowser.legacy.settings.data.AppData
import jp.hazuki.yuzubrowser.legacy.tab.BrowserTabManager
import jp.hazuki.yuzubrowser.legacy.tab.TabListLayout
import jp.hazuki.yuzubrowser.legacy.tab.UiTabManager
import jp.hazuki.yuzubrowser.legacy.tab.manager.MainTabData
import jp.hazuki.yuzubrowser.legacy.tab.manager.OnWebViewCreatedListener
import jp.hazuki.yuzubrowser.legacy.tab.manager.TabManager
import jp.hazuki.yuzubrowser.legacy.tab.manager.WebViewProvider
import jp.hazuki.yuzubrowser.legacy.toolbar.ToolbarManager
import jp.hazuki.yuzubrowser.legacy.toolbar.sub.WebViewFindDialog
import jp.hazuki.yuzubrowser.legacy.toolbar.sub.WebViewFindDialogFactory
import jp.hazuki.yuzubrowser.legacy.toolbar.sub.WebViewPageFastScroller
import jp.hazuki.yuzubrowser.legacy.utils.CrashlyticsUtils
import jp.hazuki.yuzubrowser.legacy.utils.DisplayUtils
import jp.hazuki.yuzubrowser.legacy.utils.WebUtils
import jp.hazuki.yuzubrowser.legacy.utils.extensions.saveArchive
import jp.hazuki.yuzubrowser.legacy.utils.network.ConnectionStateMonitor
import jp.hazuki.yuzubrowser.legacy.webkit.TabType
import jp.hazuki.yuzubrowser.legacy.webkit.WebCustomViewHandler
import jp.hazuki.yuzubrowser.legacy.webkit.WebViewAutoScrollManager
import jp.hazuki.yuzubrowser.legacy.webkit.WebViewProxy
import jp.hazuki.yuzubrowser.legacy.webrtc.WebRtcPermissionHandler
import jp.hazuki.yuzubrowser.legacy.webrtc.core.WebRtcRequest
import jp.hazuki.yuzubrowser.ui.theme.ThemeData
import jp.hazuki.yuzubrowser.ui.widget.PointerView
import jp.hazuki.yuzubrowser.webview.CustomWebHistoryItem
import jp.hazuki.yuzubrowser.webview.CustomWebView
import jp.hazuki.yuzubrowser.webview.WebViewFactory
import jp.hazuki.yuzubrowser.webview.WebViewType
import jp.hazuki.yuzubrowser.webview.listener.OnScrollChangedListener
import jp.hazuki.yuzubrowser.webview.listener.OnScrollableChangeListener
import kotlinx.android.synthetic.main.browser_activity.*
import java.util.*
import javax.inject.Inject

class BrowserActivity : BrowserBaseActivity(), BrowserController, FinishAlertDialog.OnFinishDialogCallBack, OnWebViewCreatedListener, AddAdBlockDialog.OnAdBlockListUpdateListener, WebRtcRequest, SaveWebArchiveDialog.OnSaveWebViewListener, WebViewProvider {

    private val asyncPermissions by lazy { AsyncPermissions(this) }
    private val handler = Handler(Looper.getMainLooper())
    private val actionController = ActionExecutor(this)
    private val iconManager = ActionIconManager(this)
    private val connectionStateMonitor = ConnectionStateMonitor { isAvailable ->
        handler.post {
            for (tab in tabManager.loadedData) {
                tab.mWebView.setNetworkAvailable(isAvailable)
            }
        }
    }

    private val saveTabsRunnable = object : Runnable {
        override fun run() {
            tabManagerIn.saveData()

            val delay = AppData.auto_tab_save_delay.get()
            if (delay > 0)
                handler.postDelayed(this, (delay * 1000).toLong())
        }
    }
    private val takeCurrentTabScreen = Runnable {
        tabManagerIn.currentTabData?.run {
            if (isShotThumbnail) {
                tabManagerIn.forceTakeThumbnail(this)
            }
        }
    }
    private val paddingReset = Runnable {
        tabManagerIn.currentTabData?.let {
            adjustBrowserPadding(it)
        }
    }
    private var scrollableChangeListener = object : OnScrollableChangeListener {
        override fun onScrollableChanged(scrollable: Boolean) {
            val tab = currentTabData ?: return
            adjustBrowserPadding(tab)
        }
    }

    private val scrollChangedListener: OnScrollChangedListener = { webView: CustomWebView, l: Int, t: Int, oldl: Int, oldt: Int ->
        webViewFastScroller.onPageScroll()
        webViewPageFastScroller?.onScrollWebView(webView)
    }

    private lateinit var browserState: BrowserState
    private lateinit var toolbar: Toolbar
    private lateinit var tabManagerIn: UiTabManager
    private lateinit var userActionManager: UserActionManager
    private lateinit var webViewBehavior: WebViewBehavior
    private lateinit var bottomBarBehavior: BottomBarBehavior
    private lateinit var webClient: WebClient
    private lateinit var menuWindow: MenuWindow

    private var isActivityDestroyed = false
    private var isResumed = false
    override var isActivityPaused: Boolean = true
        private set
    private var forceDestroy: Boolean = false

    private var closedTabs: ArrayDeque<Bundle>? = null
    private var webViewFindDialog: WebViewFindDialog? = null
    private var webViewPageFastScroller: WebViewPageFastScroller? = null
    private var webViewAutoScrollManager: WebViewAutoScrollManager? = null
    private var subGestureView: GestureOverlayView? = null
    private var tabListView: TabListLayout? = null
    private var webCustomViewHandler: WebCustomViewHandler? = null
    private var videoLoadingProgressView: View? = null
    private var mouseCursorView: PointerView? = null
    private var findOnPage: WebViewFindDialog? = null
    private var delayAction: Action? = null

    @Inject
    internal lateinit var webViewFactory: WebViewFactory
    @Inject
    internal lateinit var moshi: Moshi

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.browser_activity)

        browserState = (applicationContext as BrowserApplication).browserState

        if (browserState.isNeedLoad) {
            AppData.load(this, moshi)
            browserState.isNeedLoad = false
        }

        userActionManager = UserActionManager(this, this, actionController, iconManager)
        tabManagerIn = BrowserTabManager(TabManagerFactory.newInstance(this, webViewFactory), this)
        webClient = WebClient(this, this)

        toolbar = Toolbar(this, superFrameLayoutInfo, this, actionController, iconManager)
        toolbar.addToolbarView(resources)

        webViewBehavior = (webGestureOverlayView.layoutParams as androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams).behavior as WebViewBehavior
        bottomBarBehavior = (bottomOverlayLayout.layoutParams as androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams).behavior as BottomBarBehavior
        superFrameLayout.setOnImeShownListener { visible ->
            if (isImeShown != visible) {
                isImeShown = visible
                webViewBehavior.isImeShown = visible
                val tab = tabManagerIn.currentTabData
                if (tab != null) {
                    toolbar.notifyChangeWebState(tab)
                    adjustBrowserPadding(tab)
                }
                toolbar.onImeChanged(visible)

                if (!visible && isFullscreenMode) {
                    window.decorView.systemUiVisibility = DisplayUtils.getFullScreenVisibility()<commit_msg>Crash workaround for pagePaddingHeight<commit_after>/*
 * Copyright (C) 2017-2019 Hazuki
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jp.hazuki.yuzubrowser.browser

import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.gesture.GestureOverlayView
import android.media.AudioManager
import android.os.*
import android.text.TextUtils
import android.view.*
import android.webkit.*
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.appbar.AppBarLayout
import com.squareup.moshi.Moshi
import jp.hazuki.asyncpermissions.AsyncPermissions
import jp.hazuki.yuzubrowser.browser.behavior.BottomBarBehavior
import jp.hazuki.yuzubrowser.browser.behavior.WebViewBehavior
import jp.hazuki.yuzubrowser.browser.manager.UserActionManager
import jp.hazuki.yuzubrowser.browser.tab.TabManagerFactory
import jp.hazuki.yuzubrowser.browser.view.Toolbar
import jp.hazuki.yuzubrowser.core.utility.extensions.appCacheFilePath
import jp.hazuki.yuzubrowser.core.utility.log.ErrorReport
import jp.hazuki.yuzubrowser.core.utility.log.Logger
import jp.hazuki.yuzubrowser.core.utility.utils.ui
import jp.hazuki.yuzubrowser.favicon.FaviconManager
import jp.hazuki.yuzubrowser.legacy.BrowserApplication
import jp.hazuki.yuzubrowser.legacy.BrowserState
import jp.hazuki.yuzubrowser.legacy.Constants
import jp.hazuki.yuzubrowser.legacy.action.Action
import jp.hazuki.yuzubrowser.legacy.action.ActionNameArray
import jp.hazuki.yuzubrowser.legacy.action.item.AutoPageScrollAction
import jp.hazuki.yuzubrowser.legacy.action.item.OpenOptionsMenuAction
import jp.hazuki.yuzubrowser.legacy.action.item.TabListSingleAction
import jp.hazuki.yuzubrowser.legacy.action.manager.ActionExecutor
import jp.hazuki.yuzubrowser.legacy.action.manager.ActionIconManager
import jp.hazuki.yuzubrowser.legacy.action.manager.MenuActionManager
import jp.hazuki.yuzubrowser.legacy.action.view.ActionActivity
import jp.hazuki.yuzubrowser.legacy.adblock.AddAdBlockDialog
import jp.hazuki.yuzubrowser.legacy.bookmark.view.showAddBookmarkDialog
import jp.hazuki.yuzubrowser.legacy.browser.*
import jp.hazuki.yuzubrowser.legacy.browser.openable.BrowserOpenable
import jp.hazuki.yuzubrowser.legacy.download.service.DownloadFile
import jp.hazuki.yuzubrowser.legacy.download.ui.FastDownloadActivity
import jp.hazuki.yuzubrowser.legacy.download.ui.fragment.SaveWebArchiveDialog
import jp.hazuki.yuzubrowser.legacy.gesture.GestureManager
import jp.hazuki.yuzubrowser.legacy.history.BrowserHistoryManager
import jp.hazuki.yuzubrowser.legacy.menuwindow.MenuWindow
import jp.hazuki.yuzubrowser.legacy.readitlater.readItLater
import jp.hazuki.yuzubrowser.legacy.search.SearchActivity
import jp.hazuki.yuzubrowser.legacy.settings.data.AppData
import jp.hazuki.yuzubrowser.legacy.tab.BrowserTabManager
import jp.hazuki.yuzubrowser.legacy.tab.TabListLayout
import jp.hazuki.yuzubrowser.legacy.tab.UiTabManager
import jp.hazuki.yuzubrowser.legacy.tab.manager.MainTabData
import jp.hazuki.yuzubrowser.legacy.tab.manager.OnWebViewCreatedListener
import jp.hazuki.yuzubrowser.legacy.tab.manager.TabManager
import jp.hazuki.yuzubrowser.legacy.tab.manager.WebViewProvider
import jp.hazuki.yuzubrowser.legacy.toolbar.ToolbarManager
import jp.hazuki.yuzubrowser.legacy.toolbar.sub.WebViewFindDialog
import jp.hazuki.yuzubrowser.legacy.toolbar.sub.WebViewFindDialogFactory
import jp.hazuki.yuzubrowser.legacy.toolbar.sub.WebViewPageFastScroller
import jp.hazuki.yuzubrowser.legacy.utils.CrashlyticsUtils
import jp.hazuki.yuzubrowser.legacy.utils.DisplayUtils
import jp.hazuki.yuzubrowser.legacy.utils.WebUtils
import jp.hazuki.yuzubrowser.legacy.utils.extensions.saveArchive
import jp.hazuki.yuzubrowser.legacy.utils.network.ConnectionStateMonitor
import jp.hazuki.yuzubrowser.legacy.webkit.TabType
import jp.hazuki.yuzubrowser.legacy.webkit.WebCustomViewHandler
import jp.hazuki.yuzubrowser.legacy.webkit.WebViewAutoScrollManager
import jp.hazuki.yuzubrowser.legacy.webkit.WebViewProxy
import jp.hazuki.yuzubrowser.legacy.webrtc.WebRtcPermissionHandler
import jp.hazuki.yuzubrowser.legacy.webrtc.core.WebRtcRequest
import jp.hazuki.yuzubrowser.ui.theme.ThemeData
import jp.hazuki.yuzubrowser.ui.widget.PointerView
import jp.hazuki.yuzubrowser.webview.CustomWebHistoryItem
import jp.hazuki.yuzubrowser.webview.CustomWebView
import jp.hazuki.yuzubrowser.webview.WebViewFactory
import jp.hazuki.yuzubrowser.webview.WebViewType
import jp.hazuki.yuzubrowser.webview.listener.OnScrollChangedListener
import jp.hazuki.yuzubrowser.webview.listener.OnScrollableChangeListener
import kotlinx.android.synthetic.main.browser_activity.*
import java.util.*
import javax.inject.Inject

class BrowserActivity : BrowserBaseActivity(), BrowserController, FinishAlertDialog.OnFinishDialogCallBack, OnWebViewCreatedListener, AddAdBlockDialog.OnAdBlockListUpdateListener, WebRtcRequest, SaveWebArchiveDialog.OnSaveWebViewListener, WebViewProvider {

    private val asyncPermissions by lazy { AsyncPermissions(this) }
    private val handler = Handler(Looper.getMainLooper())
    private val actionController = ActionExecutor(this)
    private val iconManager = ActionIconManager(this)
    private val connectionStateMonitor = ConnectionStateMonitor { isAvailable ->
        handler.post {
            for (tab in tabManager.loadedData) {
                tab.mWebView.setNetworkAvailable(isAvailable)
            }
        }
    }

    private val saveTabsRunnable = object : Runnable {
        override fun run() {
            tabManagerIn.saveData()

            val delay = AppData.auto_tab_save_delay.get()
            if (delay > 0)
                handler.postDelayed(this, (delay * 1000).toLong())
        }
    }
    private val takeCurrentTabScreen = Runnable {
        tabManagerIn.currentTabData?.run {
            if (isShotThumbnail) {
                tabManagerIn.forceTakeThumbnail(this)
            }
        }
    }
    private val paddingReset = Runnable {
        tabManagerIn.currentTabData?.let {
            adjustBrowserPadding(it)
        }
    }
    private var scrollableChangeListener = object : OnScrollableChangeListener {
        override fun onScrollableChanged(scrollable: Boolean) {
            val tab = currentTabData ?: return
            adjustBrowserPadding(tab)
        }
    }

    private val scrollChangedListener: OnScrollChangedListener = { webView: CustomWebView, l: Int, t: Int, oldl: Int, oldt: Int ->
        webViewFastScroller.onPageScroll()
        webViewPageFastScroller?.onScrollWebView(webView)
    }

    private lateinit var browserState: BrowserState
    private lateinit var toolbar: Toolbar
    private lateinit var tabManagerIn: UiTabManager
    private lateinit var userActionManager: UserActionManager
    private lateinit var webViewBehavior: WebViewBehavior
    private lateinit var bottomBarBehavior: BottomBarBehavior
    private lateinit var webClient: WebClient
    private lateinit var menuWindow: MenuWindow

    private var isActivityDestroyed = false
    private var isResumed = false
    override var isActivityPaused: Boolean = true
        private set
    private var forceDestroy: Boolean = false

    private var closedTabs: ArrayDeque<Bundle>? = null
    private var webViewFindDialog: WebViewFindDialog? = null
    private var webViewPageFastScroller: WebViewPageFastScroller? = null
    private var webViewAutoScrollManager: WebViewAutoScrollManager? = null
    private var subGestureView: GestureOverlayView? = null
    private var tabListView: TabListLayout? = null
    private var webCustomViewHandler: WebCustomViewHandler? = null
    private var videoLoadingProgressView: View? = null
    private var mouseCursorView: PointerView? = null
    private var findOnPage: WebViewFindDialog? = null
    private var delayAction: Action? = null

    @Inject
    internal lateinit var webViewFactory: WebViewFactory
    @Inject
    internal lateinit var moshi: Moshi

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.browser_activity)
        //Crash workaround for pagePaddingHeight...
        toolbarPadding.visibility = View.GONE

        browserState = (applicationContext as BrowserApplication).browserState

        if (browserState.isNeedLoad) {
            AppData.load(this, moshi)
            browserState.isNeedLoad = false
        }

        userActionManager = UserActionManager(this, this, actionController, iconManager)
        tabManagerIn = BrowserTabManager(TabManagerFactory.newInstance(this, webViewFactory), this)
        webClient = WebClient(this, this)

        toolbar = Toolbar(this, superFrameLayoutInfo, this, actionController, iconManager)
        toolbar.addToolbarView(resources)

        webViewBehavior = (webGestureOverlayView.layoutParams as androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams).behavior as WebViewBehavior
        bottomBarBehavior = (bottomOverlayLayout.layoutParams as androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams).behavior as BottomBarBehavior
        superFrameLayout.setOnImeShownListener { visible ->
            if (isImeShown != visible) {
                isImeShown = visible
                webViewBehavior.isImeShown = visible
                val tab = tabManagerIn.currentTabData
                if (tab != null) {
                    toolbar.notifyChangeWebState(tab)
                    adjustBrowserPadding(tab)
                }
                toolbar.onImeChanged(visible)

                if (!visible && isFullscreenMode) {
                    window.decorView.systemUiVisibility = DisplayUtils.getFullScreenVisibility()
{'fraction_non_alphanumeric': 0.07411390857980933, 'fraction_numerical': 0.0016621852847714495, 'mean_word_length': 4.302229134266459, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4556502', 'n_tokens_mistral': 6257, 'n_tokens_neox': 6104, 'n_words': 1110}