Skip to content

Commit

Permalink
[Android WebView] Implement WebSettings.{get|set}LoadWithOverviewMode
Browse files Browse the repository at this point in the history
The 'LoadWithOverviewMode' setting controls, whether the page needs to be scaled
to fit contents into the viewport. Chrome on Android always adjusts page scale
to fit contents. We need to make this behavior controllable.


Review URL: https://chromiumcodereview.appspot.com/12217134

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184631 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
mnaganov@chromium.org committed Feb 26, 2013
1 parent 8e88fce commit f4a3a04
Show file tree
Hide file tree
Showing 16 changed files with 233 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions android_webview/common/render_view_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,15 @@ public void requestImageRef(Message msg) {
msg.sendToTarget();
}

public void resetScrollAndScaleState() {
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
nativeResetScrollAndScaleState(mNativeAwContents);
}
});
}

//--------------------------------------------------------------------------------------------
// View and ViewGroup method implementations
//--------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1069,6 +1078,8 @@ private native void nativeSetWindowViewVisibility(int nativeAwContents, boolean
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,6 @@
* 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;

Expand Down Expand Up @@ -65,11 +45,12 @@ public void testScaleUp() throws Throwable {
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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;
Expand Down Expand Up @@ -1199,6 +1200,73 @@ private String getData() {
}
}

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
Expand Down Expand Up @@ -2291,6 +2359,60 @@ public void testUseWideViewportLayoutWidth() throws Throwable {
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;
Expand Down Expand Up @@ -2415,4 +2537,13 @@ private void useTestResourceContext() {
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();
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ class TestAwContentsClient extends NullContentsClient {
private OnReceivedErrorHelper mOnReceivedErrorHelper;
private OnEvaluateJavaScriptResultHelper mOnEvaluateJavaScriptResultHelper;
private AddMessageToConsoleHelper mAddMessageToConsoleHelper;
private OnScaleChangedHelper mOnScaleChangedHelper;

public TestAwContentsClient() {
mOnPageStartedHelper = new OnPageStartedHelper();
mOnPageFinishedHelper = new OnPageFinishedHelper();
mOnReceivedErrorHelper = new OnReceivedErrorHelper();
mOnEvaluateJavaScriptResultHelper = new OnEvaluateJavaScriptResultHelper();
mAddMessageToConsoleHelper = new AddMessageToConsoleHelper();
mOnScaleChangedHelper = new OnScaleChangedHelper();
}

public OnPageStartedHelper getOnPageStartedHelper() {
Expand All @@ -48,6 +50,24 @@ public AddMessageToConsoleHelper getAddMessageToConsoleHelper() {
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;
Expand Down Expand Up @@ -113,4 +133,9 @@ void notifyCalled(int level, String message, int lineNumer, String sourceId) {
notifyCalled();
}
}

@Override
public void onScaleChanged(float oldScale, float newScale) {
mOnScaleChangedHelper.notifyCalled(oldScale, newScale);
}
}
4 changes: 4 additions & 0 deletions android_webview/native/aw_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions android_webview/native/aw_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 8 additions & 0 deletions android_webview/renderer/aw_render_view_ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions android_webview/renderer/aw_render_view_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 12 additions & 0 deletions content/browser/android/content_settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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);
}

Expand Down
Loading

0 comments on commit f4a3a04

Please sign in to comment.