Home | History | Annotate | Download | only in android
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "components/cronet/android/org_chromium_net_UrlRequestContext.h"
      6 
      7 #include <string>
      8 
      9 #include "base/android/jni_android.h"
     10 #include "base/android/jni_string.h"
     11 #include "base/json/json_reader.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/metrics/statistics_recorder.h"
     14 #include "base/values.h"
     15 #include "components/cronet/android/org_chromium_net_UrlRequest.h"
     16 #include "components/cronet/android/url_request_context_peer.h"
     17 #include "components/cronet/android/url_request_peer.h"
     18 #include "components/cronet/url_request_context_config.h"
     19 #include "jni/UrlRequestContext_jni.h"
     20 
     21 // Version of this build of Chromium NET.
     22 #define CHROMIUM_NET_VERSION "1"
     23 
     24 namespace {
     25 
     26 const char kVersion[] = CHROMIUM_VERSION "/" CHROMIUM_NET_VERSION;
     27 
     28 // Delegate of URLRequestContextPeer that delivers callbacks to the Java layer.
     29 class JniURLRequestContextPeerDelegate
     30     : public cronet::URLRequestContextPeer::URLRequestContextPeerDelegate {
     31  public:
     32   JniURLRequestContextPeerDelegate(JNIEnv* env, jobject owner)
     33       : owner_(env->NewGlobalRef(owner)) {
     34   }
     35 
     36   virtual void OnContextInitialized(
     37       cronet::URLRequestContextPeer* context) OVERRIDE {
     38     JNIEnv* env = base::android::AttachCurrentThread();
     39     cronet::Java_UrlRequestContext_initNetworkThread(env, owner_);
     40     // TODO(dplotnikov): figure out if we need to detach from the thread.
     41     // The documentation says we should detach just before the thread exits.
     42   }
     43 
     44  protected:
     45   virtual ~JniURLRequestContextPeerDelegate() {
     46     JNIEnv* env = base::android::AttachCurrentThread();
     47     env->DeleteGlobalRef(owner_);
     48   }
     49 
     50  private:
     51   jobject owner_;
     52 };
     53 
     54 }  // namespace
     55 
     56 namespace cronet {
     57 
     58 // Explicitly register static JNI functions.
     59 bool UrlRequestContextRegisterJni(JNIEnv* env) {
     60   return RegisterNativesImpl(env);
     61 }
     62 
     63 static jstring GetVersion(JNIEnv* env, jclass unused) {
     64   return base::android::ConvertUTF8ToJavaString(env, kVersion).Release();
     65 }
     66 
     67 // Sets global user-agent to be used for all subsequent requests.
     68 static jlong CreateRequestContextPeer(JNIEnv* env,
     69                                       jobject object,
     70                                       jobject context,
     71                                       jstring user_agent,
     72                                       jint log_level,
     73                                       jstring config) {
     74   std::string user_agent_string =
     75       base::android::ConvertJavaStringToUTF8(env, user_agent);
     76 
     77   std::string config_string =
     78       base::android::ConvertJavaStringToUTF8(env, config);
     79 
     80   scoped_ptr<base::Value> config_value(base::JSONReader::Read(config_string));
     81   if (!config_value || !config_value->IsType(base::Value::TYPE_DICTIONARY)) {
     82     DLOG(ERROR) << "Bad JSON: " << config_string;
     83     return 0;
     84   }
     85 
     86   scoped_ptr<URLRequestContextConfig> context_config(
     87       new URLRequestContextConfig());
     88   base::JSONValueConverter<URLRequestContextConfig> converter;
     89   if (!converter.Convert(*config_value, context_config.get())) {
     90     DLOG(ERROR) << "Bad Config: " << config_value;
     91     return 0;
     92   }
     93 
     94   // Set application context.
     95   base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context);
     96   base::android::InitApplicationContext(env, scoped_context);
     97 
     98   int logging_level = log_level;
     99 
    100   // TODO(dplotnikov): set application context.
    101   URLRequestContextPeer* peer = new URLRequestContextPeer(
    102       new JniURLRequestContextPeerDelegate(env, object),
    103       user_agent_string,
    104       logging_level,
    105       kVersion);
    106   peer->AddRef();  // Hold onto this ref-counted object.
    107   peer->Initialize(context_config.Pass());
    108   return reinterpret_cast<jlong>(peer);
    109 }
    110 
    111 // Releases native objects.
    112 static void ReleaseRequestContextPeer(JNIEnv* env,
    113                                       jobject object,
    114                                       jlong urlRequestContextPeer) {
    115   URLRequestContextPeer* peer =
    116       reinterpret_cast<URLRequestContextPeer*>(urlRequestContextPeer);
    117   // TODO(mef): Revisit this from thread safety point of view: Can we delete a
    118   // thread while running on that thread?
    119   // URLRequestContextPeer is a ref-counted object, and may have pending tasks,
    120   // so we need to release it instead of deleting here.
    121   peer->Release();
    122 }
    123 
    124 // Starts recording statistics.
    125 static void InitializeStatistics(JNIEnv* env, jobject jcaller) {
    126   base::StatisticsRecorder::Initialize();
    127 }
    128 
    129 // Gets current statistics with |filter| as a substring as JSON text (an empty
    130 // |filter| will include all registered histograms).
    131 static jstring GetStatisticsJSON(JNIEnv* env, jobject jcaller, jstring filter) {
    132   std::string query = base::android::ConvertJavaStringToUTF8(env, filter);
    133   std::string json = base::StatisticsRecorder::ToJSON(query);
    134   return base::android::ConvertUTF8ToJavaString(env, json).Release();
    135 }
    136 
    137 // Starts recording NetLog into file with |fileName|.
    138 static void StartNetLogToFile(JNIEnv* env,
    139                               jobject jcaller,
    140                               jlong urlRequestContextPeer,
    141                               jstring fileName) {
    142   URLRequestContextPeer* peer =
    143       reinterpret_cast<URLRequestContextPeer*>(urlRequestContextPeer);
    144   std::string file_name = base::android::ConvertJavaStringToUTF8(env, fileName);
    145   peer->StartNetLogToFile(file_name);
    146 }
    147 
    148 // Stops recording NetLog.
    149 static void StopNetLog(JNIEnv* env,
    150                        jobject jcaller,
    151                        jlong urlRequestContextPeer) {
    152   URLRequestContextPeer* peer =
    153       reinterpret_cast<URLRequestContextPeer*>(urlRequestContextPeer);
    154   peer->StopNetLog();
    155 }
    156 
    157 }  // namespace cronet
    158