Commit 0529e5d0 authored by Ben Murdoch's avatar Ben Murdoch
Browse files

Merge from Chromium at DEPS revision 265802

This commit was generated by merge_to_master.py.

Change-Id: I6fac2dbbce472b18ca943b6e6f247835b0bd6281
parent 8346740f

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.
......@@ -95,7 +95,6 @@ MY_CFLAGS_Debug := \
-fvisibility=hidden \
-pipe \
-fPIC \
-Wno-unknown-pragmas \
-fno-tree-sra \
-fuse-ld=gold \
-Wno-psabi \
......@@ -147,12 +146,15 @@ MY_DEFS_Debug := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -240,7 +242,6 @@ MY_CFLAGS_Release := \
-fvisibility=hidden \
-pipe \
-fPIC \
-Wno-unknown-pragmas \
-fno-tree-sra \
-fuse-ld=gold \
-Wno-psabi \
......@@ -292,12 +293,15 @@ MY_DEFS_Release := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -392,7 +396,6 @@ LOCAL_LDFLAGS_Debug := \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--icf=safe \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
......
......@@ -95,7 +95,6 @@ MY_CFLAGS_Debug := \
-fvisibility=hidden \
-pipe \
-fPIC \
-Wno-unknown-pragmas \
-EL \
-mhard-float \
-ffunction-sections \
......@@ -146,12 +145,15 @@ MY_DEFS_Debug := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -239,7 +241,6 @@ MY_CFLAGS_Release := \
-fvisibility=hidden \
-pipe \
-fPIC \
-Wno-unknown-pragmas \
-EL \
-mhard-float \
-ffunction-sections \
......@@ -290,12 +291,15 @@ MY_DEFS_Release := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -388,7 +392,6 @@ LOCAL_LDFLAGS_Debug := \
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
......
......@@ -94,7 +94,6 @@ MY_CFLAGS_Debug := \
-fvisibility=hidden \
-pipe \
-fPIC \
-Wno-unknown-pragmas \
-msse2 \
-mfpmath=sse \
-mmmx \
......@@ -148,12 +147,15 @@ MY_DEFS_Debug := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -239,7 +241,6 @@ MY_CFLAGS_Release := \
-fvisibility=hidden \
-pipe \
-fPIC \
-Wno-unknown-pragmas \
-msse2 \
-mfpmath=sse \
-mmmx \
......@@ -293,12 +294,15 @@ MY_DEFS_Release := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -390,7 +394,6 @@ LOCAL_LDFLAGS_Debug := \
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
......
......@@ -96,7 +96,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-Wno-unused-local-typedefs \
-Wno-unknown-pragmas \
-m64 \
-march=x86-64 \
-fuse-ld=gold \
......@@ -148,12 +147,15 @@ MY_DEFS_Debug := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -241,7 +243,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-Wno-unused-local-typedefs \
-Wno-unknown-pragmas \
-m64 \
-march=x86-64 \
-fuse-ld=gold \
......@@ -293,12 +294,15 @@ MY_DEFS_Release := \
'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
'-DSK_SUPPORT_LEGACY_PICTURE_CAN_RECORD' \
'-DSK_SUPPORT_DEPRECATED_RECORD_FLAGS' \
'-DSK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES' \
'-DSK_SUPPORT_LEGACY_N32_NAME' \
'-DSK_SUPPORT_LEGACY_PROCXFERMODE' \
'-DSK_SUPPORT_LEGACY_PICTURE_HEADERS' \
'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
'-DSK_BUILD_FOR_ANDROID' \
'-DSK_USE_POSIX_THREADS' \
'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DSK_IGNORE_FREETYPE_ROTATION_FIX' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
......@@ -390,7 +394,6 @@ LOCAL_LDFLAGS_Debug := \
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
-Wl,--as-needed
......
......@@ -100,6 +100,7 @@
'browser/net/android_stream_reader_url_request_job_unittest.cc',
'browser/net/input_stream_reader_unittest.cc',
'lib/main/webview_tests.cc',
'native/aw_contents_client_bridge_unittest.cc',
'native/input_stream_unittest.cc',
'native/state_serializer_unittest.cc',
],
......@@ -122,6 +123,7 @@
'type': 'none',
'sources': [
'../android_webview/unittestjava/src/org/chromium/android_webview/unittest/InputStreamUnittest.java',
'../android_webview/unittestjava/src/org/chromium/android_webview/unittest/MockAwContentsClientBridge.java',
],
'variables': {
'jni_gen_package': 'android_webview_unittests',
......@@ -138,7 +140,6 @@
],
'variables': {
'test_suite_name': 'android_webview_unittests',
'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)android_webview_unittests<(SHARED_LIB_SUFFIX)',
},
'includes': [ '../build/apk_test.gypi' ],
},
......
......@@ -359,10 +359,13 @@ void AwContentBrowserClient::SelectClientCertificate(
const net::HttpNetworkSession* network_session,
net::SSLCertRequestInfo* cert_request_info,
const base::Callback<void(net::X509Certificate*)>& callback) {
LOG(WARNING) << "Client certificate request from "
<< cert_request_info->host_and_port.ToString()
<< " rejected. (Client certificates not supported in WebView)";
callback.Run(NULL);
AwContentsClientBridgeBase* client =
AwContentsClientBridgeBase::FromID(render_process_id, render_frame_id);
if (client) {
client->SelectClientCertificate(cert_request_info, callback);
} else {
callback.Run(NULL);
}
}
blink::WebNotificationPresenter::Permission
......@@ -376,16 +379,9 @@ blink::WebNotificationPresenter::Permission
void AwContentBrowserClient::ShowDesktopNotification(
const content::ShowDesktopNotificationHostMsgParams& params,
int render_process_id,
int render_view_id,
bool worker) {
NOTREACHED() << "Android WebView does not support desktop notifications.";
}
void AwContentBrowserClient::CancelDesktopNotification(
int render_process_id,
int render_view_id,
int notification_id) {
content::RenderFrameHost* render_frame_host,
content::DesktopNotificationDelegate* delegate,
base::Closure* cancel_callback) {
NOTREACHED() << "Android WebView does not support desktop notifications.";
}
......
......@@ -118,13 +118,9 @@ class AwContentBrowserClient : public content::ContentBrowserClient {
int render_process_id) OVERRIDE;
virtual void ShowDesktopNotification(
const content::ShowDesktopNotificationHostMsgParams& params,
int render_process_id,
int render_view_id,
bool worker) OVERRIDE;
virtual void CancelDesktopNotification(
int render_process_id,
int render_view_id,
int notification_id) OVERRIDE;
content::RenderFrameHost* render_frame_host,
content::DesktopNotificationDelegate* delegate,
base::Closure* cancel_callback) OVERRIDE;
virtual bool CanCreateWindow(const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
......
......@@ -16,6 +16,7 @@ class WebContents;
}
namespace net {
class SSLCertRequestInfo;
class X509Certificate;
}
......@@ -28,6 +29,8 @@ namespace android_webview {
// native/ from browser/ layer.
class AwContentsClientBridgeBase {
public:
typedef base::Callback<void(net::X509Certificate*)> SelectCertificateCallback;
// Adds the handler to the UserData registry.
static void Associate(content::WebContents* web_contents,
AwContentsClientBridgeBase* handler);
......@@ -43,6 +46,9 @@ class AwContentsClientBridgeBase {
const GURL& request_url,
const base::Callback<void(bool)>& callback,
bool* cancel_request) = 0;
virtual void SelectClientCertificate(
net::SSLCertRequestInfo* cert_request_info,
const SelectCertificateCallback& callback) = 0;
virtual void RunJavaScriptDialog(
content::JavaScriptMessageType message_type,
......
......@@ -4,6 +4,8 @@
#include "android_webview/browser/scoped_app_gl_state_restore.h"
#include <string>
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "ui/gl/gl_context.h"
......@@ -48,7 +50,9 @@ void GLEnableDisable(GLenum cap, bool enable) {
glDisable(cap);
}
bool g_globals_initialized = false;
GLint g_gl_max_texture_units = 0;
bool g_oes_vertex_array_object = false;
} // namespace
......@@ -124,9 +128,16 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode) : mode_(mode) {
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &framebuffer_binding_ext_);
if (!g_gl_max_texture_units) {
if (!g_globals_initialized) {
g_globals_initialized = true;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &g_gl_max_texture_units);
DCHECK_GT(g_gl_max_texture_units, 0);
std::string extensions(
reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
g_oes_vertex_array_object =
extensions.find("GL_OES_vertex_array_object") != std::string::npos;
}
glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture_);
......@@ -140,6 +151,9 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode) : mode_(mode) {
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES,
&bindings.texture_external_oes);
}
if (g_oes_vertex_array_object)
glGetIntegerv(GL_VERTEX_ARRAY_BINDING_OES, &vertex_array_bindings_oes_);
}
ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
......@@ -225,6 +239,9 @@ ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
GLEnableDisable(GL_STENCIL_TEST, stencil_test_);
glStencilFunc(stencil_func_, stencil_mask_, stencil_ref_);
if (g_oes_vertex_array_object)
glBindVertexArrayOES(vertex_array_bindings_oes_);
}
} // namespace android_webview
......@@ -95,6 +95,8 @@ class ScopedAppGLStateRestore {
std::vector<TextureBindings> texture_bindings_;
GLint vertex_array_bindings_oes_;
DISALLOW_COPY_AND_ASSIGN(ScopedAppGLStateRestore);
};
......
......@@ -8,6 +8,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import org.chromium.content.browser.ContentViewStatics;
import org.chromium.net.DefaultAndroidKeyStore;
/**
* Java side of the Browser Context: contains all the java side objects needed to host one
......@@ -15,8 +16,6 @@ import org.chromium.content.browser.ContentViewStatics;
* Note that due to running in single process mode, and limitations on renderer process only
* being able to use a single browser context, currently there can only be one AwBrowserContext
* instance, so at this point the class mostly exists for conceptual clarity.
*
* Obtain the default (singleton) instance with AwBrowserProcess.getDefaultBrowserContext().
*/
public class AwBrowserContext {
......@@ -28,6 +27,8 @@ public class AwBrowserContext {
private AwCookieManager mCookieManager;
private AwFormDatabase mFormDatabase;
private HttpAuthDatabase mHttpAuthDatabase;
private DefaultAndroidKeyStore mLocalKeyStore;
private ClientCertLookupTable mClientCertLookupTable;
public AwBrowserContext(SharedPreferences sharedPreferences) {
mSharedPreferences = sharedPreferences;
......@@ -61,6 +62,20 @@ public class AwBrowserContext {
return mHttpAuthDatabase;
}
public DefaultAndroidKeyStore getKeyStore() {
if (mLocalKeyStore == null) {
mLocalKeyStore = new DefaultAndroidKeyStore();
}
return mLocalKeyStore;
}
public ClientCertLookupTable getClientCertLookupTable() {
if (mClientCertLookupTable == null) {
mClientCertLookupTable = new ClientCertLookupTable();
}
return mClientCertLookupTable;
}
/**
* @see android.webkit.WebView#pauseTimers()
*/
......
......@@ -5,18 +5,13 @@
package org.chromium.android_webview;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import org.chromium.base.PathUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.content.browser.BrowserStartupController;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Wrapper for the steps needed to initialize the java and native sides of webview chromium.
......@@ -34,58 +29,11 @@ public abstract class AwBrowserProcess {
PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
try {
LibraryLoader.loadNow();
initTraceEvent();
} catch (ProcessInitException e) {
throw new RuntimeException("Cannot load WebView", e);
}
}
// TODO(benm): Move this function into WebView code in Android tree to avoid reflection.
private static void initTraceEvent() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
try {
final Class<?> traceClass = Class.forName("android.os.Trace");
final long traceTagView = traceClass.getField("TRACE_TAG_WEBVIEW").getLong(null);
final Class<?> systemPropertiesClass = Class.forName("android.os.SystemProperties");
final Method systemPropertiesGetLongMethod = systemPropertiesClass.getDeclaredMethod(
"getLong", String.class, Long.TYPE);
final Method addChangeCallbackMethod = systemPropertiesClass.getDeclaredMethod(
"addChangeCallback", Runnable.class);
// Won't reach here if any of the above reflect lookups fail.
addChangeCallbackMethod.invoke(null, new Runnable() {
@Override
public void run() {
try {
long enabledFlags = (Long) systemPropertiesGetLongMethod.invoke(
null, "debug.atrace.tags.enableflags", 0);
TraceEvent.setATraceEnabled((enabledFlags & traceTagView) != 0);
} catch (IllegalArgumentException e) {
Log.e(TAG, "systemPropertyChanged", e);
} catch (IllegalAccessException e) {
Log.e(TAG, "systemPropertyChanged", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "systemPropertyChanged", e);
}
}
});
} catch (ClassNotFoundException e) {
Log.e(TAG, "initTraceEvent", e);
} catch (NoSuchMethodException e) {
Log.e(TAG, "initTraceEvent", e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "initTraceEvent", e);
} catch (IllegalAccessException e) {
Log.e(TAG, "initTraceEvent", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "initTraceEvent", e);
} catch (NoSuchFieldException e) {
Log.e(TAG, "initTraceEvent", e);
}
}
/**
* Starts the chromium browser process running within this process. Creates threads
* and performs other per-app resource allocations; must not be called from zygote.
......
......@@ -508,7 +508,8 @@ public class AwContents {
mLayoutSizer.setDelegate(new AwLayoutSizerDelegate());
mLayoutSizer.setDIPScale(mDIPScale);
mWebContentsDelegate = new AwWebContentsDelegateAdapter(contentsClient, mContainerView);
mContentsClientBridge = new AwContentsClientBridge(contentsClient);
mContentsClientBridge = new AwContentsClientBridge(contentsClient,
mBrowserContext.getKeyStore(), mBrowserContext.getClientCertLookupTable());
mZoomControls = new AwZoomControls(this);
mIoThreadClient = new IoThreadClientImpl();
mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl();
......@@ -1368,6 +1369,15 @@ public class AwContents {
mContentViewCore.clearSslPreferences();
}
/**
* @see android.webkit.WebView#clearClientCertPreferences()
*/
public void clearClientCertPreferences() {
mBrowserContext.getClientCertLookupTable().clear();
if (mNativeAwContents == 0) return;
nativeClearClientCertPreferences(mNativeAwContents);
}
/**
* Method to return all hit test values relevant to public WebView API.
* Note that this expose more data than needed for WebView.getHitTestResult.
......@@ -2140,4 +2150,5 @@ public class AwContents {
private native void nativeCreatePdfExporter(long nativeAwContents, AwPdfExporter awPdfExporter);
private native void nativeClearClientCertPreferences(long nativeAwContents);
}
......@@ -21,6 +21,8 @@ import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.WebContentsObserverAndroid;
import org.chromium.net.NetError;
import java.security.Principal;
/**
* Base-class that an AwContents embedder derives from to receive callbacks.
* This extends ContentViewClient, as in many cases we want to pass-thru ContentViewCore
......@@ -165,6 +167,12 @@ public abstract class AwContentsClient {
public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error);
// TODO(sgurun): Make abstract once this has rolled in downstream.
public void onReceivedClientCertRequest(
final AwContentsClientBridge.ClientCertificateRequestCallback callback,
final String[] keyTypes, final Principal[] principals, final String host,
final int port) { }
public abstract void onReceivedLoginRequest(String realm, String account, String args);
public abstract void onFormResubmission(Message dontResend, Message resend);
......
......@@ -6,10 +6,21 @@ package org.chromium.android_webview;
import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.util.Log;
import android.webkit.ValueCallback;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;
import org.chromium.net.AndroidPrivateKey;
import org.chromium.net.DefaultAndroidKeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
/**
* This class handles the JNI communication logic for the the AwContentsClient class.
......@@ -20,14 +31,125 @@ import org.chromium.base.JNINamespace;
*/
@JNINamespace("android_webview")
public class AwContentsClientBridge {
static final String TAG = "AwContentsClientBridge";
private AwContentsClient mClient;
// The native peer of this object.
private long mNativeContentsClientBridge;
public AwContentsClientBridge(AwContentsClient client) {
private DefaultAndroidKeyStore mLocalKeyStore;
private ClientCertLookupTable mLookupTable;
// Used for mocking this class in tests.
protected AwContentsClientBridge(DefaultAndroidKeyStore keyStore,
ClientCertLookupTable table) {
mLocalKeyStore = keyStore;
mLookupTable = table;
}
public AwContentsClientBridge(AwContentsClient client, DefaultAndroidKeyStore keyStore,
ClientCertLookupTable table) {
assert client != null;
mClient = client;
mLocalKeyStore = keyStore;
mLookupTable = table;
}
/**
* Callback to communicate clientcertificaterequest back to the AwContentsClientBridge.
* The public methods should be called on UI thread.
* A request can not be proceeded, ignored or canceled more than once. Doing this
* is a programming error and causes an exception.
*/
public class ClientCertificateRequestCallback {
private int mId;
private String mHost;
private int mPort;
private boolean mIsCalled;
public ClientCertificateRequestCallback(int id, String host, int port) {
mId = id;
mHost = host;
mPort = port;
}
public void proceed(final PrivateKey privateKey, final X509Certificate[] chain) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
proceedOnUiThread(privateKey, chain);
}
});
}
public void ignore() {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
ignoreOnUiThread();
}
});
}
public void cancel() {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
cancelOnUiThread();
}
});
}
private void proceedOnUiThread(PrivateKey privateKey, X509Certificate[] chain) {
checkIfCalled();
AndroidPrivateKey key = mLocalKeyStore.createKey(privateKey);
if (key == null || chain == null || chain.length == 0) {
Log.w(TAG, "Empty client certificate chain?");
provideResponse(null, null);
return;
}
// Encode the certificate chain.
byte[][] encodedChain = new byte[chain.length][];
try {
for (int i = 0; i < chain.length; ++i) {
encodedChain[i] = chain[i].getEncoded();
}
} catch (CertificateEncodingException e) {
Log.w(TAG, "Could not retrieve encoded certificate chain: " + e);
provideResponse(null, null);
return;
}
mLookupTable.allow(mHost, mPort, key, encodedChain);
provideResponse(key, encodedChain);
}
private void ignoreOnUiThread() {
checkIfCalled();
provideResponse(null, null);
}
private void cancelOnUiThread() {
checkIfCalled();
mLookupTable.deny(mHost, mPort);
provideResponse(null, null);
}
private void checkIfCalled() {
if (mIsCalled) {
throw new IllegalStateException("The callback was already called.");
}
mIsCalled = true;
}
private void provideResponse(AndroidPrivateKey androidKey, byte[][] certChain) {
nativeProvideClientCertificateResponse(mNativeContentsClientBridge, mId,
certChain, androidKey);
}
}
// Used by the native peer to set/reset a weak ref to the native peer.
......@@ -53,8 +175,13 @@ public class AwContentsClientBridge {
final SslError sslError = SslUtil.sslErrorFromNetErrorCode(certError, cert, url);
ValueCallback<Boolean> callback = new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean value) {
proceedSslError(value.booleanValue(), id);
public void onReceiveValue(final Boolean value) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
proceedSslError(value.booleanValue(), id);
}
});
}
};
mClient.onReceivedSslError(callback, sslError);
......@@ -66,6 +193,43 @@ public class AwContentsClientBridge {
nativeProceedSslError(mNativeContentsClientBridge, proceed, id);
}
// Intentionally not private for testing the native peer of this class.
@CalledByNative
protected void selectClientCertificate(final int id, final String[] keyTypes,
byte[][] encodedPrincipals, final String host, final int port) {
ClientCertLookupTable.Cert cert = mLookupTable.getCertData(host, port);
if (mLookupTable.isDenied(host, port)) {
nativeProvideClientCertificateResponse(mNativeContentsClientBridge, id,
null, null);
return;
}
if (cert != null) {
nativeProvideClientCertificateResponse(mNativeContentsClientBridge, id,
cert.certChain, cert.privateKey);
return;
}
// Build the list of principals from encoded versions.
Principal[] principals = null;
if (encodedPrincipals.length > 0) {
principals = new X500Principal[encodedPrincipals.length];
for (int n = 0; n < encodedPrincipals.length; n++) {
try {
principals[n] = new X500Principal(encodedPrincipals[n]);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Exception while decoding issuers list: " + e);
nativeProvideClientCertificateResponse(mNativeContentsClientBridge, id,
null, null);
return;
}
}
}
final ClientCertificateRequestCallback callback =
new ClientCertificateRequestCallback(id, host, port);
mClient.onReceivedClientCertRequest(callback, keyTypes, principals, host, port);
}
@CalledByNative
private void handleJsAlert(String url, String message, int id) {
JsResultHandler handler = new JsResultHandler(this, id);
......@@ -110,6 +274,8 @@ public class AwContentsClientBridge {
//--------------------------------------------------------------------------------------------
private native void nativeProceedSslError(long nativeAwContentsClientBridge, boolean proceed,
int id);
private native void nativeProvideClientCertificateResponse(long nativeAwContentsClientBridge,
int id, byte[][] certChain, AndroidPrivateKey androidKey);
private native void nativeConfirmJsResult(long nativeAwContentsClientBridge, int id,
String prompt);
......
......@@ -14,6 +14,8 @@ import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebSettings.PluginState;
import com.google.common.annotations.VisibleForTesting;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;
......@@ -36,6 +38,14 @@ public class AwSettings {
TEXT_AUTOSIZING,
}
// These constants must be kept in sync with the Android framework, defined in WebSettimgs.
@VisibleForTesting
public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0;
@VisibleForTesting
public static final int MIXED_CONTENT_NEVER_ALLOW = 1;
@VisibleForTesting
public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2;
private static final String TAG = "AwSettings";
// This class must be created on the UI thread. Afterwards, it can be
......@@ -83,6 +93,7 @@ public class AwSettings {
private float mInitialPageScalePercent = 0;
private boolean mSpatialNavigationEnabled; // Default depends on device features.
private boolean mEnableSupportedHardwareAcceleratedFeatures = false;
private int mMixedContentMode = MIXED_CONTENT_NEVER_ALLOW;
private final boolean mSupportLegacyQuirks;
......@@ -1430,6 +1441,34 @@ public class AwSettings {
}
}
public void setMixedContentMode(int mode) {
synchronized (mAwSettingsLock) {
if (mMixedContentMode != mode) {
mMixedContentMode = mode;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
public int getMixedContentMode() {
synchronized (mAwSettingsLock) {
return mMixedContentMode;
}
}
@CalledByNative
private boolean getAllowRunningInsecureContentLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mMixedContentMode == MIXED_CONTENT_ALWAYS_ALLOW;
}
@CalledByNative
private boolean getAllowDisplayingInsecureContentLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mMixedContentMode == MIXED_CONTENT_ALWAYS_ALLOW ||
mMixedContentMode == MIXED_CONTENT_COMPATIBILITY_MODE;
}
@CalledByNative
private boolean supportsDoubleTapZoomLocked() {
assert Thread.holdsLock(mAwSettingsLock);
......
// Copyright 2014 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 org.chromium.net.AndroidPrivateKey;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Store user's client certificate decision for a host and port pair. Not
* thread-safe. All accesses are done on UI thread.
*/
public class ClientCertLookupTable {
/**
* A container for the certificate data.
*/
public static class Cert {
AndroidPrivateKey privateKey;
byte[][] certChain;
public Cert(AndroidPrivateKey privateKey, byte[][] certChain) {
this.privateKey = privateKey;
byte[][] newChain = new byte[certChain.length][];
for (int i = 0; i < certChain.length; i++) {
newChain[i] = Arrays.copyOf(certChain[i], certChain[i].length);
}
this.certChain = newChain;
}
};
private final Map<String, Cert> mCerts;
private final Set<String> mDenieds;
// Clear client certificate preferences
public void clear() {
mCerts.clear();
mDenieds.clear();
}
public ClientCertLookupTable() {
mCerts = new HashMap<String, Cert>();
mDenieds = new HashSet<String>();
}
public void allow(String host, int port, AndroidPrivateKey privateKey, byte[][] chain) {
String host_and_port = hostAndPort(host, port);
mCerts.put(host_and_port, new Cert(privateKey, chain));
mDenieds.remove(host_and_port);
}
public void deny(String host, int port) {
String host_and_port = hostAndPort(host, port);
mCerts.remove(host_and_port);
mDenieds.add(host_and_port);
}
public Cert getCertData(String host, int port) {
return mCerts.get(hostAndPort(host, port));
}
public boolean isDenied(String host, int port) {
return mDenieds.contains(hostAndPort(host, port));
}
// TODO(sgurun) add a test for this. Not separating host and pair properly will be
// a security issue.
private static String hostAndPort(String host, int port) {
return host + ":" + port;
}
}
......@@ -4,39 +4,63 @@
package org.chromium.android_webview.test;
import android.test.suitebuilder.annotation.MediumTest;
import android.view.KeyEvent;
import org.chromium.android_webview.test.util.VideoTestWebServer;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.ContentVideoView;
import org.chromium.content.browser.test.util.TouchCommon;
/**
* Test WebChromeClient::onShow/HideCustomView.
*/
public class AwContentsClientFullScreenVideoTest extends AwTestBase {
private FullScreenVideoTestAwContentsClient mContentsClient;
/** Disabled to unblock the waterfall, investigating in http://crbug.com/361514. */
@MediumTest
@Feature({"AndroidWebView"})
@DisabledTest
public void testOnShowAndHideCustomView() throws Throwable {
FullScreenVideoTestAwContentsClient contentsClient =
new FullScreenVideoTestAwContentsClient(getActivity());
public void testOnShowAndHideCustomViewWithCallback() throws Throwable {
doOnShowAndHideCustomViewTest(new Runnable() {
@Override
public void run() {
mContentsClient.getExitCallback().onCustomViewHidden();
}
});
}
@MediumTest
@Feature({"AndroidWebView"})
public void testOnShowAndHideCustomViewWithBackKey() throws Throwable {
doOnShowAndHideCustomViewTest(new Runnable() {
@Override
public void run() {
ContentVideoView view = mContentsClient.getVideoView();
view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
}
});
}
private void doOnShowAndHideCustomViewTest(Runnable existFullscreen) throws Throwable {
mContentsClient = new FullScreenVideoTestAwContentsClient(getActivity());
AwTestContainerView testContainerView =
createAwTestContainerViewOnMainSync(contentsClient);
createAwTestContainerViewOnMainSync(mContentsClient);
enableJavaScriptOnUiThread(testContainerView.getAwContents());
VideoTestWebServer webServer = new VideoTestWebServer(
getInstrumentation().getTargetContext());
try {
loadUrlSync(testContainerView.getAwContents(),
contentsClient.getOnPageFinishedHelper(),
mContentsClient.getOnPageFinishedHelper(),
webServer.getFullScreenVideoTestURL());
Thread.sleep(5 * 1000);
TouchCommon touchCommon = new TouchCommon(this);
touchCommon.singleClickView(testContainerView);
contentsClient.waitForCustomViewShown();
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
contentsClient.waitForCustomViewHidden();
mContentsClient.waitForCustomViewShown();
getInstrumentation().runOnMainSync(existFullscreen);
mContentsClient.waitForCustomViewHidden();
} finally {
if (webServer != null) webServer.getTestWebServer().shutdown();
}
......
......@@ -18,7 +18,6 @@ import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwSettings;
import org.chromium.android_webview.test.TestAwContentsClient.OnDownloadStartHelper;
import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.test.util.CallbackHelper;
import org.chromium.net.test.util.TestWebServer;
......@@ -291,9 +290,8 @@ public class AwContentsTest extends AwTestBase {
}
}
/** Disabled to unblock the waterfall, investigating in http://crbug.com/363563. */
@Feature({"AndroidWebView", "Downloads"})
@DisabledTest
@SmallTest
public void testDownload() throws Throwable {
AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
AwContents awContents = testView.getAwContents();
......
......@@ -6,12 +6,14 @@ package org.chromium.android_webview.test;
import android.content.Context;
import android.graphics.Point;
import android.net.http.SslError;
import android.os.Build;
import android.os.SystemClock;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.WindowManager;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
import org.apache.http.Header;
......@@ -2633,6 +2635,61 @@ public class AwSettingsTest extends AwTestBase {
}
}
@SmallTest
@Feature({"AndroidWebView", "Preferences"})
public void testAllowMixedMode() throws Throwable {
final TestAwContentsClient contentClient = new TestAwContentsClient() {
@Override
public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) {
callback.onReceiveValue(true);
}
};
final AwTestContainerView testContainerView =
createAwTestContainerViewOnMainSync(contentClient);
final AwContents awContents = testContainerView.getAwContents();
final AwSettings awSettings = getAwSettingsOnUiThread(awContents);
awSettings.setJavaScriptEnabled(true);
TestWebServer httpsServer = new TestWebServer(true);
TestWebServer httpServer = new TestWebServer(false);
final String JS_URL = "/insecure.js";
final String IMG_URL = "/insecure.png";
final String SECURE_URL = "/secure.html";
httpServer.setResponse(JS_URL, "window.loaded_js = 42;", null);
httpServer.setResponseBase64(IMG_URL, CommonResources.FAVICON_DATA_BASE64, null);
final String JS_HTML = "<script src=\"" + httpServer.getResponseUrl(JS_URL) +
"\"></script>";
final String IMG_HTML = "<img src=\"" + httpServer.getResponseUrl(IMG_URL) + "\" />";
final String SECURE_HTML = "<body>" + IMG_HTML + " " + JS_HTML + "</body>";
String secureUrl = httpsServer.setResponse(SECURE_URL, SECURE_HTML, null);
awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_NEVER_ALLOW);
loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), secureUrl);
assertEquals(1, httpsServer.getRequestCount(SECURE_URL));
assertEquals(0, httpServer.getRequestCount(JS_URL));
assertEquals(0, httpServer.getRequestCount(IMG_URL));
awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_ALWAYS_ALLOW);
loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), secureUrl);
assertEquals(2, httpsServer.getRequestCount(SECURE_URL));
assertEquals(1, httpServer.getRequestCount(JS_URL));
assertEquals(1, httpServer.getRequestCount(IMG_URL));
awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), secureUrl);
assertEquals(3, httpsServer.getRequestCount(SECURE_URL));
assertEquals(1, httpServer.getRequestCount(JS_URL));
assertEquals(2, httpServer.getRequestCount(IMG_URL));
httpServer.shutdown();
httpsServer.shutdown();
}
static class ViewPair {
private final AwTestContainerView mContainer0;
private final TestAwContentsClient mClient0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment