/*
   * This message handler is to facilitate communication between the network
   * thread and the browser thread.
   */
  public void handleMessage(Message msg) {
    switch (msg.what) {
      case MSG_CONTENT_HEADERS:
        /*
         * This message is sent when the LoadListener has headers
         * available. The headers are sent onto WebCore to see what we
         * should do with them.
         */
        if (mNativeLoader != 0) {
          commitHeaders();
        }
        break;

      case MSG_CONTENT_DATA:
        /*
         * This message is sent when the LoadListener has data available
         * in it's data buffer. This data buffer could be filled from a
         * file (this thread) or from http (Network thread).
         */
        if (mNativeLoader != 0) {
          commitLoad();
        }
        break;

      case MSG_CONTENT_FINISHED:
        /*
         * This message is sent when the LoadListener knows that the
         * load is finished. This message is not sent in the case of an
         * error.
         *
         */
        tearDown();
        break;

      case MSG_CONTENT_ERROR:
        /*
         * This message is sent when a load error has occured. The
         * LoadListener will clean itself up.
         */
        notifyError();
        tearDown();
        break;

      case MSG_LOCATION_CHANGED:
        /*
         * This message is sent from LoadListener.endData to inform the
         * browser activity that the location of the top level page
         * changed.
         */
        doRedirect();
        break;

      case MSG_LOCATION_CHANGED_REQUEST:
        /*
         * This message is sent from endData on receipt of a 307
         * Temporary Redirect in response to a POST -- the user must
         * confirm whether to continue loading. If the user says Yes,
         * we simply call MSG_LOCATION_CHANGED. If the user says No,
         * we call MSG_CONTENT_FINISHED.
         */
        Message contMsg = obtainMessage(MSG_LOCATION_CHANGED);
        Message stopMsg = obtainMessage(MSG_CONTENT_FINISHED);
        mBrowserFrame.getCallbackProxy().onFormResubmission(stopMsg, contMsg);
        break;
    }
  }
  /**
   * 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;
  }