123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- // Copyright 2021 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/browser/aw_dark_mode.h"
- #include "android_webview/browser/aw_contents.h"
- #include "android_webview/browser_jni_headers/AwDarkMode_jni.h"
- #include "android_webview/common/aw_features.h"
- #include "base/android/scoped_java_ref.h"
- #include "base/memory/ptr_util.h"
- #include "base/metrics/histogram_macros.h"
- #include "content/public/browser/navigation_details.h"
- #include "content/public/browser/web_contents.h"
- #include "third_party/blink/public/common/web_preferences/web_preferences.h"
- #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
- using base::android::JavaParamRef;
- using base::android::ScopedJavaLocalRef;
- namespace android_webview {
- namespace {
- const void* const kAwDarkModeUserDataKey = &kAwDarkModeUserDataKey;
- bool sShouldEnableSimplifiedDarkMode = false;
- bool IsForceDarkEnabled(content::WebContents* web_contents) {
- AwContents* contents = AwContents::FromWebContents(web_contents);
- return contents && contents->GetViewTreeForceDarkState();
- }
- } // namespace
- // static
- jlong JNI_AwDarkMode_Init(JNIEnv* env,
- const JavaParamRef<jobject>& caller,
- const JavaParamRef<jobject>& java_web_contents) {
- content::WebContents* web_contents =
- content::WebContents::FromJavaWebContents(java_web_contents);
- DCHECK(web_contents);
- return reinterpret_cast<intptr_t>(new AwDarkMode(env, caller, web_contents));
- }
- void JNI_AwDarkMode_EnableSimplifiedDarkMode(JNIEnv* env) {
- sShouldEnableSimplifiedDarkMode = true;
- }
- AwDarkMode* AwDarkMode::FromWebContents(content::WebContents* contents) {
- return static_cast<AwDarkMode*>(
- contents->GetUserData(kAwDarkModeUserDataKey));
- }
- AwDarkMode::AwDarkMode(JNIEnv* env,
- jobject obj,
- content::WebContents* web_contents)
- : content::WebContentsObserver(web_contents), jobj_(env, obj) {
- web_contents->SetUserData(kAwDarkModeUserDataKey, base::WrapUnique(this));
- }
- AwDarkMode::~AwDarkMode() {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jobject> scoped_obj = jobj_.get(env);
- if (scoped_obj)
- Java_AwDarkMode_onNativeObjectDestroyed(env, scoped_obj);
- }
- void AwDarkMode::PopulateWebPreferences(
- blink::web_pref::WebPreferences* web_prefs,
- int force_dark_mode,
- int force_dark_behavior,
- bool algorithmic_darkening_allowed) {
- if (!sShouldEnableSimplifiedDarkMode) {
- PopulateWebPreferencesForPreT(web_prefs, force_dark_mode,
- force_dark_behavior);
- return;
- }
- prefers_dark_from_theme_ = IsAppUsingDarkTheme();
- web_prefs->preferred_color_scheme =
- prefers_dark_from_theme_ ? blink::mojom::PreferredColorScheme::kDark
- : blink::mojom::PreferredColorScheme::kLight;
- web_prefs->force_dark_mode_enabled = false;
- is_force_dark_applied_ = false;
- if (IsForceDarkEnabled(web_contents())) {
- is_force_dark_applied_ = true;
- web_prefs->force_dark_mode_enabled = true;
- web_prefs->preferred_color_scheme =
- blink::mojom::PreferredColorScheme::kDark;
- } else if (prefers_dark_from_theme_) {
- is_force_dark_applied_ = algorithmic_darkening_allowed;
- web_prefs->force_dark_mode_enabled = algorithmic_darkening_allowed;
- }
- }
- void AwDarkMode::PopulateWebPreferencesForPreT(
- blink::web_pref::WebPreferences* web_prefs,
- int force_dark_mode,
- int force_dark_behavior) {
- prefers_dark_from_theme_ = false;
- switch (force_dark_mode) {
- case AwSettings::ForceDarkMode::FORCE_DARK_OFF:
- is_force_dark_applied_ = false;
- break;
- case AwSettings::ForceDarkMode::FORCE_DARK_ON:
- is_force_dark_applied_ = true;
- break;
- case AwSettings::ForceDarkMode::FORCE_DARK_AUTO: {
- is_force_dark_applied_ = IsForceDarkEnabled(web_contents());
- if (!is_force_dark_applied_)
- prefers_dark_from_theme_ = IsAppUsingDarkTheme();
- break;
- }
- }
- web_prefs->preferred_color_scheme =
- is_force_dark_applied_ ? blink::mojom::PreferredColorScheme::kDark
- : blink::mojom::PreferredColorScheme::kLight;
- if (is_force_dark_applied_) {
- switch (force_dark_behavior) {
- case AwSettings::ForceDarkBehavior::FORCE_DARK_ONLY: {
- web_prefs->preferred_color_scheme =
- blink::mojom::PreferredColorScheme::kLight;
- web_prefs->force_dark_mode_enabled = true;
- break;
- }
- case AwSettings::ForceDarkBehavior::MEDIA_QUERY_ONLY: {
- web_prefs->preferred_color_scheme =
- blink::mojom::PreferredColorScheme::kDark;
- web_prefs->force_dark_mode_enabled = false;
- break;
- }
- // Blink's behavior is that if the preferred color scheme matches the
- // supported color scheme, then force dark will be disabled, otherwise
- // the preferred color scheme will be reset to 'light'. Therefore
- // when enabling force dark, we also set the preferred color scheme to
- // dark so that dark themed content will be preferred over force
- // darkening.
- case AwSettings::ForceDarkBehavior::PREFER_MEDIA_QUERY_OVER_FORCE_DARK: {
- web_prefs->preferred_color_scheme =
- blink::mojom::PreferredColorScheme::kDark;
- web_prefs->force_dark_mode_enabled = true;
- break;
- }
- }
- } else if (prefers_dark_from_theme_) {
- web_prefs->preferred_color_scheme =
- blink::mojom::PreferredColorScheme::kDark;
- if (base::FeatureList::IsEnabled(
- android_webview::features::kWebViewForceDarkModeMatchTheme)) {
- web_prefs->force_dark_mode_enabled = true;
- is_force_dark_applied_ = true;
- }
- } else {
- web_prefs->preferred_color_scheme =
- blink::mojom::PreferredColorScheme::kLight;
- web_prefs->force_dark_mode_enabled = false;
- }
- }
- bool AwDarkMode::IsAppUsingDarkTheme() {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jobject> scoped_obj = jobj_.get(env);
- if (!scoped_obj)
- return false;
- return Java_AwDarkMode_isAppUsingDarkTheme(env, scoped_obj);
- }
- void AwDarkMode::DetachFromJavaObject(JNIEnv* env,
- const JavaParamRef<jobject>& jcaller) {
- jobj_.reset();
- }
- void AwDarkMode::NavigationEntryCommitted(
- const content::LoadCommittedDetails& load_details) {
- if (!load_details.is_main_frame)
- return;
- UMA_HISTOGRAM_BOOLEAN("Android.WebView.DarkMode.PrefersDarkFromTheme",
- prefers_dark_from_theme_);
- }
- void AwDarkMode::InferredColorSchemeUpdated(
- absl::optional<blink::mojom::PreferredColorScheme> color_scheme) {
- if (prefers_dark_from_theme_ && color_scheme.has_value()) {
- UMA_HISTOGRAM_BOOLEAN(
- "Android.WebView.DarkMode.PageDarkenedAccordingToAppTheme",
- color_scheme.value() == blink::mojom::PreferredColorScheme::kDark);
- }
- }
- } // namespace android_webview
|