diff options
author | michaelbai@chromium.org <michaelbai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-14 02:15:10 +0000 |
---|---|---|
committer | michaelbai@chromium.org <michaelbai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-14 02:15:10 +0000 |
commit | 13d06c6e882da41edb535992d17d82a9e7508594 (patch) | |
tree | e238be648ecf32306783c703f9b3a964314e38d0 | |
parent | 831e4a3102c7ad705d69386e52981c66a4ba0ccd (diff) | |
download | chromium_src-13d06c6e882da41edb535992d17d82a9e7508594.zip chromium_src-13d06c6e882da41edb535992d17d82a9e7508594.tar.gz chromium_src-13d06c6e882da41edb535992d17d82a9e7508594.tar.bz2 |
Prevent media from being loading from network when AwSettings.setBlockNetworkLoads is true
BUG=313463
NOTRY=true
Review URL: https://codereview.chromium.org/52463004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@235017 0039d316-1c4b-4281-b951-d872f2087c98
9 files changed, 203 insertions, 79 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentViewClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentViewClient.java new file mode 100644 index 0000000..eda0e97 --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/AwContentViewClient.java @@ -0,0 +1,92 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview; + +import android.content.Context; +import android.view.KeyEvent; +import android.view.View; +import android.webkit.URLUtil; +import android.webkit.WebChromeClient; + +import org.chromium.content.browser.ContentVideoView; +import org.chromium.content.browser.ContentVideoViewClient; +import org.chromium.content.browser.ContentVideoViewControls; +import org.chromium.content.browser.ContentViewClient; + +/** + * ContentViewClient implementation for WebView + */ +public class AwContentViewClient extends ContentViewClient { + + private class AwContentVideoViewClient implements ContentVideoViewClient { + @Override + public void onShowCustomView(View view) { + WebChromeClient.CustomViewCallback cb = new WebChromeClient.CustomViewCallback() { + @Override + public void onCustomViewHidden() { + ContentVideoView contentVideoView = ContentVideoView.getContentVideoView(); + if (contentVideoView != null) + contentVideoView.exitFullscreen(false); + } + }; + mAwContentsClient.onShowCustomView(view, cb); + } + + @Override + public void onDestroyContentVideoView() { + mAwContentsClient.onHideCustomView(); + } + + @Override + public View getVideoLoadingProgressView() { + return mAwContentsClient.getVideoLoadingProgressView(); + } + + @Override + public ContentVideoViewControls createControls() { + return null; + } + } + + private AwContentsClient mAwContentsClient; + private AwSettings mAwSettings; + + public AwContentViewClient(AwContentsClient awContentsClient, AwSettings awSettings) { + mAwContentsClient = awContentsClient; + mAwSettings = awSettings; + } + + @Override + public void onBackgroundColorChanged(int color) { + mAwContentsClient.onBackgroundColorChanged(color); + } + + @Override + public void onStartContentIntent(Context context, String contentUrl) { + // Callback when detecting a click on a content link. + mAwContentsClient.shouldOverrideUrlLoading(contentUrl); + } + + @Override + public void onUpdateTitle(String title) { + mAwContentsClient.onReceivedTitle(title); + } + + @Override + public boolean shouldOverrideKeyEvent(KeyEvent event) { + return mAwContentsClient.shouldOverrideKeyEvent(event); + } + + @Override + final public ContentVideoViewClient getContentVideoViewClient() { + return new AwContentVideoViewClient(); + } + + @Override + public boolean shouldBlockMediaRequest(String url) { + return mAwSettings != null ? + mAwSettings.getBlockNetworkLoads() && URLUtil.isNetworkUrl(url) : true; + } +} 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 73cce05..16485ef 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -142,6 +142,7 @@ public class AwContents { private final ViewGroup mContainerView; private ContentViewCore mContentViewCore; private final AwContentsClient mContentsClient; + private final AwContentViewClient mContentViewClient; private final AwContentsClientBridge mContentsClientBridge; private final AwWebContentsDelegate mWebContentsDelegate; private final AwContentsIoThreadClient mIoThreadClient; @@ -497,6 +498,7 @@ public class AwContents { mContainerView = containerView; mInternalAccessAdapter = internalAccessAdapter; mContentsClient = contentsClient; + mContentViewClient = new AwContentViewClient(contentsClient, settings); mLayoutSizer = layoutSizer; mSettings = settings; mDIPScale = DeviceDisplayInfo.create(mContainerView.getContext()).getDIPScale(); @@ -582,8 +584,7 @@ public class AwContents { int nativeWebContents = nativeGetWebContents(mNativeAwContents); mContentViewCore = createAndInitializeContentViewCore( mContainerView, mInternalAccessAdapter, nativeWebContents, - new AwGestureStateListener(), mContentsClient.getContentViewClient(), - mZoomControls); + new AwGestureStateListener(), mContentViewClient, mZoomControls); nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge, mIoThreadClient, mInterceptNavigationDelegate); mContentsClient.installWebContentsObserver(mContentViewCore); 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 7f72b2d..3baa767 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java @@ -4,29 +4,19 @@ package org.chromium.android_webview; -import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.Picture; -import android.graphics.Rect; -import android.graphics.RectF; import android.net.http.SslError; -import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.webkit.ConsoleMessage; import android.webkit.GeolocationPermissions; -import android.webkit.SslErrorHandler; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; -import org.chromium.content.browser.ContentVideoView; -import org.chromium.content.browser.ContentVideoViewClient; -import org.chromium.content.browser.ContentVideoViewControls; -import org.chromium.content.browser.ContentViewClient; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.WebContentsObserverAndroid; import org.chromium.net.NetError; @@ -47,8 +37,6 @@ public abstract class AwContentsClient { private AwWebContentsObserver mWebContentsObserver; - private AwContentViewClient mContentViewClient = new AwContentViewClient(); - // Last background color reported from the renderer. Holds the sentinal value INVALID_COLOR // if not valid. private int mCachedRendererBackgroundColor = INVALID_COLOR; @@ -101,36 +89,6 @@ public abstract class AwContentsClient { } - private class AwContentViewClient extends ContentViewClient { - @Override - public void onBackgroundColorChanged(int color) { - // Avoid storing the sentinal INVALID_COLOR (note that both 0 and 1 are both - // fully transparent so this transpose makes no visible difference). - mCachedRendererBackgroundColor = color == INVALID_COLOR ? 1 : color; - } - - @Override - public void onStartContentIntent(Context context, String contentUrl) { - // Callback when detecting a click on a content link. - AwContentsClient.this.shouldOverrideUrlLoading(contentUrl); - } - - @Override - public void onUpdateTitle(String title) { - AwContentsClient.this.onReceivedTitle(title); - } - - @Override - public boolean shouldOverrideKeyEvent(KeyEvent event) { - return AwContentsClient.this.shouldOverrideKeyEvent(event); - } - - @Override - final public ContentVideoViewClient getContentVideoViewClient() { - return new AwContentVideoViewClient(); - } - } - final void installWebContentsObserver(ContentViewCore contentViewCore) { if (mWebContentsObserver != null) { mWebContentsObserver.detachFromWebContents(); @@ -138,44 +96,10 @@ public abstract class AwContentsClient { mWebContentsObserver = new AwWebContentsObserver(contentViewCore); } - private class AwContentVideoViewClient implements ContentVideoViewClient { - @Override - public void onShowCustomView(View view) { - WebChromeClient.CustomViewCallback cb = new WebChromeClient.CustomViewCallback() { - @Override - public void onCustomViewHidden() { - ContentVideoView contentVideoView = ContentVideoView.getContentVideoView(); - if (contentVideoView != null) - contentVideoView.exitFullscreen(false); - } - }; - AwContentsClient.this.onShowCustomView(view, cb); - } - - @Override - public void onDestroyContentVideoView() { - AwContentsClient.this.onHideCustomView(); - } - - @Override - public View getVideoLoadingProgressView() { - return AwContentsClient.this.getVideoLoadingProgressView(); - } - - @Override - public ContentVideoViewControls createControls() { - return null; - } - } - final AwContentsClientCallbackHelper getCallbackHelper() { return mCallbackHelper; } - final ContentViewClient getContentViewClient() { - return mContentViewClient; - } - final int getCachedRendererBackgroundColor() { assert isCachedRendererBackgroundColorValid(); return mCachedRendererBackgroundColor; @@ -185,6 +109,12 @@ public abstract class AwContentsClient { return mCachedRendererBackgroundColor != INVALID_COLOR; } + final void onBackgroundColorChanged(int color) { + // Avoid storing the sentinal INVALID_COLOR (note that both 0 and 1 are both + // fully transparent so this transpose makes no visible difference). + mCachedRendererBackgroundColor = color == INVALID_COLOR ? 1 : color; + } + //-------------------------------------------------------------------------------------------- // WebView specific methods that map directly to WebViewClient / WebChromeClient //-------------------------------------------------------------------------------------------- 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 dda4946..277b27e 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 @@ -14,6 +14,7 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; import android.view.MotionEvent; import android.view.WindowManager; +import android.webkit.JavascriptInterface; import android.webkit.WebSettings; import org.apache.http.Header; @@ -1925,6 +1926,71 @@ public class AwSettingsTest extends AwTestBase { } } + public static class AudioEvent { + private CallbackHelper mCallback; + public AudioEvent(CallbackHelper callback) { + mCallback = callback; + } + + @JavascriptInterface + public void onCanPlay() { + mCallback.notifyCalled(); + } + + @JavascriptInterface + public void onError() { + mCallback.notifyCalled(); + } + } + + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + public void testBlockNetworkLoadsWithAudio() throws Throwable { + final TestAwContentsClient contentClient = new TestAwContentsClient(); + final AwTestContainerView testContainer = + createAwTestContainerViewOnMainSync(contentClient); + final AwContents awContents = testContainer.getAwContents(); + final AwSettings awSettings = getAwSettingsOnUiThread(awContents); + CallbackHelper callback = new CallbackHelper(); + awSettings.setJavaScriptEnabled(true); + + TestWebServer webServer = null; + try { + webServer = new TestWebServer(false); + final String httpPath = "/audio.mp3"; + // Don't care about the response is correct or not, just want + // to know whether Url is accessed. + final String audioUrl = webServer.setResponse(httpPath, "1", null); + + String pageHtml ="<html><body><audio controls src='" + audioUrl + "' " + + "oncanplay=\"AudioEvent.onCanPlay();\" " + + "onerror=\"AudioEvent.onError();\" /> </body></html>"; + // Actual test. Blocking should trigger onerror handler. + awSettings.setBlockNetworkLoads(true); + awContents.addPossiblyUnsafeJavascriptInterface( + new AudioEvent(callback), "AudioEvent", null); + int count = callback.getCallCount(); + loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml, + "text/html", false); + callback.waitForCallback(count, 1); + assertEquals(0, webServer.getRequestCount(httpPath)); + + // The below test failed in Nexus Galaxy. + // See https://code.google.com/p/chromium/issues/detail?id=313463 + // Unblock should load normally. + /* + awSettings.setBlockNetworkLoads(false); + count = callback.getCallCount(); + loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml, + "text/html", false); + callback.waitForCallback(count, 1); + assertTrue(0 != webServer.getRequestCount(httpPath)); + */ + } finally { + if (webServer != null) webServer.shutdown(); + } + } + // Test an assert URL (file:///android_asset/) @SmallTest @Feature({"AndroidWebView", "Navigation"}) diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 94e4b76..70403ff 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc @@ -650,6 +650,17 @@ ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() { return Java_ContentViewCore_getContext(env, obj.obj()); } +bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) { + JNIEnv* env = AttachCurrentThread(); + + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (obj.is_null()) + return true; + ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec()); + return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(), + j_url.obj()); +} + gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index ce6cb59..df33f57 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h @@ -304,6 +304,9 @@ class ContentViewCoreImpl : public ContentViewCore, // typically be an Activity context for an on screen view. base::android::ScopedJavaLocalRef<jobject> GetContext(); + // Returns True if the given media should be blocked to load. + bool ShouldBlockMediaRequest(const GURL& url); + // -------------------------------------------------------------------------- // Methods called from native code // -------------------------------------------------------------------------- diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc index 8067218..13e0f4b 100644 --- a/content/browser/media/android/browser_media_player_manager.cc +++ b/content/browser/media/android/browser_media_player_manager.cc @@ -11,6 +11,7 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_view_android.h" #include "content/common/media/media_player_messages_android.h" +#include "content/public/browser/android/content_view_core.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -65,7 +66,13 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer( case MEDIA_PLAYER_TYPE_URL: { MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge( player_id, url, first_party_for_cookies, hide_url_log, manager); - media_player_bridge->Initialize(); + BrowserMediaPlayerManager* browser_media_player_manager = + static_cast<BrowserMediaPlayerManager*>(manager); + ContentViewCoreImpl* content_view_core_impl = + static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents( + browser_media_player_manager->web_contents_)); + if (!content_view_core_impl->ShouldBlockMediaRequest(url)) + media_player_bridge->Initialize(); return media_player_bridge; } diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java index 90adc27..d00b213 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java @@ -182,4 +182,13 @@ public class ContentViewClient { public ContentVideoViewClient getContentVideoViewClient() { return null; } + + /** + * Called when BrowserMediaPlayerManager wants to load a media resource. + * @param url the URL of media resource to load. + * @return true to prevent the resource from being loaded. + */ + public boolean shouldBlockMediaRequest(String url) { + return false; + } } diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index 40090a4..c175c5b 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java @@ -3221,6 +3221,11 @@ public class ContentViewCore return mContentViewClient.getContentVideoViewClient(); } + @CalledByNative + private boolean shouldBlockMediaRequest(String url) { + return mContentViewClient.shouldBlockMediaRequest(url); + } + private native void nativeOnJavaContentViewCoreDestroyed(int nativeContentViewCoreImpl); private native void nativeLoadUrl( |