diff options
16 files changed, 233 insertions, 23 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 0c7f082..bbb2351 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 @@ -68,6 +68,11 @@ void AwRenderViewHostExt::SetTextZoomLevel(double level) { Send(new AwViewMsg_SetTextZoomLevel(web_contents()->GetRoutingID(), level)); } +void AwRenderViewHostExt::ResetScrollAndScaleState() { + DCHECK(CalledOnValidThread()); + Send(new AwViewMsg_ResetScrollAndScaleState(web_contents()->GetRoutingID())); +} + void AwRenderViewHostExt::RenderViewGone(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 fae35e9..eb4ab1c 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 @@ -54,6 +54,8 @@ class AwRenderViewHostExt : public content::WebContentsObserver, // Text Autosizing. void SetTextZoomLevel(double level); + void ResetScrollAndScaleState(); + private: // content::WebContentsObserver implementation. virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE; diff --git a/android_webview/common/render_view_messages.h b/android_webview/common/render_view_messages.h index 39f1915..f3680e40 100644 --- a/android_webview/common/render_view_messages.h +++ b/android_webview/common/render_view_messages.h @@ -64,6 +64,11 @@ IPC_SYNC_MESSAGE_ROUTED0_0(AwViewMsg_CapturePictureSync) IPC_MESSAGE_ROUTED1(AwViewMsg_SetTextZoomLevel, double /* zoom_level */) +// Resets WebKit WebView scrolling and scale state. We need to send this +// message whenever we want to guarantee that page's scale will be +// recalculated by WebKit. +IPC_MESSAGE_ROUTED0(AwViewMsg_ResetScrollAndScaleState) + //----------------------------------------------------------------------------- // 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 bbd07b4..f684d8a 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -673,6 +673,15 @@ public class AwContents { msg.sendToTarget(); } + public void resetScrollAndScaleState() { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + nativeResetScrollAndScaleState(mNativeAwContents); + } + }); + } + //-------------------------------------------------------------------------------------------- // View and ViewGroup method implementations //-------------------------------------------------------------------------------------------- @@ -1069,6 +1078,8 @@ public class AwContents { private native void nativeSetWebContents(int nativeAwContents, int nativeNewWebContents); private native void nativeFocusFirstNode(int nativeAwContents); + private native void nativeResetScrollAndScaleState(int nativeAwContents); + private native boolean nativeDrawSW(int nativeAwContents, Canvas canvas, int clipX, int clipY, int clipW, int clipH); private native int nativeGetAwDrawGLViewContext(int nativeAwContents); diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java index 3e9e5c9..d3e6c6f 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java @@ -18,26 +18,6 @@ import android.util.Log; * Tests for the WebViewClient.onScaleChanged. */ public class AwContentsClientOnScaleChangedTest extends AndroidWebViewTestBase { - private static class OnScaleChangedHelper extends CallbackHelper { - private float mLastScaleRatio; - - public void notifyCalled(float ratio) { - super.notifyCalled(); - mLastScaleRatio = ratio; - } - } - - private static class TestAwContentsClient - extends org.chromium.android_webview.test.TestAwContentsClient { - private OnScaleChangedHelper mOnScaleChangedHelper = new OnScaleChangedHelper(); - @Override - public void onScaleChanged(float oldScale, float newScale) { - // We should not be getting any messages from scrolling. - assertTrue(oldScale != newScale); - mOnScaleChangedHelper.notifyCalled(newScale / oldScale); - } - } - private TestAwContentsClient mContentsClient; private AwContents mAwContents; @@ -65,11 +45,12 @@ public class AwContentsClientOnScaleChangedTest extends AndroidWebViewTestBase { loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT_HTML, "text/html", false); ContentViewCore core = mAwContents.getContentViewCore(); - int callCount = mContentsClient.mOnScaleChangedHelper.getCallCount(); + int callCount = mContentsClient.getOnScaleChangedHelper().getCallCount(); core.onSizeChanged(core.getWidth() / 2, core.getHeight() / 2, core.getWidth(), core.getHeight()); // TODO: Investigate on using core.zoomIn(); - mContentsClient.mOnScaleChangedHelper.waitForCallback(callCount); - assertTrue(mContentsClient.mOnScaleChangedHelper.mLastScaleRatio < 1); + mContentsClient.getOnScaleChangedHelper().waitForCallback(callCount); + assertTrue("Scale ratio:" + mContentsClient.getOnScaleChangedHelper().getLastScaleRatio(), + mContentsClient.getOnScaleChangedHelper().getLastScaleRatio() < 1); } } 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 c856f32..3997723 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 @@ -30,6 +30,7 @@ import org.chromium.content.browser.test.util.HistoryUtils; import org.chromium.net.test.util.TestWebServer; import org.chromium.ui.gfx.DeviceDisplayInfo; +import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.ArrayList; @@ -1199,6 +1200,73 @@ public class AwSettingsTest extends AndroidWebViewTestBase { } } + class AwSettingsLoadWithOverviewModeTestHelper extends AwSettingsTestHelper<Boolean> { + private static final float DEFAULT_PAGE_SCALE = 1.0f; + + AwSettingsLoadWithOverviewModeTestHelper( + AwContents awContents, + TestAwContentsClient contentViewClient, + boolean withViewPortTag) throws Throwable { + super(awContents, contentViewClient, true); + mWithViewPortTag = withViewPortTag; + mContentSettings.setUseWideViewPort(true); + } + + @Override + protected Boolean getAlteredValue() { + return ENABLED; + } + + @Override + protected Boolean getInitialValue() { + return DISABLED; + } + + @Override + protected Boolean getCurrentValue() { + return mContentSettings.getLoadWithOverviewMode(); + } + + @Override + protected void setCurrentValue(Boolean value) { + mExpectScaleChange = mContentSettings.getLoadWithOverviewMode() != value; + if (mExpectScaleChange) { + mOnScaleChangedCallCount = + mContentViewClient.getOnScaleChangedHelper().getCallCount(); + } + mContentSettings.setLoadWithOverviewMode(value); + mAwContents.resetScrollAndScaleState(); + } + + @Override + protected void doEnsureSettingHasValue(Boolean value) throws Throwable { + loadDataSync(getData()); + if (mExpectScaleChange) { + mContentViewClient.getOnScaleChangedHelper(). + waitForCallback(mOnScaleChangedCallCount); + mExpectScaleChange = false; + } + float currentScale = AwSettingsTest.this.getScaleOnUiThread(mAwContents); + if (value) { + assertTrue("Expected: " + currentScale + " < " + DEFAULT_PAGE_SCALE, + currentScale < DEFAULT_PAGE_SCALE); + } else { + assertEquals(DEFAULT_PAGE_SCALE, currentScale); + } + } + + private String getData() { + return "<html><head>" + + (mWithViewPortTag ? "<meta name='viewport' content='width=3000' />" : "") + + "</head>" + + "<body></body></html>"; + } + + private final boolean mWithViewPortTag; + private boolean mExpectScaleChange; + private int mOnScaleChangedCallCount; + } + // The test verifies that JavaScript is disabled upon WebView // creation without accessing ContentSettings. If the test passes, // it means that WebView-specific web preferences configuration @@ -2291,6 +2359,60 @@ public class AwSettingsTest extends AndroidWebViewTestBase { assertEquals(viewportTagSpecifiedWidth, getTitleOnUiThread(awContents)); } + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + public void testLoadWithOverviewModeWithTwoViews() throws Throwable { + ViewPair views = createViews(); + runPerViewSettingsTest( + new AwSettingsLoadWithOverviewModeTestHelper( + views.getContents0(), views.getClient0(), false), + new AwSettingsLoadWithOverviewModeTestHelper( + views.getContents1(), views.getClient1(), false)); + } + + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + public void testLoadWithOverviewModeViewportTagWithTwoViews() throws Throwable { + ViewPair views = createViews(); + runPerViewSettingsTest( + new AwSettingsLoadWithOverviewModeTestHelper( + views.getContents0(), views.getClient0(), true), + new AwSettingsLoadWithOverviewModeTestHelper( + views.getContents1(), views.getClient1(), true)); + } + + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + // Verify that LoadViewOverviewMode doesn't affect pages with initial scale + // set in the viewport tag. + public void testLoadWithOverviewModeViewportScale() throws Throwable { + final TestAwContentsClient contentClient = new TestAwContentsClient(); + final AwTestContainerView testContainerView = + createAwTestContainerViewOnMainSync(contentClient); + final AwContents awContents = testContainerView.getAwContents(); + ContentSettings settings = getContentSettingsOnUiThread(awContents); + CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); + + final int pageScale = 2; + final String page = "<html><head>" + + "<meta name='viewport' content='width=3000, initial-scale=" + pageScale + + "' /></head>" + + "<body></body></html>"; + + assertFalse(settings.getUseWideViewPort()); + assertFalse(settings.getLoadWithOverviewMode()); + loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); + assertEquals(1.0f, getScaleOnUiThread(awContents)); + + settings.setUseWideViewPort(true); + settings.setLoadWithOverviewMode(true); + awContents.resetScrollAndScaleState(); + int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); + loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); + contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); + assertEquals((float)pageScale, getScaleOnUiThread(awContents)); + } + static class ViewPair { private final AwContents contents0; private final TestAwContentsClient client0; @@ -2415,4 +2537,13 @@ public class AwSettingsTest extends AndroidWebViewTestBase { private void resetResourceContext() { AndroidProtocolHandler.setResourceContextForTesting(null); } + + private float getScaleOnUiThread(final AwContents awContents) throws Throwable { + return runTestOnUiThreadAndGetResult(new Callable<Float>() { + @Override + public Float call() throws Exception { + return awContents.getContentViewCore().getScale(); + } + }); + } } 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 8e113d9..2f81b57 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 @@ -19,6 +19,7 @@ class TestAwContentsClient extends NullContentsClient { private OnReceivedErrorHelper mOnReceivedErrorHelper; private OnEvaluateJavaScriptResultHelper mOnEvaluateJavaScriptResultHelper; private AddMessageToConsoleHelper mAddMessageToConsoleHelper; + private OnScaleChangedHelper mOnScaleChangedHelper; public TestAwContentsClient() { mOnPageStartedHelper = new OnPageStartedHelper(); @@ -26,6 +27,7 @@ class TestAwContentsClient extends NullContentsClient { mOnReceivedErrorHelper = new OnReceivedErrorHelper(); mOnEvaluateJavaScriptResultHelper = new OnEvaluateJavaScriptResultHelper(); mAddMessageToConsoleHelper = new AddMessageToConsoleHelper(); + mOnScaleChangedHelper = new OnScaleChangedHelper(); } public OnPageStartedHelper getOnPageStartedHelper() { @@ -48,6 +50,24 @@ class TestAwContentsClient extends NullContentsClient { return mAddMessageToConsoleHelper; } + public static class OnScaleChangedHelper extends CallbackHelper { + private float mPreviousScale; + private float mCurrentScale; + public void notifyCalled(float oldScale, float newScale) { + mPreviousScale = oldScale; + mCurrentScale = newScale; + super.notifyCalled(); + } + public float getLastScaleRatio() { + assert getCallCount() > 0; + return mCurrentScale / mPreviousScale; + } + } + + public OnScaleChangedHelper getOnScaleChangedHelper() { + return mOnScaleChangedHelper; + } + @Override public void onUpdateTitle(String title) { mUpdatedTitle = title; @@ -113,4 +133,9 @@ class TestAwContentsClient extends NullContentsClient { notifyCalled(); } } + + @Override + public void onScaleChanged(float oldScale, float newScale) { + mOnScaleChangedHelper.notifyCalled(oldScale, newScale); + } } diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index 6bef690..1731e20 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -665,6 +665,10 @@ jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) { return reinterpret_cast<jint>(pending_contents_.release()); } +void AwContents::ResetScrollAndScaleState(JNIEnv* env, jobject obj) { + render_view_host_ext_->ResetScrollAndScaleState(); +} + ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env, jobject obj) { return browser_view_renderer_->CapturePicture(); diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h index 889aaa8..2fc8256 100644 --- a/android_webview/native/aw_contents.h +++ b/android_webview/native/aw_contents.h @@ -159,6 +159,8 @@ class AwContents : public FindHelper::Listener, void SetPendingWebContentsForPopup(scoped_ptr<content::WebContents> pending); jint ReleasePopupWebContents(JNIEnv* env, jobject obj); + void ResetScrollAndScaleState(JNIEnv* env, jobject obj); + private: void SetWebContents(content::WebContents* web_contents); diff --git a/android_webview/renderer/aw_render_view_ext.cc b/android_webview/renderer/aw_render_view_ext.cc index c895ed47..bcc2c20 100644 --- a/android_webview/renderer/aw_render_view_ext.cc +++ b/android_webview/renderer/aw_render_view_ext.cc @@ -145,6 +145,8 @@ bool AwRenderViewExt::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(AwViewMsg_DocumentHasImages, OnDocumentHasImagesRequest) IPC_MESSAGE_HANDLER(AwViewMsg_DoHitTest, OnDoHitTest) IPC_MESSAGE_HANDLER(AwViewMsg_SetTextZoomLevel, OnSetTextZoomLevel) + IPC_MESSAGE_HANDLER(AwViewMsg_ResetScrollAndScaleState, + OnResetScrollAndScaleState) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -247,4 +249,10 @@ void AwRenderViewExt::OnSetTextZoomLevel(double zoom_level) { render_view()->GetWebView()->setZoomLevel(true, zoom_level); } +void AwRenderViewExt::OnResetScrollAndScaleState() { + if (!render_view() || !render_view()->GetWebView()) + return; + render_view()->GetWebView()->resetScrollAndScaleState(); +} + } // namespace android_webview diff --git a/android_webview/renderer/aw_render_view_ext.h b/android_webview/renderer/aw_render_view_ext.h index 8cea6e4..88f9338 100644 --- a/android_webview/renderer/aw_render_view_ext.h +++ b/android_webview/renderer/aw_render_view_ext.h @@ -43,6 +43,8 @@ class AwRenderViewExt : public content::RenderViewObserver, void OnSetTextZoomLevel(double zoom_level); + void OnResetScrollAndScaleState(); + // WebKit::WebPermissionClient implementation. virtual bool allowImage(WebKit::WebFrame* frame, bool enabledPerSettings, diff --git a/content/browser/android/content_settings.cc b/content/browser/android/content_settings.cc index 13c8ac8..45a4223 100644 --- a/content/browser/android/content_settings.cc +++ b/content/browser/android/content_settings.cc @@ -84,6 +84,8 @@ struct ContentSettings::FieldIds { GetFieldID(env, clazz, "mDatabaseEnabled", "Z"); use_wide_viewport = GetFieldID(env, clazz, "mUseWideViewport", "Z"); + load_with_overview_mode = + GetFieldID(env, clazz, "mLoadWithOverviewMode", "Z"); } // Field ids @@ -110,6 +112,7 @@ struct ContentSettings::FieldIds { jfieldID dom_storage_enabled; jfieldID database_enabled; jfieldID use_wide_viewport; + jfieldID load_with_overview_mode; }; ContentSettings::ContentSettings(JNIEnv* env, @@ -275,6 +278,12 @@ void ContentSettings::SyncFromNativeImpl() { field_ids_->use_wide_viewport, prefs.viewport_enabled); CheckException(env); + + env->SetBooleanField( + obj, + field_ids_->load_with_overview_mode, + prefs.initialize_at_minimum_page_scale); + CheckException(env); } void ContentSettings::SyncToNativeImpl() { @@ -389,6 +398,9 @@ void ContentSettings::SyncToNativeImpl() { prefs.viewport_enabled = env->GetBooleanField( obj, field_ids_->use_wide_viewport); + prefs.initialize_at_minimum_page_scale = env->GetBooleanField( + obj, field_ids_->load_with_overview_mode); + render_view_host->UpdateWebkitPreferences(prefs); } diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java b/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java index c60f2ed..cd7d600 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java @@ -92,6 +92,7 @@ public class ContentSettings { private boolean mDomStorageEnabled = false; private boolean mDatabaseEnabled = false; private boolean mUseWideViewport = false; + private boolean mLoadWithOverviewMode = false; // Not accessed by the native side. private boolean mSupportZoom = true; @@ -376,6 +377,22 @@ public class ContentSettings { return supportsMultiTouchZoom() && mDisplayZoomControls; } + public void setLoadWithOverviewMode(boolean overview) { + assert mCanModifySettings; + synchronized (mContentSettingsLock) { + if (mLoadWithOverviewMode != overview) { + mLoadWithOverviewMode = overview; + mEventHandler.syncSettingsLocked(); + } + } + } + + public boolean getLoadWithOverviewMode() { + synchronized (mContentSettingsLock) { + return mLoadWithOverviewMode; + } + } + /** * Sets the text zoom of the page in percent. Default is 100. * @@ -1191,6 +1208,7 @@ public class ContentSettings { */ public void initFrom(ContentSettings settings) { setLayoutAlgorithm(settings.getLayoutAlgorithm()); + setLoadWithOverviewMode(settings.getLoadWithOverviewMode()); setTextZoom(settings.getTextZoom()); setStandardFontFamily(settings.getStandardFontFamily()); setFixedFontFamily(settings.getFixedFontFamily()); diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h index 86b1231..94b74f7c02 100644 --- a/content/public/common/common_param_traits_macros.h +++ b/content/public/common/common_param_traits_macros.h @@ -200,6 +200,7 @@ IPC_STRUCT_TRAITS_BEGIN(webkit_glue::WebPreferences) IPC_STRUCT_TRAITS_MEMBER(editing_behavior) IPC_STRUCT_TRAITS_MEMBER(supports_multiple_windows) IPC_STRUCT_TRAITS_MEMBER(viewport_enabled) + IPC_STRUCT_TRAITS_MEMBER(initialize_at_minimum_page_scale) IPC_STRUCT_TRAITS_MEMBER(record_rendering_stats) IPC_STRUCT_TRAITS_MEMBER(cookie_enabled) IPC_STRUCT_TRAITS_MEMBER(apply_page_scale_factor_in_compositor) diff --git a/webkit/glue/webpreferences.cc b/webkit/glue/webpreferences.cc index 6fc88df..8dffec0 100644 --- a/webkit/glue/webpreferences.cc +++ b/webkit/glue/webpreferences.cc @@ -144,6 +144,7 @@ WebPreferences::WebPreferences() #endif supports_multiple_windows(true), viewport_enabled(false), + initialize_at_minimum_page_scale(true), record_rendering_stats(false), cookie_enabled(true) #if defined(OS_ANDROID) @@ -488,6 +489,7 @@ void WebPreferences::Apply(WebView* web_view) const { settings->setSupportsMultipleWindows(supports_multiple_windows); settings->setViewportEnabled(viewport_enabled); + settings->setInitializeAtMinimumPageScale(initialize_at_minimum_page_scale); #if defined(OS_ANDROID) settings->setAllowCustomScrollbarInMainFrame(false); diff --git a/webkit/glue/webpreferences.h b/webkit/glue/webpreferences.h index edb3032..87ab4ab 100644 --- a/webkit/glue/webpreferences.h +++ b/webkit/glue/webpreferences.h @@ -158,6 +158,7 @@ struct WEBKIT_GLUE_EXPORT WebPreferences { EditingBehavior editing_behavior; bool supports_multiple_windows; bool viewport_enabled; + bool initialize_at_minimum_page_scale; bool record_rendering_stats; // This flags corresponds to a Page's Settings' setCookieEnabled state. It |