diff options
11 files changed, 187 insertions, 4 deletions
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 6d1b840..ac4d11b 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 @@ -56,6 +56,7 @@ public class AwContentsClientOnScaleChangedTest extends AndroidWebViewTestBase { @SmallTest public void testScaleUp() throws Throwable { + getContentSettingsOnUiThread(mAwContents).setUseWideViewPort(true); loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT_HTML, "text/html", false); ContentViewCore core = mAwContents.getContentViewCore(); 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 803dc6b..261c108 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 @@ -26,6 +26,7 @@ import org.chromium.content.browser.test.util.CallbackHelper; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.HistoryUtils; +import org.chromium.content.common.DeviceInfo; import org.chromium.net.test.util.TestWebServer; import java.util.regex.Matcher; @@ -848,6 +849,8 @@ public class AwSettingsTest extends AndroidWebViewTestBase { AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient); + // Font autosizing doesn't step in for narrow layout widths. + mContentSettings.setUseWideViewPort(true); } @Override @@ -1051,6 +1054,59 @@ public class AwSettingsTest extends AndroidWebViewTestBase { private TestWebServer mWebServer; } + // To verify whether UseWideViewport works, we check, if the page width specified + // in the "meta viewport" tag is applied. When UseWideViewport is turned off, the + // "viewport" tag is ignored, and the layout width is set to device width in DIP pixels. + // We specify a very high width value to make sure that it doesn't intersect with + // device screen widths (in DIP pixels). + class AwSettingsUseWideViewportTestHelper extends AwSettingsTestHelper<Boolean> { + static private final String VIEWPORT_TAG_LAYOUT_WIDTH = "3000"; + + AwSettingsUseWideViewportTestHelper( + AwContents awContents, + TestAwContentsClient contentViewClient) throws Throwable { + super(awContents, contentViewClient, true); + } + + @Override + protected Boolean getAlteredValue() { + return ENABLED; + } + + @Override + protected Boolean getInitialValue() { + return DISABLED; + } + + @Override + protected Boolean getCurrentValue() { + return mContentSettings.getUseWideViewPort(); + } + + @Override + protected void setCurrentValue(Boolean value) { + mContentSettings.setUseWideViewPort(value); + } + + @Override + protected void doEnsureSettingHasValue(Boolean value) throws Throwable { + loadDataSync(getData()); + final String bodyWidth = getTitleOnUiThread(); + if (value) { + assertTrue(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth)); + } else { + assertFalse(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth)); + } + } + + private String getData() { + return "<html><head>" + + "<meta name='viewport' content='width=" + VIEWPORT_TAG_LAYOUT_WIDTH + "' />" + + "</head>" + + "<body onload='document.title=document.body.clientWidth'></body></html>"; + } + } + // 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 @@ -2012,6 +2068,75 @@ public class AwSettingsTest extends AndroidWebViewTestBase { } } + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + public void testUseWideViewportWithTwoViews() throws Throwable { + ViewPair views = createViews(); + runPerViewSettingsTest( + new AwSettingsUseWideViewportTestHelper(views.getContents0(), views.getClient0()), + new AwSettingsUseWideViewportTestHelper(views.getContents1(), views.getClient1())); + } + + @SmallTest + @Feature({"AndroidWebView", "Preferences"}) + public void testUseWideViewportLayoutWidth() 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 String pageTemplate = "<html><head>%s</head>" + + "<body onload='document.title=document.body.clientWidth'></body></html>"; + final String pageNoViewport = String.format(pageTemplate, ""); + final String pageViewportDeviceWidth = String.format( + pageTemplate, + "<meta name='viewport' content='width=device-width' />"); + final String viewportTagSpecifiedWidth = "3000"; + final String pageViewportSpecifiedWidth = String.format( + pageTemplate, + "<meta name='viewport' content='width=" + viewportTagSpecifiedWidth + "' />"); + + DeviceInfo deviceInfo = DeviceInfo.create(getInstrumentation().getTargetContext()); + int displayWidth = (int) (deviceInfo.getWidth() / deviceInfo.getDPIScale()); + + settings.setJavaScriptEnabled(true); + assertFalse(settings.getUseWideViewPort()); + // When UseWideViewPort is off, "meta viewport" tags are ignored, + // and the layout width is set to device width in CSS pixels. + // Thus, all 3 pages will have the same body width. + loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); + int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); + // Avoid rounding errors. + assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, + Math.abs(displayWidth - actualWidth) <= 1); + loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); + actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); + assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, + Math.abs(displayWidth - actualWidth) <= 1); + loadDataSync( + awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); + actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); + assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, + Math.abs(displayWidth - actualWidth) <= 1); + + settings.setUseWideViewPort(true); + // When UseWideViewPort is on, "meta viewport" tag is used. + // If there is no viewport tag, or width isn't specified, + // then layout width is set to max(980, <device-width-in-DIP-pixels>) + loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); + actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); + assertTrue("Expected: >= 980 , Actual: " + actualWidth, actualWidth >= 980); + loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); + actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); + assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, + Math.abs(displayWidth - actualWidth) <= 1); + loadDataSync( + awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); + assertEquals(viewportTagSpecifiedWidth, getTitleOnUiThread(awContents)); + } + static class ViewPair { private final AwContents contents0; private final TestAwContentsClient client0; diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewZoomTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewZoomTest.java index b9bfd5b..13bbae8 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewZoomTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/ContentViewZoomTest.java @@ -193,6 +193,7 @@ public class ContentViewZoomTest extends AndroidWebViewTestBase { } private void runMagnificationTest(boolean supportZoom) throws Throwable { + getContentSettingsOnUiThread(mAwContents).setUseWideViewPort(true); loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), getZoomableHtml(), "text/html", false); // It takes some time for scaling to settle down. @@ -238,6 +239,7 @@ public class ContentViewZoomTest extends AndroidWebViewTestBase { @Feature({"AndroidWebView"}) public void testZoomUsingMultiTouch() throws Throwable { ContentSettings webSettings = getContentSettingsOnUiThread(mAwContents); + webSettings.setUseWideViewPort(true); loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), getZoomableHtml(), "text/html", false); @@ -260,6 +262,7 @@ public class ContentViewZoomTest extends AndroidWebViewTestBase { @FlakyTest public void testZoomControls() throws Throwable { ContentSettings webSettings = getContentSettingsOnUiThread(mAwContents); + webSettings.setUseWideViewPort(true); loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), getZoomableHtml(), "text/html", false); @@ -284,6 +287,7 @@ public class ContentViewZoomTest extends AndroidWebViewTestBase { @Feature({"AndroidWebView"}) public void testZoomControlsOnNonZoomableContent() throws Throwable { ContentSettings webSettings = getContentSettingsOnUiThread(mAwContents); + webSettings.setUseWideViewPort(true); loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), getNonZoomableHtml(), "text/html", false); @@ -307,6 +311,7 @@ public class ContentViewZoomTest extends AndroidWebViewTestBase { @DisabledTest public void testZoomControlsOnOrientationChange() throws Throwable { ContentSettings webSettings = getContentSettingsOnUiThread(mAwContents); + webSettings.setUseWideViewPort(true); loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), getZoomableHtml(), "text/html", false); diff --git a/content/browser/android/content_settings.cc b/content/browser/android/content_settings.cc index b2c4b5d..cd61c41 100644 --- a/content/browser/android/content_settings.cc +++ b/content/browser/android/content_settings.cc @@ -80,6 +80,8 @@ struct ContentSettings::FieldIds { GetFieldID(env, clazz, "mSupportMultipleWindows", "Z"); dom_storage_enabled = GetFieldID(env, clazz, "mDomStorageEnabled", "Z"); + use_wide_viewport = + GetFieldID(env, clazz, "mUseWideViewport", "Z"); } // Field ids @@ -104,6 +106,7 @@ struct ContentSettings::FieldIds { jfieldID java_script_can_open_windows_automatically; jfieldID support_multiple_windows; jfieldID dom_storage_enabled; + jfieldID use_wide_viewport; }; ContentSettings::ContentSettings(JNIEnv* env, @@ -257,6 +260,12 @@ void ContentSettings::SyncFromNativeImpl() { field_ids_->dom_storage_enabled, prefs.local_storage_enabled); CheckException(env); + + env->SetBooleanField( + obj, + field_ids_->use_wide_viewport, + prefs.viewport_enabled); + CheckException(env); } void ContentSettings::SyncToNativeImpl() { @@ -361,6 +370,9 @@ void ContentSettings::SyncToNativeImpl() { prefs.local_storage_enabled = env->GetBooleanField( obj, field_ids_->dom_storage_enabled); + prefs.viewport_enabled = env->GetBooleanField( + obj, field_ids_->use_wide_viewport); + render_view_host->UpdateWebkitPreferences(prefs); } diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index ecc36e6..b7b43b4 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -652,6 +652,8 @@ WebPreferences WebContentsImpl::GetWebkitPrefs(RenderViewHost* rvh, prefs.number_of_cpu_cores = base::SysInfo::NumberOfProcessors(); + prefs.viewport_enabled = command_line.HasSwitch(switches::kEnableViewport); + prefs.deferred_image_decoding_enabled = command_line.HasSwitch(switches::kEnableDeferredImageDecoding); 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 7569758..ceb2f88 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 @@ -90,6 +90,7 @@ public class ContentSettings { private PluginState mPluginState = PluginState.OFF; private boolean mAppCacheEnabled = false; private boolean mDomStorageEnabled = false; + private boolean mUseWideViewport = false; // Not accessed by the native side. private boolean mSupportZoom = true; @@ -995,6 +996,40 @@ public class ContentSettings { } /** + * Sets whether the WebView should enable support for the "viewport" + * HTML meta tag or should use a wide viewport. + * When the value of the setting is false, the layout width is always set to the + * width of the WebView control in device-independent (CSS) pixels. + * When the value is true and the page contains the viewport meta tag, the value + * of the width specified in the tag is used. If the page does not contain the tag or + * does not provide a width, then a wide viewport will be used. + * + * @param use whether to enable support for the viewport meta tag + */ + public void setUseWideViewPort(boolean use) { + assert mCanModifySettings; + synchronized (mContentSettingsLock) { + if (mUseWideViewport != use) { + mUseWideViewport = use; + mEventHandler.syncSettingsLocked(); + } + } + } + + /** + * Gets whether the WebView supports the "viewport" + * HTML meta tag or will use a wide viewport. + * + * @return true if the WebView supports the viewport meta tag + * @see #setUseWideViewPort + */ + public boolean getUseWideViewPort() { + synchronized (mContentSettingsLock) { + return mUseWideViewport; + } + } + + /** * Sets whether the Application Caches API should be enabled. The default * is false. Note that in order for the Application Caches API to be * enabled, a non-empty database path must also be supplied to diff --git a/content/public/android/java/src/org/chromium/content/common/DeviceInfo.java b/content/public/android/java/src/org/chromium/content/common/DeviceInfo.java index 4b4a80b..ff7b2a6 100644 --- a/content/public/android/java/src/org/chromium/content/common/DeviceInfo.java +++ b/content/public/android/java/src/org/chromium/content/common/DeviceInfo.java @@ -109,7 +109,7 @@ public class DeviceInfo { } @CalledByNative - private static DeviceInfo create(Context context) { + public static DeviceInfo create(Context context) { return new DeviceInfo(context); } } diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h index e782236..36dac91 100644 --- a/content/public/common/common_param_traits_macros.h +++ b/content/public/common/common_param_traits_macros.h @@ -192,6 +192,7 @@ IPC_STRUCT_TRAITS_BEGIN(webkit_glue::WebPreferences) IPC_STRUCT_TRAITS_MEMBER(number_of_cpu_cores) IPC_STRUCT_TRAITS_MEMBER(editing_behavior) IPC_STRUCT_TRAITS_MEMBER(supports_multiple_windows) + IPC_STRUCT_TRAITS_MEMBER(viewport_enabled) IPC_STRUCT_TRAITS_MEMBER(cookie_enabled) IPC_STRUCT_TRAITS_MEMBER(apply_page_scale_factor_in_compositor) #if defined(OS_ANDROID) diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index a71c7d6..d2b9103 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -3277,9 +3277,7 @@ void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) { webview()->enableFixedLayoutMode(enable_fixed_layout || enable_viewport); webview()->settings()->setFixedElementsLayoutRelativeToFrame(true); - if (enable_viewport) { - webview()->settings()->setViewportEnabled(true); - } else if (enable_fixed_layout) { + if (!enable_viewport && enable_fixed_layout) { std::string str = command_line.GetSwitchValueASCII(switches::kEnableFixedLayout); std::vector<std::string> tokens; diff --git a/webkit/glue/webpreferences.cc b/webkit/glue/webpreferences.cc index 7c783fb..3c791e9 100644 --- a/webkit/glue/webpreferences.cc +++ b/webkit/glue/webpreferences.cc @@ -138,6 +138,7 @@ WebPreferences::WebPreferences() editing_behavior(EDITING_BEHAVIOR_MAC), #endif supports_multiple_windows(true), + viewport_enabled(false), cookie_enabled(true) #if defined(OS_ANDROID) , @@ -475,6 +476,8 @@ void WebPreferences::Apply(WebView* web_view) const { settings->setSupportsMultipleWindows(supports_multiple_windows); + settings->setViewportEnabled(viewport_enabled); + #if defined(OS_ANDROID) settings->setAllowCustomScrollbarInMainFrame(false); settings->setTextAutosizingEnabled(text_autosizing_enabled); diff --git a/webkit/glue/webpreferences.h b/webkit/glue/webpreferences.h index d807b06..3630515 100644 --- a/webkit/glue/webpreferences.h +++ b/webkit/glue/webpreferences.h @@ -153,6 +153,7 @@ struct WEBKIT_GLUE_EXPORT WebPreferences { int number_of_cpu_cores; EditingBehavior editing_behavior; bool supports_multiple_windows; + bool viewport_enabled; // This flags corresponds to a Page's Settings' setCookieEnabled state. It // only controls whether or not the "document.cookie" field is properly |