1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "android_webview/native/aw_settings.h"
7 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
8 #include "android_webview/native/aw_contents.h"
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "content/public/browser/navigation_controller.h"
12 #include "content/public/browser/navigation_entry.h"
13 #include "content/public/browser/render_view_host.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/common/content_client.h"
16 #include "jni/AwSettings_jni.h"
17 #include "webkit/glue/webkit_glue.h"
18 #include "webkit/glue/webpreferences.h"
19 #include "webkit/user_agent/user_agent.h"
21 using base::android::CheckException
;
22 using base::android::ConvertJavaStringToUTF16
;
23 using base::android::ConvertUTF16ToJavaString
;
24 using base::android::ConvertUTF8ToJavaString
;
25 using base::android::GetClass
;
26 using base::android::GetFieldID
;
27 using base::android::GetMethodIDFromClassName
;
28 using base::android::ScopedJavaLocalRef
;
30 namespace android_webview
{
32 struct AwSettings::FieldIds
{
33 // Note on speed. One may think that an approach that reads field values via
34 // JNI is ineffective and should not be used. Please keep in mind that in the
35 // legacy WebView the whole Sync method took <1ms on Xoom, and no one is
36 // expected to modify settings in performance-critical code.
39 FieldIds(JNIEnv
* env
) {
40 const char* kStringClassName
= "Ljava/lang/String;";
42 // FIXME: we should be using a new GetFieldIDFromClassName() with caching.
43 ScopedJavaLocalRef
<jclass
> clazz(
44 GetClass(env
, "org/chromium/android_webview/AwSettings"));
45 text_size_percent
= GetFieldID(env
, clazz
, "mTextSizePercent", "I");
46 standard_fond_family
=
47 GetFieldID(env
, clazz
, "mStandardFontFamily", kStringClassName
);
49 GetFieldID(env
, clazz
, "mFixedFontFamily", kStringClassName
);
50 sans_serif_font_family
=
51 GetFieldID(env
, clazz
, "mSansSerifFontFamily", kStringClassName
);
53 GetFieldID(env
, clazz
, "mSerifFontFamily", kStringClassName
);
55 GetFieldID(env
, clazz
, "mCursiveFontFamily", kStringClassName
);
57 GetFieldID(env
, clazz
, "mFantasyFontFamily", kStringClassName
);
58 default_text_encoding
=
59 GetFieldID(env
, clazz
, "mDefaultTextEncoding", kStringClassName
);
61 GetFieldID(env
, clazz
, "mUserAgent", kStringClassName
);
62 minimum_font_size
= GetFieldID(env
, clazz
, "mMinimumFontSize", "I");
63 minimum_logical_font_size
=
64 GetFieldID(env
, clazz
, "mMinimumLogicalFontSize", "I");
65 default_font_size
= GetFieldID(env
, clazz
, "mDefaultFontSize", "I");
66 default_fixed_font_size
=
67 GetFieldID(env
, clazz
, "mDefaultFixedFontSize", "I");
68 load_images_automatically
=
69 GetFieldID(env
, clazz
, "mLoadsImagesAutomatically", "Z");
71 GetFieldID(env
, clazz
, "mImagesEnabled", "Z");
73 GetFieldID(env
, clazz
, "mJavaScriptEnabled", "Z");
74 allow_universal_access_from_file_urls
=
75 GetFieldID(env
, clazz
, "mAllowUniversalAccessFromFileURLs", "Z");
76 allow_file_access_from_file_urls
=
77 GetFieldID(env
, clazz
, "mAllowFileAccessFromFileURLs", "Z");
78 java_script_can_open_windows_automatically
=
79 GetFieldID(env
, clazz
, "mJavaScriptCanOpenWindowsAutomatically", "Z");
80 support_multiple_windows
=
81 GetFieldID(env
, clazz
, "mSupportMultipleWindows", "Z");
83 GetFieldID(env
, clazz
, "mDomStorageEnabled", "Z");
85 GetFieldID(env
, clazz
, "mDatabaseEnabled", "Z");
87 GetFieldID(env
, clazz
, "mUseWideViewport", "Z");
88 load_with_overview_mode
=
89 GetFieldID(env
, clazz
, "mLoadWithOverviewMode", "Z");
90 media_playback_requires_user_gesture
=
91 GetFieldID(env
, clazz
, "mMediaPlaybackRequiresUserGesture", "Z");
92 default_video_poster_url
=
93 GetFieldID(env
, clazz
, "mDefaultVideoPosterURL", kStringClassName
);
94 support_deprecated_target_density_dpi
=
95 GetFieldID(env
, clazz
, "mSupportDeprecatedTargetDensityDPI", "Z");
97 GetFieldID(env
, clazz
, "mDIPScale", "D");
98 initial_page_scale_percent
=
99 GetFieldID(env
, clazz
, "mInitialPageScalePercent", "F");
103 jfieldID text_size_percent
;
104 jfieldID standard_fond_family
;
105 jfieldID fixed_font_family
;
106 jfieldID sans_serif_font_family
;
107 jfieldID serif_font_family
;
108 jfieldID cursive_font_family
;
109 jfieldID fantasy_font_family
;
110 jfieldID default_text_encoding
;
112 jfieldID minimum_font_size
;
113 jfieldID minimum_logical_font_size
;
114 jfieldID default_font_size
;
115 jfieldID default_fixed_font_size
;
116 jfieldID load_images_automatically
;
117 jfieldID images_enabled
;
118 jfieldID java_script_enabled
;
119 jfieldID allow_universal_access_from_file_urls
;
120 jfieldID allow_file_access_from_file_urls
;
121 jfieldID java_script_can_open_windows_automatically
;
122 jfieldID support_multiple_windows
;
123 jfieldID dom_storage_enabled
;
124 jfieldID database_enabled
;
125 jfieldID use_wide_viewport
;
126 jfieldID load_with_overview_mode
;
127 jfieldID media_playback_requires_user_gesture
;
128 jfieldID default_video_poster_url
;
129 jfieldID support_deprecated_target_density_dpi
;
131 jfieldID initial_page_scale_percent
;
134 AwSettings::AwSettings(JNIEnv
* env
, jobject obj
)
135 : aw_settings_(env
, obj
) {
138 AwSettings::~AwSettings() {
141 void AwSettings::Destroy(JNIEnv
* env
, jobject obj
) {
145 AwRenderViewHostExt
* AwSettings::GetAwRenderViewHostExt() {
146 if (!web_contents()) return NULL
;
147 AwContents
* contents
= AwContents::FromWebContents(web_contents());
148 if (!contents
) return NULL
;
149 return contents
->render_view_host_ext();
152 void AwSettings::ResetScrollAndScaleState(JNIEnv
* env
, jobject obj
) {
153 AwRenderViewHostExt
* rvhe
= GetAwRenderViewHostExt();
155 rvhe
->ResetScrollAndScaleState();
158 void AwSettings::SetWebContents(JNIEnv
* env
, jobject obj
, jint jweb_contents
) {
159 content::WebContents
* web_contents
=
160 reinterpret_cast<content::WebContents
*>(jweb_contents
);
161 Observe(web_contents
);
163 UpdateEverything(env
, obj
);
166 void AwSettings::UpdateEverything() {
167 JNIEnv
* env
= base::android::AttachCurrentThread();
169 ScopedJavaLocalRef
<jobject
> scoped_obj
= aw_settings_
.get(env
);
170 jobject obj
= scoped_obj
.obj();
172 UpdateEverything(env
, obj
);
175 void AwSettings::UpdateEverything(JNIEnv
* env
, jobject obj
) {
176 UpdateInitialPageScale(env
, obj
);
177 UpdateWebkitPreferences(env
, obj
);
178 UpdateUserAgent(env
, obj
);
179 ResetScrollAndScaleState(env
, obj
);
180 UpdatePreferredSizeMode();
183 void AwSettings::UpdateUserAgent(JNIEnv
* env
, jobject obj
) {
184 if (!web_contents()) return;
187 field_ids_
.reset(new FieldIds(env
));
189 ScopedJavaLocalRef
<jstring
> str(env
, static_cast<jstring
>(
190 env
->GetObjectField(obj
, field_ids_
->user_agent
)));
191 bool ua_overidden
= str
.obj() != NULL
;
194 std::string override
= base::android::ConvertJavaStringToUTF8(str
);
195 web_contents()->SetUserAgentOverride(override
);
198 const content::NavigationController
& controller
=
199 web_contents()->GetController();
200 for (int i
= 0; i
< controller
.GetEntryCount(); ++i
)
201 controller
.GetEntryAtIndex(i
)->SetIsOverridingUserAgent(ua_overidden
);
204 void AwSettings::UpdateWebkitPreferences(JNIEnv
* env
, jobject obj
) {
205 if (!web_contents()) return;
206 AwRenderViewHostExt
* render_view_host_ext
= GetAwRenderViewHostExt();
207 if (!render_view_host_ext
) return;
210 field_ids_
.reset(new FieldIds(env
));
212 content::RenderViewHost
* render_view_host
=
213 web_contents()->GetRenderViewHost();
214 if (!render_view_host
) return;
215 WebPreferences prefs
= render_view_host
->GetWebkitPreferences();
217 prefs
.text_autosizing_enabled
=
218 Java_AwSettings_getTextAutosizingEnabled(env
, obj
);
220 int text_size_percent
= env
->GetIntField(obj
, field_ids_
->text_size_percent
);
221 if (prefs
.text_autosizing_enabled
) {
222 prefs
.font_scale_factor
= text_size_percent
/ 100.0f
;
223 prefs
.force_enable_zoom
= text_size_percent
>= 130;
224 // Use the default zoom level value when Text Autosizer is turned on.
225 render_view_host_ext
->SetTextZoomLevel(0);
227 prefs
.force_enable_zoom
= false;
228 render_view_host_ext
->SetTextZoomLevel(webkit_glue::ZoomFactorToZoomLevel(
229 text_size_percent
/ 100.0f
));
232 ScopedJavaLocalRef
<jstring
> str(
233 env
, static_cast<jstring
>(
234 env
->GetObjectField(obj
, field_ids_
->standard_fond_family
)));
235 prefs
.standard_font_family_map
[webkit_glue::kCommonScript
] =
236 ConvertJavaStringToUTF16(str
);
239 env
, static_cast<jstring
>(
240 env
->GetObjectField(obj
, field_ids_
->fixed_font_family
)));
241 prefs
.fixed_font_family_map
[webkit_glue::kCommonScript
] =
242 ConvertJavaStringToUTF16(str
);
245 env
, static_cast<jstring
>(
246 env
->GetObjectField(obj
, field_ids_
->sans_serif_font_family
)));
247 prefs
.sans_serif_font_family_map
[webkit_glue::kCommonScript
] =
248 ConvertJavaStringToUTF16(str
);
251 env
, static_cast<jstring
>(
252 env
->GetObjectField(obj
, field_ids_
->serif_font_family
)));
253 prefs
.serif_font_family_map
[webkit_glue::kCommonScript
] =
254 ConvertJavaStringToUTF16(str
);
257 env
, static_cast<jstring
>(
258 env
->GetObjectField(obj
, field_ids_
->cursive_font_family
)));
259 prefs
.cursive_font_family_map
[webkit_glue::kCommonScript
] =
260 ConvertJavaStringToUTF16(str
);
263 env
, static_cast<jstring
>(
264 env
->GetObjectField(obj
, field_ids_
->fantasy_font_family
)));
265 prefs
.fantasy_font_family_map
[webkit_glue::kCommonScript
] =
266 ConvertJavaStringToUTF16(str
);
269 env
, static_cast<jstring
>(
270 env
->GetObjectField(obj
, field_ids_
->default_text_encoding
)));
271 prefs
.default_encoding
= ConvertJavaStringToUTF8(str
);
273 prefs
.minimum_font_size
=
274 env
->GetIntField(obj
, field_ids_
->minimum_font_size
);
276 prefs
.minimum_logical_font_size
=
277 env
->GetIntField(obj
, field_ids_
->minimum_logical_font_size
);
279 prefs
.default_font_size
=
280 env
->GetIntField(obj
, field_ids_
->default_font_size
);
282 prefs
.default_fixed_font_size
=
283 env
->GetIntField(obj
, field_ids_
->default_fixed_font_size
);
285 prefs
.loads_images_automatically
=
286 env
->GetBooleanField(obj
, field_ids_
->load_images_automatically
);
288 prefs
.images_enabled
=
289 env
->GetBooleanField(obj
, field_ids_
->images_enabled
);
291 prefs
.javascript_enabled
=
292 env
->GetBooleanField(obj
, field_ids_
->java_script_enabled
);
294 prefs
.allow_universal_access_from_file_urls
= env
->GetBooleanField(
295 obj
, field_ids_
->allow_universal_access_from_file_urls
);
297 prefs
.allow_file_access_from_file_urls
= env
->GetBooleanField(
298 obj
, field_ids_
->allow_file_access_from_file_urls
);
300 prefs
.javascript_can_open_windows_automatically
= env
->GetBooleanField(
301 obj
, field_ids_
->java_script_can_open_windows_automatically
);
303 prefs
.supports_multiple_windows
= env
->GetBooleanField(
304 obj
, field_ids_
->support_multiple_windows
);
306 prefs
.plugins_enabled
= !Java_AwSettings_getPluginsDisabled(env
, obj
);
308 prefs
.application_cache_enabled
=
309 Java_AwSettings_getAppCacheEnabled(env
, obj
);
311 prefs
.local_storage_enabled
= env
->GetBooleanField(
312 obj
, field_ids_
->dom_storage_enabled
);
314 prefs
.databases_enabled
= env
->GetBooleanField(
315 obj
, field_ids_
->database_enabled
);
317 prefs
.double_tap_to_zoom_enabled
= prefs
.use_wide_viewport
=
318 env
->GetBooleanField(obj
, field_ids_
->use_wide_viewport
);
320 prefs
.initialize_at_minimum_page_scale
= env
->GetBooleanField(
321 obj
, field_ids_
->load_with_overview_mode
);
323 prefs
.user_gesture_required_for_media_playback
= env
->GetBooleanField(
324 obj
, field_ids_
->media_playback_requires_user_gesture
);
327 env
, static_cast<jstring
>(
328 env
->GetObjectField(obj
, field_ids_
->default_video_poster_url
)));
329 prefs
.default_video_poster_url
= str
.obj() ?
330 GURL(ConvertJavaStringToUTF8(str
)) : GURL();
332 prefs
.support_deprecated_target_density_dpi
= env
->GetBooleanField(
333 obj
, field_ids_
->support_deprecated_target_density_dpi
);
335 render_view_host
->UpdateWebkitPreferences(prefs
);
338 void AwSettings::UpdateInitialPageScale(JNIEnv
* env
, jobject obj
) {
339 AwRenderViewHostExt
* rvhe
= GetAwRenderViewHostExt();
343 field_ids_
.reset(new FieldIds(env
));
345 float initial_page_scale_percent
=
346 env
->GetFloatField(obj
, field_ids_
->initial_page_scale_percent
);
347 if (initial_page_scale_percent
== 0) {
348 rvhe
->SetInitialPageScale(-1);
350 float dip_scale
= static_cast<float>(
351 env
->GetDoubleField(obj
, field_ids_
->dip_scale
));
352 rvhe
->SetInitialPageScale(initial_page_scale_percent
/ dip_scale
/ 100.0f
);
356 void AwSettings::UpdatePreferredSizeMode() {
357 if (web_contents()->GetRenderViewHost()) {
358 web_contents()->GetRenderViewHost()->EnablePreferredSizeMode();
362 void AwSettings::RenderViewCreated(content::RenderViewHost
* render_view_host
) {
363 // A single WebContents can normally have 0 to many RenderViewHost instances
364 // associated with it.
365 // This is important since there is only one RenderViewHostExt instance per
366 // WebContents (and not one RVHExt per RVH, as you might expect) and updating
367 // settings via RVHExt only ever updates the 'current' RVH.
368 // In android_webview we don't swap out the RVH on cross-site navigations, so
369 // we shouldn't have to deal with the multiple RVH per WebContents case. That
370 // in turn means that the newly created RVH is always the 'current' RVH
371 // (since we only ever go from 0 to 1 RVH instances) and hence the DCHECK.
372 DCHECK(web_contents()->GetRenderViewHost() == render_view_host
);
377 static jint
Init(JNIEnv
* env
,
380 AwSettings
* settings
= new AwSettings(env
, obj
);
381 settings
->SetWebContents(env
, obj
, web_contents
);
382 return reinterpret_cast<jint
>(settings
);
385 static jstring
GetDefaultUserAgent(JNIEnv
* env
, jclass clazz
) {
386 return base::android::ConvertUTF8ToJavaString(
387 env
, content::GetUserAgent(GURL())).Release();
390 bool RegisterAwSettings(JNIEnv
* env
) {
391 return RegisterNativesImpl(env
) >= 0;
394 } // namespace android_webview