Index: libadblockplus-android-webview/src/org/adblockplus/libadblockplus/android/webview/AdblockWebView.java
diff --git a/libadblockplus-android-webview/src/org/adblockplus/libadblockplus/android/webview/AdblockWebView.java b/libadblockplus-android-webview/src/org/adblockplus/libadblockplus/android/webview/AdblockWebView.java
deleted file mode 100644
index 73d88b377fa1b9f16ce3ed49441b1fc46231fe94..0000000000000000000000000000000000000000
--- a/libadblockplus-android-webview/src/org/adblockplus/libadblockplus/android/webview/AdblockWebView.java
+++ /dev/null
@@ -1,1441 +0,0 @@
-/*
- * This file is part of Adblock Plus <https://adblockplus.org/>,
- * Copyright (C) 2006-present eyeo GmbH
- *
- * Adblock Plus is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * Adblock Plus is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.adblockplus.libadblockplus.android.webview;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.net.http.SslError;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.View;
-import android.webkit.ConsoleMessage;
-import android.webkit.GeolocationPermissions;
-import android.webkit.HttpAuthHandler;
-import android.webkit.JavascriptInterface;
-import android.webkit.JsPromptResult;
-import android.webkit.JsResult;
-import android.webkit.SslErrorHandler;
-import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebResourceRequest;  // makes android min version to be 21
-import android.webkit.WebResourceResponse;
-import android.webkit.WebStorage;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import org.adblockplus.libadblockplus.FilterEngine;
-import org.adblockplus.libadblockplus.Subscription;
-import org.adblockplus.libadblockplus.android.AdblockEngine;
-import org.adblockplus.libadblockplus.android.AdblockEngineProvider;
-import org.adblockplus.libadblockplus.android.SingleInstanceEngineProvider;
-import org.adblockplus.libadblockplus.android.Utils;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Pattern;
-
-/**
- * WebView with ad blocking
- */
-public class AdblockWebView extends WebView
-{
-  private static final String TAG = Utils.getTag(AdblockWebView.class);
-
-  /**
-   * Default (in some conditions) start redraw delay after DOM modified with injected JS (millis)
-   */
-  public static final int ALLOW_DRAW_DELAY = 200;
-  /*
-     The value could be different for devices and completely unclear why we need it and
-     how to measure actual value
-  */
-
-  protected static final String HEADER_REFERRER = "Referer";
-  protected static final String HEADER_REQUESTED_WITH = "X-Requested-With";
-  protected static final String HEADER_REQUESTED_WITH_XMLHTTPREQUEST = "XMLHttpRequest";
-
-  private static final String BRIDGE_TOKEN = "{{BRIDGE}}";
-  private static final String DEBUG_TOKEN = "{{DEBUG}}";
-  private static final String HIDE_TOKEN = "{{HIDE}}";
-  private static final String BRIDGE = "jsBridge";
-  private static final String[] EMPTY_ARRAY = {};
-  private static final String EMPTY_ELEMHIDE_ARRAY_STRING = "[]";
-
-  private static final Pattern RE_JS = Pattern.compile("\\.js$", Pattern.CASE_INSENSITIVE);
-  private static final Pattern RE_CSS = Pattern.compile("\\.css$", Pattern.CASE_INSENSITIVE);
-  private static final Pattern RE_IMAGE = Pattern.compile("\\.(?:gif|png|jpe?g|bmp|ico)$", Pattern.CASE_INSENSITIVE);
-  private static final Pattern RE_FONT = Pattern.compile("\\.(?:ttf|woff)$", Pattern.CASE_INSENSITIVE);
-  private static final Pattern RE_HTML = Pattern.compile("\\.html?$", Pattern.CASE_INSENSITIVE);
-
-  private volatile boolean addDomListener = true;
-  private boolean adblockEnabled = true;
-  private boolean debugMode;
-  private AdblockEngineProvider provider;
-  private Integer loadError;
-  private int allowDrawDelay = ALLOW_DRAW_DELAY;
-  private WebChromeClient extWebChromeClient;
-  private WebViewClient extWebViewClient;
-  private WebViewClient intWebViewClient;
-  private Map<String, String> url2Referrer = Collections.synchronizedMap(new HashMap<String, String>());
-  private String url;
-  private String injectJs;
-  private CountDownLatch elemHideLatch;
-  private String elemHideSelectorsString;
-  private Object elemHideThreadLockObject = new Object();
-  private ElemHideThread elemHideThread;
-  private boolean loading;
-  private volatile boolean elementsHidden = false;
-  private final Handler handler = new Handler();
-
-  // used to prevent user see flickering for elements to hide
-  // for some reason it's rendered even if element is hidden on 'dom ready' event
-  private volatile boolean allowDraw = true;
-
-  public AdblockWebView(Context context)
-  {
-    super(context);
-    initAbp();
-  }
-
-  public AdblockWebView(Context context, AttributeSet attrs)
-  {
-    super(context, attrs);
-    initAbp();
-  }
-
-  public AdblockWebView(Context context, AttributeSet attrs, int defStyle)
-  {
-    super(context, attrs, defStyle);
-    initAbp();
-  }
-
-  /**
-   * Warning: do not rename (used in injected JS by method name)
-   * @param value set if one need to set DOM listener
-   */
-  @JavascriptInterface
-  public void setAddDomListener(boolean value)
-  {
-    d("addDomListener=" + value);
-    this.addDomListener = value;
-  }
-
-  @JavascriptInterface
-  public boolean getAddDomListener()
-  {
-    return addDomListener;
-  }
-
-  public boolean isAdblockEnabled()
-  {
-    return adblockEnabled;
-  }
-
-  private void applyAdblockEnabled()
-  {
-    super.setWebViewClient(adblockEnabled ? intWebViewClient : extWebViewClient);
-    super.setWebChromeClient(adblockEnabled ? intWebChromeClient : extWebChromeClient);
-  }
-
-  public void setAdblockEnabled(boolean adblockEnabled)
-  {
-    this.adblockEnabled = adblockEnabled;
-    applyAdblockEnabled();
-  }
-
-  @Override
-  public void setWebChromeClient(WebChromeClient client)
-  {
-    extWebChromeClient = client;
-    applyAdblockEnabled();
-  }
-
-  public boolean isDebugMode()
-  {
-    return debugMode;
-  }
-
-  /**
-   * Set to true to see debug log output int AdblockWebView and JS console
-   * Should be set before first URL loading if using internal AdblockEngineProvider
-   * @param debugMode is debug mode
-   */
-  public void setDebugMode(boolean debugMode)
-  {
-    this.debugMode = debugMode;
-  }
-
-  private void d(String message)
-  {
-    if (debugMode)
-    {
-      Log.d(TAG, message);
-    }
-  }
-
-  private void w(String message)
-  {
-    if (debugMode)
-    {
-      Log.w(TAG, message);
-    }
-  }
-
-  private void e(String message, Throwable t)
-  {
-    Log.e(TAG, message, t);
-  }
-
-  private void e(String message)
-  {
-    Log.e(TAG, message);
-  }
-
-  private String readScriptFile(String filename) throws IOException
-  {
-    return Utils
-      .readAssetAsString(getContext(), filename)
-      .replace(BRIDGE_TOKEN, BRIDGE)
-      .replace(DEBUG_TOKEN, (debugMode ? "" : "//"));
-  }
-
-  private void runScript(String script)
-  {
-    d("runScript started");
-    evaluateJavascript(script, null);
-    d("runScript finished");
-  }
-
-  public void setProvider(final AdblockEngineProvider provider)
-  {
-    if (this.provider != null && provider != null && this.provider == provider)
-    {
-      return;
-    }
-
-    final Runnable setRunnable = new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        AdblockWebView.this.provider = provider;
-        if (AdblockWebView.this.provider != null)
-        {
-          AdblockWebView.this.provider.retain(true); // asynchronously
-        }
-      }
-    };
-
-    if (this.provider != null)
-    {
-      // as adblockEngine can be busy with elemhide thread we need to use callback
-      this.dispose(setRunnable);
-    }
-    else
-    {
-      setRunnable.run();
-    }
-  }
-
-  private WebChromeClient intWebChromeClient = new WebChromeClient()
-  {
-    @Override
-    public void onReceivedTitle(WebView view, String title)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onReceivedTitle(view, title);
-      }
-    }
-
-    @Override
-    public void onReceivedIcon(WebView view, Bitmap icon)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onReceivedIcon(view, icon);
-      }
-    }
-
-    @Override
-    public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onReceivedTouchIconUrl(view, url, precomposed);
-      }
-    }
-
-    @Override
-    public void onShowCustomView(View view, CustomViewCallback callback)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onShowCustomView(view, callback);
-      }
-    }
-
-    @Override
-    public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onShowCustomView(view, requestedOrientation, callback);
-      }
-    }
-
-    @Override
-    public void onHideCustomView()
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onHideCustomView();
-      }
-    }
-
-    @Override
-    public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture,
-                                  Message resultMsg)
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
-      }
-      else
-      {
-        return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
-      }
-    }
-
-    @Override
-    public void onRequestFocus(WebView view)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onRequestFocus(view);
-      }
-    }
-
-    @Override
-    public void onCloseWindow(WebView window)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onCloseWindow(window);
-      }
-    }
-
-    @Override
-    public boolean onJsAlert(WebView view, String url, String message, JsResult result)
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.onJsAlert(view, url, message, result);
-      }
-      else
-      {
-        return super.onJsAlert(view, url, message, result);
-      }
-    }
-
-    @Override
-    public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.onJsConfirm(view, url, message, result);
-      }
-      else
-      {
-        return super.onJsConfirm(view, url, message, result);
-      }
-    }
-
-    @Override
-    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
-                              JsPromptResult result)
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.onJsPrompt(view, url, message, defaultValue, result);
-      }
-      else
-      {
-        return super.onJsPrompt(view, url, message, defaultValue, result);
-      }
-    }
-
-    @Override
-    public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result)
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.onJsBeforeUnload(view, url, message, result);
-      }
-      else
-      {
-        return super.onJsBeforeUnload(view, url, message, result);
-      }
-    }
-
-    @Override
-    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long quota,
-                                        long estimatedDatabaseSize, long totalQuota,
-                                        WebStorage.QuotaUpdater quotaUpdater)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onExceededDatabaseQuota(url, databaseIdentifier, quota,
-          estimatedDatabaseSize, totalQuota, quotaUpdater);
-      }
-      else
-      {
-        super.onExceededDatabaseQuota(url, databaseIdentifier, quota,
-          estimatedDatabaseSize, totalQuota, quotaUpdater);
-      }
-    }
-
-    @Override
-    public void onReachedMaxAppCacheSize(long requiredStorage, long quota,
-                                         WebStorage.QuotaUpdater quotaUpdater)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onReachedMaxAppCacheSize(requiredStorage, quota, quotaUpdater);
-      }
-      else
-      {
-        super.onReachedMaxAppCacheSize(requiredStorage, quota, quotaUpdater);
-      }
-    }
-
-    @Override
-    public void onGeolocationPermissionsShowPrompt(String origin,
-                                                   GeolocationPermissions.Callback callback)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onGeolocationPermissionsShowPrompt(origin, callback);
-      }
-      else
-      {
-        super.onGeolocationPermissionsShowPrompt(origin, callback);
-      }
-    }
-
-    @Override
-    public void onGeolocationPermissionsHidePrompt()
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onGeolocationPermissionsHidePrompt();
-      }
-      else
-      {
-        super.onGeolocationPermissionsHidePrompt();
-      }
-    }
-
-    @Override
-    public boolean onJsTimeout()
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.onJsTimeout();
-      }
-      else
-      {
-        return super.onJsTimeout();
-      }
-    }
-
-    @Override
-    public void onConsoleMessage(String message, int lineNumber, String sourceID)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onConsoleMessage(message, lineNumber, sourceID);
-      }
-      else
-      {
-        super.onConsoleMessage(message, lineNumber, sourceID);
-      }
-    }
-
-    @Override
-    public boolean onConsoleMessage(ConsoleMessage consoleMessage)
-    {
-      d("JS: level=" + consoleMessage.messageLevel()
-        + ", message=\"" + consoleMessage.message() + "\""
-        + ", sourceId=\"" + consoleMessage.sourceId() + "\""
-        + ", line=" + consoleMessage.lineNumber());
-
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.onConsoleMessage(consoleMessage);
-      }
-      else
-      {
-        return super.onConsoleMessage(consoleMessage);
-      }
-    }
-
-    @Override
-    public Bitmap getDefaultVideoPoster()
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.getDefaultVideoPoster();
-      }
-      else
-      {
-        return super.getDefaultVideoPoster();
-      }
-    }
-
-    @Override
-    public View getVideoLoadingProgressView()
-    {
-      if (extWebChromeClient != null)
-      {
-        return extWebChromeClient.getVideoLoadingProgressView();
-      }
-      else
-      {
-        return super.getVideoLoadingProgressView();
-      }
-    }
-
-    @Override
-    public void getVisitedHistory(ValueCallback<String[]> callback)
-    {
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.getVisitedHistory(callback);
-      }
-      else
-      {
-        super.getVisitedHistory(callback);
-      }
-    }
-
-    @Override
-    public void onProgressChanged(WebView view, int newProgress)
-    {
-      d("Loading progress=" + newProgress + "%");
-
-      // addDomListener is changed to 'false' in `setAddDomListener` invoked from injected JS
-      if (getAddDomListener() && loadError == null && injectJs != null)
-      {
-        d("Injecting script");
-        runScript(injectJs);
-
-        if (allowDraw && loading)
-        {
-          startPreventDrawing();
-        }
-      }
-
-      // workaround for the issue: https://issues.adblockplus.org/ticket/5303
-      if (newProgress == 100 && !allowDraw)
-      {
-        w("Workaround for the issue #5303");
-        stopPreventDrawing();
-      }
-
-      if (extWebChromeClient != null)
-      {
-        extWebChromeClient.onProgressChanged(view, newProgress);
-      }
-    }
-  };
-
-  public int getAllowDrawDelay()
-  {
-    return allowDrawDelay;
-  }
-
-  /**
-   * Set start redraw delay after DOM modified with injected JS
-   * (used to prevent flickering after 'DOM ready')
-   * @param allowDrawDelay delay (in millis)
-   */
-  public void setAllowDrawDelay(int allowDrawDelay)
-  {
-    if (allowDrawDelay < 0)
-    {
-      throw new IllegalArgumentException("Negative value is not allowed");
-    }
-
-    this.allowDrawDelay = allowDrawDelay;
-  }
-
-  @Override
-  public void setWebViewClient(WebViewClient client)
-  {
-    extWebViewClient = client;
-    applyAdblockEnabled();
-  }
-
-  private void clearReferrers()
-  {
-    d("Clearing referrers");
-    url2Referrer.clear();
-  }
-
-  /**
-   * WebViewClient for API 21 and newer
-   * (has Referrer since it overrides `shouldInterceptRequest(..., request)` with referrer)
-   */
-  private class AdblockWebViewClient extends WebViewClient
-  {
-    @Override
-    public boolean shouldOverrideUrlLoading(WebView view, String url)
-    {
-      if (extWebViewClient != null)
-      {
-        return extWebViewClient.shouldOverrideUrlLoading(view, url);
-      }
-      else
-      {
-        return super.shouldOverrideUrlLoading(view, url);
-      }
-    }
-
-    @Override
-    public void onPageStarted(WebView view, String url, Bitmap favicon)
-    {
-      if (loading)
-      {
-        stopAbpLoading();
-      }
-
-      startAbpLoading(url);
-
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onPageStarted(view, url, favicon);
-      }
-      else
-      {
-        super.onPageStarted(view, url, favicon);
-      }
-    }
-
-    @Override
-    public void onPageFinished(WebView view, String url)
-    {
-      loading = false;
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onPageFinished(view, url);
-      }
-      else
-      {
-        super.onPageFinished(view, url);
-      }
-    }
-
-    @Override
-    public void onLoadResource(WebView view, String url)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onLoadResource(view, url);
-      }
-      else
-      {
-        super.onLoadResource(view, url);
-      }
-    }
-
-    @Override
-    public void onTooManyRedirects(WebView view, Message cancelMsg, Message continueMsg)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onTooManyRedirects(view, cancelMsg, continueMsg);
-      }
-      else
-      {
-        super.onTooManyRedirects(view, cancelMsg, continueMsg);
-      }
-    }
-
-    @Override
-    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
-    {
-      e("Load error:" +
-        " code=" + errorCode +
-        " with description=" + description +
-        " for url=" + failingUrl);
-      loadError = errorCode;
-
-      stopAbpLoading();
-
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onReceivedError(view, errorCode, description, failingUrl);
-      }
-      else
-      {
-        super.onReceivedError(view, errorCode, description, failingUrl);
-      }
-    }
-
-    @Override
-    public void onFormResubmission(WebView view, Message dontResend, Message resend)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onFormResubmission(view, dontResend, resend);
-      }
-      else
-      {
-        super.onFormResubmission(view, dontResend, resend);
-      }
-    }
-
-    @Override
-    public void doUpdateVisitedHistory(WebView view, String url, boolean isReload)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.doUpdateVisitedHistory(view, url, isReload);
-      }
-      else
-      {
-        super.doUpdateVisitedHistory(view, url, isReload);
-      }
-    }
-
-    @Override
-    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onReceivedSslError(view, handler, error);
-      }
-      else
-      {
-        super.onReceivedSslError(view, handler, error);
-      }
-    }
-
-    @Override
-    public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onReceivedHttpAuthRequest(view, handler, host, realm);
-      }
-      else
-      {
-        super.onReceivedHttpAuthRequest(view, handler, host, realm);
-      }
-    }
-
-    @Override
-    public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)
-    {
-      if (extWebViewClient != null)
-      {
-        return extWebViewClient.shouldOverrideKeyEvent(view, event);
-      }
-      else
-      {
-        return super.shouldOverrideKeyEvent(view, event);
-      }
-    }
-
-    @Override
-    public void onUnhandledKeyEvent(WebView view, KeyEvent event)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onUnhandledKeyEvent(view, event);
-      }
-      else
-      {
-        super.onUnhandledKeyEvent(view, event);
-      }
-    }
-
-    @Override
-    public void onScaleChanged(WebView view, float oldScale, float newScale)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onScaleChanged(view, oldScale, newScale);
-      }
-      else
-      {
-        super.onScaleChanged(view, oldScale, newScale);
-      }
-    }
-
-    @Override
-    public void onReceivedLoginRequest(WebView view, String realm, String account, String args)
-    {
-      if (extWebViewClient != null)
-      {
-        extWebViewClient.onReceivedLoginRequest(view, realm, account, args);
-      }
-      else
-      {
-        super.onReceivedLoginRequest(view, realm, account, args);
-      }
-    }
-
-    protected WebResourceResponse shouldInterceptRequest(
-      WebView webview, String url, boolean isMainFrame,
-      boolean isXmlHttpRequest, String[] referrerChainArray)
-    {
-      // if dispose() was invoke, but the page is still loading then just let it go
-      if (provider.getCounter() == 0)
-      {
-        e("FilterEngine already disposed, allow loading");
-
-        // allow loading by returning null
-        return null;
-      }
-      else
-      {
-        provider.waitForReady();
-      }
-
-      if (isMainFrame)
-      {
-        // never blocking main frame requests, just subrequests
-        w(url + " is main frame, allow loading");
-
-        // allow loading by returning null
-        return null;
-      }
-
-      // whitelisted
-      if (provider.getEngine().isDomainWhitelisted(url, referrerChainArray))
-      {
-        w(url + " domain is whitelisted, allow loading");
-
-        // allow loading by returning null
-        return null;
-      }
-
-      if (provider.getEngine().isDocumentWhitelisted(url, referrerChainArray))
-      {
-        w(url + " document is whitelisted, allow loading");
-
-        // allow loading by returning null
-        return null;
-      }
-
-      // determine the content
-      FilterEngine.ContentType contentType;
-      if (isXmlHttpRequest)
-      {
-        contentType = FilterEngine.ContentType.XMLHTTPREQUEST;
-      }
-      else
-      {
-        if (RE_JS.matcher(url).find())
-        {
-          contentType = FilterEngine.ContentType.SCRIPT;
-        }
-        else if (RE_CSS.matcher(url).find())
-        {
-          contentType = FilterEngine.ContentType.STYLESHEET;
-        }
-        else if (RE_IMAGE.matcher(url).find())
-        {
-          contentType = FilterEngine.ContentType.IMAGE;
-        }
-        else if (RE_FONT.matcher(url).find())
-        {
-          contentType = FilterEngine.ContentType.FONT;
-        }
-        else if (RE_HTML.matcher(url).find())
-        {
-          contentType = FilterEngine.ContentType.SUBDOCUMENT;
-        }
-        else
-        {
-          contentType = FilterEngine.ContentType.OTHER;
-        }
-      }
-
-      // check if we should block
-      if (provider.getEngine().matches(url, contentType, referrerChainArray))
-      {
-        w("Blocked loading " + url);
-
-        // if we should block, return empty response which results in 'errorLoading' callback
-        return new WebResourceResponse("text/plain", "UTF-8", null);
-      }
-
-      d("Allowed loading " + url);
-
-      // continue by returning null
-      return null;
-    }
-
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    @Override
-    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
-    {
-      // here we just trying to fill url -> referrer map
-      // blocking/allowing loading will happen in `shouldInterceptRequest(WebView,String)`
-      String url = request.getUrl().toString();
-
-      boolean isXmlHttpRequest =
-        request.getRequestHeaders().containsKey(HEADER_REQUESTED_WITH) &&
-          HEADER_REQUESTED_WITH_XMLHTTPREQUEST.equals(
-            request.getRequestHeaders().get(HEADER_REQUESTED_WITH));
-
-      String referrer = request.getRequestHeaders().get(HEADER_REFERRER);
-      String[] referrers;
-
-      if (referrer != null)
-      {
-        d("Header referrer for " + url + " is " + referrer);
-        url2Referrer.put(url, referrer);
-
-        referrers = new String[]
-          {
-            referrer
-          };
-      }
-      else
-      {
-        w("No referrer header for " + url);
-        referrers = EMPTY_ARRAY;
-      }
-
-      return shouldInterceptRequest(view, url, request.isForMainFrame(), isXmlHttpRequest, referrers);
-    }
-  }
-
-  private void initAbp()
-  {
-    addJavascriptInterface(this, BRIDGE);
-    initClients();
-  }
-
-  private void initClients()
-  {
-    intWebViewClient = new AdblockWebViewClient();
-    applyAdblockEnabled();
-  }
-
-  private class ElemHideThread extends Thread
-  {
-    private String selectorsString;
-    private CountDownLatch finishedLatch;
-    private AtomicBoolean isFinished;
-    private AtomicBoolean isCancelled;
-
-    public ElemHideThread(CountDownLatch finishedLatch)
-    {
-      this.finishedLatch = finishedLatch;
-      isFinished = new AtomicBoolean(false);
-      isCancelled = new AtomicBoolean(false);
-    }
-
-    @Override
-    public void run()
-    {
-      try
-      {
-        if (provider.getCounter() == 0)
-        {
-          w("FilterEngine already disposed");
-          selectorsString = EMPTY_ELEMHIDE_ARRAY_STRING;
-        }
-        else
-        {
-          provider.waitForReady();
-          String[] referrers = new String[]
-            {
-              url
-            };
-
-          List<Subscription> subscriptions = provider
-            .getEngine()
-            .getFilterEngine()
-            .getListedSubscriptions();
-
-          try
-          {
-            d("Listed subscriptions: " + subscriptions.size());
-            if (debugMode)
-            {
-              for (Subscription eachSubscription : subscriptions)
-              {
-                d("Subscribed to "
-                  + (eachSubscription.isDisabled() ? "disabled" : "enabled")
-                  + " " + eachSubscription);
-              }
-            }
-          }
-          finally
-          {
-            for (Subscription eachSubscription : subscriptions)
-            {
-              eachSubscription.dispose();
-            }
-          }
-
-          final String domain = provider.getEngine().getFilterEngine().getHostFromURL(url);
-          if (domain == null)
-          {
-            e("Failed to extract domain from " + url);
-            selectorsString = EMPTY_ELEMHIDE_ARRAY_STRING;
-          }
-          else
-          {
-            d("Requesting elemhide selectors from AdblockEngine for " + url + " in " + this);
-            List<String> selectors = provider
-              .getEngine()
-              .getElementHidingSelectors(url, domain, referrers);
-
-            d("Finished requesting elemhide selectors, got " + selectors.size() + " in " + this);
-            selectorsString = Utils.stringListToJsonArray(selectors);
-          }
-        }
-      }
-      finally
-      {
-        if (isCancelled.get())
-        {
-          w("This thread is cancelled, exiting silently " + this);
-        }
-        else
-        {
-          finish(selectorsString);
-        }
-      }
-    }
-
-    private void onFinished()
-    {
-      finishedLatch.countDown();
-      synchronized (finishedRunnableLockObject)
-      {
-        if (finishedRunnable != null)
-        {
-          finishedRunnable.run();
-        }
-      }
-    }
-
-    private void finish(String result)
-    {
-      isFinished.set(true);
-      d("Setting elemhide string " + result.length() + " bytes");
-      elemHideSelectorsString = result;
-      onFinished();
-    }
-
-    private final Object finishedRunnableLockObject = new Object();
-    private Runnable finishedRunnable;
-
-    public void setFinishedRunnable(Runnable runnable)
-    {
-      synchronized (finishedRunnableLockObject)
-      {
-        this.finishedRunnable = runnable;
-      }
-    }
-
-    public void cancel()
-    {
-      w("Cancelling elemhide thread " + this);
-      if (isFinished.get())
-      {
-        w("This thread is finished, exiting silently " + this);
-      }
-      else
-      {
-        isCancelled.set(true);
-        finish(EMPTY_ELEMHIDE_ARRAY_STRING);
-      }
-    }
-  }
-
-  private Runnable elemHideThreadFinishedRunnable = new Runnable()
-  {
-    @Override
-    public void run()
-    {
-      synchronized (elemHideThreadLockObject)
-      {
-        w("elemHideThread set to null");
-        elemHideThread = null;
-      }
-    }
-  };
-
-  private void initAbpLoading()
-  {
-    getSettings().setJavaScriptEnabled(true);
-    buildInjectJs();
-    ensureProvider();
-  }
-
-  private void ensureProvider()
-  {
-    // if AdblockWebView works as drop-in replacement for WebView 'provider' is not set.
-    // Thus AdblockWebView is using SingleInstanceEngineProvider instance
-    if (provider == null)
-    {
-      setProvider(new SingleInstanceEngineProvider(
-        getContext(), AdblockEngine.BASE_PATH_DIRECTORY, debugMode));
-    }
-  }
-
-  private void startAbpLoading(String newUrl)
-  {
-    d("Start loading " + newUrl);
-
-    loading = true;
-    addDomListener = true;
-    elementsHidden = false;
-    loadError = null;
-    url = newUrl;
-
-    if (url != null)
-    {
-      elemHideLatch = new CountDownLatch(1);
-      elemHideThread = new ElemHideThread(elemHideLatch);
-      elemHideThread.setFinishedRunnable(elemHideThreadFinishedRunnable);
-      elemHideThread.start();
-    }
-    else
-    {
-      elemHideLatch = null;
-    }
-  }
-
-  private void buildInjectJs()
-  {
-    try
-    {
-      if (injectJs == null)
-      {
-        injectJs = readScriptFile("inject.js").replace(HIDE_TOKEN, readScriptFile("css.js"));
-      }
-    }
-    catch (IOException e)
-    {
-      e("Failed to read script", e);
-    }
-  }
-
-  @Override
-  public void goBack()
-  {
-    if (loading)
-    {
-      stopAbpLoading();
-    }
-
-    super.goBack();
-  }
-
-  @Override
-  public void goForward()
-  {
-    if (loading)
-    {
-      stopAbpLoading();
-    }
-
-    super.goForward();
-  }
-
-  @Override
-  public void reload()
-  {
-    initAbpLoading();
-
-    if (loading)
-    {
-      stopAbpLoading();
-    }
-
-    super.reload();
-  }
-
-  @Override
-  public void loadUrl(String url)
-  {
-    initAbpLoading();
-
-    if (loading)
-    {
-      stopAbpLoading();
-    }
-
-    super.loadUrl(url);
-  }
-
-  @Override
-  public void loadUrl(String url, Map<String, String> additionalHttpHeaders)
-  {
-    initAbpLoading();
-
-    if (loading)
-    {
-      stopAbpLoading();
-    }
-
-    super.loadUrl(url, additionalHttpHeaders);
-  }
-
-  @Override
-  public void loadData(String data, String mimeType, String encoding)
-  {
-    initAbpLoading();
-
-    if (loading)
-    {
-      stopAbpLoading();
-    }
-
-    super.loadData(data, mimeType, encoding);
-  }
-
-  @Override
-  public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding,
-                                  String historyUrl)
-  {
-    initAbpLoading();
-
-    if (loading)
-    {
-      stopAbpLoading();
-    }
-
-    super.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
-  }
-
-  @Override
-  public void stopLoading()
-  {
-    stopAbpLoading();
-    super.stopLoading();
-  }
-
-  private void stopAbpLoading()
-  {
-    d("Stop abp loading");
-
-    loading = false;
-    stopPreventDrawing();
-    clearReferrers();
-
-    synchronized (elemHideThreadLockObject)
-    {
-      if (elemHideThread != null)
-      {
-        elemHideThread.cancel();
-      }
-    }
-  }
-
-  // warning: do not rename (used in injected JS by method name)
-  @JavascriptInterface
-  public void setElementsHidden(boolean value)
-  {
-    // invoked with 'true' by JS callback when DOM is loaded
-    elementsHidden = value;
-
-    // fired on worker thread, but needs to be invoked on main thread
-    if (value)
-    {
-//     handler.post(allowDrawRunnable);
-//     should work, but it's not working:
-//     the user can see element visible even though it was hidden on dom event
-
-      if (allowDrawDelay > 0)
-      {
-        d("Scheduled 'allow drawing' invocation in " + allowDrawDelay + " ms");
-      }
-      handler.postDelayed(allowDrawRunnable, allowDrawDelay);
-    }
-  }
-
-  // warning: do not rename (used in injected JS by method name)
-  @JavascriptInterface
-  public boolean isElementsHidden()
-  {
-    return elementsHidden;
-  }
-
-  @Override
-  public void onPause()
-  {
-    handler.removeCallbacks(allowDrawRunnable);
-    super.onPause();
-  }
-
-  @Override
-  protected void onDraw(Canvas canvas)
-  {
-    if (allowDraw)
-    {
-      super.onDraw(canvas);
-    }
-    else
-    {
-      w("Prevent drawing");
-      drawEmptyPage(canvas);
-    }
-  }
-
-  private void drawEmptyPage(Canvas canvas)
-  {
-    // assuming default color is WHITE
-    canvas.drawColor(Color.WHITE);
-  }
-
-  protected void startPreventDrawing()
-  {
-    w("Start prevent drawing");
-
-    allowDraw = false;
-  }
-
-  protected void stopPreventDrawing()
-  {
-    d("Stop prevent drawing, invalidating");
-
-    allowDraw = true;
-    invalidate();
-  }
-
-  private Runnable allowDrawRunnable = new Runnable()
-  {
-    @Override
-    public void run()
-    {
-      stopPreventDrawing();
-    }
-  };
-
-  // warning: do not rename (used in injected JS by method name)
-  @JavascriptInterface
-  public String getElemhideSelectors()
-  {
-    if (elemHideLatch == null)
-    {
-      return EMPTY_ELEMHIDE_ARRAY_STRING;
-    }
-    else
-    {
-      try
-      {
-        // elemhide selectors list getting is started in startAbpLoad() in background thread
-        d("Waiting for elemhide selectors to be ready");
-        elemHideLatch.await();
-        d("Elemhide selectors ready, " + elemHideSelectorsString.length() + " bytes");
-
-        clearReferrers();
-
-        return elemHideSelectorsString;
-      }
-      catch (InterruptedException e)
-      {
-        w("Interrupted, returning empty selectors list");
-        return EMPTY_ELEMHIDE_ARRAY_STRING;
-      }
-    }
-  }
-
-  private void doDispose()
-  {
-    w("Disposing AdblockEngine");
-    provider.release();
-  }
-
-  private class DisposeRunnable implements Runnable
-  {
-    private Runnable disposeFinished;
-
-    private DisposeRunnable(Runnable disposeFinished)
-    {
-      this.disposeFinished = disposeFinished;
-    }
-
-    @Override
-    public void run()
-    {
-      doDispose();
-
-      if (disposeFinished != null)
-      {
-        disposeFinished.run();
-      }
-    }
-  }
-
-  /**
-   * Dispose AdblockWebView and internal adblockEngine if it was created
-   * If external AdblockEngine was passed using `setAdblockEngine()` it should be disposed explicitly
-   * Warning: runnable can be invoked from background thread
-   * @param disposeFinished runnable to run when AdblockWebView is disposed
-   */
-  public void dispose(final Runnable disposeFinished)
-  {
-    d("Dispose invoked");
-
-    if (provider == null)
-    {
-      d("No internal AdblockEngineProvider created");
-      return;
-    }
-
-    stopLoading();
-
-    DisposeRunnable disposeRunnable = new DisposeRunnable(disposeFinished);
-    synchronized (elemHideThreadLockObject)
-    {
-      if (elemHideThread != null)
-      {
-        w("Busy with elemhide selectors, delayed disposing scheduled");
-        elemHideThread.setFinishedRunnable(disposeRunnable);
-      }
-      else
-      {
-        disposeRunnable.run();
-      }
-    }
-  }
-}
