gt:         final HistoryItem item = new HistoryItem(url, title);
context: /*
   * Copyright 2015 Anthony Restaino
   */
  
  package acr.browser.lightning.browser.activity;
  
  import android.app.Activity;
  import android.app.Dialog;
  import android.content.ClipData;
  import android.content.ClipboardManager;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.res.Configuration;
  import android.graphics.Bitmap;
  import android.graphics.Color;
  import android.graphics.PorterDuff;
  import android.graphics.drawable.ColorDrawable;
  import android.graphics.drawable.Drawable;
  import android.media.MediaPlayer;
  import android.net.Uri;
  import android.os.Build;
  import android.os.Bundle;
  import android.os.Message;
  import android.provider.MediaStore;
  import android.support.annotation.ColorInt;
  import android.support.annotation.IdRes;
  import android.support.annotation.NonNull;
  import android.support.annotation.Nullable;
  import android.support.annotation.StringRes;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentManager;
  import android.support.v4.content.ContextCompat;
  import android.support.v4.view.GravityCompat;
  import android.support.v4.widget.DrawerLayout;
  import android.support.v4.widget.DrawerLayout.DrawerListener;
  import android.support.v7.app.ActionBar;
  import android.support.v7.app.AlertDialog;
  import android.support.v7.graphics.Palette;
  import android.support.v7.widget.Toolbar;
  import android.text.TextUtils;
  import android.util.Log;
  import android.view.KeyEvent;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.view.View.OnFocusChangeListener;
  import android.view.View.OnKeyListener;
  import android.view.View.OnTouchListener;
  import android.view.ViewConfiguration;
  import android.view.ViewGroup;
  import android.view.ViewGroup.LayoutParams;
  import android.view.ViewParent;
  import android.view.ViewTreeObserver;
  import android.view.Window;
  import android.view.WindowManager;
  import android.view.animation.Animation;
  import android.view.animation.Transformation;
  import android.view.inputmethod.EditorInfo;
  import android.view.inputmethod.InputMethodManager;
  import android.webkit.ValueCallback;
  import android.webkit.WebChromeClient.CustomViewCallback;
  import android.webkit.WebIconDatabase;
  import android.webkit.WebView;
  import android.widget.AdapterView;
  import android.widget.AdapterView.OnItemClickListener;
  import android.widget.AutoCompleteTextView;
  import android.widget.FrameLayout;
  import android.widget.ImageButton;
  import android.widget.ImageView;
  import android.widget.LinearLayout;
  import android.widget.RelativeLayout;
  import android.widget.TextView;
  import android.widget.TextView.OnEditorActionListener;
  import android.widget.VideoView;
  
  import com.anthonycr.bonsai.Completable;
  import com.anthonycr.bonsai.CompletableOnSubscribe;
  import com.anthonycr.bonsai.Schedulers;
  import com.anthonycr.bonsai.SingleOnSubscribe;
  import com.anthonycr.grant.PermissionsManager;
  import com.anthonycr.progress.AnimatedProgressBar;
  
  import java.io.File;
  import java.io.IOException;
  
  import javax.inject.Inject;
  
  import acr.browser.lightning.R;
  import acr.browser.lightning.reading.activity.ReadingActivity;
  import acr.browser.lightning.browser.BookmarksView;
  import acr.browser.lightning.browser.BrowserPresenter;
  import acr.browser.lightning.browser.BrowserView;
  import acr.browser.lightning.IncognitoActivity;
  import acr.browser.lightning.browser.SearchBoxModel;
  import acr.browser.lightning.browser.TabsManager;
  import acr.browser.lightning.browser.TabsView;
  import acr.browser.lightning.BrowserApp;
  import acr.browser.lightning.constant.Constants;
  import acr.browser.lightning.constant.DownloadsPage;
  import acr.browser.lightning.constant.HistoryPage;
  import acr.browser.lightning.controller.UIController;
  import acr.browser.lightning.database.HistoryItem;
  import acr.browser.lightning.database.bookmark.BookmarkModel;
  import acr.browser.lightning.database.history.HistoryModel;
  import acr.browser.lightning.dialog.BrowserDialog;
  import acr.browser.lightning.dialog.LightningDialogBuilder;
  import acr.browser.lightning.browser.fragment.BookmarksFragment;
  import acr.browser.lightning.browser.fragment.TabsFragment;
  import acr.browser.lightning.interpolator.BezierDecelerateInterpolator;
  import acr.browser.lightning.receiver.NetworkReceiver;
  import acr.browser.lightning.search.SearchEngineProvider;
  import acr.browser.lightning.search.SuggestionsAdapter;
  import acr.browser.lightning.search.engine.BaseSearchEngine;
  import acr.browser.lightning.settings.activity.SettingsActivity;
  import acr.browser.lightning.utils.DrawableUtils;
  import acr.browser.lightning.utils.IntentUtils;
  import acr.browser.lightning.utils.Preconditions;
  import acr.browser.lightning.utils.ProxyUtils;
  import acr.browser.lightning.utils.ThemeUtils;
  import acr.browser.lightning.utils.UrlUtils;
  import acr.browser.lightning.utils.Utils;
  import acr.browser.lightning.utils.WebUtils;
  import acr.browser.lightning.view.Handlers;
  import acr.browser.lightning.view.LightningView;
  import acr.browser.lightning.view.SearchView;
  import butterknife.BindView;
  import butterknife.ButterKnife;
  
  public abstract class BrowserActivity extends ThemableBrowserActivity implements BrowserView, UIController, OnClickListener {
  
      private static final String TAG = "BrowserActivity";
  
      private static final String INTENT_PANIC_TRIGGER = "info.guardianproject.panic.action.TRIGGER";
  
      private static final String TAG_BOOKMARK_FRAGMENT = "TAG_BOOKMARK_FRAGMENT";
      private static final String TAG_TABS_FRAGMENT = "TAG_TABS_FRAGMENT";
  
      // Static Layout
      @BindView(R.id.drawer_layout) DrawerLayout mDrawerLayout;
      @BindView(R.id.content_frame) FrameLayout mBrowserFrame;
      @BindView(R.id.left_drawer) ViewGroup mDrawerLeft;
      @BindView(R.id.right_drawer) ViewGroup mDrawerRight;
      @BindView(R.id.ui_layout) ViewGroup mUiLayout;
      @BindView(R.id.toolbar_layout) ViewGroup mToolbarLayout;
      @BindView(R.id.progress_view) AnimatedProgressBar mProgressBar;
      @BindView(R.id.search_bar) RelativeLayout mSearchBar;
  
      // Toolbar Views
      @BindView(R.id.toolbar) Toolbar mToolbar;
      private View mSearchBackground;
      private SearchView mSearch;
      private ImageView mArrowImage;
  
      // Current tab view being displayed
      @Nullable private View mCurrentView;
  
      // Full Screen Video Views
      private FrameLayout mFullscreenContainer;
      private VideoView mVideoView;
      private View mCustomView;
  
      // Adapter
      private SuggestionsAdapter mSuggestionsAdapter;
  
      // Callback
      private CustomViewCallback mCustomViewCallback;
      private ValueCallback<Uri> mUploadMessage;
      private ValueCallback<Uri[]> mFilePathCallback;
  
      // Primitives
      private boolean mFullScreen;
      private boolean mDarkTheme;
      private boolean mIsFullScreen = false;
      private boolean mIsImmersive = false;
      private boolean mShowTabsInDrawer;
      private boolean mSwapBookmarksAndTabs;
      private int mOriginalOrientation;
      private int mBackgroundColor;
      private int mIconColor;
      private int mDisabledIconColor;
      private int mCurrentUiColor = Color.BLACK;
      private long mKeyDownStartTime;
      private String mSearchText;
      private String mUntitledTitle;
      private String mCameraPhotoPath;
  
      // The singleton BookmarkManager
      @Inject BookmarkModel mBookmarkManager;
  
      @Inject HistoryModel mHistoryModel;
  
      @Inject LightningDialogBuilder mBookmarksDialogBuilder;
  
      @Inject SearchBoxModel mSearchBoxModel;
  
      @Inject SearchEngineProvider mSearchEngineProvider;
  
      private TabsManager mTabsManager;
  
      // Image
      private Bitmap mWebpageBitmap;
      private final ColorDrawable mBackground = new ColorDrawable();
      private Drawable mDeleteIcon, mRefreshIcon, mClearIcon, mIcon;
  
      private BrowserPresenter mPresenter;
      private TabsView mTabsView;
      private BookmarksView mBookmarksView;
  
      // Proxy
      @Inject ProxyUtils mProxyUtils;
  
      // Constant
      private static final int API = android.os.Build.VERSION.SDK_INT;
      private static final String NETWORK_BROADCAST_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
      private static final LayoutParams MATCH_PARENT = new LayoutParams(LayoutParams.MATCH_PARENT,
          LayoutParams.MATCH_PARENT);
      private static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(
          LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
  
      protected abstract boolean isIncognito();
  
      public abstract void closeActivity();
  
      public abstract void updateHistory(@Nullable final String title, @NonNull final String url);
  
      @NonNull
      protected abstract Completable updateCookiePreference();
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          BrowserApp.getAppComponent().inject(this);
          setContentView(R.layout.activity_main);
          ButterKnife.bind(this);
  
          mTabsManager = new TabsManager();
          mPresenter = new BrowserPresenter(this, isIncognito());
  
          initialize(savedInstanceState);
      }
  
      private synchronized void initialize(Bundle savedInstanceState) {
          initializeToolbarHeight(getResources().getConfiguration());
          setSupportActionBar(mToolbar);
          ActionBar actionBar = getSupportActionBar();
  
          //TODO make sure dark theme flag gets set correctly
          mDarkTheme = mPreferences.getUseTheme() != 0 || isIncognito();
          mIconColor = mDarkTheme ? ThemeUtils.getIconDarkThemeColor(this) : ThemeUtils.getIconLightThemeColor(this);
          mDisabledIconColor = mDarkTheme ? ContextCompat.getColor(this, R.color.icon_dark_theme_disabled) :
              ContextCompat.getColor(this, R.color.icon_light_theme_disabled);
          mShowTabsInDrawer = mPreferences.getShowTabsInDrawer(!isTablet());
          mSwapBookmarksAndTabs = mPreferences.getBookmarksAndTabsSwapped();
  
          // initialize background ColorDrawable
          int primaryColor = ThemeUtils.getPrimaryColor(this);
          mBackground.setColor(primaryColor);
  
          // Drawer stutters otherwise
          mDrawerLeft.setLayerType(View.LAYER_TYPE_NONE, null);
          mDrawerRight.setLayerType(View.LAYER_TYPE_NONE, null);
  
          mDrawerLayout.addDrawerListener(new DrawerListener() {
              @Override
              public void onDrawerSlide(View drawerView, float slideOffset) {}
  
              @Override
              public void onDrawerOpened(View drawerView) {}
  
              @Override
              public void onDrawerClosed(View drawerView) {}
  
              @Override
              public void onDrawerStateChanged(int newState) {
                  if (newState == DrawerLayout.STATE_DRAGGING) {
                      mDrawerLeft.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                      mDrawerRight.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                  } else if (newState == DrawerLayout.STATE_IDLE) {
                      mDrawerLeft.setLayerType(View.LAYER_TYPE_NONE, null);
                      mDrawerRight.setLayerType(View.LAYER_TYPE_NONE, null);
                  }
              }
          });
  
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !mShowTabsInDrawer) {
              getWindow().setStatusBarColor(Color.BLACK);
          }
  
          setNavigationDrawerWidth();
          mDrawerLayout.addDrawerListener(new DrawerLocker());
  
          mWebpageBitmap = ThemeUtils.getThemedBitmap(this, R.drawable.ic_webpage, mDarkTheme);
  
          final FragmentManager fragmentManager = getSupportFragmentManager();
  
          TabsFragment tabsFragment = (TabsFragment) fragmentManager.findFragmentByTag(TAG_TABS_FRAGMENT);
          BookmarksFragment bookmarksFragment = (BookmarksFragment) fragmentManager.findFragmentByTag(TAG_BOOKMARK_FRAGMENT);
  
          if (tabsFragment != null) {
              fragmentManager.beginTransaction().remove(tabsFragment).commit();
          }
          tabsFragment = TabsFragment.createTabsFragment(isIncognito(), mShowTabsInDrawer);
  
          mTabsView = tabsFragment;
  
          if (bookmarksFragment != null) {
              fragmentManager.beginTransaction().remove(bookmarksFragment).commit();
          }
          bookmarksFragment = BookmarksFragment.createFragment(isIncognito());
  
          mBookmarksView = bookmarksFragment;
  
          fragmentManager.executePendingTransactions();
  
          fragmentManager
              .beginTransaction()
              .replace(getTabsFragmentViewId(), tabsFragment, TAG_TABS_FRAGMENT)
              .replace(getBookmarksFragmentViewId(), bookmarksFragment, TAG_BOOKMARK_FRAGMENT)
              .commit();
          if (mShowTabsInDrawer) {
              mToolbarLayout.removeView(findViewById(R.id.tabs_toolbar_container));
          }
  
          Preconditions.checkNonNull(actionBar);
  
          // set display options of the ActionBar
          actionBar.setDisplayShowTitleEnabled(false);
          actionBar.setDisplayShowHomeEnabled(false);
          actionBar.setDisplayShowCustomEnabled(true);
          actionBar.setCustomView(R.layout.toolbar_content);
  
          View customView = actionBar.getCustomView();
          LayoutParams lp = customView.getLayoutParams();
          lp.width = LayoutParams.MATCH_PARENT;
          lp.height = LayoutParams.MATCH_PARENT;
          customView.setLayoutParams(lp);
  
          mArrowImage = customView.findViewById(R.id.arrow);
          FrameLayout arrowButton = customView.findViewById(R.id.arrow_button);
          if (mShowTabsInDrawer) {
              if (mArrowImage.getWidth() <= 0) {
                  mArrowImage.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
              }
              updateTabNumber(0);
  
              // Post drawer locking in case the activity is being recreated
              Handlers.MAIN.post(new Runnable() {
                  @Override
                  public void run() {
                      mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, getTabDrawer());
                  }
              });
          } else {
  
              // Post drawer locking in case the activity is being recreated
              Handlers.MAIN.post(new Runnable() {
                  @Override
                  public void run() {
                      mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, getTabDrawer());
                  }
              });
              mArrowImage.setImageResource(R.drawable.ic_action_home);
              mArrowImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
          }
  
          // Post drawer locking in case the activity is being recreated
          Handlers.MAIN.post(new Runnable() {
              @Override
              public void run() {
                  mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, getBookmarkDrawer());
              }
          });
  
          arrowButton.setOnClickListener(this);
  
          // create the search EditText in the ToolBar
          mSearch = customView.findViewById(R.id.search);
          mSearchBackground = customView.findViewById(R.id.search_container);
  
          // initialize search background color
          mSearchBackground.getBackground().setColorFilter(getSearchBarColor(primaryColor, primaryColor), PorterDuff.Mode.SRC_IN);
          mSearch.setHintTextColor(ThemeUtils.getThemedTextHintColor(mDarkTheme));
          mSearch.setTextColor(mDarkTheme ? Color.WHITE : Color.BLACK);
  
          mUntitledTitle = getString(R.string.untitled);
          mBackgroundColor = ThemeUtils.getPrimaryColor(this);
          mDeleteIcon = ThemeUtils.getThemedDrawable(this, R.drawable.ic_action_delete, mDarkTheme);
          mRefreshIcon = ThemeUtils.getThemedDrawable(this, R.drawable.ic_action_refresh, mDarkTheme);
          mClearIcon = ThemeUtils.getThemedDrawable(this, R.drawable.ic_action_delete, mDarkTheme);
  
          int iconBounds = Utils.dpToPx(24);
          mDeleteIcon.setBounds(0, 0, iconBounds, iconBounds);
          mRefreshIcon.setBounds(0, 0, iconBounds, iconBounds);
          mClearIcon.setBounds(0, 0, iconBounds, iconBounds);
          mIcon = mRefreshIcon;
          SearchListenerClass search = new SearchListenerClass();
          mSearch.setCompoundDrawablePadding(Utils.dpToPx(3));
          mSearch.setCompoundDrawables(null, null, mRefreshIcon, null);
          mSearch.setOnKeyListener(search);
          mSearch.setOnFocusChangeListener(search);
          mSearch.setOnEditorActionListener(search);
          mSearch.setOnTouchListener(search);
          mSearch.setOnPreFocusListener(search);
  
          initializeSearchSuggestions(mSearch);
  
          mDrawerLayout.setDrawerShadow(R.drawable.drawer_right_shadow, GravityCompat.END);
          mDrawerLayout.setDrawerShadow(R.drawable.drawer_left_shadow, GravityCompat.START);
  
          if (API <= Build.VERSION_CODES.JELLY_BEAN_MR2) {
              //noinspection deprecation
              WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath());
          }
  
          @SuppressWarnings("VariableNotUsedInsideIf")
          Intent intent = savedInstanceState == null ? getIntent() : null;
  
          boolean launchedFromHistory = intent != null && (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0;
  
          if (isPanicTrigger(intent)) {
              setIntent(null);
              panicClean();
          } else {
              if (launchedFromHistory) {
                  intent = null;
              }
              mPresenter.setupTabs(intent);
              setIntent(null);
              mProxyUtils.checkForProxy(this);
          }
      }
  
      @IdRes
      private int getBookmarksFragmentViewId() {
          return mSwapBookmarksAndTabs ? R.id.left_drawer : R.id.right_drawer;
      }
  
      private int getTabsFragmentViewId() {
          if (mShowTabsInDrawer) {
              return mSwapBookmarksAndTabs ? R.id.right_drawer : R.id.left_drawer;
          } else {
              return R.id.tabs_toolbar_container;
          }
      }
  
      /**
       * Determines if an intent is originating
       * from a panic trigger.
       *
       * @param intent the intent to check.
       * @return true if the panic trigger sent
       * the intent, false otherwise.
       */
      protected static boolean isPanicTrigger(@Nullable Intent intent) {
          return intent != null && INTENT_PANIC_TRIGGER.equals(intent.getAction());
      }
  
      protected void panicClean() {
          Log.d(TAG, "Closing browser");
          mTabsManager.newTab(this, "", false);
          mTabsManager.switchToTab(0);
          mTabsManager.clearSavedState();
          HistoryPage.deleteHistoryPage(getApplication()).subscribe();
          closeBrowser();
          // System exit needed in the case of receiving
          // the panic intent since finish() isn't completely
          // closing the browser
          System.exit(1);
      }
  
      private class SearchListenerClass implements OnKeyListener, OnEditorActionListener,
          OnFocusChangeListener, OnTouchListener, SearchView.PreFocusListener {
  
          @Override
          public boolean onKey(View searchView, int keyCode, KeyEvent keyEvent) {
  
              switch (keyCode) {
                  case KeyEvent.KEYCODE_ENTER:
                      InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                      imm.hideSoftInputFromWindow(mSearch.getWindowToken(), 0);
                      searchTheWeb(mSearch.getText().toString());
                      final LightningView currentView = mTabsManager.getCurrentTab();
                      if (currentView != null) {
                          currentView.requestFocus();
                      }
                      return true;
                  default:
                      break;
              }
              return false;
          }
  
          @Override
          public boolean onEditorAction(TextView arg0, int actionId, KeyEvent arg2) {
              // hide the keyboard and search the web when the enter key
              // button is pressed
              if (actionId == EditorInfo.IME_ACTION_GO || actionId == EditorInfo.IME_ACTION_DONE
                  || actionId == EditorInfo.IME_ACTION_NEXT
                  || actionId == EditorInfo.IME_ACTION_SEND
                  || actionId == EditorInfo.IME_ACTION_SEARCH
                  || (arg2.getAction() == KeyEvent.KEYCODE_ENTER)) {
                  InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                  imm.hideSoftInputFromWindow(mSearch.getWindowToken(), 0);
                  searchTheWeb(mSearch.getText().toString());
                  final LightningView currentView = mTabsManager.getCurrentTab();
                  if (currentView != null) {
                      currentView.requestFocus();
                  }
                  return true;
              }
              return false;
          }
  
          @Override
          public void onFocusChange(final View v, final boolean hasFocus) {
              final LightningView currentView = mTabsManager.getCurrentTab();
              if (!hasFocus && currentView != null) {
                  setIsLoading(currentView.getProgress() < 100);
                  updateUrl(currentView.getUrl(), false);
              } else if (hasFocus && currentView != null) {
  
                  // Hack to make sure the text gets selected
                  ((SearchView) v).selectAll();
                  mIcon = mClearIcon;
                  mSearch.setCompoundDrawables(null, null, mClearIcon, null);
              }
  
              if (!hasFocus) {
                  InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                  imm.hideSoftInputFromWindow(mSearch.getWindowToken(), 0);
              }
          }
  
          @Override
          public boolean onTouch(View v, MotionEvent event) {
              if (mSearch.getCompoundDrawables()[2] != null) {
                  boolean tappedX = event.getX() > (mSearch.getWidth()
                      - mSearch.getPaddingRight() - mIcon.getIntrinsicWidth());
                  if (tappedX) {
                      if (event.getAction() == MotionEvent.ACTION_UP) {
                          if (mSearch.hasFocus()) {
                              mSearch.setText("");
                          } else {
                              refreshOrStop();
                          }
                      }
                      return true;
                  }
              }
              return false;
          }
  
          @Override
          public void onPreFocus() {
              final LightningView currentView = mTabsManager.getCurrentTab();
              if (currentView == null) {
                  return;
              }
              String url = currentView.getUrl();
              if (!UrlUtils.isSpecialUrl(url)) {
                  if (!mSearch.hasFocus()) {
                      mSearch.setText(url);
                  }
              }
          }
      }
  
      private class DrawerLocker implements DrawerListener {
  
          @Override
          public void onDrawerClosed(View v) {
              View tabsDrawer = getTabDrawer();
              View bookmarksDrawer = getBookmarkDrawer();
  
              if (v == tabsDrawer) {
                  mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, bookmarksDrawer);
              } else if (mShowTabsInDrawer) {
                  mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, tabsDrawer);
              }
          }
  
          @Override
          public void onDrawerOpened(View v) {
              View tabsDrawer = getTabDrawer();
              View bookmarksDrawer = getBookmarkDrawer();
  
              if (v == tabsDrawer) {
                  mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, bookmarksDrawer);
              } else {
                  mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, tabsDrawer);
              }
          }
  
          @Override
          public void onDrawerSlide(View v, float arg) {}
  
          @Override
          public void onDrawerStateChanged(int arg) {}
  
      }
  
      private void setNavigationDrawerWidth() {
          int width = getResources().getDisplayMetrics().widthPixels - Utils.dpToPx(56);
          int maxWidth;
          if (isTablet()) {
              maxWidth = Utils.dpToPx(320);
          } else {
              maxWidth = Utils.dpToPx(300);
          }
          if (width > maxWidth) {
              DrawerLayout.LayoutParams params = (android.support.v4.widget.DrawerLayout.LayoutParams) mDrawerLeft
                  .getLayoutParams();
              params.width = maxWidth;
              mDrawerLeft.setLayoutParams(params);
              mDrawerLeft.requestLayout();
              DrawerLayout.LayoutParams paramsRight = (android.support.v4.widget.DrawerLayout.LayoutParams) mDrawerRight
                  .getLayoutParams();
              paramsRight.width = maxWidth;
              mDrawerRight.setLayoutParams(paramsRight);
              mDrawerRight.requestLayout();
          } else {
              DrawerLayout.LayoutParams params = (android.support.v4.widget.DrawerLayout.LayoutParams) mDrawerLeft
                  .getLayoutParams();
              params.width = width;
              mDrawerLeft.setLayoutParams(params);
              mDrawerLeft.requestLayout();
              DrawerLayout.LayoutParams paramsRight = (android.support.v4.widget.DrawerLayout.LayoutParams) mDrawerRight
                  .getLayoutParams();
              paramsRight.width = width;
              mDrawerRight.setLayoutParams(paramsRight);
              mDrawerRight.requestLayout();
          }
      }
  
      private void initializePreferences() {
          final LightningView currentView = mTabsManager.getCurrentTab();
          mFullScreen = mPreferences.getFullScreenEnabled();
          boolean colorMode = mPreferences.getColorModeEnabled();
          colorMode &= !mDarkTheme;
          if (!isIncognito() && !colorMode && !mDarkTheme && mWebpageBitmap != null) {
              changeToolbarBackground(mWebpageBitmap, null);
          } else if (!isIncognito() && currentView != null && !mDarkTheme) {
              changeToolbarBackground(currentView.getFavicon(), null);
          } else if (!isIncognito() && !mDarkTheme && mWebpageBitmap != null) {
              changeToolbarBackground(mWebpageBitmap, null);
          }
  
          FragmentManager manager = getSupportFragmentManager();
          Fragment tabsFragment = manager.findFragmentByTag(TAG_TABS_FRAGMENT);
          if (tabsFragment instanceof TabsFragment) {
              ((TabsFragment) tabsFragment).reinitializePreferences();
          }
          Fragment bookmarksFragment = manager.findFragmentByTag(TAG_BOOKMARK_FRAGMENT);
          if (bookmarksFragment instanceof BookmarksFragment) {
              ((BookmarksFragment) bookmarksFragment).reinitializePreferences();
          }
  
          // TODO layout transition causing memory leak
  //        mBrowserFrame.setLayoutTransition(new LayoutTransition());
  
          setFullscreen(mPreferences.getHideStatusBarEnabled(), false);
  
          BaseSearchEngine currentSearchEngine = mSearchEngineProvider.getCurrentSearchEngine();
          mSearchText = currentSearchEngine.getQueryUrl();
  
          updateCookiePreference().subscribeOn(Schedulers.worker()).subscribe();
          mProxyUtils.updateProxySettings(this);
      }
  
      @Override
      public void onWindowVisibleToUserAfterResume() {
          super.onWindowVisibleToUserAfterResume();
          mToolbarLayout.setTranslationY(0);
          setWebViewTranslation(mToolbarLayout.getHeight());
      }
  
      @Override
      public boolean onKeyDown(int keyCode, KeyEvent event) {
          if (keyCode == KeyEvent.KEYCODE_ENTER) {
              if (mSearch.hasFocus()) {
                  searchTheWeb(mSearch.getText().toString());
              }
          } else if ((keyCode == KeyEvent.KEYCODE_MENU)
              && (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN)
              && (Build.MANUFACTURER.compareTo("LGE") == 0)) {
              // Workaround for stupid LG devices that crash
              return true;
          } else if (keyCode == KeyEvent.KEYCODE_BACK) {
              mKeyDownStartTime = System.currentTimeMillis();
              Handlers.MAIN.postDelayed(mLongPressBackRunnable, ViewConfiguration.getLongPressTimeout());
          }
          return super.onKeyDown(keyCode, event);
      }
  
      private final Runnable mLongPressBackRunnable = new Runnable() {
          @Override
          public void run() {
              final LightningView currentTab = mTabsManager.getCurrentTab();
              showCloseDialog(mTabsManager.positionOf(currentTab));
          }
      };
  
      @Override
      public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
          if ((keyCode == KeyEvent.KEYCODE_MENU)
              && (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN)
              && (Build.MANUFACTURER.compareTo("LGE") == 0)) {
              // Workaround for stupid LG devices that crash
              openOptionsMenu();
              return true;
          } else if (keyCode == KeyEvent.KEYCODE_BACK) {
              Handlers.MAIN.removeCallbacks(mLongPressBackRunnable);
              if ((System.currentTimeMillis() - mKeyDownStartTime) > ViewConfiguration.getLongPressTimeout()) {
                  return true;
              }
          }
          return super.onKeyUp(keyCode, event);
      }
  
      @Override
      public boolean dispatchKeyEvent(KeyEvent event) {
          // Keyboard shortcuts
          if (event.getAction() == KeyEvent.ACTION_DOWN) {
              if (event.isCtrlPressed()) {
                  switch (event.getKeyCode()) {
                      case KeyEvent.KEYCODE_F:
                          // Search in page
                          findInPage();
                          return true;
                      case KeyEvent.KEYCODE_T:
                          // Open new tab
                          newTab(null, true);
                          return true;
                      case KeyEvent.KEYCODE_W:
                          // Close current tab
                          mPresenter.deleteTab(mTabsManager.indexOfCurrentTab());
                          return true;
                      case KeyEvent.KEYCODE_Q:
                          // Close browser
                          closeBrowser();
                          return true;
                      case KeyEvent.KEYCODE_R:
                          // Refresh current tab
                          LightningView currentTab = mTabsManager.getCurrentTab();
                          if (currentTab != null) {
                              currentTab.reload();
                          }
                          return true;
                      case KeyEvent.KEYCODE_TAB:
                          int nextIndex;
                          if (event.isShiftPressed()) {
                              // Go back one tab
                              if (mTabsManager.indexOfCurrentTab() > 0) {
                                  nextIndex = mTabsManager.indexOfCurrentTab() - 1;
                              } else {
                                  nextIndex = mTabsManager.last();
                              }
                          } else {
                              // Go forward one tab
                              if (mTabsManager.indexOfCurrentTab() < mTabsManager.last()) {
                                  nextIndex = mTabsManager.indexOfCurrentTab() + 1;
                              } else {
                                  nextIndex = 0;
                              }
                          }
                          mPresenter.tabChanged(nextIndex);
                          return true;
                  }
              } else if (event.getKeyCode() == KeyEvent.KEYCODE_SEARCH) {
                  // Highlight search field
                  mSearch.requestFocus();
                  mSearch.selectAll();
                  return true;
              } else if (event.isAltPressed()) {
                  // Alt + tab number
                  if (KeyEvent.KEYCODE_0 <= event.getKeyCode() && event.getKeyCode() <= KeyEvent.KEYCODE_9) {
                      int nextIndex;
                      if (event.getKeyCode() > mTabsManager.last() + KeyEvent.KEYCODE_1 || event.getKeyCode() == KeyEvent.KEYCODE_0) {
                          nextIndex = mTabsManager.last();
                      } else {
                          nextIndex = event.getKeyCode() - KeyEvent.KEYCODE_1;
                      }
                      mPresenter.tabChanged(nextIndex);
                      return true;
                  }
              }
          }
          return super.dispatchKeyEvent(event);
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          final LightningView currentView = mTabsManager.getCurrentTab();
          final String currentUrl = currentView != null ? currentView.getUrl() : null;
          // Handle action buttons
          switch (item.getItemId()) {
              case android.R.id.home:
                  if (mDrawerLayout.isDrawerOpen(getBookmarkDrawer())) {
                      mDrawerLayout.closeDrawer(getBookmarkDrawer());
                  }
                  return true;
              case R.id.action_back:
                  if (currentView != null && currentView.canGoBack()) {
                      currentView.goBack();
                  }
                  return true;
              case R.id.action_forward:
                  if (currentView != null && currentView.canGoForward()) {
                      currentView.goForward();
                  }
                  return true;
              case R.id.action_add_to_homescreen:
                  if (currentView != null) {
                      HistoryItem shortcut = new HistoryItem(currentView.getUrl(), currentView.getTitle());
                      shortcut.setBitmap(currentView.getFavicon());
                      Utils.createShortcut(this, shortcut);
                  }
                  return true;
              case R.id.action_new_tab:
                  newTab(null, true);
                  return true;
              case R.id.action_incognito:
                  startActivity(new Intent(this, IncognitoActivity.class));
                  overridePendingTransition(R.anim.slide_up_in, R.anim.fade_out_scale);
                  return true;
              case R.id.action_share:
                  new IntentUtils(this).shareUrl(currentUrl, currentView != null ? currentView.getTitle() : null);
                  return true;
              case R.id.action_bookmarks:
                  openBookmarks();
                  return true;
              case R.id.action_copy:
                  if (currentUrl != null && !UrlUtils.isSpecialUrl(currentUrl)) {
                      ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
                      ClipData clip = ClipData.newPlainText("label", currentUrl);
                      clipboard.setPrimaryClip(clip);
                      Utils.showSnackbar(this, R.string.message_link_copied);
                  }
                  return true;
              case R.id.action_settings:
                  startActivity(new Intent(this, SettingsActivity.class));
                  return true;
              case R.id.action_history:
                  openHistory();
                  return true;
              case R.id.action_downloads:
                  openDownloads();
                  return true;
              case R.id.action_add_bookmark:
                  if (currentUrl != null && !UrlUtils.isSpecialUrl(currentUrl)) {
                      addBookmark(currentView.getTitle(), currentUrl);
                  }
                  return true;
              case R.id.action_find:
                  findInPage();
                  return true;
              case R.id.action_reading_mode:
                  if (currentUrl != null) {
                      Intent read = new Intent(this, ReadingActivity.class);
                      read.putExtra(Constants.LOAD_READING_URL, currentUrl);
                      startActivity(read);
                  }
                  return true;
              default:
                  return super.onOptionsItemSelected(item);
          }
      }
  
      // By using a manager, adds a bookmark and notifies third parties about that
      private void addBookmark(final String title, final String url) {
  
          final HistoryItem item = new HistoryItem(url, title);
          mBookmarkManager.addBookmarkIfNotExists(item)
              .subscribeOn(Schedulers.io())
              .observeOn(Schedulers.main())
              .subscribe(new SingleOnSubscribe<Boolean>() {
                  @Override
                  public void onItem(@Nullable Boolean item) {
                      if (Boolean.TRUE.equals(item)) {
                          mSuggestionsAdapter.refreshBookmarks();
                          mBookmarksView.handleUpdatedUrl(url);
                      }
                  }
              });
      }
  
      private void deleteBookmark(final String title, final String url) {
  