1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
// 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"
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertJavaStringToUTF8;
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)) {}
void OnContextInitialized(
cronet::URLRequestContextAdapter* context_adapter) 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:
~JniURLRequestContextAdapterDelegate() override {
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 jcaller,
jobject jcontext,
jstring juser_agent,
jint jlog_level,
jstring jconfig) {
std::string user_agent = ConvertJavaStringToUTF8(env, juser_agent);
std::string config = ConvertJavaStringToUTF8(env, jconfig);
scoped_ptr<base::Value> config_value(base::JSONReader::Read(config));
if (!config_value || !config_value->IsType(base::Value::TYPE_DICTIONARY)) {
DLOG(ERROR) << "Bad JSON: " << config;
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, jcontext);
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>(jlog_level));
// TODO(dplotnikov): set application context.
URLRequestContextAdapter* context_adapter = new URLRequestContextAdapter(
new JniURLRequestContextAdapterDelegate(env, jcaller), user_agent);
context_adapter->AddRef(); // Hold onto this ref-counted object.
context_adapter->Initialize(context_config.Pass());
return reinterpret_cast<jlong>(context_adapter);
}
// Releases native objects.
static void ReleaseRequestContextAdapter(JNIEnv* env,
jobject jcaller,
jlong jurl_request_context_adapter) {
URLRequestContextAdapter* context_adapter =
reinterpret_cast<URLRequestContextAdapter*>(jurl_request_context_adapter);
// 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.
context_adapter->Release();
}
// Starts recording statistics.
static void InitializeStatistics(JNIEnv* env, jobject jcaller) {
base::StatisticsRecorder::Initialize();
}
// Gets current statistics with |jfilter| as a substring as JSON text (an empty
// |jfilter| will include all registered histograms).
static jstring GetStatisticsJSON(JNIEnv* env,
jobject jcaller,
jstring jfilter) {
std::string query = ConvertJavaStringToUTF8(env, jfilter);
std::string json = base::StatisticsRecorder::ToJSON(query);
return ConvertUTF8ToJavaString(env, json).Release();
}
// Starts recording NetLog into file with |jfilename|.
static void StartNetLogToFile(JNIEnv* env,
jobject jcaller,
jlong jurl_request_context_adapter,
jstring jfilename) {
URLRequestContextAdapter* context_adapter =
reinterpret_cast<URLRequestContextAdapter*>(jurl_request_context_adapter);
std::string filename = ConvertJavaStringToUTF8(env, jfilename);
context_adapter->StartNetLogToFile(filename);
}
// Stops recording NetLog.
static void StopNetLog(JNIEnv* env,
jobject jcaller,
jlong jurl_request_context_adapter) {
URLRequestContextAdapter* context_adapter =
reinterpret_cast<URLRequestContextAdapter*>(jurl_request_context_adapter);
context_adapter->StopNetLog();
}
// Called on application's main Java thread.
static void InitRequestContextOnMainThread(JNIEnv* env,
jobject jcaller,
jlong jurl_request_context_adapter) {
URLRequestContextAdapter* context_adapter =
reinterpret_cast<URLRequestContextAdapter*>(jurl_request_context_adapter);
context_adapter->InitRequestContextOnMainThread();
}
} // namespace cronet
|