blob: b3c9da24298ad60d08aa162edfb3fe6b391c0957 [file] [log] [blame]
// Copyright 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 "chrome/browser/data_reduction_proxy/data_reduction_proxy_settings_android.h"
#include <stdint.h>
#include <map>
#include <string>
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h"
#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
#include "components/data_reduction_proxy/core/browser/data_usage_store.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/previews/core/previews_experiments.h"
#include "jni/DataReductionProxySettings_jni.h"
#include "net/base/proxy_server.h"
#include "net/base/url_util.h"
#include "url/gurl.h"
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using data_reduction_proxy::DataReductionProxySettings;
namespace {
constexpr size_t kBucketsPerDay =
24 * 60 / data_reduction_proxy::kDataUsageBucketLengthInMinutes;
struct DataUsageForHost {
DataUsageForHost() : data_used(0), original_size(0) {}
int64_t data_used;
int64_t original_size;
};
} // namespace
DataReductionProxySettingsAndroid::DataReductionProxySettingsAndroid()
: weak_factory_(this) {}
DataReductionProxySettingsAndroid::DataReductionProxySettingsAndroid(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj)
: weak_factory_(this) {}
DataReductionProxySettingsAndroid::~DataReductionProxySettingsAndroid() {}
jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyPromoAllowed(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return data_reduction_proxy::params::IsIncludedInPromoFieldTrial();
}
jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyFREPromoAllowed(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return data_reduction_proxy::params::IsIncludedInFREPromoFieldTrial();
}
jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyEnabled(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return Settings()->IsDataReductionProxyEnabled();
}
jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyManaged(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return Settings()->IsDataReductionProxyManaged();
}
void DataReductionProxySettingsAndroid::SetDataReductionProxyEnabled(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean enabled) {
Settings()->SetDataReductionProxyEnabled(enabled);
}
jlong DataReductionProxySettingsAndroid::GetDataReductionLastUpdateTime(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return Settings()->GetDataReductionLastUpdateTime();
}
void DataReductionProxySettingsAndroid::ClearDataSavingStatistics(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint reason) {
Settings()->ClearDataSavingStatistics(
static_cast<data_reduction_proxy::DataReductionProxySavingsClearedReason>(
reason));
}
base::android::ScopedJavaLocalRef<jobject>
DataReductionProxySettingsAndroid::GetContentLengths(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
int64_t original_content_length;
int64_t received_content_length;
int64_t last_update_internal;
Settings()->GetContentLengths(
data_reduction_proxy::kNumDaysInHistorySummary, &original_content_length,
&received_content_length, &last_update_internal);
return Java_ContentLengths_create(env, original_content_length,
received_content_length);
}
jlong DataReductionProxySettingsAndroid::GetTotalHttpContentLengthSaved(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return Settings()->GetTotalHttpContentLengthSaved();
}
ScopedJavaLocalRef<jlongArray>
DataReductionProxySettingsAndroid::GetDailyOriginalContentLengths(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return GetDailyContentLengths(
env, data_reduction_proxy::prefs::kDailyHttpOriginalContentLength);
}
ScopedJavaLocalRef<jlongArray>
DataReductionProxySettingsAndroid::GetDailyReceivedContentLengths(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return GetDailyContentLengths(
env, data_reduction_proxy::prefs::kDailyHttpReceivedContentLength);
}
ScopedJavaLocalRef<jstring>
DataReductionProxySettingsAndroid::GetDataReductionProxyPassThroughHeader(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return ConvertUTF8ToJavaString(
env, data_reduction_proxy::chrome_proxy_pass_through_header());
}
jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyUnreachable(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return Settings()->IsDataReductionProxyUnreachable();
}
ScopedJavaLocalRef<jstring>
DataReductionProxySettingsAndroid::MaybeRewriteWebliteUrl(
JNIEnv* env,
const base::android::JavaRef<jobject>& obj,
const base::android::JavaRef<jstring>& url) {
if (url.is_null() || !Settings()->IsDataReductionProxyEnabled() ||
!previews::params::ArePreviewsAllowed()) {
return ScopedJavaLocalRef<jstring>(url);
}
GURL gurl(base::android::ConvertJavaStringToUTF8(url));
if (!gurl.is_valid() || gurl.is_empty())
return ScopedJavaLocalRef<jstring>(url);
std::string weblite_host_and_path = base::GetFieldTrialParamValueByFeature(
data_reduction_proxy::features::kDataReductionProxyDecidesTransform,
"weblite_url_host_and_path");
if (weblite_host_and_path.empty())
weblite_host_and_path = "googleweblight.com/i";
if (gurl.host() + gurl.path() != weblite_host_and_path)
return ScopedJavaLocalRef<jstring>(url);
std::string weblite_query_param = base::GetFieldTrialParamValueByFeature(
data_reduction_proxy::features::kDataReductionProxyDecidesTransform,
"weblite_url_query_param");
if (weblite_query_param.empty())
weblite_query_param = "u";
std::string wrapped_url_str;
if (!net::GetValueForKeyInQuery(gurl, weblite_query_param, &wrapped_url_str))
return ScopedJavaLocalRef<jstring>(url);
GURL wrapped_gurl(wrapped_url_str);
if (!wrapped_gurl.is_valid() || wrapped_gurl.is_empty() ||
(!wrapped_gurl.SchemeIs("http") && !wrapped_gurl.SchemeIs("https"))) {
return ScopedJavaLocalRef<jstring>(url);
}
// For http:// webpages that are fetched via data saver proxy, do not
// rewrite the URL if the use of proxy or previews delivered via proxy is
// disabled.
if (wrapped_gurl.SchemeIs("http")) {
if (data_reduction_proxy::params::IsIncludedInHoldbackFieldTrial() ||
!base::FeatureList::IsEnabled(
data_reduction_proxy::features::
kDataReductionProxyDecidesTransform)) {
return ScopedJavaLocalRef<jstring>(url);
}
}
return base::android::ConvertUTF8ToJavaString(env, wrapped_gurl.spec());
}
ScopedJavaLocalRef<jlongArray>
DataReductionProxySettingsAndroid::GetDailyContentLengths(
JNIEnv* env,
const char* pref_name) {
jlongArray result =
env->NewLongArray(data_reduction_proxy::kNumDaysInHistory);
data_reduction_proxy::ContentLengthList lengths =
Settings()->GetDailyContentLengths(pref_name);
if (!lengths.empty()) {
DCHECK_EQ(lengths.size(), data_reduction_proxy::kNumDaysInHistory);
std::vector<jlong> lengths_jlong(lengths.begin(), lengths.end());
env->SetLongArrayRegion(result, 0, lengths_jlong.size(),
lengths_jlong.data());
return ScopedJavaLocalRef<jlongArray>(env, result);
}
return ScopedJavaLocalRef<jlongArray>(env, result);
}
DataReductionProxySettings* DataReductionProxySettingsAndroid::Settings() {
DataReductionProxySettings* settings =
DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
ProfileManager::GetActiveUserProfile());
DCHECK(settings);
return settings;
}
void DataReductionProxySettingsAndroid::QueryDataUsage(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& j_result_obj,
jint num_days) {
DCHECK(num_days <= data_reduction_proxy::kDataUsageHistoryNumDays);
Settings()
->data_reduction_proxy_service()
->compression_stats()
->GetHistoricalDataUsage(base::Bind(
&DataReductionProxySettingsAndroid::OnQueryDataUsageComplete,
weak_factory_.GetWeakPtr(), JavaObjectWeakGlobalRef(env, obj),
base::android::ScopedJavaGlobalRef<jobject>(j_result_obj), num_days));
}
void DataReductionProxySettingsAndroid::OnQueryDataUsageComplete(
JavaObjectWeakGlobalRef obj,
const base::android::ScopedJavaGlobalRef<jobject>& j_result_obj,
jint num_days,
std::unique_ptr<std::vector<data_reduction_proxy::DataUsageBucket>>
data_usage) {
if (j_result_obj.is_null())
return;
JNIEnv* env = base::android::AttachCurrentThread();
std::map<base::StringPiece, DataUsageForHost> per_site_usage_map;
// Data usage is sorted chronologically with the last entry corresponding to
// |base::Time::Now()|.
const size_t num_buckets_to_display = num_days * kBucketsPerDay;
for (auto data_usage_it = data_usage->size() > num_buckets_to_display
? data_usage->end() - num_buckets_to_display
: data_usage->begin();
data_usage_it != data_usage->end(); ++data_usage_it) {
for (const auto& connection_usage : data_usage_it->connection_usage()) {
for (const auto& site_usage : connection_usage.site_usage()) {
DataUsageForHost& usage = per_site_usage_map[site_usage.hostname()];
usage.data_used += site_usage.data_used();
usage.original_size += site_usage.original_size();
}
}
}
for (const auto& site_bucket : per_site_usage_map) {
Java_DataReductionProxySettings_createDataUseItemAndAddToList(
env, j_result_obj, ConvertUTF8ToJavaString(env, site_bucket.first),
site_bucket.second.data_used, site_bucket.second.original_size);
}
Java_DataReductionProxySettings_onQueryDataUsageComplete(env, obj.get(env),
j_result_obj);
}
// Used by generated jni code.
static jlong JNI_DataReductionProxySettings_Init(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return reinterpret_cast<intptr_t>(
new DataReductionProxySettingsAndroid(env, obj));
}