/**
   * If this looks like a POST request (form submission) containing a username and password, give
   * the user the option of saving them. Will either do nothing, or block until the UI interaction
   * is complete.
   *
   * <p>Called directly by WebKit.
   *
   * @param postData The data about to be sent as the body of a POST request.
   * @param username The username entered by the user (sniffed from the DOM).
   * @param password The password entered by the user (sniffed from the DOM).
   */
  private void maybeSavePassword(byte[] postData, String username, String password) {
    if (postData == null
        || username == null
        || username.isEmpty()
        || password == null
        || password.isEmpty()) {
      return; // No password to save.
    }

    if (!mSettings.getSavePassword()) {
      return; // User doesn't want to save passwords.
    }

    try {
      if (DebugFlags.BROWSER_FRAME) {
        Assert.assertNotNull(mCallbackProxy.getBackForwardList().getCurrentItem());
      }
      WebAddress uri =
          new WebAddress(mCallbackProxy.getBackForwardList().getCurrentItem().getUrl());
      String schemePlusHost = uri.getScheme() + uri.getHost();
      // 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(username))
          && postString.contains(URLEncoder.encode(password))) {
        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, username, password);
          }
        } else {
          // CallbackProxy will handle creating the resume
          // message
          mCallbackProxy.onSavePassword(schemePlusHost, username, password, null);
        }
      }
    } catch (ParseException ex) {
      // if it is bad uri, don't save its password
    }
  }
 @SuppressWarnings("unused")
 private void saveFormData(HashMap<String, String> data) {
   if (mSettings.getSaveFormData()) {
     final WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
     if (h != null) {
       String url = WebTextView.urlForAutoCompleteData(h.getUrl());
       if (url != null) {
         mDatabase.setFormData(url, data);
       }
     }
   }
 }
  /**
   * Create a new BrowserFrame to be used in an application.
   *
   * @param context An application context to use when retrieving assets.
   * @param w A WebViewCore used as the view for this frame.
   * @param proxy A CallbackProxy for posting messages to the UI thread and querying a client for
   *     information.
   * @param settings A WebSettings object that holds all settings. XXX: Called by WebCore thread.
   */
  public BrowserFrame(
      Context context,
      WebViewCore w,
      CallbackProxy proxy,
      WebSettingsClassic settings,
      Map<String, Object> javascriptInterfaces) {

    Context appContext = context.getApplicationContext();

    // Create a global JWebCoreJavaBridge to handle timers and
    // cookies in the WebCore thread.
    if (sJavaBridge == null) {
      sJavaBridge = new JWebCoreJavaBridge();
      // set WebCore native cache size
      ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
      if (am.getMemoryClass() > 16) {
        sJavaBridge.setCacheSize(8 * 1024 * 1024);
      } else {
        sJavaBridge.setCacheSize(4 * 1024 * 1024);
      }
      // initialize CacheManager
      CacheManager.init(appContext);
      // create CookieSyncManager with current Context
      CookieSyncManager.createInstance(appContext);
      // create PluginManager with current Context
      PluginManager.getInstance(appContext);
    }

    if (sConfigCallback == null) {
      sConfigCallback =
          new ConfigCallback((WindowManager) appContext.getSystemService(Context.WINDOW_SERVICE));
      ViewRootImpl.addConfigCallback(sConfigCallback);
    }
    sConfigCallback.addHandler(this);

    mJavaScriptObjects = new HashMap<String, JSObject>();
    addJavaScriptObjects(javascriptInterfaces);
    mRemovedJavaScriptObjects = new HashSet<Object>();

    mSettings = settings;
    mContext = context;
    mCallbackProxy = proxy;
    mDatabase = WebViewDatabaseClassic.getInstance(appContext);
    mWebViewCore = w;

    AssetManager am = context.getAssets();
    nativeCreateFrame(w, am, proxy.getBackForwardList());

    if (DebugFlags.BROWSER_FRAME) {
      Log.v(LOGTAG, "BrowserFrame constructor: this=" + this);
    }
  }
  /**
   * Handle messages posted to us.
   *
   * @param msg The message to handle.
   */
  @Override
  public void handleMessage(Message msg) {
    if (mBlockMessages) {
      return;
    }
    switch (msg.what) {
      case FRAME_COMPLETED:
        {
          if (mSettings.getSavePassword() && hasPasswordField()) {
            WebHistoryItem item = mCallbackProxy.getBackForwardList().getCurrentItem();
            if (item != null) {
              WebAddress uri = new WebAddress(item.getUrl());
              String schemePlusHost = uri.getScheme() + uri.getHost();
              String[] up = mDatabase.getUsernamePassword(schemePlusHost);
              if (up != null && up[0] != null) {
                setUsernamePassword(up[0], up[1]);
              }
            }
          }
          break;
        }

      case POLICY_FUNCTION:
        {
          nativeCallPolicyFunction(msg.arg1, msg.arg2);
          break;
        }

      case ORIENTATION_CHANGED:
        {
          if (mOrientation != msg.arg1) {
            mOrientation = msg.arg1;
            nativeOrientationChanged(msg.arg1);
          }
          break;
        }

      default:
        break;
    }
  }