/**
   * Start loading a resource.
   *
   * @param loaderHandle The native ResourceLoader that is the target of the data.
   * @param url The url to load.
   * @param method The http method.
   * @param headers The http headers.
   * @param postData If the method is "POST" postData is sent as the request body. Is null when
   *     empty.
   * @param cacheMode The cache mode to use when loading this resource.
   * @param isHighPriority True if this resource needs to be put at the front of the network queue.
   * @param synchronous True if the load is synchronous.
   * @return A newly created LoadListener object.
   */
  private LoadListener startLoadingResource(
      int loaderHandle,
      String url,
      String method,
      HashMap headers,
      byte[] postData,
      int cacheMode,
      boolean isHighPriority,
      boolean synchronous) {
    PerfChecker checker = new PerfChecker();

    if (mSettings.getCacheMode() != WebSettings.LOAD_DEFAULT) {
      cacheMode = mSettings.getCacheMode();
    }

    if (method.equals("POST")) {
      // Don't use the cache on POSTs when issuing a normal POST
      // request.
      if (cacheMode == WebSettings.LOAD_NORMAL) {
        cacheMode = WebSettings.LOAD_NO_CACHE;
      }
      if (mSettings.getSavePassword() && hasPasswordField()) {
        try {
          if (WebView.DEBUG) {
            Assert.assertNotNull(mCallbackProxy.getBackForwardList().getCurrentItem());
          }
          WebAddress uri =
              new WebAddress(mCallbackProxy.getBackForwardList().getCurrentItem().getUrl());
          String schemePlusHost = uri.mScheme + uri.mHost;
          String[] ret = getUsernamePassword();
          // Has the user entered a username/password pair and is
          // there some POST data
          if (ret != null && postData != null && ret[0].length() > 0 && ret[1].length() > 0) {
            // Check to see if the username & password appear in
            // the post data (there could be another form on the
            // page and that was posted instead.
            String postString = new String(postData);
            if (postString.contains(URLEncoder.encode(ret[0]))
                && postString.contains(URLEncoder.encode(ret[1]))) {
              String[] saved = mDatabase.getUsernamePassword(schemePlusHost);
              if (saved != null) {
                // null username implies that user has chosen not to
                // save password
                if (saved[0] != null) {
                  // non-null username implies that user has
                  // chosen to save password, so update the
                  // recorded password
                  mDatabase.setUsernamePassword(schemePlusHost, ret[0], ret[1]);
                }
              } else {
                // CallbackProxy will handle creating the resume
                // message
                mCallbackProxy.onSavePassword(schemePlusHost, ret[0], ret[1], null);
              }
            }
          }
        } catch (ParseException ex) {
          // if it is bad uri, don't save its password
        }
      }
    }

    // is this resource the main-frame top-level page?
    boolean isMainFramePage = mIsMainFrame;

    if (WebView.LOGV_ENABLED) {
      Log.v(
          LOGTAG,
          "startLoadingResource: url="
              + url
              + ", method="
              + method
              + ", postData="
              + postData
              + ", isHighPriority="
              + isHighPriority
              + ", isMainFramePage="
              + isMainFramePage);
    }

    // Create a LoadListener
    LoadListener loadListener =
        LoadListener.getLoadListener(
            mContext, this, url, loaderHandle, synchronous, isMainFramePage);

    mCallbackProxy.onLoadResource(url);

    if (LoadListener.getNativeLoaderCount() > MAX_OUTSTANDING_REQUESTS) {
      loadListener.error(
          android.net.http.EventHandler.ERROR,
          mContext.getString(com.android.internal.R.string.httpErrorTooManyRequests));
      loadListener.notifyError();
      loadListener.tearDown();
      return null;
    }

    // during synchronous load, the WebViewCore thread is blocked, so we
    // need to endCacheTransaction first so that http thread won't be
    // blocked in setupFile() when createCacheFile.
    if (synchronous) {
      CacheManager.endCacheTransaction();
    }

    FrameLoader loader = new FrameLoader(loadListener, mSettings, method, isHighPriority);
    loader.setHeaders(headers);
    loader.setPostData(postData);
    // Set the load mode to the mode used for the current page.
    // If WebKit wants validation, go to network directly.
    loader.setCacheMode(
        headers.containsKey("If-Modified-Since") || headers.containsKey("If-None-Match")
            ? WebSettings.LOAD_NO_CACHE
            : cacheMode);
    // Set referrer to current URL?
    if (!loader.executeLoad()) {
      checker.responseAlert("startLoadingResource fail");
    }
    checker.responseAlert("startLoadingResource succeed");

    if (synchronous) {
      CacheManager.startCacheTransaction();
    }

    return !synchronous ? loadListener : null;
  }
  /**
   * Start loading a resource.
   *
   * @param loaderHandle The native ResourceLoader that is the target of the data.
   * @param url The url to load.
   * @param method The http method.
   * @param headers The http headers.
   * @param postData If the method is "POST" postData is sent as the request body. Is null when
   *     empty.
   * @param postDataIdentifier If the post data contained form this is the form identifier,
   *     otherwise it is 0.
   * @param cacheMode The cache mode to use when loading this resource. See WebSettings.setCacheMode
   * @param mainResource True if the this resource is the main request, not a supporting resource
   * @param userGesture
   * @param synchronous True if the load is synchronous.
   * @return A newly created LoadListener object.
   */
  private LoadListener startLoadingResource(
      int loaderHandle,
      String url,
      String method,
      HashMap headers,
      byte[] postData,
      long postDataIdentifier,
      int cacheMode,
      boolean mainResource,
      boolean userGesture,
      boolean synchronous,
      String username,
      String password) {
    if (mSettings.getCacheMode() != WebSettings.LOAD_DEFAULT) {
      cacheMode = mSettings.getCacheMode();
    }

    if (method.equals("POST")) {
      // Don't use the cache on POSTs when issuing a normal POST
      // request.
      if (cacheMode == WebSettings.LOAD_NORMAL) {
        cacheMode = WebSettings.LOAD_NO_CACHE;
      }
      String[] ret = getUsernamePassword();
      if (ret != null) {
        String domUsername = ret[0];
        String domPassword = ret[1];
        maybeSavePassword(postData, domUsername, domPassword);
      }
    }

    // is this resource the main-frame top-level page?
    boolean isMainFramePage = mIsMainFrame;

    if (DebugFlags.BROWSER_FRAME) {
      Log.v(
          LOGTAG,
          "startLoadingResource: url="
              + url
              + ", method="
              + method
              + ", postData="
              + postData
              + ", isMainFramePage="
              + isMainFramePage
              + ", mainResource="
              + mainResource
              + ", userGesture="
              + userGesture);
    }

    // Create a LoadListener
    LoadListener loadListener =
        LoadListener.getLoadListener(
            mContext,
            this,
            url,
            loaderHandle,
            synchronous,
            isMainFramePage,
            mainResource,
            userGesture,
            postDataIdentifier,
            username,
            password);

    if (LoadListener.getNativeLoaderCount() > MAX_OUTSTANDING_REQUESTS) {
      // send an error message, so that loadListener can be deleted
      // after this is returned. This is important as LoadListener's
      // nativeError will remove the request from its DocLoader's request
      // list. But the set up is not done until this method is returned.
      loadListener.error(
          android.net.http.EventHandler.ERROR,
          mContext.getString(com.android.internal.R.string.httpErrorTooManyRequests));
      return loadListener;
    }

    // Note that we are intentionally skipping
    // inputStreamForAndroidResource.  This is so that FrameLoader will use
    // the various StreamLoader classes to handle assets.
    FrameLoader loader =
        new FrameLoader(
            loadListener, mSettings, method, mCallbackProxy.shouldInterceptRequest(url));
    loader.setHeaders(headers);
    loader.setPostData(postData);
    // Set the load mode to the mode used for the current page.
    // If WebKit wants validation, go to network directly.
    loader.setCacheMode(
        headers.containsKey("If-Modified-Since") || headers.containsKey("If-None-Match")
            ? WebSettings.LOAD_NO_CACHE
            : cacheMode);
    loader.executeLoad();
    // Set referrer to current URL?
    return !synchronous ? loadListener : null;
  }