Skip to content

Commit

Permalink
[Android WebView] Implement WebSettings.setTextZoom for legacy layout…
Browse files Browse the repository at this point in the history
… modes

We rely on the fact that on Android, page scaling factor isn't used for page zooming, so text scaling can be used (unlike desktop Chrome).

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182481 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
mnaganov@chromium.org committed Feb 14, 2013
1 parent 776936b commit cbe55d2
Show file tree
Hide file tree
Showing 17 changed files with 274 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ void AwRenderViewHostExt::EnableCapturePictureCallback(bool enabled) {
web_contents()->GetRoutingID(), enabled));
}

void AwRenderViewHostExt::SetTextZoomLevel(double level) {
DCHECK(CalledOnValidThread());
Send(new AwViewMsg_SetTextZoomLevel(web_contents()->GetRoutingID(), level));
}

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 @@ -66,6 +66,10 @@ class AwRenderViewHostExt : public content::WebContentsObserver,
// Captures the latest available picture pile synchronously.
void CapturePictureSync();

// Sets the zoom level for text only. Used in layout modes other than
// Text Autosizing.
void SetTextZoomLevel(double level);

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 @@ -59,6 +59,11 @@ IPC_MESSAGE_ROUTED1(AwViewMsg_EnableCapturePictureCallback,
// This message blocks the browser process on the renderer until complete.
IPC_SYNC_MESSAGE_ROUTED0_0(AwViewMsg_CapturePictureSync)

// Sets the zoom level for text only. Used in layout modes other than
// Text Autosizing.
IPC_MESSAGE_ROUTED1(AwViewMsg_SetTextZoomLevel,
double /* zoom_level */)

//-----------------------------------------------------------------------------
// 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 @@ -255,16 +255,17 @@ public AwContents(ViewGroup containerView, InternalAccessDelegate internalAccess
mContentsClient = contentsClient;
mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents));

int nativeWebContents = nativeGetWebContents(mNativeAwContents);
mContentViewCore.initialize(containerView, internalAccessAdapter,
nativeGetWebContents(mNativeAwContents),
nativeWebContents,
new AwNativeWindow(mContainerView.getContext()),
isAccessFromFileURLsGrantedByDefault);
mContentViewCore.setContentViewClient(mContentsClient);
mLayoutSizer = new AwLayoutSizer(new AwLayoutSizerDelegate());
mContentViewCore.setContentSizeChangeListener(mLayoutSizer);
mContentsClient.installWebContentsObserver(mContentViewCore);

mSettings = new AwSettings(mContentViewCore.getContext());
mSettings = new AwSettings(mContentViewCore.getContext(), nativeWebContents);
setIoThreadClient(new IoThreadClientImpl());
setInterceptNavigationDelegate(new InterceptNavigationDelegateImpl());

Expand Down Expand Up @@ -299,6 +300,8 @@ private void setInterceptNavigationDelegate(InterceptNavigationDelegateImpl dele

public void destroy() {
mContentViewCore.destroy();
// The native part of AwSettings isn't needed for the IoThreadClient instance.
mSettings.destroy();
// We explicitly do not null out the mContentViewCore reference here
// because ContentViewCore already has code to deal with the case
// methods are called on it after it's been destroyed, and other
Expand Down Expand Up @@ -482,6 +485,8 @@ private void setNewWebContents(int newWebContentsPtr) {
nativeSetIoThreadClient(mNativeAwContents, mIoThreadClient);
nativeSetInterceptNavigationDelegate(mNativeAwContents, mInterceptNavigationDelegate);

mSettings.setWebContents(newWebContentsPtr);

// Finally poke the new ContentViewCore with the size of the container view and show it.
if (mContainerView.getWidth() != 0 || mContainerView.getHeight() != 0) {
mContentViewCore.onSizeChanged(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
import android.os.Process;
import android.webkit.WebSettings;

import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;

/**
* Stores Android WebView specific settings that does not need to be synced to WebKit.
* Use {@link org.chromium.content.browser.ContentSettings} for WebKit settings.
*
* Methods in this class can be called from any thread, including threads created by
* the client of WebView.
*/
@JNINamespace("android_webview")
public class AwSettings {
// Lock to protect all settings.
private final Object mAwSettingsLock = new Object();
Expand All @@ -28,12 +32,22 @@ public class AwSettings {
private boolean mShouldFocusFirstNode = true;
private boolean mGeolocationEnabled = true;

public AwSettings(Context context) {
// The native side of this object.
private int mNativeAwSettings = 0;

public AwSettings(Context context, int nativeWebContents) {
mContext = context;
mBlockNetworkLoads = mContext.checkPermission(
android.Manifest.permission.INTERNET,
Process.myPid(),
Process.myUid()) != PackageManager.PERMISSION_GRANTED;
mNativeAwSettings = nativeInit(nativeWebContents);
assert mNativeAwSettings != 0;
}

public void destroy() {
nativeDestroy(mNativeAwSettings);
mNativeAwSettings = 0;
}

/**
Expand Down Expand Up @@ -130,6 +144,22 @@ public void setShouldFocusFirstNode(boolean flag) {
}
}

/**
* Sets the text zoom of the page in percent. This kind of zooming is
* only applicable when Text Autosizing is turned off. Passing -1 will
* reset the zoom to the default value.
*/
public void setTextZoom(final int textZoom) {
// There is no need to lock, because the native code doesn't
// read anything from the Java side.
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
nativeSetTextZoom(mNativeAwSettings, textZoom);
}
});
}

/**
* See {@link android.webkit.WebSettings#setNeedInitialFocus}.
*/
Expand Down Expand Up @@ -158,4 +188,16 @@ boolean getGeolocationEnabled() {
return mGeolocationEnabled;
}
}

public void setWebContents(int nativeWebContents) {
nativeSetWebContents(mNativeAwSettings, nativeWebContents);
}

private native int nativeInit(int webContentsPtr);

private native void nativeDestroy(int nativeAwSettings);

private native void nativeSetWebContents(int nativeAwSettings, int nativeWebContents);

private native void nativeSetTextZoom(int nativeAwSettings, int textZoom);
}
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,8 @@ protected void doEnsureSettingHasValue(Boolean value) throws Throwable {

// This class provides helper methods for testing of settings related to
// the text autosizing feature.
abstract class AwSettingsTextAutosizingTestHelper<T> extends AwSettingsTestHelper<T> {
abstract class AwSettingsTextAutosizingTestHelper<T>
extends AwSettingsWithSettingsTestHelper<T> {
protected static final float PARAGRAPH_FONT_SIZE = 14.0f;

AwSettingsTextAutosizingTestHelper(
Expand Down Expand Up @@ -895,7 +896,54 @@ class AwSettingsTextZoomTestHelper extends AwSettingsTextAutosizingTestHelper<In
AwContents awContents,
TestAwContentsClient contentViewClient) throws Throwable {
super(awContents, contentViewClient);
// See b/7873666.
mInitialActualFontSize = getActualFontSize();
}

@Override
protected Integer getAlteredValue() {
return INITIAL_TEXT_ZOOM * 2;
}

@Override
protected Integer getInitialValue() {
return INITIAL_TEXT_ZOOM;
}

@Override
protected Integer getCurrentValue() {
return mContentSettings.getTextZoom();
}

@Override
protected void setCurrentValue(Integer value) {
mContentSettings.setTextZoom(value);
mAwSettings.setTextZoom(value);
}

@Override
protected void doEnsureSettingHasValue(Integer value) throws Throwable {
final float actualFontSize = getActualFontSize();
// Ensure that actual vs. initial font size ratio is similar to actual vs. initial
// text zoom values ratio.
final float ratiosDelta = Math.abs(
(actualFontSize / mInitialActualFontSize) -
(value / (float)INITIAL_TEXT_ZOOM));
assertTrue(
"|(" + actualFontSize + " / " + mInitialActualFontSize + ") - (" +
value + " / " + INITIAL_TEXT_ZOOM + ")| = " + ratiosDelta,
ratiosDelta <= 0.2f);
}
}

class AwSettingsTextZoomAutosizingTestHelper
extends AwSettingsTextAutosizingTestHelper<Integer> {
private static final int INITIAL_TEXT_ZOOM = 100;
private final float mInitialActualFontSize;

AwSettingsTextZoomAutosizingTestHelper(
AwContents awContents,
TestAwContentsClient contentViewClient) throws Throwable {
super(awContents, contentViewClient);
mContentSettings.setLayoutAlgorithm(LayoutAlgorithm.TEXT_AUTOSIZING);
// The initial font size can be adjusted by font autosizer depending on the page's
// viewport width.
Expand All @@ -920,6 +968,8 @@ protected Integer getCurrentValue() {
@Override
protected void setCurrentValue(Integer value) {
mContentSettings.setTextZoom(value);
// This is to verify that AwSettings will not affect font boosting by Autosizer.
mAwSettings.setTextZoom(-1);
}

@Override
Expand Down Expand Up @@ -1803,6 +1853,15 @@ public void testTextZoomWithTwoViews() throws Throwable {
new AwSettingsTextZoomTestHelper(views.getContents1(), views.getClient1()));
}

@SmallTest
@Feature({"AndroidWebView", "Preferences"})
public void testTextZoomAutosizingWithTwoViews() throws Throwable {
ViewPair views = createViews();
runPerViewSettingsTest(
new AwSettingsTextZoomAutosizingTestHelper(views.getContents0(), views.getClient0()),
new AwSettingsTextZoomAutosizingTestHelper(views.getContents1(), views.getClient1()));
}

@SmallTest
@Feature({"AndroidWebView", "Preferences"})
public void testJavaScriptPopupsWithTwoViews() throws Throwable {
Expand Down
2 changes: 2 additions & 0 deletions android_webview/native/android_webview_jni_registrar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "android_webview/native/aw_contents_io_thread_client_impl.h"
#include "android_webview/native/aw_http_auth_handler.h"
#include "android_webview/native/aw_resource.h"
#include "android_webview/native/aw_settings.h"
#include "android_webview/native/aw_web_contents_delegate.h"
#include "android_webview/native/cookie_manager.h"
#include "android_webview/native/input_stream_impl.h"
Expand All @@ -24,6 +25,7 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = {
{ "AndroidProtocolHandler", RegisterAndroidProtocolHandler },
{ "AwContents", RegisterAwContents },
{ "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl},
{ "AwSettings", RegisterAwSettings },
{ "AwHttpAuthHandler", RegisterAwHttpAuthHandler },
{ "AwResource", AwResource::RegisterAwResource },
{ "AwWebContentsDelegate", RegisterAwWebContentsDelegate },
Expand Down
4 changes: 4 additions & 0 deletions android_webview/native/aw_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ class AwContents : public FindHelper::Listener,
jobject web_contents_delegate);
virtual ~AwContents();

AwRenderViewHostExt* render_view_host_ext() {
return render_view_host_ext_.get();
}

void DrawGL(AwDrawGLInfo* draw_info);
bool DrawSW(JNIEnv* env,
jobject obj,
Expand Down
67 changes: 67 additions & 0 deletions android_webview/native/aw_settings.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 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.

#include "android_webview/native/aw_settings.h"

#include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
#include "android_webview/native/aw_contents.h"
#include "jni/AwSettings_jni.h"
#include "webkit/glue/webkit_glue.h"

namespace android_webview {

AwSettings::AwSettings(JNIEnv* env, jobject obj)
: java_ref_(env, obj),
text_zoom_percent_(100) {
}

AwSettings::~AwSettings() {
}

void AwSettings::Destroy(JNIEnv* env, jobject obj) {
delete this;
}

void AwSettings::SetTextZoom(JNIEnv* env, jobject obj, jint text_zoom_percent) {
if (text_zoom_percent_ == text_zoom_percent) return;
text_zoom_percent_ = text_zoom_percent;
UpdateTextZoom();
}

void AwSettings::SetWebContents(JNIEnv* env, jobject obj, jint web_contents) {
Observe(reinterpret_cast<content::WebContents*>(web_contents));
}

void AwSettings::UpdateTextZoom() {
if (!web_contents()) return;
AwContents* contents = AwContents::FromWebContents(web_contents());
if (!contents) return;
AwRenderViewHostExt* rvhe = contents->render_view_host_ext();
if (!rvhe) return;
if (text_zoom_percent_ > 0) {
rvhe->SetTextZoomLevel(webkit_glue::ZoomFactorToZoomLevel(
text_zoom_percent_ / 100.0f));
} else {
// Use the default zoom level value when Text Autosizer is turned on.
rvhe->SetTextZoomLevel(0);
}
}

void AwSettings::RenderViewCreated(content::RenderViewHost* render_view_host) {
UpdateTextZoom();
}

static jint Init(JNIEnv* env,
jobject obj,
jint web_contents) {
AwSettings* settings = new AwSettings(env, obj);
settings->SetWebContents(env, obj, web_contents);
return reinterpret_cast<jint>(settings);
}

bool RegisterAwSettings(JNIEnv* env) {
return RegisterNativesImpl(env) >= 0;
}

} // namespace android_webview
41 changes: 41 additions & 0 deletions android_webview/native/aw_settings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 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.

#ifndef ANDROID_WEBVIEW_NATIVE_AW_SETTINGS_H_
#define ANDROID_WEBVIEW_NATIVE_AW_SETTINGS_H_

#include <jni.h>

#include "base/android/jni_helper.h"
#include "base/android/scoped_java_ref.h"
#include "content/public/browser/web_contents_observer.h"

namespace android_webview {

class AwSettings : public content::WebContentsObserver {
public:
AwSettings(JNIEnv* env, jobject obj);
virtual ~AwSettings();

// Called from Java.
void Destroy(JNIEnv* env, jobject obj);
void SetTextZoom(JNIEnv* env, jobject obj, jint text_zoom_percent);
void SetWebContents(JNIEnv* env, jobject obj, jint web_contents);

private:
void UpdateTextZoom();

// WebContentsObserver overrides:
virtual void RenderViewCreated(
content::RenderViewHost* render_view_host) OVERRIDE;

JavaObjectWeakGlobalRef java_ref_;
int text_zoom_percent_;
};

bool RegisterAwSettings(JNIEnv* env);

} // namespace android_webview

#endif // ANDROID_WEBVIEW_NATIVE_AW_SETTINGS_H_
3 changes: 3 additions & 0 deletions android_webview/native/webview_native.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
'aw_javascript_dialog_manager.h',
'aw_resource.cc',
'aw_resource.h',
'aw_settings.cc',
'aw_settings.h',
'aw_web_contents_delegate.cc',
'aw_web_contents_delegate.h',
'aw_web_contents_view_delegate.cc',
Expand Down Expand Up @@ -77,6 +79,7 @@
'../java/src/org/chromium/android_webview/AwCookieManager.java',
'../java/src/org/chromium/android_webview/AwHttpAuthHandler.java',
'../java/src/org/chromium/android_webview/AwResource.java',
'../java/src/org/chromium/android_webview/AwSettings.java',
'../java/src/org/chromium/android_webview/AwWebContentsDelegate.java',
'../java/src/org/chromium/android_webview/InterceptedRequestData.java',
'../java/src/org/chromium/android_webview/JsResultHandler.java',
Expand Down
Loading

0 comments on commit cbe55d2

Please sign in to comment.