/** * 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 by startLoadingResource when using the Apache HTTP stack. Called directly by WebKit * when using the Chrome HTTP stack. * * @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 } }
/** * 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; }