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/common/aw_content_client.h"
9 #include "android_webview/native/aw_contents.h"
10 #include "base/android/jni_android.h"
11 #include "base/android/jni_string.h"
12 #include "base/supports_user_data.h"
13 #include "content/public/browser/navigation_controller.h"
14 #include "content/public/browser/navigation_entry.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/common/renderer_preferences.h"
18 #include "content/public/common/web_preferences.h"
19 #include "jni/AwSettings_jni.h"
20 #include "ui/gfx/font_render_params.h"
22 using base::android::ConvertJavaStringToUTF16
;
23 using base::android::ConvertUTF8ToJavaString
;
24 using base::android::ScopedJavaLocalRef
;
25 using content::RendererPreferences
;
26 using content::WebPreferences
;
28 namespace android_webview
{
32 // TODO(boliu): Deduplicate with chrome/ code.
33 content::RendererPreferencesHintingEnum
GetRendererPreferencesHintingEnum(
34 gfx::FontRenderParams::Hinting hinting
) {
36 case gfx::FontRenderParams::HINTING_NONE
:
37 return content::RENDERER_PREFERENCES_HINTING_NONE
;
38 case gfx::FontRenderParams::HINTING_SLIGHT
:
39 return content::RENDERER_PREFERENCES_HINTING_SLIGHT
;
40 case gfx::FontRenderParams::HINTING_MEDIUM
:
41 return content::RENDERER_PREFERENCES_HINTING_MEDIUM
;
42 case gfx::FontRenderParams::HINTING_FULL
:
43 return content::RENDERER_PREFERENCES_HINTING_FULL
;
45 NOTREACHED() << "Unhandled hinting style " << hinting
;
46 return content::RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT
;
50 // TODO(boliu): Deduplicate with chrome/ code.
51 content::RendererPreferencesSubpixelRenderingEnum
52 GetRendererPreferencesSubpixelRenderingEnum(
53 gfx::FontRenderParams::SubpixelRendering subpixel_rendering
) {
54 switch (subpixel_rendering
) {
55 case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE
:
56 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE
;
57 case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB
:
58 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB
;
59 case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR
:
60 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR
;
61 case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB
:
62 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB
;
63 case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR
:
64 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR
;
66 NOTREACHED() << "Unhandled subpixel rendering style "
67 << subpixel_rendering
;
68 return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT
;
72 void PopulateFixedRendererPreferences(RendererPreferences
* prefs
) {
73 prefs
->tap_multiple_targets_strategy
=
74 content::TAP_MULTIPLE_TARGETS_STRATEGY_NONE
;
76 // TODO(boliu): Deduplicate with chrome/ code.
77 const gfx::FontRenderParams
& params
= gfx::GetDefaultWebKitFontRenderParams();
78 prefs
->should_antialias_text
= params
.antialiasing
;
79 prefs
->use_subpixel_positioning
= params
.subpixel_positioning
;
80 prefs
->hinting
= GetRendererPreferencesHintingEnum(params
.hinting
);
81 prefs
->use_autohinter
= params
.autohinter
;
82 prefs
->use_bitmaps
= params
.use_bitmaps
;
83 prefs
->subpixel_rendering
=
84 GetRendererPreferencesSubpixelRenderingEnum(params
.subpixel_rendering
);
87 void PopulateFixedWebPreferences(WebPreferences
* web_prefs
) {
88 web_prefs
->shrinks_standalone_images_to_fit
= false;
89 web_prefs
->should_clear_document_background
= false;
94 const void* kAwSettingsUserDataKey
= &kAwSettingsUserDataKey
;
96 class AwSettingsUserData
: public base::SupportsUserData::Data
{
98 AwSettingsUserData(AwSettings
* ptr
) : settings_(ptr
) {}
100 static AwSettings
* GetSettings(content::WebContents
* web_contents
) {
103 AwSettingsUserData
* data
= reinterpret_cast<AwSettingsUserData
*>(
104 web_contents
->GetUserData(kAwSettingsUserDataKey
));
105 return data
? data
->settings_
: NULL
;
109 AwSettings
* settings_
;
112 AwSettings::AwSettings(JNIEnv
* env
, jobject obj
, jlong web_contents
)
113 : WebContentsObserver(
114 reinterpret_cast<content::WebContents
*>(web_contents
)),
115 renderer_prefs_initialized_(false),
116 aw_settings_(env
, obj
) {
117 reinterpret_cast<content::WebContents
*>(web_contents
)->
118 SetUserData(kAwSettingsUserDataKey
, new AwSettingsUserData(this));
121 AwSettings::~AwSettings() {
122 if (web_contents()) {
123 web_contents()->SetUserData(kAwSettingsUserDataKey
, NULL
);
126 JNIEnv
* env
= base::android::AttachCurrentThread();
127 ScopedJavaLocalRef
<jobject
> scoped_obj
= aw_settings_
.get(env
);
128 jobject obj
= scoped_obj
.obj();
130 Java_AwSettings_nativeAwSettingsGone(env
, obj
,
131 reinterpret_cast<intptr_t>(this));
134 void AwSettings::Destroy(JNIEnv
* env
, jobject obj
) {
138 AwSettings
* AwSettings::FromWebContents(content::WebContents
* web_contents
) {
139 return AwSettingsUserData::GetSettings(web_contents
);
142 AwRenderViewHostExt
* AwSettings::GetAwRenderViewHostExt() {
143 if (!web_contents()) return NULL
;
144 AwContents
* contents
= AwContents::FromWebContents(web_contents());
145 if (!contents
) return NULL
;
146 return contents
->render_view_host_ext();
149 void AwSettings::ResetScrollAndScaleState(JNIEnv
* env
, jobject obj
) {
150 AwRenderViewHostExt
* rvhe
= GetAwRenderViewHostExt();
152 rvhe
->ResetScrollAndScaleState();
155 void AwSettings::UpdateEverything() {
156 JNIEnv
* env
= base::android::AttachCurrentThread();
158 ScopedJavaLocalRef
<jobject
> scoped_obj
= aw_settings_
.get(env
);
159 jobject obj
= scoped_obj
.obj();
161 // Grab the lock and call UpdateEverythingLocked.
162 Java_AwSettings_updateEverything(env
, obj
);
165 void AwSettings::UpdateEverythingLocked(JNIEnv
* env
, jobject obj
) {
166 UpdateInitialPageScaleLocked(env
, obj
);
167 UpdateWebkitPreferencesLocked(env
, obj
);
168 UpdateUserAgentLocked(env
, obj
);
169 ResetScrollAndScaleState(env
, obj
);
170 UpdateFormDataPreferencesLocked(env
, obj
);
171 UpdateRendererPreferencesLocked(env
, obj
);
174 void AwSettings::UpdateUserAgentLocked(JNIEnv
* env
, jobject obj
) {
175 if (!web_contents()) return;
177 ScopedJavaLocalRef
<jstring
> str
=
178 Java_AwSettings_getUserAgentLocked(env
, obj
);
179 bool ua_overidden
= str
.obj() != NULL
;
182 std::string override
= base::android::ConvertJavaStringToUTF8(str
);
183 web_contents()->SetUserAgentOverride(override
);
186 const content::NavigationController
& controller
=
187 web_contents()->GetController();
188 for (int i
= 0; i
< controller
.GetEntryCount(); ++i
)
189 controller
.GetEntryAtIndex(i
)->SetIsOverridingUserAgent(ua_overidden
);
192 void AwSettings::UpdateWebkitPreferencesLocked(JNIEnv
* env
, jobject obj
) {
193 if (!web_contents()) return;
194 AwRenderViewHostExt
* render_view_host_ext
= GetAwRenderViewHostExt();
195 if (!render_view_host_ext
) return;
197 content::RenderViewHost
* render_view_host
=
198 web_contents()->GetRenderViewHost();
199 if (!render_view_host
) return;
200 render_view_host
->UpdateWebkitPreferences(
201 render_view_host
->GetWebkitPreferences());
204 void AwSettings::UpdateInitialPageScaleLocked(JNIEnv
* env
, jobject obj
) {
205 AwRenderViewHostExt
* rvhe
= GetAwRenderViewHostExt();
208 float initial_page_scale_percent
=
209 Java_AwSettings_getInitialPageScalePercentLocked(env
, obj
);
210 if (initial_page_scale_percent
== 0) {
211 rvhe
->SetInitialPageScale(-1);
213 float dip_scale
= static_cast<float>(
214 Java_AwSettings_getDIPScaleLocked(env
, obj
));
215 rvhe
->SetInitialPageScale(initial_page_scale_percent
/ dip_scale
/ 100.0f
);
219 void AwSettings::UpdateFormDataPreferencesLocked(JNIEnv
* env
, jobject obj
) {
220 if (!web_contents()) return;
221 AwContents
* contents
= AwContents::FromWebContents(web_contents());
222 if (!contents
) return;
224 contents
->SetSaveFormData(Java_AwSettings_getSaveFormDataLocked(env
, obj
));
227 void AwSettings::UpdateRendererPreferencesLocked(JNIEnv
* env
, jobject obj
) {
228 if (!web_contents()) return;
230 bool update_prefs
= false;
231 RendererPreferences
* prefs
= web_contents()->GetMutableRendererPrefs();
233 if (!renderer_prefs_initialized_
) {
234 PopulateFixedRendererPreferences(prefs
);
235 renderer_prefs_initialized_
= true;
240 Java_AwSettings_getVideoOverlayForEmbeddedVideoEnabledLocked(env
, obj
);
241 if (video_overlay
!= prefs
->use_video_overlay_for_embedded_encrypted_video
) {
242 prefs
->use_video_overlay_for_embedded_encrypted_video
= video_overlay
;
246 content::RenderViewHost
* host
= web_contents()->GetRenderViewHost();
247 if (update_prefs
&& host
)
248 host
->SyncRendererPrefs();
251 void AwSettings::RenderViewCreated(content::RenderViewHost
* render_view_host
) {
252 // A single WebContents can normally have 0 to many RenderViewHost instances
253 // associated with it.
254 // This is important since there is only one RenderViewHostExt instance per
255 // WebContents (and not one RVHExt per RVH, as you might expect) and updating
256 // settings via RVHExt only ever updates the 'current' RVH.
257 // In android_webview we don't swap out the RVH on cross-site navigations, so
258 // we shouldn't have to deal with the multiple RVH per WebContents case. That
259 // in turn means that the newly created RVH is always the 'current' RVH
260 // (since we only ever go from 0 to 1 RVH instances) and hence the DCHECK.
261 DCHECK(web_contents()->GetRenderViewHost() == render_view_host
);
266 void AwSettings::WebContentsDestroyed() {
270 void AwSettings::PopulateWebPreferences(WebPreferences
* web_prefs
) {
271 JNIEnv
* env
= base::android::AttachCurrentThread();
273 ScopedJavaLocalRef
<jobject
> scoped_obj
= aw_settings_
.get(env
);
274 jobject obj
= scoped_obj
.obj();
276 // Grab the lock and call PopulateWebPreferencesLocked.
277 Java_AwSettings_populateWebPreferences(
278 env
, obj
, reinterpret_cast<jlong
>(web_prefs
));
281 void AwSettings::PopulateWebPreferencesLocked(
282 JNIEnv
* env
, jobject obj
, jlong web_prefs_ptr
) {
283 AwRenderViewHostExt
* render_view_host_ext
= GetAwRenderViewHostExt();
284 if (!render_view_host_ext
) return;
286 WebPreferences
* web_prefs
= reinterpret_cast<WebPreferences
*>(web_prefs_ptr
);
287 PopulateFixedWebPreferences(web_prefs
);
289 web_prefs
->text_autosizing_enabled
=
290 Java_AwSettings_getTextAutosizingEnabledLocked(env
, obj
);
292 int text_size_percent
= Java_AwSettings_getTextSizePercentLocked(env
, obj
);
293 if (web_prefs
->text_autosizing_enabled
) {
294 web_prefs
->font_scale_factor
= text_size_percent
/ 100.0f
;
295 web_prefs
->force_enable_zoom
= text_size_percent
>= 130;
296 // Use the default zoom factor value when Text Autosizer is turned on.
297 render_view_host_ext
->SetTextZoomFactor(1);
299 web_prefs
->force_enable_zoom
= false;
300 render_view_host_ext
->SetTextZoomFactor(text_size_percent
/ 100.0f
);
303 web_prefs
->standard_font_family_map
[content::kCommonScript
] =
304 ConvertJavaStringToUTF16(
305 Java_AwSettings_getStandardFontFamilyLocked(env
, obj
));
307 web_prefs
->fixed_font_family_map
[content::kCommonScript
] =
308 ConvertJavaStringToUTF16(
309 Java_AwSettings_getFixedFontFamilyLocked(env
, obj
));
311 web_prefs
->sans_serif_font_family_map
[content::kCommonScript
] =
312 ConvertJavaStringToUTF16(
313 Java_AwSettings_getSansSerifFontFamilyLocked(env
, obj
));
315 web_prefs
->serif_font_family_map
[content::kCommonScript
] =
316 ConvertJavaStringToUTF16(
317 Java_AwSettings_getSerifFontFamilyLocked(env
, obj
));
319 web_prefs
->cursive_font_family_map
[content::kCommonScript
] =
320 ConvertJavaStringToUTF16(
321 Java_AwSettings_getCursiveFontFamilyLocked(env
, obj
));
323 web_prefs
->fantasy_font_family_map
[content::kCommonScript
] =
324 ConvertJavaStringToUTF16(
325 Java_AwSettings_getFantasyFontFamilyLocked(env
, obj
));
327 web_prefs
->default_encoding
= ConvertJavaStringToUTF8(
328 Java_AwSettings_getDefaultTextEncodingLocked(env
, obj
));
330 web_prefs
->minimum_font_size
=
331 Java_AwSettings_getMinimumFontSizeLocked(env
, obj
);
333 web_prefs
->minimum_logical_font_size
=
334 Java_AwSettings_getMinimumLogicalFontSizeLocked(env
, obj
);
336 web_prefs
->default_font_size
=
337 Java_AwSettings_getDefaultFontSizeLocked(env
, obj
);
339 web_prefs
->default_fixed_font_size
=
340 Java_AwSettings_getDefaultFixedFontSizeLocked(env
, obj
);
342 // Blink's LoadsImagesAutomatically and ImagesEnabled must be
343 // set cris-cross to Android's. See
344 // https://code.google.com/p/chromium/issues/detail?id=224317#c26
345 web_prefs
->loads_images_automatically
=
346 Java_AwSettings_getImagesEnabledLocked(env
, obj
);
347 web_prefs
->images_enabled
=
348 Java_AwSettings_getLoadsImagesAutomaticallyLocked(env
, obj
);
350 web_prefs
->javascript_enabled
=
351 Java_AwSettings_getJavaScriptEnabledLocked(env
, obj
);
353 web_prefs
->allow_universal_access_from_file_urls
=
354 Java_AwSettings_getAllowUniversalAccessFromFileURLsLocked(env
, obj
);
356 web_prefs
->allow_file_access_from_file_urls
=
357 Java_AwSettings_getAllowFileAccessFromFileURLsLocked(env
, obj
);
359 web_prefs
->javascript_can_open_windows_automatically
=
360 Java_AwSettings_getJavaScriptCanOpenWindowsAutomaticallyLocked(env
, obj
);
362 web_prefs
->supports_multiple_windows
=
363 Java_AwSettings_getSupportMultipleWindowsLocked(env
, obj
);
365 web_prefs
->plugins_enabled
=
366 !Java_AwSettings_getPluginsDisabledLocked(env
, obj
);
368 web_prefs
->application_cache_enabled
=
369 Java_AwSettings_getAppCacheEnabledLocked(env
, obj
);
371 web_prefs
->local_storage_enabled
=
372 Java_AwSettings_getDomStorageEnabledLocked(env
, obj
);
374 web_prefs
->databases_enabled
=
375 Java_AwSettings_getDatabaseEnabledLocked(env
, obj
);
377 web_prefs
->wide_viewport_quirk
= true;
378 web_prefs
->use_wide_viewport
=
379 Java_AwSettings_getUseWideViewportLocked(env
, obj
);
381 web_prefs
->double_tap_to_zoom_enabled
=
382 Java_AwSettings_supportsDoubleTapZoomLocked(env
, obj
);
384 web_prefs
->initialize_at_minimum_page_scale
=
385 Java_AwSettings_getLoadWithOverviewModeLocked(env
, obj
);
387 web_prefs
->user_gesture_required_for_media_playback
=
388 Java_AwSettings_getMediaPlaybackRequiresUserGestureLocked(env
, obj
);
390 ScopedJavaLocalRef
<jstring
> url
=
391 Java_AwSettings_getDefaultVideoPosterURLLocked(env
, obj
);
392 web_prefs
->default_video_poster_url
= url
.obj() ?
393 GURL(ConvertJavaStringToUTF8(url
)) : GURL();
395 bool support_quirks
= Java_AwSettings_getSupportLegacyQuirksLocked(env
, obj
);
396 // Please see the corresponding Blink settings for bug references.
397 web_prefs
->support_deprecated_target_density_dpi
= support_quirks
;
398 web_prefs
->use_legacy_background_size_shorthand_behavior
= support_quirks
;
399 web_prefs
->viewport_meta_layout_size_quirk
= support_quirks
;
400 web_prefs
->viewport_meta_merge_content_quirk
= support_quirks
;
401 web_prefs
->viewport_meta_non_user_scalable_quirk
= support_quirks
;
402 web_prefs
->viewport_meta_zero_values_quirk
= support_quirks
;
403 web_prefs
->clobber_user_agent_initial_scale_quirk
= support_quirks
;
404 web_prefs
->ignore_main_frame_overflow_hidden_quirk
= support_quirks
;
405 web_prefs
->report_screen_size_in_physical_pixels_quirk
= support_quirks
;
407 web_prefs
->password_echo_enabled
=
408 Java_AwSettings_getPasswordEchoEnabledLocked(env
, obj
);
409 web_prefs
->spatial_navigation_enabled
=
410 Java_AwSettings_getSpatialNavigationLocked(env
, obj
);
412 bool enable_supported_hardware_accelerated_features
=
413 Java_AwSettings_getEnableSupportedHardwareAcceleratedFeaturesLocked(
416 bool accelerated_2d_canvas_enabled_by_switch
=
417 web_prefs
->accelerated_2d_canvas_enabled
;
418 web_prefs
->accelerated_2d_canvas_enabled
= true;
419 if (!accelerated_2d_canvas_enabled_by_switch
||
420 !enable_supported_hardware_accelerated_features
) {
421 // Any canvas smaller than this will fallback to software. Abusing this
422 // slightly to turn canvas off without changing
423 // accelerated_2d_canvas_enabled, which also affects compositing mode.
424 // Using 100M instead of max int to avoid overflows.
425 web_prefs
->minimum_accelerated_2d_canvas_size
= 100 * 1000 * 1000;
427 web_prefs
->experimental_webgl_enabled
=
428 web_prefs
->experimental_webgl_enabled
&&
429 enable_supported_hardware_accelerated_features
;
431 web_prefs
->allow_displaying_insecure_content
=
432 Java_AwSettings_getAllowDisplayingInsecureContentLocked(env
, obj
);
433 web_prefs
->allow_running_insecure_content
=
434 Java_AwSettings_getAllowRunningInsecureContentLocked(env
, obj
);
436 web_prefs
->disallow_fullscreen_for_non_media_elements
= true;
439 static jlong
Init(JNIEnv
* env
,
441 jlong web_contents
) {
442 AwSettings
* settings
= new AwSettings(env
, obj
, web_contents
);
443 return reinterpret_cast<intptr_t>(settings
);
446 static jstring
GetDefaultUserAgent(JNIEnv
* env
, jclass clazz
) {
447 return base::android::ConvertUTF8ToJavaString(env
, GetUserAgent()).Release();
450 bool RegisterAwSettings(JNIEnv
* env
) {
451 return RegisterNativesImpl(env
);
454 } // namespace android_webview