// Called by jni from the chrome network stack. private WebResourceResponse shouldInterceptRequest(String url) { InputStream androidResource = inputStreamForAndroidResource(url); if (androidResource != null) { return new WebResourceResponse(null, null, androidResource); } // Note that we check this after looking for an android_asset or // android_res URL, as we allow those even if file access is disabled. if (!mSettings.getAllowFileAccess() && url.startsWith("file://")) { return new WebResourceResponse(null, null, null); } WebResourceResponse response = mCallbackProxy.shouldInterceptRequest(url); if (response == null && "browser:incognito".equals(url)) { try { Resources res = mContext.getResources(); InputStream ins = res.openRawResource(com.android.internal.R.raw.incognito_mode_start_page); response = new WebResourceResponse("text/html", "utf8", ins); } catch (NotFoundException ex) { // This shouldn't happen, but try and gracefully handle it jic Log.w(LOGTAG, "Failed opening raw.incognito_mode_start_page", ex); } } return response; }
@SuppressWarnings("unused") private boolean shouldSaveFormData() { if (mSettings.getSaveFormData()) { final WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem(); return h != null && h.getUrl() != null; } return false; }
public void show() { if (!getControls().isVisible() && !mZoomManager.isZoomScaleFixed()) { mZoomButtonsController.setVisible(true); if (mZoomManager.isDoubleTapEnabled()) { WebSettingsClassic settings = mWebView.getSettings(); int count = settings.getDoubleTapToastCount(); if (mZoomManager.isInZoomOverview() && count > 0) { settings.setDoubleTapToastCount(--count); Toast.makeText( mWebView.getContext(), com.android.internal.R.string.double_tap_toast, Toast.LENGTH_LONG) .show(); } } } }
@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); } } } }
/** * 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 } }
/** * 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; } }
/** Returns the User Agent used by this frame */ String getUserAgentString() { return mSettings.getUserAgentString(); }
/** * Get the InputStream for an Android resource There are three different kinds of android * resources: - file:///android_res - file:///android_asset - content:// * * @param url The url to load. * @return An InputStream to the android resource */ private InputStream inputStreamForAndroidResource(String url) { final String ANDROID_ASSET = URLUtil.ASSET_BASE; final String ANDROID_RESOURCE = URLUtil.RESOURCE_BASE; final String ANDROID_CONTENT = URLUtil.CONTENT_BASE; if (url.startsWith(ANDROID_RESOURCE)) { url = url.replaceFirst(ANDROID_RESOURCE, ""); if (url == null || url.length() == 0) { Log.e(LOGTAG, "url has length 0 " + url); return null; } int slash = url.indexOf('/'); int dot = url.indexOf('.', slash); if (slash == -1 || dot == -1) { Log.e(LOGTAG, "Incorrect res path: " + url); return null; } String subClassName = url.substring(0, slash); String fieldName = url.substring(slash + 1, dot); String errorMsg = null; try { final Class<?> d = mContext .getApplicationContext() .getClassLoader() .loadClass(mContext.getPackageName() + ".R$" + subClassName); final java.lang.reflect.Field field = d.getField(fieldName); final int id = field.getInt(null); TypedValue value = new TypedValue(); mContext.getResources().getValue(id, value, true); if (value.type == TypedValue.TYPE_STRING) { return mContext .getAssets() .openNonAsset( value.assetCookie, value.string.toString(), AssetManager.ACCESS_STREAMING); } else { // Old stack only supports TYPE_STRING for res files Log.e(LOGTAG, "not of type string: " + url); return null; } } catch (Exception e) { Log.e(LOGTAG, "Exception: " + url); return null; } } else if (url.startsWith(ANDROID_ASSET)) { url = url.replaceFirst(ANDROID_ASSET, ""); try { AssetManager assets = mContext.getAssets(); Uri uri = Uri.parse(url); return assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING); } catch (IOException e) { return null; } } else if (mSettings.getAllowContentAccess() && url.startsWith(ANDROID_CONTENT)) { try { // Strip off MIME type. If we don't do this, we can fail to // load Gmail attachments, because the URL being loaded doesn't // exactly match the URL we have permission to read. int mimeIndex = url.lastIndexOf('?'); if (mimeIndex != -1) { url = url.substring(0, mimeIndex); } Uri uri = Uri.parse(url); return mContext.getContentResolver().openInputStream(uri); } catch (Exception e) { Log.e(LOGTAG, "Exception: " + url); return null; } } else { return null; } }