3779cd80a2768f85e9a6e0063fc358ddf81bf9ad
[platform/framework/web/crosswalk.git] / src / android_webview / native / aw_settings.cc
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.
4
5 #include "android_webview/native/aw_settings.h"
6
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/command_line.h"
13 #include "base/supports_user_data.h"
14 #include "content/public/browser/navigation_controller.h"
15 #include "content/public/browser/navigation_entry.h"
16 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/common/content_switches.h"
19 #include "content/public/common/renderer_preferences.h"
20 #include "jni/AwSettings_jni.h"
21 #include "ui/gfx/font_render_params_linux.h"
22 #include "webkit/common/webpreferences.h"
23
24 using base::android::ConvertJavaStringToUTF16;
25 using base::android::ConvertUTF8ToJavaString;
26 using base::android::ScopedJavaLocalRef;
27 using content::RendererPreferences;
28
29 namespace android_webview {
30
31 namespace {
32
33 // TODO(boliu): Deduplicate with chrome/ code.
34 content::RendererPreferencesHintingEnum GetRendererPreferencesHintingEnum(
35     gfx::FontRenderParams::Hinting hinting) {
36   switch (hinting) {
37     case gfx::FontRenderParams::HINTING_NONE:
38       return content::RENDERER_PREFERENCES_HINTING_NONE;
39     case gfx::FontRenderParams::HINTING_SLIGHT:
40       return content::RENDERER_PREFERENCES_HINTING_SLIGHT;
41     case gfx::FontRenderParams::HINTING_MEDIUM:
42       return content::RENDERER_PREFERENCES_HINTING_MEDIUM;
43     case gfx::FontRenderParams::HINTING_FULL:
44       return content::RENDERER_PREFERENCES_HINTING_FULL;
45     default:
46       NOTREACHED() << "Unhandled hinting style " << hinting;
47       return content::RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT;
48   }
49 }
50
51 // TODO(boliu): Deduplicate with chrome/ code.
52 content::RendererPreferencesSubpixelRenderingEnum
53 GetRendererPreferencesSubpixelRenderingEnum(
54     gfx::FontRenderParams::SubpixelRendering subpixel_rendering) {
55   switch (subpixel_rendering) {
56     case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE:
57       return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE;
58     case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB:
59       return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB;
60     case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR:
61       return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR;
62     case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB:
63       return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB;
64     case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR:
65       return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR;
66     default:
67       NOTREACHED() << "Unhandled subpixel rendering style "
68                    << subpixel_rendering;
69       return content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT;
70   }
71 }
72
73 void PopulateFixedRendererPreferences(RendererPreferences* prefs) {
74   prefs->tap_multiple_targets_strategy =
75       content::TAP_MULTIPLE_TARGETS_STRATEGY_NONE;
76
77   // TODO(boliu): Deduplicate with chrome/ code.
78   const gfx::FontRenderParams& params = gfx::GetDefaultWebKitFontRenderParams();
79   prefs->should_antialias_text = params.antialiasing;
80   prefs->use_subpixel_positioning = params.subpixel_positioning;
81   prefs->hinting = GetRendererPreferencesHintingEnum(params.hinting);
82   prefs->use_autohinter = params.autohinter;
83   prefs->use_bitmaps = params.use_bitmaps;
84   prefs->subpixel_rendering =
85       GetRendererPreferencesSubpixelRenderingEnum(params.subpixel_rendering);
86 }
87
88 void PopulateFixedWebPreferences(WebPreferences* web_prefs) {
89   web_prefs->shrinks_standalone_images_to_fit = false;
90   web_prefs->should_clear_document_background = false;
91 }
92
93 };  // namespace
94
95 const void* kAwSettingsUserDataKey = &kAwSettingsUserDataKey;
96
97 class AwSettingsUserData : public base::SupportsUserData::Data {
98  public:
99   AwSettingsUserData(AwSettings* ptr) : settings_(ptr) {}
100
101   static AwSettings* GetSettings(content::WebContents* web_contents) {
102     if (!web_contents)
103       return NULL;
104     AwSettingsUserData* data = reinterpret_cast<AwSettingsUserData*>(
105         web_contents->GetUserData(kAwSettingsUserDataKey));
106     return data ? data->settings_ : NULL;
107   }
108
109  private:
110   AwSettings* settings_;
111 };
112
113 AwSettings::AwSettings(JNIEnv* env, jobject obj, jlong web_contents)
114     : WebContentsObserver(
115           reinterpret_cast<content::WebContents*>(web_contents)),
116       accelerated_2d_canvas_disabled_by_switch_(
117           CommandLine::ForCurrentProcess()->HasSwitch(
118               switches::kDisableAccelerated2dCanvas)),
119       renderer_prefs_initialized_(false),
120       aw_settings_(env, obj) {
121   reinterpret_cast<content::WebContents*>(web_contents)->
122       SetUserData(kAwSettingsUserDataKey, new AwSettingsUserData(this));
123 }
124
125 AwSettings::~AwSettings() {
126   if (web_contents()) {
127     web_contents()->SetUserData(kAwSettingsUserDataKey, NULL);
128   }
129
130   JNIEnv* env = base::android::AttachCurrentThread();
131   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
132   jobject obj = scoped_obj.obj();
133   if (!obj) return;
134   Java_AwSettings_nativeAwSettingsGone(env, obj,
135                                        reinterpret_cast<intptr_t>(this));
136 }
137
138 void AwSettings::Destroy(JNIEnv* env, jobject obj) {
139   delete this;
140 }
141
142 AwSettings* AwSettings::FromWebContents(content::WebContents* web_contents) {
143   return AwSettingsUserData::GetSettings(web_contents);
144 }
145
146 AwRenderViewHostExt* AwSettings::GetAwRenderViewHostExt() {
147   if (!web_contents()) return NULL;
148   AwContents* contents = AwContents::FromWebContents(web_contents());
149   if (!contents) return NULL;
150   return contents->render_view_host_ext();
151 }
152
153 void AwSettings::ResetScrollAndScaleState(JNIEnv* env, jobject obj) {
154   AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
155   if (!rvhe) return;
156   rvhe->ResetScrollAndScaleState();
157 }
158
159 void AwSettings::UpdateEverything() {
160   JNIEnv* env = base::android::AttachCurrentThread();
161   CHECK(env);
162   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
163   jobject obj = scoped_obj.obj();
164   if (!obj) return;
165   // Grab the lock and call UpdateEverythingLocked.
166   Java_AwSettings_updateEverything(env, obj);
167 }
168
169 void AwSettings::UpdateEverythingLocked(JNIEnv* env, jobject obj) {
170   UpdateInitialPageScaleLocked(env, obj);
171   UpdateWebkitPreferencesLocked(env, obj);
172   UpdateUserAgentLocked(env, obj);
173   ResetScrollAndScaleState(env, obj);
174   UpdateFormDataPreferencesLocked(env, obj);
175   UpdateRendererPreferencesLocked(env, obj);
176 }
177
178 void AwSettings::UpdateUserAgentLocked(JNIEnv* env, jobject obj) {
179   if (!web_contents()) return;
180
181   ScopedJavaLocalRef<jstring> str =
182       Java_AwSettings_getUserAgentLocked(env, obj);
183   bool ua_overidden = str.obj() != NULL;
184
185   if (ua_overidden) {
186     std::string override = base::android::ConvertJavaStringToUTF8(str);
187     web_contents()->SetUserAgentOverride(override);
188   }
189
190   const content::NavigationController& controller =
191       web_contents()->GetController();
192   for (int i = 0; i < controller.GetEntryCount(); ++i)
193     controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(ua_overidden);
194 }
195
196 void AwSettings::UpdateWebkitPreferencesLocked(JNIEnv* env, jobject obj) {
197   if (!web_contents()) return;
198   AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
199   if (!render_view_host_ext) return;
200
201   content::RenderViewHost* render_view_host =
202       web_contents()->GetRenderViewHost();
203   if (!render_view_host) return;
204   render_view_host->UpdateWebkitPreferences(
205       render_view_host->GetWebkitPreferences());
206 }
207
208 void AwSettings::UpdateInitialPageScaleLocked(JNIEnv* env, jobject obj) {
209   AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
210   if (!rvhe) return;
211
212   float initial_page_scale_percent =
213       Java_AwSettings_getInitialPageScalePercentLocked(env, obj);
214   if (initial_page_scale_percent == 0) {
215     rvhe->SetInitialPageScale(-1);
216   } else {
217     float dip_scale = static_cast<float>(
218         Java_AwSettings_getDIPScaleLocked(env, obj));
219     rvhe->SetInitialPageScale(initial_page_scale_percent / dip_scale / 100.0f);
220   }
221 }
222
223 void AwSettings::UpdateFormDataPreferencesLocked(JNIEnv* env, jobject obj) {
224   if (!web_contents()) return;
225   AwContents* contents = AwContents::FromWebContents(web_contents());
226   if (!contents) return;
227
228   contents->SetSaveFormData(Java_AwSettings_getSaveFormDataLocked(env, obj));
229 }
230
231 void AwSettings::UpdateRendererPreferencesLocked(JNIEnv* env, jobject obj) {
232   if (!web_contents()) return;
233
234   bool update_prefs = false;
235   RendererPreferences* prefs = web_contents()->GetMutableRendererPrefs();
236
237   if (!renderer_prefs_initialized_) {
238     PopulateFixedRendererPreferences(prefs);
239     renderer_prefs_initialized_ = true;
240     update_prefs = true;
241   }
242
243   bool video_overlay =
244       Java_AwSettings_getVideoOverlayForEmbeddedVideoEnabledLocked(env, obj);
245   if (video_overlay != prefs->use_video_overlay_for_embedded_encrypted_video) {
246     prefs->use_video_overlay_for_embedded_encrypted_video = video_overlay;
247     update_prefs = true;
248   }
249
250   content::RenderViewHost* host = web_contents()->GetRenderViewHost();
251   if (update_prefs && host)
252     host->SyncRendererPrefs();
253 }
254
255 void AwSettings::RenderViewCreated(content::RenderViewHost* render_view_host) {
256   // A single WebContents can normally have 0 to many RenderViewHost instances
257   // associated with it.
258   // This is important since there is only one RenderViewHostExt instance per
259   // WebContents (and not one RVHExt per RVH, as you might expect) and updating
260   // settings via RVHExt only ever updates the 'current' RVH.
261   // In android_webview we don't swap out the RVH on cross-site navigations, so
262   // we shouldn't have to deal with the multiple RVH per WebContents case. That
263   // in turn means that the newly created RVH is always the 'current' RVH
264   // (since we only ever go from 0 to 1 RVH instances) and hence the DCHECK.
265   DCHECK(web_contents()->GetRenderViewHost() == render_view_host);
266
267   UpdateEverything();
268 }
269
270 void AwSettings::WebContentsDestroyed() {
271   delete this;
272 }
273
274 void AwSettings::PopulateWebPreferences(WebPreferences* web_prefs) {
275   JNIEnv* env = base::android::AttachCurrentThread();
276   CHECK(env);
277   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
278   jobject obj = scoped_obj.obj();
279   if (!obj) return;
280   // Grab the lock and call PopulateWebPreferencesLocked.
281   Java_AwSettings_populateWebPreferences(
282       env, obj, reinterpret_cast<jlong>(web_prefs));
283 }
284
285 void AwSettings::PopulateWebPreferencesLocked(
286     JNIEnv* env, jobject obj, jlong web_prefs_ptr) {
287   AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
288   if (!render_view_host_ext) return;
289
290   WebPreferences* web_prefs = reinterpret_cast<WebPreferences*>(web_prefs_ptr);
291   PopulateFixedWebPreferences(web_prefs);
292
293   web_prefs->text_autosizing_enabled =
294       Java_AwSettings_getTextAutosizingEnabledLocked(env, obj);
295
296   int text_size_percent = Java_AwSettings_getTextSizePercentLocked(env, obj);
297   if (web_prefs->text_autosizing_enabled) {
298     web_prefs->font_scale_factor = text_size_percent / 100.0f;
299     web_prefs->force_enable_zoom = text_size_percent >= 130;
300     // Use the default zoom factor value when Text Autosizer is turned on.
301     render_view_host_ext->SetTextZoomFactor(1);
302   } else {
303     web_prefs->force_enable_zoom = false;
304     render_view_host_ext->SetTextZoomFactor(text_size_percent / 100.0f);
305   }
306
307   web_prefs->standard_font_family_map[webkit_glue::kCommonScript] =
308       ConvertJavaStringToUTF16(
309           Java_AwSettings_getStandardFontFamilyLocked(env, obj));
310
311   web_prefs->fixed_font_family_map[webkit_glue::kCommonScript] =
312       ConvertJavaStringToUTF16(
313           Java_AwSettings_getFixedFontFamilyLocked(env, obj));
314
315   web_prefs->sans_serif_font_family_map[webkit_glue::kCommonScript] =
316       ConvertJavaStringToUTF16(
317           Java_AwSettings_getSansSerifFontFamilyLocked(env, obj));
318
319   web_prefs->serif_font_family_map[webkit_glue::kCommonScript] =
320       ConvertJavaStringToUTF16(
321           Java_AwSettings_getSerifFontFamilyLocked(env, obj));
322
323   web_prefs->cursive_font_family_map[webkit_glue::kCommonScript] =
324       ConvertJavaStringToUTF16(
325           Java_AwSettings_getCursiveFontFamilyLocked(env, obj));
326
327   web_prefs->fantasy_font_family_map[webkit_glue::kCommonScript] =
328       ConvertJavaStringToUTF16(
329           Java_AwSettings_getFantasyFontFamilyLocked(env, obj));
330
331   web_prefs->default_encoding = ConvertJavaStringToUTF8(
332       Java_AwSettings_getDefaultTextEncodingLocked(env, obj));
333
334   web_prefs->minimum_font_size =
335       Java_AwSettings_getMinimumFontSizeLocked(env, obj);
336
337   web_prefs->minimum_logical_font_size =
338       Java_AwSettings_getMinimumLogicalFontSizeLocked(env, obj);
339
340   web_prefs->default_font_size =
341       Java_AwSettings_getDefaultFontSizeLocked(env, obj);
342
343   web_prefs->default_fixed_font_size =
344       Java_AwSettings_getDefaultFixedFontSizeLocked(env, obj);
345
346   // Blink's LoadsImagesAutomatically and ImagesEnabled must be
347   // set cris-cross to Android's. See
348   // https://code.google.com/p/chromium/issues/detail?id=224317#c26
349   web_prefs->loads_images_automatically =
350       Java_AwSettings_getImagesEnabledLocked(env, obj);
351   web_prefs->images_enabled =
352       Java_AwSettings_getLoadsImagesAutomaticallyLocked(env, obj);
353
354   web_prefs->javascript_enabled =
355       Java_AwSettings_getJavaScriptEnabledLocked(env, obj);
356
357   web_prefs->allow_universal_access_from_file_urls =
358       Java_AwSettings_getAllowUniversalAccessFromFileURLsLocked(env, obj);
359
360   web_prefs->allow_file_access_from_file_urls =
361       Java_AwSettings_getAllowFileAccessFromFileURLsLocked(env, obj);
362
363   web_prefs->javascript_can_open_windows_automatically =
364       Java_AwSettings_getJavaScriptCanOpenWindowsAutomaticallyLocked(env, obj);
365
366   web_prefs->supports_multiple_windows =
367       Java_AwSettings_getSupportMultipleWindowsLocked(env, obj);
368
369   web_prefs->plugins_enabled =
370       !Java_AwSettings_getPluginsDisabledLocked(env, obj);
371
372   web_prefs->application_cache_enabled =
373       Java_AwSettings_getAppCacheEnabledLocked(env, obj);
374
375   web_prefs->local_storage_enabled =
376       Java_AwSettings_getDomStorageEnabledLocked(env, obj);
377
378   web_prefs->databases_enabled =
379       Java_AwSettings_getDatabaseEnabledLocked(env, obj);
380
381   web_prefs->wide_viewport_quirk = true;
382   web_prefs->use_wide_viewport =
383       Java_AwSettings_getUseWideViewportLocked(env, obj);
384
385   web_prefs->double_tap_to_zoom_enabled =
386       Java_AwSettings_supportsDoubleTapZoomLocked(env, obj);
387
388   web_prefs->initialize_at_minimum_page_scale =
389       Java_AwSettings_getLoadWithOverviewModeLocked(env, obj);
390
391   web_prefs->user_gesture_required_for_media_playback =
392       Java_AwSettings_getMediaPlaybackRequiresUserGestureLocked(env, obj);
393
394   ScopedJavaLocalRef<jstring> url =
395       Java_AwSettings_getDefaultVideoPosterURLLocked(env, obj);
396   web_prefs->default_video_poster_url = url.obj() ?
397       GURL(ConvertJavaStringToUTF8(url)) : GURL();
398
399   bool support_quirks = Java_AwSettings_getSupportLegacyQuirksLocked(env, obj);
400   // Please see the corresponding Blink settings for bug references.
401   web_prefs->support_deprecated_target_density_dpi = support_quirks;
402   web_prefs->use_legacy_background_size_shorthand_behavior = support_quirks;
403   web_prefs->viewport_meta_layout_size_quirk = support_quirks;
404   web_prefs->viewport_meta_merge_content_quirk = support_quirks;
405   web_prefs->viewport_meta_non_user_scalable_quirk = support_quirks;
406   web_prefs->viewport_meta_zero_values_quirk = support_quirks;
407   web_prefs->clobber_user_agent_initial_scale_quirk = support_quirks;
408   web_prefs->ignore_main_frame_overflow_hidden_quirk = support_quirks;
409   web_prefs->report_screen_size_in_physical_pixels_quirk = support_quirks;
410
411   web_prefs->password_echo_enabled =
412       Java_AwSettings_getPasswordEchoEnabledLocked(env, obj);
413   web_prefs->spatial_navigation_enabled =
414       Java_AwSettings_getSpatialNavigationLocked(env, obj);
415
416   web_prefs->accelerated_2d_canvas_enabled = true;
417   if (accelerated_2d_canvas_disabled_by_switch_ ||
418       !Java_AwSettings_getEnableSupportedHardwareAcceleratedFeaturesLocked(
419           env, obj)) {
420     // Any canvas smaller than this will fallback to software. Abusing this
421     // slightly to turn canvas off without changing
422     // accelerated_2d_canvas_enabled, which also affects compositing mode.
423     // Using 100M instead of max int to avoid overflows.
424     web_prefs->minimum_accelerated_2d_canvas_size = 100 * 1000 * 1000;
425   }
426
427   web_prefs->allow_displaying_insecure_content =
428       Java_AwSettings_getAllowDisplayingInsecureContentLocked(env, obj);
429   web_prefs->allow_running_insecure_content =
430       Java_AwSettings_getAllowRunningInsecureContentLocked(env, obj);
431 }
432
433 static jlong Init(JNIEnv* env,
434                   jobject obj,
435                   jlong web_contents) {
436   AwSettings* settings = new AwSettings(env, obj, web_contents);
437   return reinterpret_cast<intptr_t>(settings);
438 }
439
440 static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
441   return base::android::ConvertUTF8ToJavaString(env, GetUserAgent()).Release();
442 }
443
444 bool RegisterAwSettings(JNIEnv* env) {
445   return RegisterNativesImpl(env);
446 }
447
448 }  // namespace android_webview