Home | History | Annotate | Download | only in native
      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/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 "content/public/common/page_zoom.h"
     18 #include "jni/AwSettings_jni.h"
     19 #include "webkit/common/user_agent/user_agent.h"
     20 #include "webkit/common/webpreferences.h"
     21 #include "webkit/glue/webkit_glue.h"
     22 
     23 using base::android::ConvertJavaStringToUTF16;
     24 using base::android::ConvertUTF8ToJavaString;
     25 using base::android::ScopedJavaLocalRef;
     26 
     27 namespace android_webview {
     28 
     29 const void* kAwSettingsUserDataKey = &kAwSettingsUserDataKey;
     30 
     31 class AwSettingsUserData : public base::SupportsUserData::Data {
     32  public:
     33   AwSettingsUserData(AwSettings* ptr) : settings_(ptr) {}
     34 
     35   static AwSettings* GetSettings(content::WebContents* web_contents) {
     36     if (!web_contents)
     37       return NULL;
     38     AwSettingsUserData* data = reinterpret_cast<AwSettingsUserData*>(
     39         web_contents->GetUserData(kAwSettingsUserDataKey));
     40     return data ? data->settings_ : NULL;
     41   }
     42 
     43  private:
     44   AwSettings* settings_;
     45 };
     46 
     47 AwSettings::AwSettings(JNIEnv* env, jobject obj, jint web_contents)
     48     : WebContentsObserver(
     49           reinterpret_cast<content::WebContents*>(web_contents)),
     50       aw_settings_(env, obj) {
     51   reinterpret_cast<content::WebContents*>(web_contents)->
     52       SetUserData(kAwSettingsUserDataKey, new AwSettingsUserData(this));
     53 }
     54 
     55 AwSettings::~AwSettings() {
     56   if (web_contents()) {
     57     web_contents()->SetUserData(kAwSettingsUserDataKey, NULL);
     58   }
     59 
     60   JNIEnv* env = base::android::AttachCurrentThread();
     61   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
     62   jobject obj = scoped_obj.obj();
     63   if (!obj) return;
     64   Java_AwSettings_nativeAwSettingsGone(env, obj,
     65                                        reinterpret_cast<jint>(this));
     66 }
     67 
     68 void AwSettings::Destroy(JNIEnv* env, jobject obj) {
     69   delete this;
     70 }
     71 
     72 AwSettings* AwSettings::FromWebContents(content::WebContents* web_contents) {
     73   return AwSettingsUserData::GetSettings(web_contents);
     74 }
     75 
     76 AwRenderViewHostExt* AwSettings::GetAwRenderViewHostExt() {
     77   if (!web_contents()) return NULL;
     78   AwContents* contents = AwContents::FromWebContents(web_contents());
     79   if (!contents) return NULL;
     80   return contents->render_view_host_ext();
     81 }
     82 
     83 void AwSettings::ResetScrollAndScaleState(JNIEnv* env, jobject obj) {
     84   AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
     85   if (!rvhe) return;
     86   rvhe->ResetScrollAndScaleState();
     87 }
     88 
     89 void AwSettings::UpdateEverything() {
     90   JNIEnv* env = base::android::AttachCurrentThread();
     91   CHECK(env);
     92   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
     93   jobject obj = scoped_obj.obj();
     94   if (!obj) return;
     95   // Grab the lock and call UpdateEverythingLocked.
     96   Java_AwSettings_updateEverything(env, obj);
     97 }
     98 
     99 void AwSettings::UpdateEverythingLocked(JNIEnv* env, jobject obj) {
    100   UpdateInitialPageScaleLocked(env, obj);
    101   UpdateWebkitPreferencesLocked(env, obj);
    102   UpdateUserAgentLocked(env, obj);
    103   ResetScrollAndScaleState(env, obj);
    104   UpdateFormDataPreferencesLocked(env, obj);
    105 }
    106 
    107 void AwSettings::UpdateUserAgentLocked(JNIEnv* env, jobject obj) {
    108   if (!web_contents()) return;
    109 
    110   ScopedJavaLocalRef<jstring> str =
    111       Java_AwSettings_getUserAgentLocked(env, obj);
    112   bool ua_overidden = str.obj() != NULL;
    113 
    114   if (ua_overidden) {
    115     std::string override = base::android::ConvertJavaStringToUTF8(str);
    116     web_contents()->SetUserAgentOverride(override);
    117   }
    118 
    119   const content::NavigationController& controller =
    120       web_contents()->GetController();
    121   for (int i = 0; i < controller.GetEntryCount(); ++i)
    122     controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(ua_overidden);
    123 }
    124 
    125 void AwSettings::UpdateWebkitPreferencesLocked(JNIEnv* env, jobject obj) {
    126   if (!web_contents()) return;
    127   AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
    128   if (!render_view_host_ext) return;
    129 
    130   content::RenderViewHost* render_view_host =
    131       web_contents()->GetRenderViewHost();
    132   if (!render_view_host) return;
    133   render_view_host->UpdateWebkitPreferences(
    134       render_view_host->GetWebkitPreferences());
    135 }
    136 
    137 void AwSettings::UpdateInitialPageScaleLocked(JNIEnv* env, jobject obj) {
    138   AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
    139   if (!rvhe) return;
    140 
    141   float initial_page_scale_percent =
    142       Java_AwSettings_getInitialPageScalePercentLocked(env, obj);
    143   if (initial_page_scale_percent == 0) {
    144     rvhe->SetInitialPageScale(-1);
    145   } else {
    146     float dip_scale = static_cast<float>(
    147         Java_AwSettings_getDIPScaleLocked(env, obj));
    148     rvhe->SetInitialPageScale(initial_page_scale_percent / dip_scale / 100.0f);
    149   }
    150 }
    151 
    152 void AwSettings::UpdateFormDataPreferencesLocked(JNIEnv* env, jobject obj) {
    153   if (!web_contents()) return;
    154   AwContents* contents = AwContents::FromWebContents(web_contents());
    155   if (!contents) return;
    156 
    157   contents->SetSaveFormData(Java_AwSettings_getSaveFormDataLocked(env, obj));
    158 }
    159 
    160 void AwSettings::RenderViewCreated(content::RenderViewHost* render_view_host) {
    161   // A single WebContents can normally have 0 to many RenderViewHost instances
    162   // associated with it.
    163   // This is important since there is only one RenderViewHostExt instance per
    164   // WebContents (and not one RVHExt per RVH, as you might expect) and updating
    165   // settings via RVHExt only ever updates the 'current' RVH.
    166   // In android_webview we don't swap out the RVH on cross-site navigations, so
    167   // we shouldn't have to deal with the multiple RVH per WebContents case. That
    168   // in turn means that the newly created RVH is always the 'current' RVH
    169   // (since we only ever go from 0 to 1 RVH instances) and hence the DCHECK.
    170   DCHECK(web_contents()->GetRenderViewHost() == render_view_host);
    171 
    172   UpdateEverything();
    173 }
    174 
    175 void AwSettings::WebContentsDestroyed(content::WebContents* web_contents) {
    176   delete this;
    177 }
    178 
    179 // static
    180 void AwSettings::PopulateFixedPreferences(WebPreferences* web_prefs) {
    181   web_prefs->shrinks_standalone_images_to_fit = false;
    182   web_prefs->should_clear_document_background = false;
    183 }
    184 
    185 void AwSettings::PopulateWebPreferences(WebPreferences* web_prefs) {
    186   JNIEnv* env = base::android::AttachCurrentThread();
    187   CHECK(env);
    188 
    189   AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
    190   if (!render_view_host_ext) return;
    191 
    192   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
    193   jobject obj = scoped_obj.obj();
    194   if (!obj) return;
    195 
    196   PopulateFixedPreferences(web_prefs);
    197 
    198   web_prefs->text_autosizing_enabled =
    199       Java_AwSettings_getTextAutosizingEnabledLocked(env, obj);
    200 
    201   int text_size_percent = Java_AwSettings_getTextSizePercentLocked(env, obj);
    202   if (web_prefs->text_autosizing_enabled) {
    203     web_prefs->font_scale_factor = text_size_percent / 100.0f;
    204     web_prefs->force_enable_zoom = text_size_percent >= 130;
    205     // Use the default zoom level value when Text Autosizer is turned on.
    206     render_view_host_ext->SetTextZoomLevel(0);
    207   } else {
    208     web_prefs->force_enable_zoom = false;
    209     render_view_host_ext->SetTextZoomLevel(content::ZoomFactorToZoomLevel(
    210         text_size_percent / 100.0f));
    211   }
    212 
    213   web_prefs->standard_font_family_map[webkit_glue::kCommonScript] =
    214       ConvertJavaStringToUTF16(
    215           Java_AwSettings_getStandardFontFamilyLocked(env, obj));
    216 
    217   web_prefs->fixed_font_family_map[webkit_glue::kCommonScript] =
    218       ConvertJavaStringToUTF16(
    219           Java_AwSettings_getFixedFontFamilyLocked(env, obj));
    220 
    221   web_prefs->sans_serif_font_family_map[webkit_glue::kCommonScript] =
    222       ConvertJavaStringToUTF16(
    223           Java_AwSettings_getSansSerifFontFamilyLocked(env, obj));
    224 
    225   web_prefs->serif_font_family_map[webkit_glue::kCommonScript] =
    226       ConvertJavaStringToUTF16(
    227           Java_AwSettings_getSerifFontFamilyLocked(env, obj));
    228 
    229   web_prefs->cursive_font_family_map[webkit_glue::kCommonScript] =
    230       ConvertJavaStringToUTF16(
    231           Java_AwSettings_getCursiveFontFamilyLocked(env, obj));
    232 
    233   web_prefs->fantasy_font_family_map[webkit_glue::kCommonScript] =
    234       ConvertJavaStringToUTF16(
    235           Java_AwSettings_getFantasyFontFamilyLocked(env, obj));
    236 
    237   web_prefs->default_encoding = ConvertJavaStringToUTF8(
    238       Java_AwSettings_getDefaultTextEncodingLocked(env, obj));
    239 
    240   web_prefs->minimum_font_size =
    241       Java_AwSettings_getMinimumFontSizeLocked(env, obj);
    242 
    243   web_prefs->minimum_logical_font_size =
    244       Java_AwSettings_getMinimumLogicalFontSizeLocked(env, obj);
    245 
    246   web_prefs->default_font_size =
    247       Java_AwSettings_getDefaultFontSizeLocked(env, obj);
    248 
    249   web_prefs->default_fixed_font_size =
    250       Java_AwSettings_getDefaultFixedFontSizeLocked(env, obj);
    251 
    252   // Blink's LoadsImagesAutomatically and ImagesEnabled must be
    253   // set cris-cross to Android's. See
    254   // https://code.google.com/p/chromium/issues/detail?id=224317#c26
    255   web_prefs->loads_images_automatically =
    256       Java_AwSettings_getImagesEnabledLocked(env, obj);
    257   web_prefs->images_enabled =
    258       Java_AwSettings_getLoadsImagesAutomaticallyLocked(env, obj);
    259 
    260   web_prefs->javascript_enabled =
    261       Java_AwSettings_getJavaScriptEnabledLocked(env, obj);
    262 
    263   web_prefs->allow_universal_access_from_file_urls =
    264       Java_AwSettings_getAllowUniversalAccessFromFileURLsLocked(env, obj);
    265 
    266   web_prefs->allow_file_access_from_file_urls =
    267       Java_AwSettings_getAllowFileAccessFromFileURLsLocked(env, obj);
    268 
    269   web_prefs->javascript_can_open_windows_automatically =
    270       Java_AwSettings_getJavaScriptCanOpenWindowsAutomaticallyLocked(env, obj);
    271 
    272   web_prefs->supports_multiple_windows =
    273       Java_AwSettings_getSupportMultipleWindowsLocked(env, obj);
    274 
    275   web_prefs->plugins_enabled =
    276       !Java_AwSettings_getPluginsDisabledLocked(env, obj);
    277 
    278   web_prefs->application_cache_enabled =
    279       Java_AwSettings_getAppCacheEnabledLocked(env, obj);
    280 
    281   web_prefs->local_storage_enabled =
    282       Java_AwSettings_getDomStorageEnabledLocked(env, obj);
    283 
    284   web_prefs->databases_enabled =
    285       Java_AwSettings_getDatabaseEnabledLocked(env, obj);
    286 
    287   web_prefs->wide_viewport_quirk = true;
    288   web_prefs->double_tap_to_zoom_enabled = web_prefs->use_wide_viewport =
    289       Java_AwSettings_getUseWideViewportLocked(env, obj);
    290 
    291   web_prefs->initialize_at_minimum_page_scale =
    292       Java_AwSettings_getLoadWithOverviewModeLocked(env, obj);
    293 
    294   web_prefs->user_gesture_required_for_media_playback =
    295       Java_AwSettings_getMediaPlaybackRequiresUserGestureLocked(env, obj);
    296 
    297   // Temporary setting, for K release only
    298   // This is a fork from upstream chromium, and should go away once
    299   // https://code.google.com/p/chromium/issues/detail?id=297216
    300   // is implemented
    301   web_prefs->allow_running_insecure_content = true;
    302 
    303   ScopedJavaLocalRef<jstring> url =
    304       Java_AwSettings_getDefaultVideoPosterURLLocked(env, obj);
    305   web_prefs->default_video_poster_url = url.obj() ?
    306       GURL(ConvertJavaStringToUTF8(url)) : GURL();
    307 
    308   bool support_quirks = Java_AwSettings_getSupportLegacyQuirksLocked(env, obj);
    309   web_prefs->support_deprecated_target_density_dpi = support_quirks;
    310   web_prefs->use_legacy_background_size_shorthand_behavior = support_quirks;
    311   web_prefs->viewport_meta_layout_size_quirk = support_quirks;
    312   web_prefs->viewport_meta_merge_quirk = support_quirks;
    313   web_prefs->viewport_meta_zero_values_quirk = support_quirks;
    314   web_prefs->ignore_main_frame_overflow_hidden_quirk = support_quirks;
    315   web_prefs->report_screen_size_in_physical_pixels_quirk = support_quirks;
    316 
    317   web_prefs->password_echo_enabled =
    318       Java_AwSettings_getPasswordEchoEnabledLocked(env, obj);
    319   web_prefs->spatial_navigation_enabled =
    320       Java_AwSettings_getSpatialNavigationLocked(env, obj);
    321 }
    322 
    323 static jint Init(JNIEnv* env,
    324                  jobject obj,
    325                  jint web_contents) {
    326   AwSettings* settings = new AwSettings(env, obj, web_contents);
    327   return reinterpret_cast<jint>(settings);
    328 }
    329 
    330 static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
    331   return base::android::ConvertUTF8ToJavaString(
    332       env, content::GetUserAgent(GURL())).Release();
    333 }
    334 
    335 bool RegisterAwSettings(JNIEnv* env) {
    336   return RegisterNativesImpl(env) >= 0;
    337 }
    338 
    339 }  // namespace android_webview
    340