Skip to content

Commit

Permalink
Implement Webviewclient.onReceivedSslError
Browse files Browse the repository at this point in the history
BUG=


Review URL: https://chromiumcodereview.appspot.com/12091111

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184643 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
sgurun@chromium.org committed Feb 26, 2013
1 parent 6ac9e31 commit 01d1fee
Show file tree
Hide file tree
Showing 19 changed files with 475 additions and 47 deletions.
2 changes: 2 additions & 0 deletions android_webview/android_webview.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@
'browser/aw_browser_context.h',
'browser/aw_browser_main_parts.cc',
'browser/aw_browser_main_parts.h',
'browser/aw_contents_client_bridge_base.cc',
'browser/aw_contents_client_bridge_base.h',
'browser/aw_content_browser_client.cc',
'browser/aw_content_browser_client.h',
'browser/aw_contents_io_thread_client.h',
Expand Down
14 changes: 11 additions & 3 deletions android_webview/browser/aw_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_browser_main_parts.h"
#include "android_webview/browser/aw_contents_client_bridge_base.h"
#include "android_webview/browser/aw_cookie_access_policy.h"
#include "android_webview/browser/aw_quota_permission_context.h"
#include "android_webview/browser/jni_dependency_factory.h"
Expand All @@ -22,6 +23,7 @@
#include "content/public/common/url_constants.h"
#include "grit/ui_resources.h"
#include "net/android/network_library.h"
#include "net/base/ssl_info.h"
#include "ui/base/resource/resource_bundle.h"

namespace {
Expand Down Expand Up @@ -273,9 +275,15 @@ void AwContentBrowserClient::AllowCertificateError(
bool strict_enforcement,
const base::Callback<void(bool)>& callback,
bool* cancel_request) {
// TODO(boliu): Implement this to power WebViewClient.onReceivedSslError.
NOTIMPLEMENTED();
*cancel_request = true;

AwContentsClientBridgeBase* client =
AwContentsClientBridgeBase::FromID(render_process_id, render_view_id);
if (client) {
client->AllowCertificateError(cert_error, ssl_info.cert, request_url,
callback, cancel_request);
} else {
*cancel_request = true;
}
}

WebKit::WebNotificationPresenter::Permission
Expand Down
72 changes: 72 additions & 0 deletions android_webview/browser/aw_contents_client_bridge_base.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/browser/aw_contents_client_bridge_base.h"

#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"

using content::BrowserThread;
using content::WebContents;

namespace android_webview {

namespace {

const void* kAwContentsClientBridgeBase = &kAwContentsClientBridgeBase;

// This class is invented so that the UserData registry that we inject the
// AwContentsClientBridgeBase object does not own and destroy it.
class UserData : public base::SupportsUserData::Data {
public:
static AwContentsClientBridgeBase* GetContents(
content::WebContents* web_contents) {
if (!web_contents)
return NULL;
UserData* data = reinterpret_cast<UserData*>(
web_contents->GetUserData(kAwContentsClientBridgeBase));
return data ? data->contents_ : NULL;
}

explicit UserData(AwContentsClientBridgeBase* ptr) : contents_(ptr) {}
private:
AwContentsClientBridgeBase* contents_;

DISALLOW_COPY_AND_ASSIGN(UserData);
};

} // namespace

// static
void AwContentsClientBridgeBase::Associate(
WebContents* web_contents,
AwContentsClientBridgeBase* handler) {
web_contents->SetUserData(kAwContentsClientBridgeBase,
new UserData(handler));
}

// static
AwContentsClientBridgeBase* AwContentsClientBridgeBase::FromWebContents(
WebContents* web_contents) {
return UserData::GetContents(web_contents);
}

// static
AwContentsClientBridgeBase* AwContentsClientBridgeBase::FromID(
int render_process_id,
int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const content::RenderViewHost* rvh =
content::RenderViewHost::FromID(render_process_id, render_view_id);
if (!rvh) return NULL;
content::WebContents* web_contents =
content::WebContents::FromRenderViewHost(rvh);
return UserData::GetContents(web_contents);
}

AwContentsClientBridgeBase::~AwContentsClientBridgeBase() {
}

} // namespace android_webview
49 changes: 49 additions & 0 deletions android_webview/browser/aw_contents_client_bridge_base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ANDROID_WEBVIEW_BROWSER_AW_CONTENTS_CLIENT_BRIDGE_BASE_H_
#define ANDROID_WEBVIEW_BROWSER_AW_CONTENTS_CLIENT_BRIDGE_BASE_H_

#include "base/callback_forward.h"
#include "base/supports_user_data.h"

class GURL;

namespace content {
class WebContents;
}

namespace net {
class X509Certificate;
}

namespace android_webview {

// browser/ layer interface for AwContensClientBridge, as DEPS prevents this
// layer from depending on native/ where the implementation lives. The
// implementor of the base class plumbs the request to the Java side and
// eventually to the webviewclient. This layering hides the details of
// native/ from browser/ layer.
class AwContentsClientBridgeBase {
public:
// Adds the handler to the UserData registry.
static void Associate(content::WebContents* web_contents,
AwContentsClientBridgeBase* handler);
static AwContentsClientBridgeBase* FromWebContents(
content::WebContents* web_contents);
static AwContentsClientBridgeBase* FromID(int render_process_id,
int render_view_id);

virtual ~AwContentsClientBridgeBase();

virtual void AllowCertificateError(int cert_error,
net::X509Certificate* cert,
const GURL& request_url,
const base::Callback<void(bool)>& callback,
bool* cancel_request) = 0;
};

} // namespace android_webview

#endif // ANDROID_WEBVIEW_BROWSER_AW_CONTENTS_CLIENT_BRIDGE_BASE_H_
2 changes: 1 addition & 1 deletion android_webview/browser/aw_http_auth_handler_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class AwHttpAuthHandlerBase {

// Provides an 'escape-hatch' out to Java for the browser/ layer
// AwLoginDelegate.
virtual void HandleOnUIThread(content::WebContents*) = 0;
virtual bool HandleOnUIThread(content::WebContents*) = 0;
};

} // namespace android_webview
Expand Down
5 changes: 4 additions & 1 deletion android_webview/browser/aw_login_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ void AwLoginDelegate::HandleHttpAuthRequestOnUIThread(

WebContents* web_contents = WebContents::FromRenderViewHost(
render_view_host);
aw_http_auth_handler_->HandleOnUIThread(web_contents);
if (!aw_http_auth_handler_->HandleOnUIThread(web_contents)) {
Cancel();
return;
}
}

void AwLoginDelegate::CancelOnIOThread() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,12 @@
import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
import org.chromium.components.navigation_interception.NavigationParams;
import org.chromium.net.GURLUtils;
import org.chromium.net.X509Util;
import org.chromium.ui.gfx.DeviceDisplayInfo;
import org.chromium.ui.gfx.NativeWindow;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
* Exposes the native AwContents class, and together these classes wrap the ContentViewCore
Expand Down Expand Up @@ -94,6 +89,7 @@ public interface InternalAccessDelegate extends ContentViewCore.InternalAccessDe
private ViewGroup mContainerView;
private ContentViewCore mContentViewCore;
private AwContentsClient mContentsClient;
private AwContentsClientBridge mContentsClientBridge;
private AwContentsIoThreadClient mIoThreadClient;
private InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
private InternalAccessDelegate mInternalAccessAdapter;
Expand Down Expand Up @@ -241,7 +237,9 @@ public AwContents(ViewGroup containerView, InternalAccessDelegate internalAccess
// setup performs process initialisation work needed by AwContents.
mContentViewCore = new ContentViewCore(containerView.getContext(),
ContentViewCore.PERSONALITY_VIEW);
mNativeAwContents = nativeInit(contentsClient.getWebContentsDelegate());
mContentsClientBridge = new AwContentsClientBridge(contentsClient);
mNativeAwContents = nativeInit(contentsClient.getWebContentsDelegate(),
mContentsClientBridge);
mContentsClient = contentsClient;
mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents));

Expand Down Expand Up @@ -608,29 +606,7 @@ public void setHttpAuthUsernamePassword(String host, String realm, String userna
*/
public SslCertificate getCertificate() {
if (mNativeAwContents == 0) return null;
byte[] derBytes = nativeGetCertificate(mNativeAwContents);
if (derBytes == null) {
return null;
}

try {
X509Certificate x509Certificate =
X509Util.createCertificateFromBytes(derBytes);
return new SslCertificate(x509Certificate);
} catch (CertificateException e) {
// Intentional fall through
// A SSL related exception must have occured. This shouldn't happen.
Log.w(TAG, "Could not read certificate: " + e);
} catch (KeyStoreException e) {
// Intentional fall through
// A SSL related exception must have occured. This shouldn't happen.
Log.w(TAG, "Could not read certificate: " + e);
} catch (NoSuchAlgorithmException e) {
// Intentional fall through
// A SSL related exception must have occured. This shouldn't happen.
Log.w(TAG, "Could not read certificate: " + e);
}
return null;
return SslUtil.getCertificateFromDerBytes(nativeGetCertificate(mNativeAwContents));
}

/**
Expand Down Expand Up @@ -1030,7 +1006,8 @@ private void handleJsPrompt(String url, String message, String defaultValue,
// Native methods
//--------------------------------------------------------------------------------------------

private native int nativeInit(AwWebContentsDelegate webViewWebContentsDelegate);
private native int nativeInit(AwWebContentsDelegate webViewWebContentsDelegate,
AwContentsClientBridge contentsClientBridge);
private static native void nativeDestroy(int nativeAwContents);
private static native void nativeSetAwDrawSWFunctionTable(int functionTablePointer);
private static native int nativeGetAwDrawGLFunction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.http.SslError;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
Expand All @@ -16,6 +17,7 @@
import android.view.View;
import android.webkit.ConsoleMessage;
import android.webkit.GeolocationPermissions;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;

Expand Down Expand Up @@ -230,6 +232,9 @@ final AwContentsClientCallbackHelper getCallbackHelper() {
public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler,
String host, String realm);

// TODO(sgurun) make this abstract once the corresponding changes for the glue layer lands.
public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) { }

public abstract void onReceivedLoginRequest(String realm, String account, String args);

public abstract void onFormResubmission(Message dontResend, Message resend);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.android_webview;

import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.webkit.ValueCallback;

import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;

/**
* This class handles the JNI communication logic for the the AwContentsClient class.
* Both the Java and the native peers of AwContentsClientBridge are owned by the
* corresponding AwContents instances. This class and its native peer are connected
* via weak references. The native AwContentsClientBridge sets up and clear these weak
* references.
*/
@JNINamespace("android_webview")
public class AwContentsClientBridge {

private AwContentsClient mClient;
// The native peer of this object.
private int mNativeContentsClientBridge;

public AwContentsClientBridge(AwContentsClient client) {
assert client != null;
mClient = client;
}

// Used by the native peer to set/reset a weak ref to the native peer.
@CalledByNative
private void setNativeContentsClientBridge(int nativeContentsClientBridge) {
mNativeContentsClientBridge = nativeContentsClientBridge;
}

// If returns false, the request is immediately canceled, and any call to proceedSslError
// has no effect. If returns true, the request should be canceled or proceeded using
// proceedSslError().
// Unlike the webview classic, we do not keep keep a database of certificates that
// are allowed by the user, because this functionality is already handled via
// ssl_policy in native layers.
@CalledByNative
private boolean allowCertificateError(int certError, byte[] derBytes, final String url,
final int id) {
final SslCertificate cert = SslUtil.getCertificateFromDerBytes(derBytes);
if (cert == null) {
// if the certificate or the client is null, cancel the request
return false;
}
final SslError sslError = SslUtil.sslErrorFromNetErrorCode(certError, cert, url);
ValueCallback<Boolean> callback = new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean value) {
proceedSslError(value.booleanValue(), id);
}
};
mClient.onReceivedSslError(callback, sslError);
return true;
}

private void proceedSslError(boolean proceed, int id) {
if (mNativeContentsClientBridge == 0) return;
nativeProceedSslError(mNativeContentsClientBridge, proceed, id);
}

//--------------------------------------------------------------------------------------------
// Native methods
//--------------------------------------------------------------------------------------------
private native void nativeProceedSslError(int nativeAwContentsClientBridge, boolean proceed,
int id);
}
Loading

0 comments on commit 01d1fee

Please sign in to comment.