blob: 45fca439f193574e0ae57910748141c37683bbf9 [file] [log] [blame]
// Copyright 2014 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 "components/cronet/android/chromium_url_request_context.h"
#include <string>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/statistics_recorder.h"
#include "base/values.h"
#include "components/cronet/android/chromium_url_request.h"
#include "components/cronet/android/url_request_adapter.h"
#include "components/cronet/android/url_request_context_adapter.h"
#include "components/cronet/url_request_context_config.h"
#include "jni/ChromiumUrlRequestContext_jni.h"
namespace {
// Delegate of URLRequestContextAdapter that delivers callbacks to the Java
// layer.
class JniURLRequestContextAdapterDelegate
: public cronet::URLRequestContextAdapter::
URLRequestContextAdapterDelegate {
public:
JniURLRequestContextAdapterDelegate(JNIEnv* env, jobject owner)
: owner_(env->NewGlobalRef(owner)) {}
virtual void OnContextInitialized(
cronet::URLRequestContextAdapter* context) override {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_ChromiumUrlRequestContext_initNetworkThread(env, owner_);
// TODO(dplotnikov): figure out if we need to detach from the thread.
// The documentation says we should detach just before the thread exits.
}
protected:
virtual ~JniURLRequestContextAdapterDelegate() {
JNIEnv* env = base::android::AttachCurrentThread();
env->DeleteGlobalRef(owner_);
}
private:
jobject owner_;
};
} // namespace
namespace cronet {
// Explicitly register static JNI functions.
bool ChromiumUrlRequestContextRegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
// Sets global user-agent to be used for all subsequent requests.
static jlong CreateRequestContextAdapter(JNIEnv* env,
jobject object,
jobject context,
jstring user_agent,
jint log_level,
jstring config) {
std::string user_agent_string =
base::android::ConvertJavaStringToUTF8(env, user_agent);
std::string config_string =
base::android::ConvertJavaStringToUTF8(env, config);
scoped_ptr<base::Value> config_value(base::JSONReader::Read(config_string));
if (!config_value || !config_value->IsType(base::Value::TYPE_DICTIONARY)) {
DLOG(ERROR) << "Bad JSON: " << config_string;
return 0;
}
scoped_ptr<URLRequestContextConfig> context_config(
new URLRequestContextConfig());
base::JSONValueConverter<URLRequestContextConfig> converter;
if (!converter.Convert(*config_value, context_config.get())) {
DLOG(ERROR) << "Bad Config: " << config_value;
return 0;
}
// Set application context.
base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context);
base::android::InitApplicationContext(env, scoped_context);
// TODO(mef): MinLogLevel is global, shared by all URLRequestContexts.
// Revisit this if each URLRequestContext would need an individual log level.
logging::SetMinLogLevel(static_cast<int>(log_level));
// TODO(dplotnikov): set application context.
URLRequestContextAdapter* adapter = new URLRequestContextAdapter(
new JniURLRequestContextAdapterDelegate(env, object), user_agent_string);
adapter->AddRef(); // Hold onto this ref-counted object.
adapter->Initialize(context_config.Pass());
return reinterpret_cast<jlong>(adapter);
}
// Releases native objects.
static void ReleaseRequestContextAdapter(JNIEnv* env,
jobject object,
jlong urlRequestContextAdapter) {
URLRequestContextAdapter* adapter =
reinterpret_cast<URLRequestContextAdapter*>(urlRequestContextAdapter);
// TODO(mef): Revisit this from thread safety point of view: Can we delete a
// thread while running on that thread?
// URLRequestContextAdapter is a ref-counted object, and may have pending
// tasks,
// so we need to release it instead of deleting here.
adapter->Release();
}
// Starts recording statistics.
static void InitializeStatistics(JNIEnv* env, jobject jcaller) {
base::StatisticsRecorder::Initialize();
}
// Gets current statistics with |filter| as a substring as JSON text (an empty
// |filter| will include all registered histograms).
static jstring GetStatisticsJSON(JNIEnv* env, jobject jcaller, jstring filter) {
std::string query = base::android::ConvertJavaStringToUTF8(env, filter);
std::string json = base::StatisticsRecorder::ToJSON(query);
return base::android::ConvertUTF8ToJavaString(env, json).Release();
}
// Starts recording NetLog into file with |fileName|.
static void StartNetLogToFile(JNIEnv* env,
jobject jcaller,
jlong urlRequestContextAdapter,
jstring fileName) {
URLRequestContextAdapter* adapter =
reinterpret_cast<URLRequestContextAdapter*>(urlRequestContextAdapter);
std::string file_name = base::android::ConvertJavaStringToUTF8(env, fileName);
adapter->StartNetLogToFile(file_name);
}
// Stops recording NetLog.
static void StopNetLog(JNIEnv* env,
jobject jcaller,
jlong urlRequestContextAdapter) {
URLRequestContextAdapter* adapter =
reinterpret_cast<URLRequestContextAdapter*>(urlRequestContextAdapter);
adapter->StopNetLog();
}
// Called on application's main Java thread.
static void InitRequestContextOnMainThread(JNIEnv* env,
jobject jcaller,
jlong url_request_context_adapter) {
URLRequestContextAdapter* adapter =
reinterpret_cast<URLRequestContextAdapter*>(url_request_context_adapter);
adapter->InitRequestContextOnMainThread();
}
} // namespace cronet