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 "base/supports_user_data.h"
12 #include "content/public/browser/navigation_controller.h"
13 #include "content/public/browser/navigation_entry.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/common/content_client.h"
17 #include "jni/AwSettings_jni.h"
18 #include "webkit/common/user_agent/user_agent.h"
19 #include "webkit/common/webpreferences.h"
20 #include "webkit/glue/webkit_glue.h"
22 using base::android::ConvertJavaStringToUTF16;
23 using base::android::ConvertUTF8ToJavaString;
24 using base::android::ScopedJavaLocalRef;
26 namespace android_webview {
28 const void* kAwSettingsUserDataKey = &kAwSettingsUserDataKey;
30 class AwSettingsUserData : public base::SupportsUserData::Data {
32 AwSettingsUserData(AwSettings* ptr) : settings_(ptr) {}
34 static AwSettings* GetSettings(content::WebContents* web_contents) {
37 AwSettingsUserData* data = reinterpret_cast<AwSettingsUserData*>(
38 web_contents->GetUserData(kAwSettingsUserDataKey));
39 return data ? data->settings_ : NULL;
43 AwSettings* settings_;
46 AwSettings::AwSettings(JNIEnv* env, jobject obj, jint web_contents)
47 : WebContentsObserver(
48 reinterpret_cast<content::WebContents*>(web_contents)),
49 aw_settings_(env, obj) {
50 reinterpret_cast<content::WebContents*>(web_contents)->
51 SetUserData(kAwSettingsUserDataKey, new AwSettingsUserData(this));
54 AwSettings::~AwSettings() {
56 web_contents()->SetUserData(kAwSettingsUserDataKey, NULL);
59 JNIEnv* env = base::android::AttachCurrentThread();
60 ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
61 jobject obj = scoped_obj.obj();
63 Java_AwSettings_nativeAwSettingsGone(env, obj,
64 reinterpret_cast<jint>(this));
67 void AwSettings::Destroy(JNIEnv* env, jobject obj) {
71 AwSettings* AwSettings::FromWebContents(content::WebContents* web_contents) {
72 return AwSettingsUserData::GetSettings(web_contents);
75 AwRenderViewHostExt* AwSettings::GetAwRenderViewHostExt() {
76 if (!web_contents()) return NULL;
77 AwContents* contents = AwContents::FromWebContents(web_contents());
78 if (!contents) return NULL;
79 return contents->render_view_host_ext();
82 void AwSettings::ResetScrollAndScaleState(JNIEnv* env, jobject obj) {
83 AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
85 rvhe->ResetScrollAndScaleState();
88 void AwSettings::UpdateEverything() {
89 JNIEnv* env = base::android::AttachCurrentThread();
91 ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
92 jobject obj = scoped_obj.obj();
94 // Grab the lock and call UpdateEverythingLocked.
95 Java_AwSettings_updateEverything(env, obj);
98 void AwSettings::UpdateEverythingLocked(JNIEnv* env, jobject obj) {
99 UpdateInitialPageScaleLocked(env, obj);
100 UpdateWebkitPreferencesLocked(env, obj);
101 UpdateUserAgentLocked(env, obj);
102 ResetScrollAndScaleState(env, obj);
103 UpdateFormDataPreferencesLocked(env, obj);
106 void AwSettings::UpdateUserAgentLocked(JNIEnv* env, jobject obj) {
107 if (!web_contents()) return;
109 ScopedJavaLocalRef<jstring> str =
110 Java_AwSettings_getUserAgentLocked(env, obj);
111 bool ua_overidden = str.obj() != NULL;
114 std::string override = base::android::ConvertJavaStringToUTF8(str);
115 web_contents()->SetUserAgentOverride(override);
118 const content::NavigationController& controller =
119 web_contents()->GetController();
120 for (int i = 0; i < controller.GetEntryCount(); ++i)
121 controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(ua_overidden);
124 void AwSettings::UpdateWebkitPreferencesLocked(JNIEnv* env, jobject obj) {
125 if (!web_contents()) return;
126 AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
127 if (!render_view_host_ext) return;
129 content::RenderViewHost* render_view_host =
130 web_contents()->GetRenderViewHost();
131 if (!render_view_host) return;
132 render_view_host->UpdateWebkitPreferences(
133 render_view_host->GetWebkitPreferences());
136 void AwSettings::UpdateInitialPageScaleLocked(JNIEnv* env, jobject obj) {
137 AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
140 float initial_page_scale_percent =
141 Java_AwSettings_getInitialPageScalePercentLocked(env, obj);
142 if (initial_page_scale_percent == 0) {
143 rvhe->SetInitialPageScale(-1);
145 float dip_scale = static_cast<float>(
146 Java_AwSettings_getDIPScaleLocked(env, obj));
147 rvhe->SetInitialPageScale(initial_page_scale_percent / dip_scale / 100.0f);
151 void AwSettings::UpdateFormDataPreferencesLocked(JNIEnv* env, jobject obj) {
152 if (!web_contents()) return;
153 AwContents* contents = AwContents::FromWebContents(web_contents());
154 if (!contents) return;
156 contents->SetSaveFormData(Java_AwSettings_getSaveFormDataLocked(env, obj));
159 void AwSettings::RenderViewCreated(content::RenderViewHost* render_view_host) {
160 // A single WebContents can normally have 0 to many RenderViewHost instances
161 // associated with it.
162 // This is important since there is only one RenderViewHostExt instance per
163 // WebContents (and not one RVHExt per RVH, as you might expect) and updating
164 // settings via RVHExt only ever updates the 'current' RVH.
165 // In android_webview we don't swap out the RVH on cross-site navigations, so
166 // we shouldn't have to deal with the multiple RVH per WebContents case. That
167 // in turn means that the newly created RVH is always the 'current' RVH
168 // (since we only ever go from 0 to 1 RVH instances) and hence the DCHECK.
169 DCHECK(web_contents()->GetRenderViewHost() == render_view_host);
174 void AwSettings::WebContentsDestroyed(content::WebContents* web_contents) {
179 void AwSettings::PopulateFixedPreferences(WebPreferences* web_prefs) {
180 web_prefs->shrinks_standalone_images_to_fit = false;
183 void AwSettings::PopulateWebPreferences(WebPreferences* web_prefs) {
184 JNIEnv* env = base::android::AttachCurrentThread();
187 AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
188 if (!render_view_host_ext) return;
190 ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
191 jobject obj = scoped_obj.obj();
194 PopulateFixedPreferences(web_prefs);
196 web_prefs->text_autosizing_enabled =
197 Java_AwSettings_getTextAutosizingEnabledLocked(env, obj);
199 int text_size_percent = Java_AwSettings_getTextSizePercentLocked(env, obj);
200 if (web_prefs->text_autosizing_enabled) {
201 web_prefs->font_scale_factor = text_size_percent / 100.0f;
202 web_prefs->force_enable_zoom = text_size_percent >= 130;
203 // Use the default zoom factor value when Text Autosizer is turned on.
204 render_view_host_ext->SetTextZoomFactor(1);
206 web_prefs->force_enable_zoom = false;
207 render_view_host_ext->SetTextZoomFactor(text_size_percent / 100.0f);
210 web_prefs->standard_font_family_map[webkit_glue::kCommonScript] =
211 ConvertJavaStringToUTF16(
212 Java_AwSettings_getStandardFontFamilyLocked(env, obj));
214 web_prefs->fixed_font_family_map[webkit_glue::kCommonScript] =
215 ConvertJavaStringToUTF16(
216 Java_AwSettings_getFixedFontFamilyLocked(env, obj));
218 web_prefs->sans_serif_font_family_map[webkit_glue::kCommonScript] =
219 ConvertJavaStringToUTF16(
220 Java_AwSettings_getSansSerifFontFamilyLocked(env, obj));
222 web_prefs->serif_font_family_map[webkit_glue::kCommonScript] =
223 ConvertJavaStringToUTF16(
224 Java_AwSettings_getSerifFontFamilyLocked(env, obj));
226 web_prefs->cursive_font_family_map[webkit_glue::kCommonScript] =
227 ConvertJavaStringToUTF16(
228 Java_AwSettings_getCursiveFontFamilyLocked(env, obj));
230 web_prefs->fantasy_font_family_map[webkit_glue::kCommonScript] =
231 ConvertJavaStringToUTF16(
232 Java_AwSettings_getFantasyFontFamilyLocked(env, obj));
234 web_prefs->default_encoding = ConvertJavaStringToUTF8(
235 Java_AwSettings_getDefaultTextEncodingLocked(env, obj));
237 web_prefs->minimum_font_size =
238 Java_AwSettings_getMinimumFontSizeLocked(env, obj);
240 web_prefs->minimum_logical_font_size =
241 Java_AwSettings_getMinimumLogicalFontSizeLocked(env, obj);
243 web_prefs->default_font_size =
244 Java_AwSettings_getDefaultFontSizeLocked(env, obj);
246 web_prefs->default_fixed_font_size =
247 Java_AwSettings_getDefaultFixedFontSizeLocked(env, obj);
249 // Blink's LoadsImagesAutomatically and ImagesEnabled must be
250 // set cris-cross to Android's. See
251 // https://code.google.com/p/chromium/issues/detail?id=224317#c26
252 web_prefs->loads_images_automatically =
253 Java_AwSettings_getImagesEnabledLocked(env, obj);
254 web_prefs->images_enabled =
255 Java_AwSettings_getLoadsImagesAutomaticallyLocked(env, obj);
257 web_prefs->javascript_enabled =
258 Java_AwSettings_getJavaScriptEnabledLocked(env, obj);
260 web_prefs->allow_universal_access_from_file_urls =
261 Java_AwSettings_getAllowUniversalAccessFromFileURLsLocked(env, obj);
263 web_prefs->allow_file_access_from_file_urls =
264 Java_AwSettings_getAllowFileAccessFromFileURLsLocked(env, obj);
266 web_prefs->javascript_can_open_windows_automatically =
267 Java_AwSettings_getJavaScriptCanOpenWindowsAutomaticallyLocked(env, obj);
269 web_prefs->supports_multiple_windows =
270 Java_AwSettings_getSupportMultipleWindowsLocked(env, obj);
272 web_prefs->plugins_enabled =
273 !Java_AwSettings_getPluginsDisabledLocked(env, obj);
275 web_prefs->application_cache_enabled =
276 Java_AwSettings_getAppCacheEnabledLocked(env, obj);
278 web_prefs->local_storage_enabled =
279 Java_AwSettings_getDomStorageEnabledLocked(env, obj);
281 web_prefs->databases_enabled =
282 Java_AwSettings_getDatabaseEnabledLocked(env, obj);
284 web_prefs->wide_viewport_quirk = true;
285 web_prefs->double_tap_to_zoom_enabled = web_prefs->use_wide_viewport =
286 Java_AwSettings_getUseWideViewportLocked(env, obj);
288 web_prefs->initialize_at_minimum_page_scale =
289 Java_AwSettings_getLoadWithOverviewModeLocked(env, obj);
291 web_prefs->user_gesture_required_for_media_playback =
292 Java_AwSettings_getMediaPlaybackRequiresUserGestureLocked(env, obj);
294 ScopedJavaLocalRef<jstring> url =
295 Java_AwSettings_getDefaultVideoPosterURLLocked(env, obj);
296 web_prefs->default_video_poster_url = url.obj() ?
297 GURL(ConvertJavaStringToUTF8(url)) : GURL();
299 bool support_quirks = Java_AwSettings_getSupportLegacyQuirksLocked(env, obj);
300 web_prefs->support_deprecated_target_density_dpi = support_quirks;
301 web_prefs->use_legacy_background_size_shorthand_behavior = support_quirks;
302 web_prefs->viewport_meta_layout_size_quirk = support_quirks;
303 web_prefs->viewport_meta_merge_content_quirk = support_quirks;
304 web_prefs->viewport_meta_zero_values_quirk = support_quirks;
305 web_prefs->ignore_main_frame_overflow_hidden_quirk = support_quirks;
306 web_prefs->report_screen_size_in_physical_pixels_quirk = support_quirks;
308 web_prefs->password_echo_enabled =
309 Java_AwSettings_getPasswordEchoEnabledLocked(env, obj);
310 web_prefs->spatial_navigation_enabled =
311 Java_AwSettings_getSpatialNavigationLocked(env, obj);
314 static jint Init(JNIEnv* env,
317 AwSettings* settings = new AwSettings(env, obj, web_contents);
318 return reinterpret_cast<jint>(settings);
321 static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
322 return base::android::ConvertUTF8ToJavaString(
323 env, content::GetUserAgent(GURL())).Release();
326 bool RegisterAwSettings(JNIEnv* env) {
327 return RegisterNativesImpl(env) >= 0;
330 } // namespace android_webview