blob: 375300a8cc916f6b2161b45a2642e7c519b975df [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/org_chromium_net_UrlRequestContext.h"
#include <string>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/json/json_reader.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/statistics_recorder.h"
#include "base/values.h"
#include "components/cronet/android/org_chromium_net_UrlRequest.h"
#include "components/cronet/android/url_request_context_peer.h"
#include "components/cronet/android/url_request_peer.h"
#include "components/cronet/url_request_context_config.h"
#include "jni/UrlRequestContext_jni.h"
// Version of this build of Chromium NET.
#define CHROMIUM_NET_VERSION "1"
namespace {
const char kVersion[] = CHROMIUM_VERSION "/" CHROMIUM_NET_VERSION;
// Delegate of URLRequestContextPeer that delivers callbacks to the Java layer.
class JniURLRequestContextPeerDelegate
: public cronet::URLRequestContextPeer::URLRequestContextPeerDelegate {
public:
JniURLRequestContextPeerDelegate(JNIEnv* env, jobject owner)
: owner_(env->NewGlobalRef(owner)) {
}
virtual void OnContextInitialized(
cronet::URLRequestContextPeer* context) OVERRIDE {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_UrlRequestContext_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 ~JniURLRequestContextPeerDelegate() {
JNIEnv* env = base::android::AttachCurrentThread();
env->DeleteGlobalRef(owner_);
}
private:
jobject owner_;
};
} // namespace
namespace cronet {
// Explicitly register static JNI functions.
bool UrlRequestContextRegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
static jstring GetVersion(JNIEnv* env, jclass unused) {
return base::android::ConvertUTF8ToJavaString(env, kVersion).Release();
}
// Sets global user-agent to be used for all subsequent requests.
static jlong CreateRequestContextPeer(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);
int logging_level = log_level;
// TODO(dplotnikov): set application context.
URLRequestContextPeer* peer = new URLRequestContextPeer(
new JniURLRequestContextPeerDelegate(env, object),
user_agent_string,
logging_level,
kVersion);
peer->AddRef(); // Hold onto this ref-counted object.
peer->Initialize(context_config.Pass());
return reinterpret_cast<jlong>(peer);
}
// Releases native objects.
static void ReleaseRequestContextPeer(JNIEnv* env,
jobject object,
jlong urlRequestContextPeer) {
URLRequestContextPeer* peer =
reinterpret_cast<URLRequestContextPeer*>(urlRequestContextPeer);
// TODO(mef): Revisit this from thread safety point of view: Can we delete a
// thread while running on that thread?
// URLRequestContextPeer is a ref-counted object, and may have pending tasks,
// so we need to release it instead of deleting here.
peer->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 urlRequestContextPeer,
jstring fileName) {
URLRequestContextPeer* peer =
reinterpret_cast<URLRequestContextPeer*>(urlRequestContextPeer);
std::string file_name = base::android::ConvertJavaStringToUTF8(env, fileName);
peer->StartNetLogToFile(file_name);
}
// Stops recording NetLog.
static void StopNetLog(JNIEnv* env,
jobject jcaller,
jlong urlRequestContextPeer) {
URLRequestContextPeer* peer =
reinterpret_cast<URLRequestContextPeer*>(urlRequestContextPeer);
peer->StopNetLog();
}
} // namespace cronet