aw_settings.cc 12.1 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/native/aw_settings.h"

#include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
#include "android_webview/native/aw_contents.h"
9 10
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
11
#include "base/supports_user_data.h"
12 13 14 15 16
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#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 24 25

using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
26 27 28

namespace android_webview {

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
const void* kAwSettingsUserDataKey = &kAwSettingsUserDataKey;

class AwSettingsUserData : public base::SupportsUserData::Data {
 public:
  AwSettingsUserData(AwSettings* ptr) : settings_(ptr) {}

  static AwSettings* GetSettings(content::WebContents* web_contents) {
    if (!web_contents)
      return NULL;
    AwSettingsUserData* data = reinterpret_cast<AwSettingsUserData*>(
        web_contents->GetUserData(kAwSettingsUserDataKey));
    return data ? data->settings_ : NULL;
  }

 private:
  AwSettings* settings_;
};

47 48 49 50
AwSettings::AwSettings(JNIEnv* env, jobject obj, jint web_contents)
    : WebContentsObserver(
          reinterpret_cast<content::WebContents*>(web_contents)),
      aw_settings_(env, obj) {
51 52
  reinterpret_cast<content::WebContents*>(web_contents)->
      SetUserData(kAwSettingsUserDataKey, new AwSettingsUserData(this));
53 54 55
}

AwSettings::~AwSettings() {
56 57 58 59
  if (web_contents()) {
    web_contents()->SetUserData(kAwSettingsUserDataKey, NULL);
  }

60 61 62 63 64 65
  JNIEnv* env = base::android::AttachCurrentThread();
  ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
  jobject obj = scoped_obj.obj();
  if (!obj) return;
  Java_AwSettings_nativeAwSettingsGone(env, obj,
                                       reinterpret_cast<jint>(this));
66 67 68 69 70 71
}

void AwSettings::Destroy(JNIEnv* env, jobject obj) {
  delete this;
}

72 73 74 75
AwSettings* AwSettings::FromWebContents(content::WebContents* web_contents) {
  return AwSettingsUserData::GetSettings(web_contents);
}

76 77 78 79 80 81 82 83 84 85 86 87 88
AwRenderViewHostExt* AwSettings::GetAwRenderViewHostExt() {
  if (!web_contents()) return NULL;
  AwContents* contents = AwContents::FromWebContents(web_contents());
  if (!contents) return NULL;
  return contents->render_view_host_ext();
}

void AwSettings::ResetScrollAndScaleState(JNIEnv* env, jobject obj) {
  AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
  if (!rvhe) return;
  rvhe->ResetScrollAndScaleState();
}

89 90 91 92 93 94
void AwSettings::UpdateEverything() {
  JNIEnv* env = base::android::AttachCurrentThread();
  CHECK(env);
  ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
  jobject obj = scoped_obj.obj();
  if (!obj) return;
95 96
  // Grab the lock and call UpdateEverythingLocked.
  Java_AwSettings_updateEverything(env, obj);
97 98
}

99 100 101 102
void AwSettings::UpdateEverythingLocked(JNIEnv* env, jobject obj) {
  UpdateInitialPageScaleLocked(env, obj);
  UpdateWebkitPreferencesLocked(env, obj);
  UpdateUserAgentLocked(env, obj);
103
  ResetScrollAndScaleState(env, obj);
104
  UpdateFormDataPreferencesLocked(env, obj);
105 106
}

107
void AwSettings::UpdateUserAgentLocked(JNIEnv* env, jobject obj) {
108 109
  if (!web_contents()) return;

110 111
  ScopedJavaLocalRef<jstring> str =
      Java_AwSettings_getUserAgentLocked(env, obj);
112 113 114 115 116 117 118 119 120 121 122
  bool ua_overidden = str.obj() != NULL;

  if (ua_overidden) {
    std::string override = base::android::ConvertJavaStringToUTF8(str);
    web_contents()->SetUserAgentOverride(override);
  }

  const content::NavigationController& controller =
      web_contents()->GetController();
  for (int i = 0; i < controller.GetEntryCount(); ++i)
    controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(ua_overidden);
123 124
}

125
void AwSettings::UpdateWebkitPreferencesLocked(JNIEnv* env, jobject obj) {
126
  if (!web_contents()) return;
127 128
  AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
  if (!render_view_host_ext) return;
129

130 131 132
  content::RenderViewHost* render_view_host =
      web_contents()->GetRenderViewHost();
  if (!render_view_host) return;
133 134 135 136 137 138 139
  render_view_host->UpdateWebkitPreferences(
      render_view_host->GetWebkitPreferences());
}

void AwSettings::UpdateInitialPageScaleLocked(JNIEnv* env, jobject obj) {
  AwRenderViewHostExt* rvhe = GetAwRenderViewHostExt();
  if (!rvhe) return;
140

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
  float initial_page_scale_percent =
      Java_AwSettings_getInitialPageScalePercentLocked(env, obj);
  if (initial_page_scale_percent == 0) {
    rvhe->SetInitialPageScale(-1);
  } else {
    float dip_scale = static_cast<float>(
        Java_AwSettings_getDIPScaleLocked(env, obj));
    rvhe->SetInitialPageScale(initial_page_scale_percent / dip_scale / 100.0f);
  }
}

void AwSettings::UpdateFormDataPreferencesLocked(JNIEnv* env, jobject obj) {
  if (!web_contents()) return;
  AwContents* contents = AwContents::FromWebContents(web_contents());
  if (!contents) return;

  contents->SetSaveFormData(Java_AwSettings_getSaveFormDataLocked(env, obj));
}

void AwSettings::RenderViewCreated(content::RenderViewHost* render_view_host) {
  // A single WebContents can normally have 0 to many RenderViewHost instances
  // associated with it.
  // This is important since there is only one RenderViewHostExt instance per
  // WebContents (and not one RVHExt per RVH, as you might expect) and updating
  // settings via RVHExt only ever updates the 'current' RVH.
  // In android_webview we don't swap out the RVH on cross-site navigations, so
  // we shouldn't have to deal with the multiple RVH per WebContents case. That
  // in turn means that the newly created RVH is always the 'current' RVH
  // (since we only ever go from 0 to 1 RVH instances) and hence the DCHECK.
  DCHECK(web_contents()->GetRenderViewHost() == render_view_host);

  UpdateEverything();
}

void AwSettings::WebContentsDestroyed(content::WebContents* web_contents) {
  delete this;
}

179 180 181
// static
void AwSettings::PopulateFixedPreferences(WebPreferences* web_prefs) {
  web_prefs->shrinks_standalone_images_to_fit = false;
182
  web_prefs->should_clear_document_background = false;
183 184
}

185 186 187 188 189 190 191 192 193 194 195
void AwSettings::PopulateWebPreferences(WebPreferences* web_prefs) {
  JNIEnv* env = base::android::AttachCurrentThread();
  CHECK(env);

  AwRenderViewHostExt* render_view_host_ext = GetAwRenderViewHostExt();
  if (!render_view_host_ext) return;

  ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
  jobject obj = scoped_obj.obj();
  if (!obj) return;

196 197
  PopulateFixedPreferences(web_prefs);

198
  web_prefs->text_autosizing_enabled =
199
      Java_AwSettings_getTextAutosizingEnabledLocked(env, obj);
200

201
  int text_size_percent = Java_AwSettings_getTextSizePercentLocked(env, obj);
202 203 204
  if (web_prefs->text_autosizing_enabled) {
    web_prefs->font_scale_factor = text_size_percent / 100.0f;
    web_prefs->force_enable_zoom = text_size_percent >= 130;
205 206 207
    // Use the default zoom level value when Text Autosizer is turned on.
    render_view_host_ext->SetTextZoomLevel(0);
  } else {
208
    web_prefs->force_enable_zoom = false;
209 210
    render_view_host_ext->SetTextZoomLevel(content::ZoomFactorToZoomLevel(
        text_size_percent / 100.0f));
211 212
  }

213
  web_prefs->standard_font_family_map[webkit_glue::kCommonScript] =
214 215
      ConvertJavaStringToUTF16(
          Java_AwSettings_getStandardFontFamilyLocked(env, obj));
216

217
  web_prefs->fixed_font_family_map[webkit_glue::kCommonScript] =
218 219
      ConvertJavaStringToUTF16(
          Java_AwSettings_getFixedFontFamilyLocked(env, obj));
220

221
  web_prefs->sans_serif_font_family_map[webkit_glue::kCommonScript] =
222 223
      ConvertJavaStringToUTF16(
          Java_AwSettings_getSansSerifFontFamilyLocked(env, obj));
224

225
  web_prefs->serif_font_family_map[webkit_glue::kCommonScript] =
226 227
      ConvertJavaStringToUTF16(
          Java_AwSettings_getSerifFontFamilyLocked(env, obj));
228

229
  web_prefs->cursive_font_family_map[webkit_glue::kCommonScript] =
230 231
      ConvertJavaStringToUTF16(
          Java_AwSettings_getCursiveFontFamilyLocked(env, obj));
232

233
  web_prefs->fantasy_font_family_map[webkit_glue::kCommonScript] =
234 235
      ConvertJavaStringToUTF16(
          Java_AwSettings_getFantasyFontFamilyLocked(env, obj));
236

237
  web_prefs->default_encoding = ConvertJavaStringToUTF8(
238
      Java_AwSettings_getDefaultTextEncodingLocked(env, obj));
239

240 241
  web_prefs->minimum_font_size =
      Java_AwSettings_getMinimumFontSizeLocked(env, obj);
242

243
  web_prefs->minimum_logical_font_size =
244
      Java_AwSettings_getMinimumLogicalFontSizeLocked(env, obj);
245

246 247
  web_prefs->default_font_size =
      Java_AwSettings_getDefaultFontSizeLocked(env, obj);
248

249
  web_prefs->default_fixed_font_size =
250
      Java_AwSettings_getDefaultFixedFontSizeLocked(env, obj);
251

252 253 254
  // Blink's LoadsImagesAutomatically and ImagesEnabled must be
  // set cris-cross to Android's. See
  // 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 276
  web_prefs->plugins_enabled =
      !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 285
  web_prefs->databases_enabled =
      Java_AwSettings_getDatabaseEnabledLocked(env, obj);
286

287 288
  web_prefs->wide_viewport_quirk = true;
  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

Kristian Monsen's avatar
Kristian Monsen committed
297 298 299 300
  // Temporary setting, for K release only
  // This is a fork from upstream chromium, and should go away once
  // https://code.google.com/p/chromium/issues/detail?id=297216
  // is implemented
301
  web_prefs->allow_running_insecure_content = true;
Kristian Monsen's avatar
Kristian Monsen committed
302

303 304
  ScopedJavaLocalRef<jstring> url =
      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 310 311 312 313
  web_prefs->support_deprecated_target_density_dpi = support_quirks;
  web_prefs->use_legacy_background_size_shorthand_behavior = support_quirks;
  web_prefs->viewport_meta_layout_size_quirk = support_quirks;
  web_prefs->viewport_meta_zero_values_quirk = support_quirks;
  web_prefs->ignore_main_frame_overflow_hidden_quirk = support_quirks;
314
  web_prefs->report_screen_size_in_physical_pixels_quirk = support_quirks;
315

316
  web_prefs->password_echo_enabled =
317
      Java_AwSettings_getPasswordEchoEnabled(env, obj);
318 319
}

320 321 322
static jint Init(JNIEnv* env,
                 jobject obj,
                 jint web_contents) {
323
  AwSettings* settings = new AwSettings(env, obj, web_contents);
324 325 326
  return reinterpret_cast<jint>(settings);
}

327 328 329 330 331
static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
  return base::android::ConvertUTF8ToJavaString(
      env, content::GetUserAgent(GURL())).Release();
}

332 333 334 335 336
bool RegisterAwSettings(JNIEnv* env) {
  return RegisterNativesImpl(env) >= 0;
}

}  // namespace android_webview