diff options
author | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-01 23:38:46 +0000 |
---|---|---|
committer | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-01 23:38:46 +0000 |
commit | e83c53f70b0bbd51d16d60f13e02b036bece6be4 (patch) | |
tree | 7907f270810e12a39025919996c980f34e4db71a /android_webview | |
parent | c9348b5d43fabce2824a91384e115db0130bce85 (diff) | |
download | chromium_src-e83c53f70b0bbd51d16d60f13e02b036bece6be4.zip chromium_src-e83c53f70b0bbd51d16d60f13e02b036bece6be4.tar.gz chromium_src-e83c53f70b0bbd51d16d60f13e02b036bece6be4.tar.bz2 |
Implement Android WebSettings.[get|set]BlockNetworkLoads
The existing implementation simply sets the net::LOAD_ONLY_FROM_CACHE load
flag. Chromium also supports ftp which ignores this flag, so need to
explicitly block ftp loads.
BUG=
Review URL: https://chromiumcodereview.appspot.com/10979045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159588 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'android_webview')
17 files changed, 369 insertions, 137 deletions
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp index 6962450..695e93e 100644 --- a/android_webview/android_webview.gyp +++ b/android_webview/android_webview.gyp @@ -28,6 +28,7 @@ 'common/render_view_messages.h', 'common/url_constants.cc', 'common/url_constants.h', + 'browser/aw_contents_io_thread_client.h', 'browser/aw_cookie_access_policy.cc', 'browser/aw_cookie_access_policy.h', 'browser/aw_http_auth_handler_base.cc', @@ -43,6 +44,7 @@ 'browser/renderer_host/aw_resource_dispatcher_host_delegate.cc', 'browser/renderer_host/aw_resource_dispatcher_host_delegate.h', 'browser/scoped_allow_wait_for_legacy_web_view_api.h', + 'browser/scoped_allow_wait_for_legacy_web_view_api.h', 'lib/aw_browser_dependency_factory_impl.cc', 'lib/aw_browser_dependency_factory_impl.h', 'lib/aw_content_browser_client.cc', diff --git a/android_webview/browser/aw_contents_io_thread_client.h b/android_webview/browser/aw_contents_io_thread_client.h new file mode 100644 index 0000000..ac55035 --- /dev/null +++ b/android_webview/browser/aw_contents_io_thread_client.h @@ -0,0 +1,55 @@ +// 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_CONTENTS_IO_THREAD_CLIENT_H_ +#define ANDROID_WEBVIEW_BROWSER_AW_CONTENTS_IO_THREAD_CLIENT_H_ + +#include "base/memory/scoped_ptr.h" + +class InterceptedRequestData; + +namespace net { +class URLRequest; +} + +namespace android_webview { + +// 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. +// +// Specifically this is used to associate URLRequests with the WebContents that +// the URLRequest is made for. +// +// The native class is intended to be a short-lived handle that pins the +// Java-side instance. It is preferable to use the static getter methods to +// obtain a new instance of the class rather than holding on to one for +// prolonged periods of time (see note for more details). +// +// Note: The native AwContentsIoThreadClient instance has a Global ref to +// the Java object. By keeping the native AwContentsIoThreadClient +// instance alive you're also prolonging the lifetime of the Java instance, so +// don't keep a AwContentsIoThreadClient if you don't need to. +class AwContentsIoThreadClient { + public: + virtual ~AwContentsIoThreadClient() {} + + // This will attempt to fetch the AwContentsIoThreadClient for the given + // |render_process_id|, |render_view_id| pair. + // This method can be called from any thread. + // An empty scoped_ptr is a valid return value. + static scoped_ptr<AwContentsIoThreadClient> FromID(int render_process_id, + int render_view_id); + + // This method is called on the IO thread only. + virtual scoped_ptr<InterceptedRequestData> ShouldInterceptRequest( + const net::URLRequest* request) = 0; + + // Retrieve the BlockNetworkLoads setting value of this AwContents. + // This method is called on the IO thread only. + virtual bool ShouldBlockNetworkLoads() const = 0; +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_AW_CONTENTS_IO_THREAD_CLIENT_H_ diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc index d205a98..cb5d870 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc @@ -5,17 +5,32 @@ #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h" #include "android_webview/browser/aw_login_delegate.h" +#include "android_webview/browser/aw_contents_io_thread_client.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" +#include "content/public/browser/resource_controller.h" #include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/resource_dispatcher_host_login_delegate.h" #include "content/public/browser/resource_throttle.h" +#include "content/public/common/url_constants.h" +#include "net/base/load_flags.h" +#include "net/url_request/url_request.h" namespace { base::LazyInstance<android_webview::AwResourceDispatcherHostDelegate> g_webview_resource_dispatcher_host_delegate = LAZY_INSTANCE_INITIALIZER; +// Will unconditionally cancel this resource request. +class CancelResourceThrottle : public content::ResourceThrottle { + public: + virtual void WillStartRequest(bool* defer) OVERRIDE; +}; + +void CancelResourceThrottle::WillStartRequest(bool* defer) { + controller()->Cancel(); +} + } // namespace namespace android_webview { @@ -42,6 +57,26 @@ void AwResourceDispatcherHostDelegate::RequestBeginning( int route_id, bool is_continuation_of_transferred_request, ScopedVector<content::ResourceThrottle>* throttles) { + + // Part of Implemention of WebSettings.blockNetworkLoads. + scoped_ptr<AwContentsIoThreadClient> io_client = + AwContentsIoThreadClient::FromID(child_id, route_id); + DCHECK(io_client.get()); + + if (io_client->ShouldBlockNetworkLoads()) { + // Need to cancel ftp since it does not support net::LOAD_ONLY_FROM_CACHE + // flag, so must cancel the request if network load is blocked. + if (request->url().SchemeIs(chrome::kFtpScheme)) { + throttles->push_back(new CancelResourceThrottle); + } else { + int load_flags = request->load_flags(); + load_flags &= ~(net::LOAD_BYPASS_CACHE & + net::LOAD_VALIDATE_CACHE & + net::LOAD_PREFERRING_CACHE); + load_flags |= net::LOAD_ONLY_FROM_CACHE; + request->set_load_flags(load_flags); + } + } } bool AwResourceDispatcherHostDelegate::AcceptAuthRequest( 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 fa1dde2..635d16b 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -41,6 +41,8 @@ public class AwContents { private ContentViewCore mContentViewCore; private AwContentsClient mContentsClient; private AwContentsIoThreadClient mIoThreadClient; + // This can be accessed on any thread after construction. See AwContentsIoThreadClient. + private final AwSettings mSettings; private static final class DestroyRunnable implements Runnable { private int mNativeAwContents; @@ -55,8 +57,18 @@ public class AwContents { private CleanupReference mCleanupReference; - private AwContents(ContentViewCore contentViewCore, - AwWebContentsDelegate webContentsDelegate) { + private class IoThreadClientImpl implements AwContentsIoThreadClient { + // Called on the IO thread. + @Override + public InterceptedRequestData shouldInterceptRequest(String url) { + return AwContents.this.mContentsClient.shouldInterceptRequest(url); + } + + // Called on the IO thread. + @Override + public boolean shouldBlockNetworkLoads() { + return AwContents.this.mSettings.getBlockNetworkLoads(); + } } /** @@ -69,26 +81,34 @@ public class AwContents { * @param isAccessFromFileURLsGrantedByDefault passed to ContentViewCore.initialize. */ public AwContents(ViewGroup containerView, - ContentViewCore.InternalAccessDelegate internalAccessAdapter, - ContentViewCore contentViewCore, AwContentsClient contentsClient, - NativeWindow nativeWindow, boolean privateBrowsing, - boolean isAccessFromFileURLsGrantedByDefault) { - mNativeAwContents = nativeInit(contentsClient.getWebContentsDelegate(), privateBrowsing); - mContentViewCore = contentViewCore; - mContentsClient = contentsClient; - mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents)); - - mContentViewCore.initialize(containerView, internalAccessAdapter, - nativeGetWebContents(mNativeAwContents), nativeWindow, - isAccessFromFileURLsGrantedByDefault); - mContentViewCore.setContentViewClient(contentsClient); - mContentsClient.installWebContentsObserver(mContentViewCore); + ContentViewCore.InternalAccessDelegate internalAccessAdapter, + ContentViewCore contentViewCore, AwContentsClient contentsClient, + NativeWindow nativeWindow, boolean privateBrowsing, + boolean isAccessFromFileURLsGrantedByDefault) { + mNativeAwContents = nativeInit(contentsClient.getWebContentsDelegate(), privateBrowsing); + mContentViewCore = contentViewCore; + mContentsClient = contentsClient; + mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents)); + + mContentViewCore.initialize(containerView, internalAccessAdapter, + nativeGetWebContents(mNativeAwContents), nativeWindow, + isAccessFromFileURLsGrantedByDefault); + mContentViewCore.setContentViewClient(contentsClient); + mContentsClient.installWebContentsObserver(mContentViewCore); + + mSettings = new AwSettings(mContentViewCore.getContext()); + setIoThreadClient(new IoThreadClientImpl()); } public ContentViewCore getContentViewCore() { return mContentViewCore; } + // Can be called from any thread. + public AwSettings getSettings() { + return mSettings; + } + public void setIoThreadClient(AwContentsIoThreadClient ioThreadClient) { mIoThreadClient = ioThreadClient; nativeSetIoThreadClient(mNativeAwContents, mIoThreadClient); 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 9f971e2..15be569 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java @@ -145,6 +145,8 @@ public abstract class AwContentsClient extends ContentViewClient { public abstract void onProgressChanged(int progress); + public abstract InterceptedRequestData shouldInterceptRequest(String url); + public abstract boolean shouldOverrideUrlLoading(String url); public abstract void onUnhandledKeyEvent(KeyEvent event); diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java index ba1f91e..a81c06b 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java @@ -18,5 +18,9 @@ import org.chromium.base.JNINamespace; public interface AwContentsIoThreadClient { // Called on the IO thread. @CalledByNative - InterceptedRequestData shouldInterceptRequest(String url); + public InterceptedRequestData shouldInterceptRequest(String url); + + // Called on the IO thread. + @CalledByNative + public boolean shouldBlockNetworkLoads(); } diff --git a/android_webview/java/src/org/chromium/android_webview/AwSettings.java b/android_webview/java/src/org/chromium/android_webview/AwSettings.java new file mode 100644 index 0000000..a6d2e17 --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/AwSettings.java @@ -0,0 +1,57 @@ +// 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; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Process; + +/** + * Stores Android WebView specific settings that does not need to be synced to WebKit. + * Use {@link org.chromium.content.browser.ContentSettings} for WebKit settings. + * + * Methods in this class can be called from any thread, including threads created by + * the client of WebView. + */ +public class AwSettings { + // Lock to protect all settings. + private final Object mAwSettingsLock = new Object(); + + private final Context mContext; + private boolean mBlockNetworkLoads; // Default depends on permission of embedding APK. + + public AwSettings(Context context) { + mContext = context; + mBlockNetworkLoads = mContext.checkPermission( + android.Manifest.permission.INTERNET, + Process.myPid(), + Process.myUid()) != PackageManager.PERMISSION_GRANTED; + } + + /** + * See {@link android.webkit.WebSettings#setBlockNetworkLoads}. + */ + public void setBlockNetworkLoads(boolean flag) { + synchronized (mAwSettingsLock) { + if (!flag && mContext.checkPermission( + android.Manifest.permission.INTERNET, + Process.myPid(), + Process.myUid()) != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Permission denied - " + + "application missing INTERNET permission"); + } + mBlockNetworkLoads = flag; + } + } + + /** + * See {@link android.webkit.WebSettings#getBlockNetworkLoads}. + */ + public boolean getBlockNetworkLoads() { + synchronized (mAwSettingsLock) { + return mBlockNetworkLoads; + } + } +} 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 176db98..211f6dd 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 @@ -12,6 +12,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.content.browser.ContentSettings; import org.chromium.content.browser.ContentView; import org.chromium.content.browser.ContentViewCore; @@ -203,6 +204,16 @@ public class AndroidWebViewTestBase }); } + protected AwSettings getAwSettingsOnUiThread( + final AwContents awContents) throws Throwable { + return runTestOnUiThreadAndGetResult(new Callable<AwSettings>() { + @Override + public AwSettings call() throws Exception { + return awContents.getSettings(); + } + }); + } + /** * Executes the given snippet of JavaScript code within the given ContentView. Returns the * result of its execution in JSON format. diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java index 7680da1..d3bf304 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java @@ -10,6 +10,8 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; import org.chromium.android_webview.AndroidProtocolHandler; +import org.chromium.android_webview.AwContents; +import org.chromium.android_webview.AwSettings; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.TestFileUtil; import org.chromium.base.test.util.UrlUtils; @@ -1492,7 +1494,7 @@ public class AwSettingsTest extends AndroidWebViewTestBase { imageHeaders.add(Pair.create("Content-Type", "image/png")); final String imagePath = "/image.png"; webServer.setResponseBase64( - imagePath, generator.getImageSourceNoAdvance(), imageHeaders); + imagePath, generator.getImageSourceNoAdvance(), imageHeaders); final String pagePath = "/html_image.html"; final String httpUrlImageHtml = generator.getPageTemplateSource(imagePath); @@ -1501,7 +1503,7 @@ public class AwSettingsTest extends AndroidWebViewTestBase { settings.setImagesEnabled(false); loadUrlSync(contentView, contentClient.getOnPageFinishedHelper(), httpImageUrl); assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING, - getTitleOnUiThread(contentView)); + getTitleOnUiThread(contentView)); settings.setImagesEnabled(true); assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { @@ -1735,4 +1737,61 @@ public class AwSettingsTest extends AndroidWebViewTestBase { private void resetResourceContext() { AndroidProtocolHandler.setResourceContextForTesting(null); } + + @SmallTest + @Feature({"Android-WebView", "Preferences"}) + public void testBlockNetworkLoadsWithHttpResources() throws Throwable { + final TestAwContentsClient contentClient = new TestAwContentsClient(); + final AwTestContainerView testContainer = + createAwTestContainerViewOnMainSync(false, contentClient); + final ContentViewCore contentView = testContainer.getContentViewCore(); + final ContentSettings contentSettings = getContentSettingsOnUiThread(contentView); + final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents()); + contentSettings.setJavaScriptEnabled(true); + ImagePageGenerator generator = new ImagePageGenerator(0, false); + + TestWebServer webServer = null; + String fileName = null; + try { + // Set up http image. + webServer = new TestWebServer(false); + List<Pair<String, String>> imageHeaders = new ArrayList<Pair<String, String>>(); + imageHeaders.add(Pair.create("Content-Type", "image/png")); + imageHeaders.add(Pair.create("Cache-Control", "no-store")); + final String httpPath = "/image.png"; + final String imageUrl = webServer.setResponseBase64( + httpPath, generator.getImageSourceNoAdvance(), imageHeaders); + + // Set up file html that loads http iframe. + String pageHtml ="<img src='" + imageUrl + "' " + + "onload=\"document.title='img_onload_fired';\" " + + "onerror=\"document.title='img_onerror_fired';\" />"; + Context context = getInstrumentation().getTargetContext(); + fileName = context.getCacheDir() + "/block_network_loads_test.html"; + TestFileUtil.deleteFile(fileName); // Remove leftover file if any. + TestFileUtil.createNewHtmlFile(fileName, "unset", pageHtml); + + // Actual test. Note that image may have been cached before test started. + // Blocking should trigger onerror handler. + awSettings.setBlockNetworkLoads(true); + loadUrlSync( + contentView, + contentClient.getOnPageFinishedHelper(), + "file:///" + fileName); + assertEquals(0, webServer.getRequestCount(httpPath)); + assertEquals("img_onerror_fired", getTitleOnUiThread(contentView)); + + // Unblock should load normally. + awSettings.setBlockNetworkLoads(false); + loadUrlSync( + contentView, + contentClient.getOnPageFinishedHelper(), + "file:///" + fileName); + assertEquals(1, webServer.getRequestCount(httpPath)); + assertEquals("img_onload_fired", getTitleOnUiThread(contentView)); + } finally { + if (fileName != null) TestFileUtil.deleteFile(fileName); + if (webServer != null) webServer.shutdown(); + } + } } 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 e753795..5605715 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 @@ -10,6 +10,7 @@ import android.webkit.ConsoleMessage; import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwHttpAuthHandler; +import org.chromium.android_webview.InterceptedRequestData; import org.chromium.android_webview.JsPromptResultReceiver; import org.chromium.android_webview.JsResultReceiver; @@ -32,6 +33,11 @@ class NullContentsClient extends AwContentsClient { } @Override + public InterceptedRequestData shouldInterceptRequest(String url) { + return null; + } + + @Override public boolean onConsoleMessage(ConsoleMessage consoleMessage) { return false; } diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/TestWebServer.java b/android_webview/javatests/src/org/chromium/android_webview/test/TestWebServer.java index 0e56f56..d52cd49 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/TestWebServer.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/TestWebServer.java @@ -82,6 +82,7 @@ public class TestWebServer { } private Map<String, Response> mResponseMap = new HashMap<String, Response>(); + private Map<String, Integer> mResponseCountMap = new HashMap<String, Integer>(); /** * Create and start a local HTTP server instance. @@ -155,6 +156,7 @@ public class TestWebServer { String requestPath, String responseString, List<Pair<String, String>> responseHeaders) { mResponseMap.put(requestPath, new Response(responseString.getBytes(), responseHeaders)); + mResponseCountMap.put(requestPath, new Integer(0)); return mServerUri + requestPath; } @@ -176,9 +178,16 @@ public class TestWebServer { mResponseMap.put(requestPath, new Response(Base64.decode(base64EncodedResponse, Base64.DEFAULT), responseHeaders)); + mResponseCountMap.put(requestPath, Integer.valueOf(0)); return mServerUri + requestPath; } + public int getRequestCount(String requestPath) { + Integer count = mResponseCountMap.get(requestPath); + if (count == null) throw new IllegalArgumentException("Path not set: " + requestPath); + return count.intValue(); + } + private URLConnection openConnection(URL url) throws IOException, NoSuchAlgorithmException, KeyManagementException { if (mSsl) { @@ -258,6 +267,8 @@ public class TestWebServer { for (Pair<String, String> header : response.mResponseHeaders) { httpResponse.addHeader(header.first, header.second); } + mResponseCountMap.put(path, Integer.valueOf( + mResponseCountMap.get(path).intValue() + 1)); } StatusLine sl = httpResponse.getStatusLine(); Log.i(TAG, sl.getStatusCode() + "(" + sl.getReasonPhrase() + ")"); diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc index 8e877e1..f041015 100644 --- a/android_webview/native/android_webview_jni_registrar.cc +++ b/android_webview/native/android_webview_jni_registrar.cc @@ -8,7 +8,7 @@ #include "android_webview/native/android_stream_reader_url_request_job.h" #include "android_webview/native/android_web_view_util.h" #include "android_webview/native/aw_contents.h" -#include "android_webview/native/aw_contents_io_thread_client.h" +#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/js_result_handler.h" @@ -24,7 +24,7 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = { RegisterAndroidStreamReaderUrlRequestJob }, { "AndroidWebViewUtil", RegisterAndroidWebViewUtil }, { "AwContents", RegisterAwContents }, - { "AwContentsIoThreadClient", RegisterAwContentsIoThreadClient}, + { "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl}, { "AwHttpAuthHandler", RegisterAwHttpAuthHandler }, { "CookieManager", RegisterCookieManager }, { "JsResultHandler", RegisterJsResultHandler }, diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index 024da78..f1c6322 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -8,7 +8,7 @@ #include "android_webview/native/aw_browser_dependency_factory.h" #include "android_webview/native/aw_contents_container.h" #include "android_webview/native/aw_web_contents_delegate.h" -#include "android_webview/native/aw_contents_io_thread_client.h" +#include "android_webview/native/aw_contents_io_thread_client_impl.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/bind.h" @@ -209,7 +209,7 @@ void AwContents::onReceivedHttpAuthRequest( void AwContents::SetIoThreadClient(JNIEnv* env, jobject obj, jobject client) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); content::WebContents* web_contents = contents_container_->GetWebContents(); - AwContentsIoThreadClient::Associate( + AwContentsIoThreadClientImpl::Associate( web_contents, ScopedJavaLocalRef<jobject>(env, client)); } diff --git a/android_webview/native/aw_contents_io_thread_client.h b/android_webview/native/aw_contents_io_thread_client.h deleted file mode 100644 index 3ba8b09..0000000 --- a/android_webview/native/aw_contents_io_thread_client.h +++ /dev/null @@ -1,78 +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 ANDROID_WEBVIEW_NATIVE_AW_CONTENTS_IO_THREAD_CLIENT_H_ -#define ANDROID_WEBVIEW_NATIVE_AW_CONTENTS_IO_THREAD_CLIENT_H_ - -#include "base/android/scoped_java_ref.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -class GURL; -class InterceptedRequestData; -class JavaDelegateMapMaintainer; - -namespace content { -class WebContents; -} - -namespace net { -class URLRequest; -} - -namespace android_webview { - -// 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. -// -// Specifically this is used to implement URLRequest intercepting in a way that -// lets the embedder associate URLRequests with the WebContents that the -// URLRequest is made for. -// -// The native class is intended to be a short-lived handle that pins the -// Java-side instance. It is preferable to use the static getter methods to -// obtain a new instance of the class rather than holding on to one for -// prolonged periods of time (see note for more details). -// -// Note: The native AwContentsIoThreadClient instance has a Global ref to -// the Java object. By keeping the native AwContentsIoThreadClient -// instance alive you're also prolonging the lifetime of the Java instance, so -// don't keep a AwContentsIoThreadClient if you don't need to. -class AwContentsIoThreadClient { - public: - // This will attempt to fetch the AwContentsIoThreadClient for the given - // |render_process_id|, |render_view_id| pair. - // This method can be called from any thread. - // An empty scoped_ptr is a valid return value. - static AwContentsIoThreadClient FromID(int render_process_id, - int render_view_id); - - // Associates the |jclient| instance (which must implement the - // AwContentsIoThreadClient Java interface) with the |web_contents|. - // This should be called at most once per |web_contents|. - static void Associate(content::WebContents* web_contents, - const base::android::JavaRef<jobject>& jclient); - - AwContentsIoThreadClient(const AwContentsIoThreadClient& orig); - ~AwContentsIoThreadClient(); - void operator=(const AwContentsIoThreadClient& rhs); - - // This method is called on the IO thread only. - scoped_ptr<InterceptedRequestData> ShouldInterceptRequest( - const net::URLRequest* request); - - private: - AwContentsIoThreadClient(); - AwContentsIoThreadClient(const base::android::JavaRef<jobject>& jclient); - - base::android::ScopedJavaGlobalRef<jobject> java_object_; -}; - -// JNI registration method. -bool RegisterAwContentsIoThreadClient(JNIEnv* env); - - -} // namespace android_webview - -#endif // ANDROID_WEBVIEW_NATIVE_AW_CONTENTS_IO_THREAD_CLIENT_H_ diff --git a/android_webview/native/aw_contents_io_thread_client.cc b/android_webview/native/aw_contents_io_thread_client_impl.cc index 820a418..0e80d44 100644 --- a/android_webview/native/aw_contents_io_thread_client.cc +++ b/android_webview/native/aw_contents_io_thread_client_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "android_webview/native/aw_contents_io_thread_client.h" +#include "android_webview/native/aw_contents_io_thread_client_impl.h" #include <map> #include <utility> @@ -54,18 +54,18 @@ class RvhToIoThreadClientMap { void Erase(pair<int, int> rvh_id); private: - static LazyInstance<RvhToIoThreadClientMap> s_instance_; + static LazyInstance<RvhToIoThreadClientMap> g_instance_; base::Lock map_lock_; RenderViewHostToWeakDelegateMapType rvh_to_weak_delegate_map_; }; // static -LazyInstance<RvhToIoThreadClientMap> RvhToIoThreadClientMap::s_instance_ = +LazyInstance<RvhToIoThreadClientMap> RvhToIoThreadClientMap::g_instance_ = LAZY_INSTANCE_INITIALIZER; // static RvhToIoThreadClientMap* RvhToIoThreadClientMap::GetInstance() { - return s_instance_.Pointer(); + return g_instance_.Pointer(); } void RvhToIoThreadClientMap::Insert(pair<int, int> rvh_id, @@ -142,50 +142,37 @@ void ClientMapEntryUpdater::WebContentsDestroyed(WebContents* web_contents) { } // namespace -// AwContentsIoThreadClient --------------------------------------------------- +// AwContentsIoThreadClientImpl ----------------------------------------------- // static -void AwContentsIoThreadClient::Associate( - WebContents* web_contents, - const JavaRef<jobject>& jclient) { - JNIEnv* env = AttachCurrentThread(); - // The ClientMapEntryUpdater lifespan is tied to the WebContents. - new ClientMapEntryUpdater(env, web_contents, jclient.obj()); -} - -// static -AwContentsIoThreadClient +scoped_ptr<AwContentsIoThreadClient> AwContentsIoThreadClient::FromID(int render_process_id, int render_view_id) { pair<int, int> rvh_id(render_process_id, render_view_id); ScopedJavaLocalRef<jobject> java_delegate = RvhToIoThreadClientMap::GetInstance()->Get(rvh_id); if (java_delegate.is_null()) - return AwContentsIoThreadClient(); - - return AwContentsIoThreadClient(java_delegate); -} - -AwContentsIoThreadClient::AwContentsIoThreadClient() { -} - -AwContentsIoThreadClient::AwContentsIoThreadClient(const JavaRef<jobject>& obj) - : java_object_(obj) { -} + return scoped_ptr<AwContentsIoThreadClient>(); -AwContentsIoThreadClient::AwContentsIoThreadClient( - const AwContentsIoThreadClient& orig) - : java_object_(orig.java_object_) { + return scoped_ptr<AwContentsIoThreadClient>( + new AwContentsIoThreadClientImpl(java_delegate)); } -void AwContentsIoThreadClient::operator=(const AwContentsIoThreadClient& rhs) { - java_object_.Reset(rhs.java_object_); +// static +void AwContentsIoThreadClientImpl::Associate( + WebContents* web_contents, + const JavaRef<jobject>& jclient) { + JNIEnv* env = AttachCurrentThread(); + // The ClientMapEntryUpdater lifespan is tied to the WebContents. + new ClientMapEntryUpdater(env, web_contents, jclient.obj()); } -AwContentsIoThreadClient::~AwContentsIoThreadClient() { +AwContentsIoThreadClientImpl::AwContentsIoThreadClientImpl( + const JavaRef<jobject>& obj) + : java_object_(obj) { } scoped_ptr<InterceptedRequestData> -AwContentsIoThreadClient::ShouldInterceptRequest( +AwContentsIoThreadClientImpl::ShouldInterceptRequest( const net::URLRequest* request) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (java_object_.is_null()) @@ -203,7 +190,17 @@ AwContentsIoThreadClient::ShouldInterceptRequest( new InterceptedRequestData(ret)); } -bool RegisterAwContentsIoThreadClient(JNIEnv* env) { +bool AwContentsIoThreadClientImpl::ShouldBlockNetworkLoads() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (java_object_.is_null()) + return false; + + JNIEnv* env = AttachCurrentThread(); + return Java_AwContentsIoThreadClient_shouldBlockNetworkLoads( + env, java_object_.obj()); +} + +bool RegisterAwContentsIoThreadClientImpl(JNIEnv* env) { return RegisterNativesImpl(env); } diff --git a/android_webview/native/aw_contents_io_thread_client_impl.h b/android_webview/native/aw_contents_io_thread_client_impl.h new file mode 100644 index 0000000..b0529a1 --- /dev/null +++ b/android_webview/native/aw_contents_io_thread_client_impl.h @@ -0,0 +1,51 @@ +// 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_AW_CONTENTS_IO_THREAD_CLIENT_IMPL_H_ +#define ANDROID_WEBVIEW_NATIVE_AW_CONTENTS_IO_THREAD_CLIENT_IMPL_H_ + +#include "android_webview/browser/aw_contents_io_thread_client.h" + +#include "base/android/scoped_java_ref.h" +#include "base/memory/scoped_ptr.h" + +class InterceptedRequestData; + +namespace content { +class WebContents; +} + +namespace net { +class URLRequest; +} + +namespace android_webview { + +class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient { + public: + // Associates the |jclient| instance (which must implement the + // AwContentsIoThreadClient Java interface) with the |web_contents|. + // This should be called at most once per |web_contents|. + static void Associate(content::WebContents* web_contents, + const base::android::JavaRef<jobject>& jclient); + + AwContentsIoThreadClientImpl(const base::android::JavaRef<jobject>& jclient); + + // Implementation of AwContentsIoThreadClient. + virtual scoped_ptr<InterceptedRequestData> ShouldInterceptRequest( + const net::URLRequest* request) OVERRIDE; + virtual bool ShouldBlockNetworkLoads() const OVERRIDE; + + private: + base::android::ScopedJavaGlobalRef<jobject> java_object_; + + DISALLOW_COPY_AND_ASSIGN(AwContentsIoThreadClientImpl); +}; + +// JNI registration method. +bool RegisterAwContentsIoThreadClientImpl(JNIEnv* env); + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_NATIVE_AW_CONTENTS_IO_THREAD_CLIENT_IMPL_H_ diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp index 57d0e89..95f0cde 100644 --- a/android_webview/native/webview_native.gyp +++ b/android_webview/native/webview_native.gyp @@ -33,8 +33,8 @@ 'aw_contents.cc', 'aw_contents.h', 'aw_contents_container.h', - 'aw_contents_io_thread_client.cc', - 'aw_contents_io_thread_client.h', + 'aw_contents_io_thread_client_impl.cc', + 'aw_contents_io_thread_client_impl.h', 'aw_http_auth_handler.cc', 'aw_http_auth_handler.h', 'aw_javascript_dialog_creator.cc', |