/*
  * This function is used by handleUrlInterecpt and handleCache to
  * setup a load from the byte stream in a CacheResult.
  */
 private void startCacheLoad(CacheResult result) {
   if (WebView.LOGV_ENABLED) {
     Log.v(LOGTAG, "FrameLoader: loading from cache: " + mListener.url());
   }
   // Tell the Listener respond with the cache file
   CacheLoader cacheLoader = new CacheLoader(mListener, result);
   mListener.setCacheLoader(cacheLoader);
   cacheLoader.load();
 }
  /*
   * This function is used by handleHTTPLoad to allow URL
   * interception. This can be used to provide alternative load
   * methods such as locally stored versions or for debugging.
   *
   * Returns true if the response was handled by UrlIntercept.
   */
  private boolean handleUrlIntercept() {
    // Check if the URL can be served from UrlIntercept. If
    // successful, return the data just like a cache hit.

    PluginData data = UrlInterceptRegistry.getPluginData(mListener.url(), mHeaders);

    if (data != null) {
      PluginContentLoader loader = new PluginContentLoader(mListener, data);
      loader.load();
      return true;
    }
    // Not intercepted. Carry on as normal.
    return false;
  }
  /**
   * Issues the load request.
   *
   * <p>Return value does not indicate if the load was successful or not. It simply indicates that
   * the load request is reasonable.
   *
   * @return true if the load is reasonable.
   */
  public boolean executeLoad() {
    String url = mListener.url();

    // Attempt to decode the percent-encoded url.
    try {
      url = new String(URLUtil.decode(url.getBytes()));
    } catch (IllegalArgumentException e) {
      // Fail with a bad url error if the decode fails.
      mListener.error(
          EventHandler.ERROR_BAD_URL,
          mListener.getContext().getString(com.android.internal.R.string.httpErrorBadUrl));
      return false;
    }

    if (URLUtil.isNetworkUrl(url)) {
      if (mSettings.getBlockNetworkLoads()) {
        mListener.error(
            EventHandler.ERROR_BAD_URL,
            mListener.getContext().getString(com.android.internal.R.string.httpErrorBadUrl));
        return false;
      }
      mNetwork = Network.getInstance(mListener.getContext());
      return handleHTTPLoad();
    } else if (handleLocalFile(url, mListener, mSettings)) {
      return true;
    }
    if (WebView.LOGV_ENABLED) {
      Log.v(LOGTAG, "FrameLoader.executeLoad: url protocol not supported:" + mListener.url());
    }
    mListener.error(
        EventHandler.ERROR_UNSUPPORTED_SCHEME,
        mListener
            .getContext()
            .getText(com.android.internal.R.string.httpErrorUnsupportedScheme)
            .toString());
    return false;
  }
  private boolean handleHTTPLoad() {
    if (mHeaders == null) {
      mHeaders = new HashMap<String, String>();
    }
    populateStaticHeaders();
    populateHeaders();

    // response was handled by UrlIntercept, don't issue HTTP request
    if (handleUrlIntercept()) return true;

    // response was handled by Cache, don't issue HTTP request
    if (handleCache()) {
      // push the request data down to the LoadListener
      // as response from the cache could be a redirect
      // and we may need to initiate a network request if the cache
      // can't satisfy redirect URL
      mListener.setRequestData(mMethod, mHeaders, mPostData, mIsHighPriority);
      return true;
    }

    if (WebView.LOGV_ENABLED) {
      Log.v(LOGTAG, "FrameLoader: http " + mMethod + " load for: " + mListener.url());
    }

    boolean ret = false;
    int error = EventHandler.ERROR_UNSUPPORTED_SCHEME;

    try {
      ret = mNetwork.requestURL(mMethod, mHeaders, mPostData, mListener, mIsHighPriority);
    } catch (android.net.ParseException ex) {
      error = EventHandler.ERROR_BAD_URL;
    } catch (java.lang.RuntimeException ex) {
      /* probably an empty header set by javascript.  We want
      the same result as bad URL  */
      error = EventHandler.ERROR_BAD_URL;
    }
    if (!ret) {
      mListener.error(
          error,
          mListener
              .getContext()
              .getText(EventHandler.errorStringResources[Math.abs(error)])
              .toString());
      return false;
    }
    return true;
  }
 /* package */
 static boolean handleLocalFile(String url, LoadListener loadListener, WebSettings settings) {
   if (URLUtil.isAssetUrl(url)) {
     FileLoader.requestUrl(
         url, loadListener, loadListener.getContext(), true, settings.getAllowFileAccess());
     return true;
   } else if (URLUtil.isFileUrl(url)) {
     FileLoader.requestUrl(
         url, loadListener, loadListener.getContext(), false, settings.getAllowFileAccess());
     return true;
   } else if (URLUtil.isContentUrl(url)) {
     // Send the raw url to the ContentLoader because it will do a
     // permission check and the url has to match..
     ContentLoader.requestUrl(loadListener.url(), loadListener, loadListener.getContext());
     return true;
   } else if (URLUtil.isDataUrl(url)) {
     DataLoader.requestUrl(url, loadListener);
     return true;
   } else if (URLUtil.isAboutUrl(url)) {
     loadListener.data(mAboutBlank.getBytes(), mAboutBlank.length());
     loadListener.endData();
     return true;
   }
   return false;
 }
  /*
   * This function is used by the handleHTTPLoad to setup the cache headers
   * correctly.
   * Returns true if the response was handled from the cache
   */
  private boolean handleCache() {
    switch (mCacheMode) {
        // This mode is normally used for a reload, it instructs the http
        // loader to not use the cached content.
      case WebSettings.LOAD_NO_CACHE:
        break;

        // This mode is used when the content should only be loaded from
        // the cache. If it is not there, then fail the load. This is used
        // to load POST content in a history navigation.
      case WebSettings.LOAD_CACHE_ONLY:
        {
          CacheResult result = CacheManager.getCacheFile(mListener.url(), null);
          if (result != null) {
            startCacheLoad(result);
          } else {
            // This happens if WebCore was first told that the POST
            // response was in the cache, then when we try to use it
            // it has gone.
            // Generate a file not found error
            int err = EventHandler.FILE_NOT_FOUND_ERROR;
            mListener.error(
                err,
                mListener
                    .getContext()
                    .getText(EventHandler.errorStringResources[Math.abs(err)])
                    .toString());
          }
          return true;
        }

        // This mode is for when the user is doing a history navigation
        // in the browser and should returned cached content regardless
        // of it's state. If it is not in the cache, then go to the
        // network.
      case WebSettings.LOAD_CACHE_ELSE_NETWORK:
        {
          if (WebView.LOGV_ENABLED) {
            Log.v(LOGTAG, "FrameLoader: checking cache: " + mListener.url());
          }
          // Get the cache file name for the current URL, passing null for
          // the validation headers causes no validation to occur
          CacheResult result = CacheManager.getCacheFile(mListener.url(), null);
          if (result != null) {
            startCacheLoad(result);
            return true;
          }
          break;
        }

        // This is the default case, which is to check to see if the
        // content in the cache can be used. If it can be used, then
        // use it. If it needs revalidation then the relevant headers
        // are added to the request.
      default:
      case WebSettings.LOAD_NORMAL:
        return mListener.checkCache(mHeaders);
    } // end of switch

    return false;
  }