diff options
14 files changed, 234 insertions, 47 deletions
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc index 46bb312..95f2358 100644 --- a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc +++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc @@ -25,6 +25,7 @@ AwRenderViewHostExt::AwRenderViewHostExt( AwRenderViewHostExtClient* client, content::WebContents* contents) : content::WebContentsObserver(contents), client_(client), + background_color_(SK_ColorWHITE), has_new_hit_test_data_(false) { DCHECK(client_); } @@ -85,6 +86,22 @@ void AwRenderViewHostExt::SetInitialPageScale(double page_scale_factor) { page_scale_factor)); } +void AwRenderViewHostExt::SetBackgroundColor(SkColor c) { + if (background_color_ == c) + return; + background_color_ = c; + if (web_contents()->GetRenderViewHost()) { + Send(new AwViewMsg_SetBackgroundColor(web_contents()->GetRoutingID(), + background_color_)); + } +} + +void AwRenderViewHostExt::RenderViewCreated( + content::RenderViewHost* render_view_host) { + Send(new AwViewMsg_SetBackgroundColor(web_contents()->GetRoutingID(), + background_color_)); +} + void AwRenderViewHostExt::RenderProcessGone(base::TerminationStatus status) { DCHECK(CalledOnValidThread()); for (std::map<int, DocumentHasImagesResult>::iterator pending_req = diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.h b/android_webview/browser/renderer_host/aw_render_view_host_ext.h index 1f764f8..da9bcac 100644 --- a/android_webview/browser/renderer_host/aw_render_view_host_ext.h +++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.h @@ -10,6 +10,7 @@ #include "android_webview/common/aw_hit_test_data.h" #include "base/callback_forward.h" #include "base/threading/non_thread_safe.h" +#include "third_party/skia/include/core/SkColor.h" class GURL; @@ -70,9 +71,11 @@ class AwRenderViewHostExt : public content::WebContentsObserver, // Sets the initial page scale. This overrides initial scale set by // the meta viewport tag. void SetInitialPageScale(double page_scale_factor); + void SetBackgroundColor(SkColor c); private: // content::WebContentsObserver implementation. + virtual void RenderViewCreated(content::RenderViewHost* view_host) OVERRIDE; virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; virtual void DidNavigateAnyFrame( const content::LoadCommittedDetails& details, @@ -87,6 +90,8 @@ class AwRenderViewHostExt : public content::WebContentsObserver, AwRenderViewHostExtClient* client_; + SkColor background_color_; + std::map<int, DocumentHasImagesResult> pending_document_has_images_requests_; // Master copy of hit test data on the browser side. This is updated diff --git a/android_webview/common/render_view_messages.h b/android_webview/common/render_view_messages.h index 68ce3bc..69f826c 100644 --- a/android_webview/common/render_view_messages.h +++ b/android_webview/common/render_view_messages.h @@ -8,6 +8,7 @@ #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_platform_file.h" +#include "third_party/skia/include/core/SkColor.h" // Singly-included section for enums and custom IPC traits. #ifndef ANDROID_WEBVIEW_COMMON_RENDER_VIEW_MESSAGES_H_ @@ -66,6 +67,10 @@ IPC_MESSAGE_ROUTED0(AwViewMsg_ResetScrollAndScaleState) IPC_MESSAGE_ROUTED1(AwViewMsg_SetInitialPageScale, double /* page_scale_factor */) +// Sets the base background color for this view. +IPC_MESSAGE_ROUTED1(AwViewMsg_SetBackgroundColor, + SkColor); + //----------------------------------------------------------------------------- // RenderView messages // These are messages sent from the renderer to the browser process. 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 40075d7..c94c1ab 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -156,12 +156,15 @@ public class AwContents { // TODO(boliu): This should be in a global context, not per webview. private final double mDIPScale; + // The base background color, i.e. not accounting for any CSS body from the current page. + private int mBaseBackgroundColor = Color.WHITE; + // Must call nativeUpdateLastHitTestData first to update this before use. private final HitTestData mPossiblyStaleHitTestData = new HitTestData(); private DefaultVideoPosterRequestHandler mDefaultVideoPosterRequestHandler; - // Bound method for suppling Picture instances to the AwContentClient. Will be null if the + // Bound method for suppling Picture instances to the AwContentsClient. Will be null if the // picture listener API has not yet been enabled, or if it is using invalidation-only mode. private Callable<Picture> mPictureListenerContentProvider; @@ -641,7 +644,10 @@ public class AwContents { private final Rect mClipBoundsTemporary = new Rect(); public void onDraw(Canvas canvas) { - if (mNativeAwContents == 0) return; + if (mNativeAwContents == 0) { + canvas.drawColor(getEffectiveBackgroundColor()); + return; + } mScrollOffsetManager.syncScrollOffsetFromOnDraw(); @@ -651,8 +657,7 @@ public class AwContents { mClipBoundsTemporary.left, mClipBoundsTemporary.top, mClipBoundsTemporary.right, mClipBoundsTemporary.bottom )) { Log.w(TAG, "nativeOnDraw failed; clearing to background color."); - int c = mContentViewCore.getBackgroundColor(); - canvas.drawRGB(Color.red(c), Color.green(c), Color.blue(c)); + canvas.drawColor(getEffectiveBackgroundColor()); } } @@ -818,6 +823,21 @@ public class AwContents { } } + public void setBackgroundColor(int color) { + mBaseBackgroundColor = color; + if (mNativeAwContents != 0) nativeSetBackgroundColor(mNativeAwContents, color); + } + + private int getEffectiveBackgroundColor() { + // Do not ask the ContentViewCore for the background color, as it will always + // report white prior to initial navigation or post destruction, whereas we want + // to use the client supplied base value in those cases. + if (mNativeAwContents == 0 || !mContentsClient.isCachedRendererBackgroundColorValid()) { + return mBaseBackgroundColor; + } + return mContentsClient.getCachedRendererBackgroundColor(); + } + public boolean isMultiTouchZoomSupported() { return mSettings.supportsMultiTouchZoom(); } @@ -1718,6 +1738,7 @@ public class AwContents { private native int nativeReleasePopupAwContents(int nativeAwContents); private native void nativeFocusFirstNode(int nativeAwContents); + private native void nativeSetBackgroundColor(int nativeAwContents, int color); private native int nativeGetAwDrawGLViewContext(int nativeAwContents); private native Picture nativeCapturePicture(int nativeAwContents); 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 7de19e5..fe42ad3 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java @@ -52,6 +52,12 @@ public abstract class AwContentsClient { private double mDIPScale; + // Last background color reported from the renderer. Holds the sentinal value INVALID_COLOR + // if not valid. + private int mCachedRendererBackgroundColor = INVALID_COLOR; + + private static final int INVALID_COLOR = 0; + class AwWebContentsObserver extends WebContentsObserverAndroid { public AwWebContentsObserver(ContentViewCore contentViewCore) { super(contentViewCore); @@ -90,6 +96,12 @@ 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 onScaleChanged(float oldScale, float newScale) { @@ -174,6 +186,15 @@ public abstract class AwContentsClient { return mContentViewClient; } + final int getCachedRendererBackgroundColor() { + assert isCachedRendererBackgroundColorValid(); + return mCachedRendererBackgroundColor; + } + + final boolean isCachedRendererBackgroundColorValid() { + return mCachedRendererBackgroundColor != INVALID_COLOR; + } + //-------------------------------------------------------------------------------------------- // WebView specific methods that map directly to WebViewClient / WebChromeClient //-------------------------------------------------------------------------------------------- diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java new file mode 100644 index 0000000..05d44ee --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java @@ -0,0 +1,119 @@ +// 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.test; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.net.Proxy; +import android.test.FlakyTest; +import android.test.mock.MockContext; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.android_webview.AwContents; +import org.chromium.base.test.util.DisabledTest; +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.UrlUtils; +import org.chromium.base.ThreadUtils; +import org.chromium.content.browser.ContentViewCore; +import org.chromium.content.browser.ContentViewStatics; +import org.chromium.net.ProxyChangeListener; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.Callable; + +/** + * AwContents rendering / pixel tests. + */ +public class AwContentsRenderTest extends AwTestBase { + + private TestAwContentsClient mContentsClient; + private AwContents mAwContents; + + @Override + public void setUp() throws Exception { + super.setUp(); + mContentsClient = new TestAwContentsClient(); + final AwTestContainerView testContainerView = + createAwTestContainerViewOnMainSync(mContentsClient); + mAwContents = testContainerView.getAwContents(); + } + + void setBackgroundColorOnUiThread(final int c) { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mAwContents.setBackgroundColor(c); + } + }); + } + + Bitmap grabViewToBitmap() { + final Bitmap result = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); + mAwContents.onDraw(new android.graphics.Canvas(result)); + return result; + } + + void waitForBackgroundColor(final int c) throws Throwable { + pollOnUiThread(new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return grabViewToBitmap().getPixel(0, 0) == c; + } + }); + } + + @SmallTest + @Feature({"AndroidWebView"}) + public void testSetGetBackgroundColor() throws Throwable { + setBackgroundColorOnUiThread(Color.MAGENTA); + waitForBackgroundColor(Color.MAGENTA); + + setBackgroundColorOnUiThread(Color.CYAN); + waitForBackgroundColor(Color.CYAN); + + loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + + // TODO(joth): Remove this bogus check and replace with commented out block when + // AwRenderViewExt::OnSetBackgroundColor() is fully implemented (i.e. when + // crrev.com/19883002/ has rolled in) + waitForBackgroundColor(Color.WHITE); + + // waitForBackgroundColor(Color.CYAN); + // setBackgroundColorOnUiThread(Color.YELLOW); + // waitForBackgroundColor(Color.YELLOW); + // loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), + // "data:text/html,<html><head><style>body {background-color:#227788}</style></head>" + + // "<body><br>HelloWorld</body></html>"); + // waitForBackgroundColor(Color.rgb(0x22, 0x77, 0x88)); + // + // // Changing the base background should not override CSS background. + // setBackgroundColorOnUiThread(Color.MAGENTA); + // Thread.sleep(1000); + // waitForBackgroundColor(Color.rgb(0x22, 0x77, 0x88)); + + } + + @SmallTest + @Feature({"AndroidWebView"}) + public void testPictureListener() throws Throwable { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mAwContents.enableOnNewPicture(true, true); + } + }); + + int pictureCount = mContentsClient.getPictureListenerHelper().getCallCount(); + loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + mContentsClient.getPictureListenerHelper().waitForCallback(pictureCount, 1); + // Invalidation only, so picture should be null. + assertNull(mContentsClient.getPictureListenerHelper().getPicture()); + } +} diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewMiscTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewMiscTest.java index 5998b34..42de0be 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewMiscTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewMiscTest.java @@ -8,8 +8,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.graphics.Bitmap; -import android.graphics.Color; import android.net.Proxy; import android.test.FlakyTest; import android.test.mock.MockContext; @@ -113,28 +111,4 @@ public class ContentViewMiscTest extends AwTestBase { receiverRef.get().onReceive(context, intent); assertEquals(true, proxyChanged.get()); } - - /** - * @SmallTest - * @Feature({"AndroidWebView"}) - * Bug 6931901 - */ - @DisabledTest - public void testSetGetBackgroundColor() throws Throwable { - loadUrlSync(mAwContents , mContentsClient.getOnPageFinishedHelper(), "about:blank"); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mContentViewCore.setBackgroundColor(Color.MAGENTA); - } - }); - int backgroundColor = ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - Bitmap map = mContentViewCore.getBitmap(1, 1); - return map.getPixel(0,0); - } - }); - assertEquals(Color.MAGENTA, backgroundColor); - } } diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java b/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java index 512184d..cd85ef5 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java @@ -4,6 +4,7 @@ package org.chromium.android_webview.test; +import android.graphics.Picture; import android.webkit.ConsoleMessage; import org.chromium.content.browser.test.util.CallbackHelper; @@ -20,6 +21,7 @@ class TestAwContentsClient extends NullContentsClient { private final OnEvaluateJavaScriptResultHelper mOnEvaluateJavaScriptResultHelper; private final AddMessageToConsoleHelper mAddMessageToConsoleHelper; private final OnScaleChangedHelper mOnScaleChangedHelper; + private final PictureListenerHelper mPictureListenerHelper; public TestAwContentsClient() { mOnPageStartedHelper = new OnPageStartedHelper(); @@ -28,6 +30,7 @@ class TestAwContentsClient extends NullContentsClient { mOnEvaluateJavaScriptResultHelper = new OnEvaluateJavaScriptResultHelper(); mAddMessageToConsoleHelper = new AddMessageToConsoleHelper(); mOnScaleChangedHelper = new OnScaleChangedHelper(); + mPictureListenerHelper = new PictureListenerHelper(); } public OnPageStartedHelper getOnPageStartedHelper() { @@ -68,6 +71,10 @@ class TestAwContentsClient extends NullContentsClient { return mOnScaleChangedHelper; } + public PictureListenerHelper getPictureListenerHelper() { + return mPictureListenerHelper; + } + @Override public void onReceivedTitle(String title) { mUpdatedTitle = title; @@ -138,4 +145,24 @@ class TestAwContentsClient extends NullContentsClient { public void onScaleChangedScaled(float oldScale, float newScale) { mOnScaleChangedHelper.notifyCalled(oldScale, newScale); } + + public static class PictureListenerHelper extends CallbackHelper { + // Generally null, depending on |invalidationOnly| in enableOnNewPicture() + private Picture mPicture; + + public Picture getPicture() { + assert getCallCount() > 0; + return mPicture; + } + + void notifyCalled(Picture picture) { + mPicture = picture; + notifyCalled(); + } + } + + @Override + public void onNewPicture(Picture picture) { + mPictureListenerHelper.notifyCalled(picture); + } } diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index 0c128bf..9627eaa 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -676,6 +676,10 @@ void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) { web_contents_->FocusThroughTabTraversal(false); } +void AwContents::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) { + render_view_host_ext_->SetBackgroundColor(color); +} + jint AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) { return reinterpret_cast<jint>(pending_contents_.release()); } diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h index 0cef64e..8515e22 100644 --- a/android_webview/native/aw_contents.h +++ b/android_webview/native/aw_contents.h @@ -99,6 +99,7 @@ class AwContents : public FindHelper::Listener, JNIEnv* env, jobject obj); jboolean RestoreFromOpaqueState(JNIEnv* env, jobject obj, jbyteArray state); void FocusFirstNode(JNIEnv* env, jobject obj); + void SetBackgroundColor(JNIEnv* env, jobject obj, jint color); bool OnDraw(JNIEnv* env, jobject obj, jobject canvas, diff --git a/android_webview/renderer/aw_render_view_ext.cc b/android_webview/renderer/aw_render_view_ext.cc index ddc6f56..66e5233 100644 --- a/android_webview/renderer/aw_render_view_ext.cc +++ b/android_webview/renderer/aw_render_view_ext.cc @@ -155,6 +155,7 @@ bool AwRenderViewExt::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(AwViewMsg_ResetScrollAndScaleState, OnResetScrollAndScaleState) IPC_MESSAGE_HANDLER(AwViewMsg_SetInitialPageScale, OnSetInitialPageScale) + IPC_MESSAGE_HANDLER(AwViewMsg_SetBackgroundColor, OnSetBackgroundColor) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -283,4 +284,11 @@ void AwRenderViewExt::OnSetInitialPageScale(double page_scale_factor) { page_scale_factor); } +void AwRenderViewExt::OnSetBackgroundColor(SkColor c) { + if (!render_view() || !render_view()->GetWebView()) + return; + // TODO(joth): Uncomment when crrev.com/19883002/ has rolled in. + // render_view()->GetWebView()->setBaseBackgroundColor(c); +} + } // namespace android_webview diff --git a/android_webview/renderer/aw_render_view_ext.h b/android_webview/renderer/aw_render_view_ext.h index d47c1ad..744c045 100644 --- a/android_webview/renderer/aw_render_view_ext.h +++ b/android_webview/renderer/aw_render_view_ext.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/public/web/WebPermissionClient.h" +#include "third_party/skia/include/core/SkColor.h" namespace WebKit { @@ -47,6 +48,7 @@ class AwRenderViewExt : public content::RenderViewObserver, void OnResetScrollAndScaleState(); void OnSetInitialPageScale(double page_scale_factor); + void OnSetBackgroundColor(SkColor c); void UpdatePageScaleFactor(); diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 9ee3838..4d19514 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc @@ -325,15 +325,6 @@ jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) { return rwhva->GetCachedBackgroundColor(); } -void ContentViewCoreImpl::SetBackgroundColor(JNIEnv* env, - jobject obj, - jint color) { - RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid(); - if (!rwhva) - return; - rwhva->OnDidChangeBodyBackgroundColor(color); -} - void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) { Hide(); } 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 bc7e3f9..e86056e 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 @@ -883,12 +883,6 @@ import java.util.Map; return Color.WHITE; } - public void setBackgroundColor(int color) { - if (mNativeContentViewCore != 0 && getBackgroundColor() != color) { - nativeSetBackgroundColor(mNativeContentViewCore, color); - } - } - @CalledByNative private void onBackgroundColorChanged(int color) { getContentViewClient().onBackgroundColorChanged(color); @@ -3101,8 +3095,6 @@ import java.util.Map; private native int nativeGetBackgroundColor(int nativeContentViewCoreImpl); - private native void nativeSetBackgroundColor(int nativeContentViewCoreImpl, int color); - private native void nativeOnShow(int nativeContentViewCoreImpl); private native void nativeOnHide(int nativeContentViewCoreImpl); |