c2c6ca197a827009c3617019cd1cd5560701db6e
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / android / xwalk_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 "xwalk/runtime/browser/android/xwalk_settings.h"
6
7 #include <string>
8
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/command_line.h"
12 #include "content/browser/renderer_host/java/jni_helper.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 "jni/XWalkSettings_jni.h"
18 #include "webkit/common/webpreferences.h"
19 #include "xwalk/runtime/common/xwalk_content_client.h"
20 #include "xwalk/runtime/browser/android/renderer_host/xwalk_render_view_host_ext.h"
21 #include "xwalk/runtime/browser/android/xwalk_content.h"
22
23 using base::android::CheckException;
24 using base::android::ConvertJavaStringToUTF16;
25 using base::android::ConvertUTF16ToJavaString;
26 using base::android::ConvertUTF8ToJavaString;
27 using base::android::GetClass;
28 using base::android::ScopedJavaLocalRef;
29 using content::GetFieldID;
30
31 namespace xwalk {
32
33 struct XWalkSettings::FieldIds {
34   // Note on speed. One may think that an approach that reads field values via
35   // JNI is ineffective and should not be used. Please keep in mind that in the
36   // legacy WebView the whole Sync method took <1ms on Xoom, and no one is
37   // expected to modify settings in performance-critical code.
38   FieldIds() { }
39
40   explicit FieldIds(JNIEnv* env) {
41     const char* kStringClassName = "Ljava/lang/String;";
42
43     // FIXME: we should be using a new GetFieldIDFromClassName() with caching.
44     ScopedJavaLocalRef<jclass> clazz(
45         GetClass(env, "org/xwalk/core/XWalkSettings"));
46     allow_scripts_to_close_windows =
47         GetFieldID(env, clazz, "mAllowScriptsToCloseWindows", "Z");
48     load_images_automatically =
49         GetFieldID(env, clazz, "mLoadsImagesAutomatically", "Z");
50     images_enabled =
51         GetFieldID(env, clazz, "mImagesEnabled", "Z");
52     java_script_enabled =
53         GetFieldID(env, clazz, "mJavaScriptEnabled", "Z");
54     allow_universal_access_from_file_urls =
55         GetFieldID(env, clazz, "mAllowUniversalAccessFromFileURLs", "Z");
56     allow_file_access_from_file_urls =
57         GetFieldID(env, clazz, "mAllowFileAccessFromFileURLs", "Z");
58     java_script_can_open_windows_automatically =
59         GetFieldID(env, clazz, "mJavaScriptCanOpenWindowsAutomatically", "Z");
60     support_multiple_windows =
61         GetFieldID(env, clazz, "mSupportMultipleWindows", "Z");
62     dom_storage_enabled =
63         GetFieldID(env, clazz, "mDomStorageEnabled", "Z");
64     database_enabled =
65         GetFieldID(env, clazz, "mDatabaseEnabled", "Z");
66     use_wide_viewport =
67         GetFieldID(env, clazz, "mUseWideViewport", "Z");
68     media_playback_requires_user_gesture =
69         GetFieldID(env, clazz, "mMediaPlaybackRequiresUserGesture", "Z");
70     default_video_poster_url =
71         GetFieldID(env, clazz, "mDefaultVideoPosterURL", kStringClassName);
72   }
73
74   // Field ids
75   jfieldID allow_scripts_to_close_windows;
76   jfieldID load_images_automatically;
77   jfieldID images_enabled;
78   jfieldID java_script_enabled;
79   jfieldID allow_universal_access_from_file_urls;
80   jfieldID allow_file_access_from_file_urls;
81   jfieldID java_script_can_open_windows_automatically;
82   jfieldID support_multiple_windows;
83   jfieldID dom_storage_enabled;
84   jfieldID database_enabled;
85   jfieldID use_wide_viewport;
86   jfieldID media_playback_requires_user_gesture;
87   jfieldID default_video_poster_url;
88 };
89
90 XWalkSettings::XWalkSettings(JNIEnv* env, jobject obj, jint web_contents)
91     : WebContentsObserver(
92           reinterpret_cast<content::WebContents*>(web_contents)),
93       xwalk_settings_(env, obj) {
94 }
95
96 XWalkSettings::~XWalkSettings() {
97     JNIEnv* env = base::android::AttachCurrentThread();
98     ScopedJavaLocalRef<jobject> scoped_obj = xwalk_settings_.get(env);
99     jobject obj = scoped_obj.obj();
100     if (!obj) return;
101     Java_XWalkSettings_nativeXWalkSettingsGone(env, obj,
102                                                reinterpret_cast<jint>(this));
103 }
104
105 void XWalkSettings::Destroy(JNIEnv* env, jobject obj) {
106   delete this;
107 }
108
109 XWalkRenderViewHostExt* XWalkSettings::GetXWalkRenderViewHostExt() {
110   if (!web_contents()) return NULL;
111   XWalkContent* contents = XWalkContent::FromWebContents(web_contents());
112   if (!contents) return NULL;
113   return contents->render_view_host_ext();
114 }
115
116 void XWalkSettings::UpdateEverything() {
117   JNIEnv* env = base::android::AttachCurrentThread();
118   CHECK(env);
119   ScopedJavaLocalRef<jobject> scoped_obj = xwalk_settings_.get(env);
120   jobject obj = scoped_obj.obj();
121   if (!obj) return;
122
123   Java_XWalkSettings_updateEverything(env, obj);
124 }
125
126 void XWalkSettings::UpdateEverythingLocked(JNIEnv* env, jobject obj) {
127   UpdateWebkitPreferences(env, obj);
128   UpdateUserAgent(env, obj);
129 }
130
131 void XWalkSettings::UpdateUserAgent(JNIEnv* env, jobject obj) {
132   if (!web_contents()) return;
133
134   ScopedJavaLocalRef<jstring> str =
135       Java_XWalkSettings_getUserAgentLocked(env, obj);
136   bool ua_overidden = str.obj() != NULL;
137
138   if (ua_overidden) {
139     std::string override = base::android::ConvertJavaStringToUTF8(str);
140     web_contents()->SetUserAgentOverride(override);
141   }
142
143   const content::NavigationController& controller =
144       web_contents()->GetController();
145   for (int i = 0; i < controller.GetEntryCount(); ++i)
146     controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(ua_overidden);
147 }
148
149 void XWalkSettings::UpdateWebkitPreferences(JNIEnv* env, jobject obj) {
150   if (!web_contents()) return;
151   XWalkRenderViewHostExt* render_view_host_ext = GetXWalkRenderViewHostExt();
152   if (!render_view_host_ext) return;
153
154   if (!field_ids_)
155     field_ids_.reset(new FieldIds(env));
156
157   content::RenderViewHost* render_view_host =
158       web_contents()->GetRenderViewHost();
159   if (!render_view_host) return;
160   WebPreferences prefs = render_view_host->GetWebkitPreferences();
161
162   prefs.allow_scripts_to_close_windows =
163       env->GetBooleanField(obj, field_ids_->allow_scripts_to_close_windows);
164
165   prefs.loads_images_automatically =
166       env->GetBooleanField(obj, field_ids_->load_images_automatically);
167
168   prefs.images_enabled =
169       env->GetBooleanField(obj, field_ids_->images_enabled);
170
171   prefs.javascript_enabled =
172       env->GetBooleanField(obj, field_ids_->java_script_enabled);
173
174   prefs.allow_universal_access_from_file_urls = env->GetBooleanField(
175       obj, field_ids_->allow_universal_access_from_file_urls);
176
177   prefs.allow_file_access_from_file_urls = env->GetBooleanField(
178       obj, field_ids_->allow_file_access_from_file_urls);
179
180   prefs.javascript_can_open_windows_automatically = env->GetBooleanField(
181       obj, field_ids_->java_script_can_open_windows_automatically);
182
183   prefs.supports_multiple_windows = env->GetBooleanField(
184       obj, field_ids_->support_multiple_windows);
185
186   prefs.application_cache_enabled =
187       Java_XWalkSettings_getAppCacheEnabled(env, obj);
188
189   prefs.local_storage_enabled = env->GetBooleanField(
190       obj, field_ids_->dom_storage_enabled);
191
192   prefs.databases_enabled = env->GetBooleanField(
193       obj, field_ids_->database_enabled);
194
195   prefs.double_tap_to_zoom_enabled = prefs.use_wide_viewport =
196       env->GetBooleanField(obj, field_ids_->use_wide_viewport);
197
198   prefs.user_gesture_required_for_media_playback = env->GetBooleanField(
199       obj, field_ids_->media_playback_requires_user_gesture);
200
201   ScopedJavaLocalRef<jstring> str;
202   str.Reset(
203       env, static_cast<jstring>(
204           env->GetObjectField(obj, field_ids_->default_video_poster_url)));
205   prefs.default_video_poster_url = str.obj() ?
206       GURL(ConvertJavaStringToUTF8(str)) : GURL();
207
208   render_view_host->UpdateWebkitPreferences(prefs);
209 }
210
211 void XWalkSettings::RenderViewCreated(
212     content::RenderViewHost* render_view_host) {
213   // A single WebContents can normally have 0 to many RenderViewHost instances
214   // associated with it.
215   // This is important since there is only one RenderViewHostExt instance per
216   // WebContents (and not one RVHExt per RVH, as you might expect) and updating
217   // settings via RVHExt only ever updates the 'current' RVH.
218   // In android_webview we don't swap out the RVH on cross-site navigations, so
219   // we shouldn't have to deal with the multiple RVH per WebContents case. That
220   // in turn means that the newly created RVH is always the 'current' RVH
221   // (since we only ever go from 0 to 1 RVH instances) and hence the DCHECK.
222   DCHECK(web_contents()->GetRenderViewHost() == render_view_host);
223
224   UpdateEverything();
225 }
226
227 static jint Init(JNIEnv* env,
228                  jobject obj,
229                  jint web_contents) {
230   XWalkSettings* settings = new XWalkSettings(env, obj, web_contents);
231   return reinterpret_cast<jint>(settings);
232 }
233
234 static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
235   return base::android::ConvertUTF8ToJavaString(
236       env, GetUserAgent()).Release();
237 }
238
239 bool RegisterXWalkSettings(JNIEnv* env) {
240   return RegisterNativesImpl(env) >= 0;
241 }
242
243 }  // namespace xwalk