summaryrefslogtreecommitdiffstats
path: root/android_webview
diff options
context:
space:
mode:
authormkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-16 16:28:51 +0000
committermkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-16 16:28:51 +0000
commit5b15e13c68d8ca8165698d50410557f44b012b31 (patch)
tree08ce7da669bd4a0eb41b3b0fa0ca2f9e0b9040b7 /android_webview
parent81b9ab27d60b4645099c14e6a45eb66a59c5137e (diff)
downloadchromium_src-5b15e13c68d8ca8165698d50410557f44b012b31.zip
chromium_src-5b15e13c68d8ca8165698d50410557f44b012b31.tar.gz
chromium_src-5b15e13c68d8ca8165698d50410557f44b012b31.tar.bz2
Implement android_webview url intercepting.
This implements the WebViewClient shouldInterceptRequest and onLoadResource callbacks. BUG=138481 Android-only change - ran through android try. NOTRY=true Review URL: https://chromiumcodereview.appspot.com/11110013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162141 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'android_webview')
-rw-r--r--android_webview/android_webview.gyp3
-rw-r--r--android_webview/browser/aw_contents_io_thread_client.h5
-rw-r--r--android_webview/browser/aw_request_interceptor.cc137
-rw-r--r--android_webview/browser/aw_request_interceptor.h61
-rw-r--r--android_webview/browser/intercepted_request_data.h43
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContents.java31
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContentsClient.java2
-rw-r--r--android_webview/java/src/org/chromium/android_webview/InterceptedRequestData.java2
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java18
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldIgnoreNavigationTest.java (renamed from android_webview/javatests/src/org/chromium/android_webview/test/AwShouldIgnoreNavigationTest.java)52
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java308
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java4
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/util/CommonResources.java17
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java77
-rw-r--r--android_webview/lib/aw_browser_dependency_factory_impl.cc14
-rw-r--r--android_webview/lib/aw_browser_dependency_factory_impl.h2
-rw-r--r--android_webview/native/android_webview_jni_registrar.cc2
-rw-r--r--android_webview/native/aw_contents_io_thread_client_impl.cc10
-rw-r--r--android_webview/native/aw_contents_io_thread_client_impl.h5
-rw-r--r--android_webview/native/intercepted_request_data.cc55
-rw-r--r--android_webview/native/intercepted_request_data.h32
-rw-r--r--android_webview/native/intercepted_request_data_impl.cc101
-rw-r--r--android_webview/native/intercepted_request_data_impl.h40
-rw-r--r--android_webview/native/webview_native.gyp4
24 files changed, 864 insertions, 161 deletions
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 3ff9aa8..78f002b 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -38,8 +38,11 @@
'browser/aw_http_auth_handler_base.h',
'browser/aw_login_delegate.cc',
'browser/aw_login_delegate.h',
+ 'browser/aw_request_interceptor.cc',
+ 'browser/aw_request_interceptor.h',
'browser/find_helper.cc',
'browser/find_helper.h',
+ 'browser/intercepted_request_data.h',
'browser/net/aw_network_delegate.cc',
'browser/net/aw_network_delegate.h',
'browser/net_disk_cache_remover.cc',
diff --git a/android_webview/browser/aw_contents_io_thread_client.h b/android_webview/browser/aw_contents_io_thread_client.h
index 659be10..0dd4146 100644
--- a/android_webview/browser/aw_contents_io_thread_client.h
+++ b/android_webview/browser/aw_contents_io_thread_client.h
@@ -7,7 +7,7 @@
#include "base/memory/scoped_ptr.h"
-class InterceptedRequestData;
+class GURL;
namespace net {
class URLRequest;
@@ -15,6 +15,8 @@ class URLRequest;
namespace android_webview {
+class InterceptedRequestData;
+
// This class provides a means of calling Java methods on an instance that has
// a 1:1 relationship with a WebContents instance directly from the IO thread.
//
@@ -43,6 +45,7 @@ class AwContentsIoThreadClient {
// This method is called on the IO thread only.
virtual scoped_ptr<InterceptedRequestData> ShouldInterceptRequest(
+ const GURL& location,
const net::URLRequest* request) = 0;
// Retrieve the AllowContentAccess setting value of this AwContents.
diff --git a/android_webview/browser/aw_request_interceptor.cc b/android_webview/browser/aw_request_interceptor.cc
new file mode 100644
index 0000000..c48a090
--- /dev/null
+++ b/android_webview/browser/aw_request_interceptor.cc
@@ -0,0 +1,137 @@
+// Copyright (c) 2012 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_request_interceptor.h"
+
+#include "android_webview/browser/aw_contents_io_thread_client.h"
+#include "android_webview/browser/intercepted_request_data.h"
+#include "base/android/jni_string.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/resource_request_info.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/url_request/url_request_job.h"
+
+using content::BrowserThread;
+using content::RenderViewHost;
+using content::ResourceRequestInfo;
+
+namespace android_webview {
+
+namespace {
+
+const void* kURLRequestUserDataKey = &kURLRequestUserDataKey;
+
+class URLRequestUserData : public base::SupportsUserData::Data {
+ public:
+ URLRequestUserData(
+ scoped_ptr<InterceptedRequestData> intercepted_request_data)
+ : intercepted_request_data_(intercepted_request_data.Pass()) {
+ }
+
+ static URLRequestUserData* Get(net::URLRequest* request) {
+ return reinterpret_cast<URLRequestUserData*>(
+ request->GetUserData(kURLRequestUserDataKey));
+ }
+
+ const InterceptedRequestData* intercepted_request_data() const {
+ return intercepted_request_data_.get();
+ }
+
+ private:
+ scoped_ptr<InterceptedRequestData> intercepted_request_data_;
+};
+
+} // namespace
+
+AwRequestInterceptor::AwRequestInterceptor() {
+}
+
+AwRequestInterceptor::~AwRequestInterceptor() {
+}
+
+scoped_ptr<InterceptedRequestData>
+AwRequestInterceptor::QueryForInterceptedRequestData(
+ const GURL& location,
+ net::URLRequest* request) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ int render_process_id, render_view_id;
+ if (!ResourceRequestInfo::GetRenderViewForRequest(
+ request, &render_process_id, &render_view_id))
+ return scoped_ptr<InterceptedRequestData>();
+
+ scoped_ptr<AwContentsIoThreadClient> io_thread_client =
+ AwContentsIoThreadClient::FromID(render_process_id, render_view_id);
+
+ if (!io_thread_client.get())
+ return scoped_ptr<InterceptedRequestData>();
+
+ return io_thread_client->ShouldInterceptRequest(location, request).Pass();
+}
+
+net::URLRequestJob* AwRequestInterceptor::MaybeInterceptInternal(
+ const GURL& location,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // See if we've already found out the intercepted_request_data for this
+ // request.
+ // This is done not only for efficiency reasons, but also for correctness
+ // as it is possible for the Interceptor chain to be invoked more than once
+ // (in which case we don't want to query the embedder multiple times).
+ URLRequestUserData* user_data = URLRequestUserData::Get(request);
+
+ if (!user_data) {
+ // To ensure we only query the embedder once, we rely on the fact that the
+ // user_data object will be created and attached to the URLRequest after a
+ // call to QueryForInterceptedRequestData is made (regardless of whether
+ // the result of that call is a valid InterceptedRequestData* pointer or
+ // NULL.
+ user_data = new URLRequestUserData(
+ QueryForInterceptedRequestData(location, request));
+ request->SetUserData(kURLRequestUserDataKey, user_data);
+ }
+
+ const InterceptedRequestData* intercepted_request_data =
+ user_data->intercepted_request_data();
+
+ if (!intercepted_request_data)
+ return NULL;
+ return intercepted_request_data->CreateJobFor(request, network_delegate);
+}
+
+net::URLRequestJob* AwRequestInterceptor::MaybeIntercept(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ return MaybeInterceptInternal(request->url(), request, network_delegate);
+}
+
+net::URLRequestJob* AwRequestInterceptor::MaybeInterceptRedirect(
+ const GURL& location,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ return MaybeInterceptInternal(location, request, network_delegate);
+}
+
+net::URLRequestJob* AwRequestInterceptor::MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ return NULL;
+}
+
+//static
+void AwRequestInterceptor::RegisterInterceptorOnIOThread(
+ net::URLRequestContextGetter* context_getter) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // The job factory takes ownership of the interceptor.
+ const_cast<net::URLRequestJobFactory*>(
+ context_getter->GetURLRequestContext()->job_factory())->AddInterceptor(
+ new AwRequestInterceptor());
+}
+
+} // namespace android_webview
diff --git a/android_webview/browser/aw_request_interceptor.h b/android_webview/browser/aw_request_interceptor.h
new file mode 100644
index 0000000..ebafad9
--- /dev/null
+++ b/android_webview/browser/aw_request_interceptor.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 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_REQUEST_INTERCEPTOR_H_
+#define ANDROID_WEBVIEW_BROWSER_AW_REQUEST_INTERCEPTOR_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/url_request/url_request_job_factory.h"
+
+class GURL;
+
+namespace net {
+class URLRequest;
+class URLRequestContextGetter;
+class URLRequestJob;
+class NetworkDelegate;
+}
+
+namespace android_webview {
+
+class InterceptedRequestData;
+
+// This class allows the Java-side embedder to substitute the default
+// URLRequest of a given request for an alternative job that will read data
+// from a Java stream.
+class AwRequestInterceptor : public net::URLRequestJobFactory::Interceptor {
+ public:
+ AwRequestInterceptor();
+ virtual ~AwRequestInterceptor();
+
+ static void RegisterInterceptorOnIOThread(
+ net::URLRequestContextGetter* context_getter);
+
+ // net::URLRequestJobFactory::Interceptor overrides -------------------------
+ virtual net::URLRequestJob* MaybeIntercept(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+ virtual net::URLRequestJob* MaybeInterceptRedirect(
+ const GURL& location,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+ virtual net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+
+ private:
+ net::URLRequestJob* MaybeInterceptInternal(
+ const GURL& location,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const;
+ scoped_ptr<InterceptedRequestData> QueryForInterceptedRequestData(
+ const GURL& location,
+ net::URLRequest* request) const;
+
+ DISALLOW_COPY_AND_ASSIGN(AwRequestInterceptor);
+};
+
+} // namespace android_webview
+
+#endif // ANDROID_WEBVIEW_BROWSER_AW_REQUEST_INTERCEPTOR_H_
diff --git a/android_webview/browser/intercepted_request_data.h b/android_webview/browser/intercepted_request_data.h
new file mode 100644
index 0000000..672833c
--- /dev/null
+++ b/android_webview/browser/intercepted_request_data.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 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_INTERCEPTED_REQUEST_DATA_H_
+#define ANDROID_WEBVIEW_BROWSER_INTERCEPTED_REQUEST_DATA_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace net {
+class URLRequest;
+class URLRequestJob;
+class NetworkDelegate;
+}
+
+namespace android_webview {
+
+// This class represents the Java-side data that is to be used to complete a
+// particular URLRequest.
+class InterceptedRequestData {
+ public:
+ virtual ~InterceptedRequestData() {}
+
+ // This creates a URLRequestJob for the |request| wich will read data from
+ // the |intercepted_request_data| structure (instead of going to the network
+ // or to the cache).
+ // The newly created job does not take ownership of |this|.
+ virtual net::URLRequestJob* CreateJobFor(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const = 0;
+
+ protected:
+ InterceptedRequestData() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InterceptedRequestData);
+};
+
+} // namespace android_webview
+
+#endif // ANDROID_WEBVIEW_BROWSER_INTERCEPTED_REQUEST_DATA_H_
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 476fd78..36511fd 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -7,6 +7,8 @@ package org.chromium.android_webview;
import android.graphics.Bitmap;
import android.net.http.SslCertificate;
import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
@@ -46,6 +48,7 @@ public class AwContents {
private static final String WEB_ARCHIVE_EXTENSION = ".mht";
+
private int mNativeAwContents;
private ContentViewCore mContentViewCore;
private AwContentsClient mContentsClient;
@@ -53,6 +56,7 @@ public class AwContents {
private InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
// This can be accessed on any thread after construction. See AwContentsIoThreadClient.
private final AwSettings mSettings;
+ private final IoThreadClientHandler mIoThreadClientHandler;
private static final class DestroyRunnable implements Runnable {
private int mNativeAwContents;
@@ -67,11 +71,33 @@ public class AwContents {
private CleanupReference mCleanupReference;
+ private class IoThreadClientHandler extends Handler {
+ public static final int MSG_SHOULD_INTERCEPT_REQUEST = 1;
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_SHOULD_INTERCEPT_REQUEST:
+ final String url = (String)msg.obj;
+ AwContents.this.mContentsClient.onLoadResource(url);
+ break;
+ }
+ }
+ }
+
private class IoThreadClientImpl implements AwContentsIoThreadClient {
// Called on the IO thread.
@Override
- public InterceptedRequestData shouldInterceptRequest(String url) {
- return AwContents.this.mContentsClient.shouldInterceptRequest(url);
+ public InterceptedRequestData shouldInterceptRequest(final String url) {
+ InterceptedRequestData interceptedRequestData =
+ AwContents.this.mContentsClient.shouldInterceptRequest(url);
+ if (interceptedRequestData == null) {
+ mIoThreadClientHandler.sendMessage(
+ mIoThreadClientHandler.obtainMessage(
+ IoThreadClientHandler.MSG_SHOULD_INTERCEPT_REQUEST,
+ url));
+ }
+ return interceptedRequestData;
}
// Called on the IO thread.
@@ -132,6 +158,7 @@ public class AwContents {
mContentViewCore = contentViewCore;
mContentsClient = contentsClient;
mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents));
+ mIoThreadClientHandler = new IoThreadClientHandler();
mContentViewCore.initialize(containerView, internalAccessAdapter,
nativeGetWebContents(mNativeAwContents), nativeWindow,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
index f646040..87fda07 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -142,6 +142,8 @@ public abstract class AwContentsClient extends ContentViewClient {
public abstract InterceptedRequestData shouldInterceptRequest(String url);
+ public abstract void onLoadResource(String url);
+
public abstract boolean shouldIgnoreNavigation(String url);
public abstract void onUnhandledKeyEvent(KeyEvent event);
diff --git a/android_webview/java/src/org/chromium/android_webview/InterceptedRequestData.java b/android_webview/java/src/org/chromium/android_webview/InterceptedRequestData.java
index 2a5460e..f6f3d9d 100644
--- a/android_webview/java/src/org/chromium/android_webview/InterceptedRequestData.java
+++ b/android_webview/java/src/org/chromium/android_webview/InterceptedRequestData.java
@@ -5,12 +5,14 @@
package org.chromium.android_webview;
import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
import java.io.InputStream;
/**
* The response information that is to be returned for a particular resource fetch.
*/
+@JNINamespace("android_webview")
public class InterceptedRequestData {
private String mMimeType;
private String mCharset;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java
index 9d2f5c4..dd043ef 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidWebViewTestBase.java
@@ -13,6 +13,7 @@ import junit.framework.Assert;
import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwContentsClient;
import org.chromium.android_webview.AwSettings;
+import org.chromium.android_webview.test.util.JSUtils;
import org.chromium.content.browser.ContentSettings;
import org.chromium.content.browser.ContentView;
import org.chromium.content.browser.ContentViewCore;
@@ -233,19 +234,8 @@ public class AndroidWebViewTestBase
*/
protected String executeJavaScriptAndWaitForResult(final AwContents awContents,
TestAwContentsClient viewClient, final String code) throws Throwable {
- final AtomicInteger requestId = new AtomicInteger();
- TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper
- onEvaluateJavaScriptResultHelper = viewClient.getOnEvaluateJavaScriptResultHelper();
- int currentCallCount = onEvaluateJavaScriptResultHelper.getCallCount();
- runTestOnUiThread(new Runnable() {
- @Override
- public void run() {
- requestId.set(awContents.getContentViewCore().evaluateJavaScript(code));
- }
- });
- onEvaluateJavaScriptResultHelper.waitForCallback(currentCallCount);
- Assert.assertEquals("Response ID mismatch when evaluating JavaScript.",
- requestId.get(), onEvaluateJavaScriptResultHelper.getId());
- return onEvaluateJavaScriptResultHelper.getJsonResult();
+ return JSUtils.executeJavaScriptAndWaitForResult(this, awContents,
+ viewClient.getOnEvaluateJavaScriptResultHelper(),
+ code);
}
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwShouldIgnoreNavigationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldIgnoreNavigationTest.java
index dd1fd4c..3fc4d1a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwShouldIgnoreNavigationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldIgnoreNavigationTest.java
@@ -12,6 +12,8 @@ import android.view.MotionEvent;
import android.util.Log;
import org.chromium.android_webview.AwContents;
+import org.chromium.android_webview.test.util.CommonResources;
+import org.chromium.android_webview.test.util.JSUtils;
import org.chromium.android_webview.test.util.TestWebServer;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
@@ -31,10 +33,11 @@ import java.util.concurrent.Callable;
/**
* Tests for the WebViewClient.shouldOverrideUrlLoading() method.
*/
-public class AwShouldIgnoreNavigationTest extends AndroidWebViewTestBase {
+public class AwContentsClientShouldIgnoreNavigationTest extends AndroidWebViewTestBase {
private final static String ABOUT_BLANK_URL = "about:blank";
private final static String DATA_URL = "data:text/html,<div/>";
private final static String REDIRECT_TARGET_PATH = "/redirect_target.html";
+ private final static String TITLE = "TITLE";
private static final long TEST_TIMEOUT = 20000L;
private static final int CHECK_INTERVAL = 100;
@@ -85,7 +88,6 @@ public class AwShouldIgnoreNavigationTest extends AndroidWebViewTestBase {
private ShouldIgnoreNavigationHelper mShouldIgnoreNavigationHelper;
public TestAwContentsClient() {
- super();
mShouldIgnoreNavigationHelper = new ShouldIgnoreNavigationHelper();
}
@@ -97,32 +99,8 @@ public class AwShouldIgnoreNavigationTest extends AndroidWebViewTestBase {
private void clickOnLinkUsingJs(final AwContents awContents,
final TestAwContentsClient contentsClient) throws Throwable {
enableJavaScriptOnUiThread(awContents);
-
- assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
- @Override
- public boolean isSatisfied() {
- try {
- String linkIsNotNull = executeJavaScriptAndWaitForResult(awContents,
- contentsClient, "document.getElementById('link') != null");
- return linkIsNotNull.equals("true");
- } catch (Throwable t) {
- t.printStackTrace();
- fail("Failed to check if DOM is loaded: " + t.toString());
- return false;
- }
- }
- }, WAIT_TIMEOUT_SECONDS * 1000, CHECK_INTERVAL));
-
- runTestOnUiThread(new Runnable() {
- @Override
- public void run() {
- awContents.getContentViewCore().evaluateJavaScript(
- "var evObj = document.createEvent('Events'); " +
- "evObj.initEvent('click', true, false); " +
- "document.getElementById('link').dispatchEvent(evObj);" +
- "console.log('element with id link clicked');");
- }
- });
+ JSUtils.clickOnLinkUsingJs(this, awContents,
+ contentsClient.getOnEvaluateJavaScriptResultHelper(), "link");
}
// Since this value is read on the UI thread, it's simpler to set it there too.
@@ -138,21 +116,7 @@ public class AwShouldIgnoreNavigationTest extends AndroidWebViewTestBase {
}
private String makeHtmlPageFrom(String headers, String body) {
- return "<html>" +
- "<head>" +
- "<title>Title</title>" +
- "<style type=\"text/css\">" +
- // Make the image take up all of the page so that we don't have to do
- // any fancy hit target calculations when synthesizing the touch event
- // to click it.
- "img.big { width:100%; height:100%; background-color:blue; }" +
- "</style>" +
- headers +
- "</head>" +
- "<body>" +
- body +
- "</body>" +
- "</html>";
+ return CommonResources.makeHtmlPageFrom("<title>" + TITLE + "</title> " + headers, body);
}
private String getHtmlForPageWithSimpleLinkTo(String destination) {
@@ -241,7 +205,7 @@ public class AwShouldIgnoreNavigationTest extends AndroidWebViewTestBase {
loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
getHtmlForPageWithSimpleLinkTo(DATA_URL), "text/html", false);
- assertEquals("Title", getTitleOnUiThread(awContents));
+ assertEquals(TITLE, getTitleOnUiThread(awContents));
}
/**
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java
new file mode 100644
index 0000000..f5b4546
--- /dev/null
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java
@@ -0,0 +1,308 @@
+// Copyright (c) 2012 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.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.util.Pair;
+
+import org.chromium.android_webview.AwContents;
+import org.chromium.android_webview.InterceptedRequestData;
+import org.chromium.android_webview.test.util.CommonResources;
+import org.chromium.android_webview.test.util.JSUtils;
+import org.chromium.android_webview.test.util.TestWebServer;
+import org.chromium.base.test.util.Feature;
+import org.chromium.content.browser.test.util.CallbackHelper;
+import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
+import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Tests for the WebViewClient.shouldInterceptRequest() method.
+ */
+public class AwContentsClientShouldInterceptRequestTest extends AndroidWebViewTestBase {
+
+ private static class TestAwContentsClient
+ extends org.chromium.android_webview.test.TestAwContentsClient {
+
+ public static class ShouldInterceptRequestHelper extends CallbackHelper {
+ private List<String> mShouldInterceptRequestUrls = new ArrayList<String>();
+ // This is read from the IO thread, so needs to be marked volatile.
+ private volatile InterceptedRequestData mShouldInterceptRequestReturnValue = null;
+ void setReturnValue(InterceptedRequestData value) {
+ mShouldInterceptRequestReturnValue = value;
+ }
+ public List<String> getUrls() {
+ assert getCallCount() > 0;
+ return mShouldInterceptRequestUrls;
+ }
+ public InterceptedRequestData getReturnValue() {
+ return mShouldInterceptRequestReturnValue;
+ }
+ public void notifyCalled(String url) {
+ mShouldInterceptRequestUrls.add(url);
+ notifyCalled();
+ }
+ }
+
+ public static class OnLoadResourceHelper extends CallbackHelper {
+ private String mUrl;
+
+ public String getUrl() {
+ assert getCallCount() > 0;
+ return mUrl;
+ }
+
+ public void notifyCalled(String url) {
+ mUrl = url;
+ notifyCalled();
+ }
+ }
+
+ @Override
+ public InterceptedRequestData shouldInterceptRequest(String url) {
+ InterceptedRequestData returnValue = mShouldInterceptRequestHelper.getReturnValue();
+ mShouldInterceptRequestHelper.notifyCalled(url);
+ return returnValue;
+ }
+
+ @Override
+ public void onLoadResource(String url) {
+ super.onLoadResource(url);
+ mOnLoadResourceHelper.notifyCalled(url);
+ }
+
+ private ShouldInterceptRequestHelper mShouldInterceptRequestHelper;
+ private OnLoadResourceHelper mOnLoadResourceHelper;
+
+ public TestAwContentsClient() {
+ mShouldInterceptRequestHelper = new ShouldInterceptRequestHelper();
+ mOnLoadResourceHelper = new OnLoadResourceHelper();
+ }
+
+ public ShouldInterceptRequestHelper getShouldInterceptRequestHelper() {
+ return mShouldInterceptRequestHelper;
+ }
+
+ public OnLoadResourceHelper getOnLoadResourceHelper() {
+ return mOnLoadResourceHelper;
+ }
+ }
+
+ private String addPageToTestServer(TestWebServer webServer, String httpPath, String html) {
+ List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
+ headers.add(Pair.create("Content-Type", "text/html"));
+ headers.add(Pair.create("Cache-Control", "no-store"));
+ return webServer.setResponse(httpPath, html, headers);
+ }
+
+ private String addAboutPageToTestServer(TestWebServer webServer) {
+ return addPageToTestServer(webServer, "/" + CommonResources.ABOUT_FILENAME,
+ CommonResources.ABOUT_HTML);
+ }
+
+ private InterceptedRequestData stringToInterceptedRequestData(String input) throws Throwable {
+ final String mimeType = "text/html";
+ final String encoding = "UTF-8";
+
+ return new InterceptedRequestData(
+ mimeType, encoding, new ByteArrayInputStream(input.getBytes(encoding)));
+ }
+
+ private TestWebServer mWebServer;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mWebServer = new TestWebServer(false);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mWebServer.shutdown();
+ super.tearDown();
+ }
+
+ @SmallTest
+ @Feature({"Android-WebView"})
+ public void testCalledWithCorrectUrl() throws Throwable {
+ final TestAwContentsClient contentsClient = new TestAwContentsClient();
+ final AwTestContainerView testContainerView =
+ createAwTestContainerViewOnMainSync(contentsClient);
+ final AwContents awContents = testContainerView.getAwContents();
+ final TestAwContentsClient.ShouldInterceptRequestHelper shouldInterceptRequestHelper =
+ contentsClient.getShouldInterceptRequestHelper();
+
+ final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
+
+ int callCount = shouldInterceptRequestHelper.getCallCount();
+ int onPageFinishedCallCount = contentsClient.getOnPageFinishedHelper().getCallCount();
+
+ loadUrlAsync(awContents, aboutPageUrl);
+
+ shouldInterceptRequestHelper.waitForCallback(callCount);
+ assertEquals(1, shouldInterceptRequestHelper.getUrls().size());
+ assertEquals(aboutPageUrl,
+ shouldInterceptRequestHelper.getUrls().get(0));
+
+ contentsClient.getOnPageFinishedHelper().waitForCallback(onPageFinishedCallCount);
+ assertEquals(CommonResources.ABOUT_TITLE, getTitleOnUiThread(awContents));
+ }
+
+ @SmallTest
+ @Feature({"Android-WebView"})
+ public void testOnLoadResourceCalledWithCorrectUrl() throws Throwable {
+ final TestAwContentsClient contentsClient = new TestAwContentsClient();
+ final AwTestContainerView testContainerView =
+ createAwTestContainerViewOnMainSync(contentsClient);
+ final AwContents awContents = testContainerView.getAwContents();
+ final TestAwContentsClient.OnLoadResourceHelper onLoadResourceHelper =
+ contentsClient.getOnLoadResourceHelper();
+
+ final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
+
+ int callCount = onLoadResourceHelper.getCallCount();
+ int onPageFinishedCallCount = contentsClient.getOnPageFinishedHelper().getCallCount();
+
+ loadUrlAsync(awContents, aboutPageUrl);
+
+ onLoadResourceHelper.waitForCallback(callCount);
+ assertEquals(aboutPageUrl, onLoadResourceHelper.getUrl());
+ }
+
+ @SmallTest
+ @Feature({"Android-WebView"})
+ public void testDoesNotCrashOnInvalidData() throws Throwable {
+ final TestAwContentsClient contentsClient = new TestAwContentsClient();
+ final AwTestContainerView testContainerView =
+ createAwTestContainerViewOnMainSync(contentsClient);
+ final AwContents awContents = testContainerView.getAwContents();
+ final TestAwContentsClient.ShouldInterceptRequestHelper shouldInterceptRequestHelper =
+ contentsClient.getShouldInterceptRequestHelper();
+
+ final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
+
+ shouldInterceptRequestHelper.setReturnValue(
+ new InterceptedRequestData("text/html", "UTF-8", null));
+ int callCount = shouldInterceptRequestHelper.getCallCount();
+ loadUrlAsync(awContents, aboutPageUrl);
+ shouldInterceptRequestHelper.waitForCallback(callCount);
+
+ shouldInterceptRequestHelper.setReturnValue(
+ new InterceptedRequestData(null, null, new ByteArrayInputStream(new byte[0])));
+ callCount = shouldInterceptRequestHelper.getCallCount();
+ loadUrlAsync(awContents, aboutPageUrl);
+ shouldInterceptRequestHelper.waitForCallback(callCount);
+
+ shouldInterceptRequestHelper.setReturnValue(
+ new InterceptedRequestData(null, null, null));
+ callCount = shouldInterceptRequestHelper.getCallCount();
+ loadUrlAsync(awContents, aboutPageUrl);
+ shouldInterceptRequestHelper.waitForCallback(callCount);
+ }
+
+ private String makePageWithTitle(String title) {
+ return CommonResources.makeHtmlPageFrom("<title>" + title + "</title>",
+ "<div> The title is: " + title + " </div>");
+ }
+
+ @SmallTest
+ @Feature({"Android-WebView"})
+ public void testCanInterceptMainFrame() throws Throwable {
+ final TestAwContentsClient contentsClient = new TestAwContentsClient();
+ final AwTestContainerView testContainerView =
+ createAwTestContainerViewOnMainSync(contentsClient);
+ final AwContents awContents = testContainerView.getAwContents();
+ final TestAwContentsClient.ShouldInterceptRequestHelper shouldInterceptRequestHelper =
+ contentsClient.getShouldInterceptRequestHelper();
+
+ final String expectedTitle = "testShouldInterceptRequestCanInterceptMainFrame";
+ final String expectedPage = makePageWithTitle(expectedTitle);
+
+ shouldInterceptRequestHelper.setReturnValue(
+ stringToInterceptedRequestData(expectedPage));
+
+ final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
+
+ loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), aboutPageUrl);
+
+ assertEquals(expectedTitle, getTitleOnUiThread(awContents));
+ assertEquals(0, mWebServer.getRequestCount("/" + CommonResources.ABOUT_FILENAME));
+ }
+
+ @SmallTest
+ @Feature({"Android-WebView"})
+ public void testDoesNotChangeReportedUrl() throws Throwable {
+ final TestAwContentsClient contentsClient = new TestAwContentsClient();
+ final AwTestContainerView testContainerView =
+ createAwTestContainerViewOnMainSync(contentsClient);
+ final AwContents awContents = testContainerView.getAwContents();
+ final TestAwContentsClient.ShouldInterceptRequestHelper shouldInterceptRequestHelper =
+ contentsClient.getShouldInterceptRequestHelper();
+
+ shouldInterceptRequestHelper.setReturnValue(
+ stringToInterceptedRequestData(makePageWithTitle("some title")));
+
+ final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
+
+ loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), aboutPageUrl);
+
+ assertEquals(aboutPageUrl, contentsClient.getOnPageFinishedHelper().getUrl());
+ assertEquals(aboutPageUrl, contentsClient.getOnPageStartedHelper().getUrl());
+ }
+
+
+ @SmallTest
+ @Feature({"Android-WebView"})
+ public void testCalledForImage() throws Throwable {
+ final TestAwContentsClient contentsClient = new TestAwContentsClient();
+ final AwTestContainerView testContainerView =
+ createAwTestContainerViewOnMainSync(contentsClient);
+ final AwContents awContents = testContainerView.getAwContents();
+ final TestAwContentsClient.ShouldInterceptRequestHelper shouldInterceptRequestHelper =
+ contentsClient.getShouldInterceptRequestHelper();
+
+ final String imagePath = "/" + CommonResources.FAVICON_FILENAME;
+ final String imageUrl = mWebServer.setResponseBase64(imagePath,
+ CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
+ final String pageWithImage =
+ addPageToTestServer(mWebServer, "/page_with_image.html",
+ CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME));
+
+ int callCount = shouldInterceptRequestHelper.getCallCount();
+ loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), pageWithImage);
+ shouldInterceptRequestHelper.waitForCallback(callCount, 2);
+
+ assertEquals(2, shouldInterceptRequestHelper.getUrls().size());
+ assertTrue(shouldInterceptRequestHelper.getUrls().get(1).endsWith(
+ CommonResources.FAVICON_FILENAME));
+ }
+
+ @SmallTest
+ @Feature({"Android-WebView"})
+ public void testCalledForIframe() throws Throwable {
+ final TestAwContentsClient contentsClient = new TestAwContentsClient();
+ final AwTestContainerView testContainerView =
+ createAwTestContainerViewOnMainSync(contentsClient);
+ final AwContents awContents = testContainerView.getAwContents();
+ final TestAwContentsClient.ShouldInterceptRequestHelper shouldInterceptRequestHelper =
+ contentsClient.getShouldInterceptRequestHelper();
+
+ final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
+ final String pageWithIframe = addPageToTestServer(mWebServer, "/page_with_iframe.html",
+ CommonResources.makeHtmlPageFrom("",
+ "<iframe src=\"" + aboutPageUrl + "\"/>"));
+
+ int callCount = shouldInterceptRequestHelper.getCallCount();
+ loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), pageWithIframe);
+ shouldInterceptRequestHelper.waitForCallback(callCount, 2);
+ assertEquals(2, shouldInterceptRequestHelper.getUrls().size());
+ assertEquals(aboutPageUrl, shouldInterceptRequestHelper.getUrls().get(1));
+ }
+}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java b/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java
index 9c4bd57..2760c2d 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/NullContentsClient.java
@@ -38,6 +38,10 @@ class NullContentsClient extends AwContentsClient {
}
@Override
+ public void onLoadResource(String url) {
+ }
+
+ @Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
return false;
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/util/CommonResources.java b/android_webview/javatests/src/org/chromium/android_webview/test/util/CommonResources.java
index dff151b..f7ccb0f 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/util/CommonResources.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/util/CommonResources.java
@@ -85,4 +85,21 @@ public class CommonResources {
" This is the Google!" +
" </body>" +
"</html>";
+
+ public static String makeHtmlPageFrom(String headers, String body) {
+ return "<html>" +
+ "<head>" +
+ "<style type=\"text/css\">" +
+ // Make the image take up all of the page so that we don't have to do
+ // any fancy hit target calculations when synthesizing the touch event
+ // to click it.
+ "img.big { width:100%; height:100%; background-color:blue; }" +
+ "</style>" +
+ headers +
+ "</head>" +
+ "<body>" +
+ body +
+ "</body>" +
+ "</html>";
+ }
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java b/android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java
new file mode 100644
index 0000000..33956a0
--- /dev/null
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 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.test.util;
+
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import org.chromium.android_webview.AwContents;
+import org.chromium.content.browser.test.util.CallbackHelper;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
+import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+// Collection of functions for JavaScript-based interactions with a page.
+public class JSUtils {
+ private static final int WAIT_TIMEOUT_SECONDS = 2;
+ private static final int CHECK_INTERVAL = 100;
+
+ public static void clickOnLinkUsingJs(
+ final InstrumentationTestCase testCase,
+ final AwContents awContents,
+ final OnEvaluateJavaScriptResultHelper onEvaluateJavaScriptResultHelper,
+ final String linkId) throws Throwable {
+
+ Assert.assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
+ @Override
+ public boolean isSatisfied() {
+ try {
+ String linkIsNotNull = executeJavaScriptAndWaitForResult(testCase, awContents,
+ onEvaluateJavaScriptResultHelper,
+ "document.getElementById('" + linkId + "') != null");
+ return linkIsNotNull.equals("true");
+ } catch (Throwable t) {
+ t.printStackTrace();
+ Assert.fail("Failed to check if DOM is loaded: " + t.toString());
+ return false;
+ }
+ }
+ }, WAIT_TIMEOUT_SECONDS * 1000, CHECK_INTERVAL));
+
+ testCase.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ awContents.getContentViewCore().evaluateJavaScript(
+ "var evObj = document.createEvent('Events'); " +
+ "evObj.initEvent('click', true, false); " +
+ "document.getElementById('" + linkId + "').dispatchEvent(evObj);" +
+ "console.log('element with id [" + linkId + "] clicked');");
+ }
+ });
+ }
+
+ public static String executeJavaScriptAndWaitForResult(
+ InstrumentationTestCase testCase,
+ final AwContents awContents,
+ OnEvaluateJavaScriptResultHelper onEvaluateJavaScriptResultHelper,
+ final String code) throws Throwable {
+ final AtomicInteger requestId = new AtomicInteger();
+ int currentCallCount = onEvaluateJavaScriptResultHelper.getCallCount();
+ testCase.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ requestId.set(awContents.getContentViewCore().evaluateJavaScript(code));
+ }
+ });
+ onEvaluateJavaScriptResultHelper.waitForCallback(currentCallCount);
+ Assert.assertEquals("Response ID mismatch when evaluating JavaScript.",
+ requestId.get(), onEvaluateJavaScriptResultHelper.getId());
+ return onEvaluateJavaScriptResultHelper.getJsonResult();
+ }
+}
diff --git a/android_webview/lib/aw_browser_dependency_factory_impl.cc b/android_webview/lib/aw_browser_dependency_factory_impl.cc
index 4eba90a..dccf033 100644
--- a/android_webview/lib/aw_browser_dependency_factory_impl.cc
+++ b/android_webview/lib/aw_browser_dependency_factory_impl.cc
@@ -6,6 +6,7 @@
// TODO(joth): Componentize or remove chrome/... dependencies.
#include "android_webview/browser/net/aw_network_delegate.h"
+#include "android_webview/browser/aw_request_interceptor.h"
#include "android_webview/native/android_protocol_handler.h"
#include "android_webview/native/aw_contents_container.h"
#include "base/bind.h"
@@ -59,10 +60,10 @@ void AwBrowserDependencyFactoryImpl::InstallInstance() {
SetInstance(g_lazy_instance.Pointer());
}
-// Initializing the Network Delegate here is only a temporary solution until we
-// build an Android WebView specific BrowserContext that can handle building
-// this internally.
-void AwBrowserDependencyFactoryImpl::InitializeNetworkDelegateOnIOThread(
+// Initializing the Network Delegate here is only a temporary solution until
+// an Android WebView specific BrowserContext (which can then handle building
+// this internally is) available.
+void AwBrowserDependencyFactoryImpl::InitOnIOThreadWithBrowserContext(
net::URLRequestContextGetter* normal_context,
net::URLRequestContextGetter* incognito_context) {
network_delegate_.reset(new AwNetworkDelegate());
@@ -70,6 +71,9 @@ void AwBrowserDependencyFactoryImpl::InitializeNetworkDelegateOnIOThread(
network_delegate_.get());
incognito_context->GetURLRequestContext()->set_network_delegate(
network_delegate_.get());
+
+ AwRequestInterceptor::RegisterInterceptorOnIOThread(normal_context);
+ AwRequestInterceptor::RegisterInterceptorOnIOThread(incognito_context);
}
void AwBrowserDependencyFactoryImpl::EnsureContextDependentHooksInitialized()
@@ -81,7 +85,7 @@ void AwBrowserDependencyFactoryImpl::EnsureContextDependentHooksInitialized()
profile->GetRequestContext()->GetNetworkTaskRunner()->PostTask(
FROM_HERE,
base::Bind(
- &AwBrowserDependencyFactoryImpl::InitializeNetworkDelegateOnIOThread,
+ &AwBrowserDependencyFactoryImpl::InitOnIOThreadWithBrowserContext,
base::Unretained(this),
make_scoped_refptr(profile->GetRequestContext()),
make_scoped_refptr(
diff --git a/android_webview/lib/aw_browser_dependency_factory_impl.h b/android_webview/lib/aw_browser_dependency_factory_impl.h
index 08eb1ef..f7cc270 100644
--- a/android_webview/lib/aw_browser_dependency_factory_impl.h
+++ b/android_webview/lib/aw_browser_dependency_factory_impl.h
@@ -33,7 +33,7 @@ class AwBrowserDependencyFactoryImpl : public AwBrowserDependencyFactory {
content::WebContents* contents) OVERRIDE;
private:
- void InitializeNetworkDelegateOnIOThread(
+ void InitOnIOThreadWithBrowserContext(
net::URLRequestContextGetter* normal_context,
net::URLRequestContextGetter* incognito_context);
void EnsureContextDependentHooksInitialized();
diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc
index bec2cb6..8fdff21 100644
--- a/android_webview/native/android_webview_jni_registrar.cc
+++ b/android_webview/native/android_webview_jni_registrar.cc
@@ -11,6 +11,7 @@
#include "android_webview/native/aw_contents_io_thread_client_impl.h"
#include "android_webview/native/aw_http_auth_handler.h"
#include "android_webview/native/cookie_manager.h"
+#include "android_webview/native/intercepted_request_data_impl.h"
#include "android_webview/native/js_result_handler.h"
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
@@ -33,6 +34,7 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = {
{ "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl},
{ "AwHttpAuthHandler", RegisterAwHttpAuthHandler },
{ "CookieManager", RegisterCookieManager },
+ { "InterceptedRequestDataImpl", RegisterInterceptedRequestData },
{ "JsResultHandler", RegisterJsResultHandler },
};
diff --git a/android_webview/native/aw_contents_io_thread_client_impl.cc b/android_webview/native/aw_contents_io_thread_client_impl.cc
index e798364..d302608 100644
--- a/android_webview/native/aw_contents_io_thread_client_impl.cc
+++ b/android_webview/native/aw_contents_io_thread_client_impl.cc
@@ -7,7 +7,7 @@
#include <map>
#include <utility>
-#include "android_webview/native/intercepted_request_data.h"
+#include "android_webview/native/intercepted_request_data_impl.h"
#include "base/android/jni_helper.h"
#include "base/android/jni_string.h"
#include "base/lazy_instance.h"
@@ -15,10 +15,11 @@
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
+#include "googleurl/src/gurl.h"
#include "net/url_request/url_request.h"
#include "jni/AwContentsIoThreadClient_jni.h"
@@ -177,6 +178,7 @@ AwContentsIoThreadClientImpl::~AwContentsIoThreadClientImpl() {
scoped_ptr<InterceptedRequestData>
AwContentsIoThreadClientImpl::ShouldInterceptRequest(
+ const GURL& location,
const net::URLRequest* request) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (java_object_.is_null())
@@ -184,14 +186,14 @@ AwContentsIoThreadClientImpl::ShouldInterceptRequest(
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> jstring_url =
- ConvertUTF8ToJavaString(env, request->url().spec());
+ ConvertUTF8ToJavaString(env, location.spec());
ScopedJavaLocalRef<jobject> ret =
Java_AwContentsIoThreadClient_shouldInterceptRequest(
env, java_object_.obj(), jstring_url.obj());
if (ret.is_null())
return scoped_ptr<InterceptedRequestData>();
return scoped_ptr<InterceptedRequestData>(
- new InterceptedRequestData(ret));
+ new InterceptedRequestDataImpl(ret));
}
bool AwContentsIoThreadClientImpl::ShouldBlockContentUrls() const {
diff --git a/android_webview/native/aw_contents_io_thread_client_impl.h b/android_webview/native/aw_contents_io_thread_client_impl.h
index 8a2a1d8..7e56127 100644
--- a/android_webview/native/aw_contents_io_thread_client_impl.h
+++ b/android_webview/native/aw_contents_io_thread_client_impl.h
@@ -10,7 +10,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/memory/scoped_ptr.h"
-class InterceptedRequestData;
+class GURL;
namespace content {
class WebContents;
@@ -22,6 +22,8 @@ class URLRequest;
namespace android_webview {
+class InterceptedRequestData;
+
class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient {
public:
// Associates the |jclient| instance (which must implement the
@@ -35,6 +37,7 @@ class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient {
// Implementation of AwContentsIoThreadClient.
virtual scoped_ptr<InterceptedRequestData> ShouldInterceptRequest(
+ const GURL& location,
const net::URLRequest* request) OVERRIDE;
virtual bool ShouldBlockContentUrls() const OVERRIDE;
virtual bool ShouldBlockFileUrls() const OVERRIDE;
diff --git a/android_webview/native/intercepted_request_data.cc b/android_webview/native/intercepted_request_data.cc
deleted file mode 100644
index 4ef26a1..0000000
--- a/android_webview/native/intercepted_request_data.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 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/native/intercepted_request_data.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "jni/InterceptedRequestData_jni.h"
-
-using std::string;
-using base::android::ScopedJavaLocalRef;
-
-InterceptedRequestData::InterceptedRequestData(
- const base::android::JavaRef<jobject>& obj)
- : java_object_(obj) {
-}
-
-InterceptedRequestData::~InterceptedRequestData() {
-}
-
-ScopedJavaLocalRef<jobject>
-InterceptedRequestData::GetInputStream(JNIEnv* env) const {
- return Java_InterceptedRequestData_getData(env, java_object_.obj());
-}
-
-bool InterceptedRequestData::GetMimeType(JNIEnv* env,
- string* mime_type) const {
- ScopedJavaLocalRef<jstring> jstring_mime_type =
- Java_InterceptedRequestData_getMimeType(env, java_object_.obj());
- if (jstring_mime_type.is_null())
- return false;
- *mime_type = ConvertJavaStringToUTF8(jstring_mime_type);
- return true;
-}
-
-bool InterceptedRequestData::GetCharset(
- JNIEnv* env, string* charset) const {
- ScopedJavaLocalRef<jstring> jstring_charset =
- Java_InterceptedRequestData_getCharset(env, java_object_.obj());
- if (jstring_charset.is_null())
- return false;
- *charset = ConvertJavaStringToUTF8(jstring_charset);
- return true;
-}
-
-bool RegisterInterceptedRequestData(JNIEnv* env) {
- if (g_InterceptedRequestData_clazz)
- return true;
- if (!base::android::HasClass(env, kInterceptedRequestDataClassPath)) {
- DLOG(ERROR) << "Unable to find class InterceptedRequestData!";
- return false;
- }
- return RegisterNativesImpl(env);
-}
diff --git a/android_webview/native/intercepted_request_data.h b/android_webview/native/intercepted_request_data.h
deleted file mode 100644
index acbe15d..0000000
--- a/android_webview/native/intercepted_request_data.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_ANDROID_INTERCEPTED_REQUEST_DATA_H_
-#define CONTENT_BROWSER_ANDROID_INTERCEPTED_REQUEST_DATA_H_
-
-#include <string>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/memory/ref_counted.h"
-
-// This class represents the Java-side data that is to be used to complete a
-// particular URLRequest.
-class InterceptedRequestData {
- public:
- InterceptedRequestData(const base::android::JavaRef<jobject>& obj);
- ~InterceptedRequestData();
-
- base::android::ScopedJavaLocalRef<jobject> GetInputStream(JNIEnv* env) const;
- bool GetMimeType(JNIEnv* env, std::string* mime_type) const;
- bool GetCharset(JNIEnv* env, std::string* charset) const;
-
- private:
- base::android::ScopedJavaGlobalRef<jobject> java_object_;
-
- DISALLOW_COPY_AND_ASSIGN(InterceptedRequestData);
-};
-
-bool RegisterInterceptedRequestData(JNIEnv* env);
-
-#endif // CONTENT_BROWSER_ANDROID_INTERCEPTED_REQUEST_DATA_H_
diff --git a/android_webview/native/intercepted_request_data_impl.cc b/android_webview/native/intercepted_request_data_impl.cc
new file mode 100644
index 0000000..e3d9096
--- /dev/null
+++ b/android_webview/native/intercepted_request_data_impl.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2012 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/native/intercepted_request_data_impl.h"
+
+#include "android_webview/native/android_stream_reader_url_request_job.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "jni/InterceptedRequestData_jni.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_job.h"
+
+using base::android::ScopedJavaLocalRef;
+
+namespace android_webview {
+
+namespace {
+
+class StreamReaderJobDelegateImpl :
+ public AndroidStreamReaderURLRequestJob::Delegate {
+ public:
+ StreamReaderJobDelegateImpl(
+ const InterceptedRequestDataImpl* intercepted_request_data)
+ : intercepted_request_data_impl_(intercepted_request_data) {
+ DCHECK(intercepted_request_data_impl_);
+ }
+
+ virtual base::android::ScopedJavaLocalRef<jobject> OpenInputStream(
+ JNIEnv* env,
+ net::URLRequest* request) OVERRIDE {
+ return intercepted_request_data_impl_->GetInputStream(env);
+ }
+
+ virtual bool GetMimeType(JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* mime_type) OVERRIDE {
+ return intercepted_request_data_impl_->GetMimeType(env, mime_type);
+ }
+
+ virtual bool GetCharset(JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* charset) OVERRIDE {
+ return intercepted_request_data_impl_->GetCharset(env, charset);
+ }
+
+ private:
+ const InterceptedRequestDataImpl* intercepted_request_data_impl_;
+};
+
+} // namespace
+
+InterceptedRequestDataImpl::InterceptedRequestDataImpl(
+ const base::android::JavaRef<jobject>& obj)
+ : java_object_(obj) {
+}
+
+InterceptedRequestDataImpl::~InterceptedRequestDataImpl() {
+}
+
+ScopedJavaLocalRef<jobject>
+InterceptedRequestDataImpl::GetInputStream(JNIEnv* env) const {
+ return Java_InterceptedRequestData_getData(env, java_object_.obj());
+}
+
+bool InterceptedRequestDataImpl::GetMimeType(JNIEnv* env,
+ std::string* mime_type) const {
+ ScopedJavaLocalRef<jstring> jstring_mime_type =
+ Java_InterceptedRequestData_getMimeType(env, java_object_.obj());
+ if (jstring_mime_type.is_null())
+ return false;
+ *mime_type = ConvertJavaStringToUTF8(jstring_mime_type);
+ return true;
+}
+
+bool InterceptedRequestDataImpl::GetCharset(
+ JNIEnv* env, std::string* charset) const {
+ ScopedJavaLocalRef<jstring> jstring_charset =
+ Java_InterceptedRequestData_getCharset(env, java_object_.obj());
+ if (jstring_charset.is_null())
+ return false;
+ *charset = ConvertJavaStringToUTF8(jstring_charset);
+ return true;
+}
+
+bool RegisterInterceptedRequestData(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+net::URLRequestJob* InterceptedRequestDataImpl::CreateJobFor(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>
+ stream_reader_job_delegate_impl(new StreamReaderJobDelegateImpl(this));
+ return new AndroidStreamReaderURLRequestJob(
+ request, network_delegate, stream_reader_job_delegate_impl.Pass());
+}
+
+} // namespace android_webview
diff --git a/android_webview/native/intercepted_request_data_impl.h b/android_webview/native/intercepted_request_data_impl.h
new file mode 100644
index 0000000..ecafaa7
--- /dev/null
+++ b/android_webview/native/intercepted_request_data_impl.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 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_NATIVE_INTERCEPTED_REQUEST_DATA_IMPL_H_
+#define ANDROID_WEBVIEW_NATIVE_INTERCEPTED_REQUEST_DATA_IMPL_H_
+
+#include "android_webview/browser/intercepted_request_data.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/compiler_specific.h"
+
+namespace android_webview {
+
+class InterceptedRequestDataImpl : public InterceptedRequestData {
+ public:
+ // It is expected that |obj| is an instance of the Java-side
+ // org.chromium.android_webview.InterceptedRequestData class.
+ InterceptedRequestDataImpl(const base::android::JavaRef<jobject>& obj);
+ virtual ~InterceptedRequestDataImpl();
+
+ virtual base::android::ScopedJavaLocalRef<jobject>
+ GetInputStream(JNIEnv* env) const;
+ virtual bool GetMimeType(JNIEnv* env, std::string* mime_type) const;
+ virtual bool GetCharset(JNIEnv* env, std::string* charset) const;
+
+ virtual net::URLRequestJob* CreateJobFor(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+
+ private:
+ base::android::ScopedJavaGlobalRef<jobject> java_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(InterceptedRequestDataImpl);
+};
+
+bool RegisterInterceptedRequestData(JNIEnv* env);
+
+} // namespace android_webview
+
+#endif // ANDROID_WEBVIEW_NATIVE_INTERCEPTED_REQUEST_DATA_IMPL_H_
diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp
index 95f0cde..af790f0 100644
--- a/android_webview/native/webview_native.gyp
+++ b/android_webview/native/webview_native.gyp
@@ -43,8 +43,8 @@
'aw_web_contents_delegate.h',
'cookie_manager.cc',
'cookie_manager.h',
- 'intercepted_request_data.cc',
- 'intercepted_request_data.h',
+ 'intercepted_request_data_impl.cc',
+ 'intercepted_request_data_impl.h',
'js_result_handler.cc',
'js_result_handler.h',
],