Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / components / safe_json / json_sanitizer_android.cc
blob9ccad08f6c9d6966cabb818d07756c1cb0b149ca
1 // Copyright 2015 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.
5 #include "components/safe_json/json_sanitizer.h"
7 #include "base/android/jni_string.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_util.h"
13 #include "jni/JsonSanitizer_jni.h"
15 namespace safe_json {
17 namespace {
19 // An implementation of JsonSanitizer that calls into Java. It deals with
20 // malformed input (in particular malformed Unicode encodings) in the following
21 // steps:
22 // 1. The input string is checked for whether it is well-formed UTF-8. Malformed
23 // UTF-8 is rejected.
24 // 2. The UTF-8 string is converted in native code to a Java String, which is
25 // encoded as UTF-16.
26 // 2. The Java String is parsed as JSON in the memory-safe environment of the
27 // Java VM and any string literals are unescaped.
28 // 3. The string literals themselves are now untrusted, so they are checked in
29 // Java for whether they are valid UTF-16.
30 // 4. The parsed JSON with sanitized literals is encoded back into a Java
31 // String and passed back to native code.
32 // 5. The Java String is converted back to UTF-8 in native code.
33 // This ensures that both invalid UTF-8 and invalid escaped UTF-16 will be
34 // rejected.
35 class JsonSanitizerAndroid : public JsonSanitizer {
36 public:
37 JsonSanitizerAndroid(const StringCallback& success_callback,
38 const StringCallback& error_callback);
39 ~JsonSanitizerAndroid() {}
41 void Sanitize(const std::string& unsafe_json);
43 void OnSuccess(const std::string& json);
44 void OnError(const std::string& error);
46 private:
47 StringCallback success_callback_;
48 StringCallback error_callback_;
50 DISALLOW_COPY_AND_ASSIGN(JsonSanitizerAndroid);
53 JsonSanitizerAndroid::JsonSanitizerAndroid(
54 const StringCallback& success_callback,
55 const StringCallback& error_callback)
56 : success_callback_(success_callback),
57 error_callback_(error_callback) {}
59 void JsonSanitizerAndroid::Sanitize(const std::string& unsafe_json) {
60 // The JSON parser only accepts wellformed UTF-8.
61 if (!base::IsStringUTF8(unsafe_json)) {
62 OnError("Unsupported encoding");
63 return;
66 JNIEnv* env = base::android::AttachCurrentThread();
67 base::android::ScopedJavaLocalRef<jstring> unsafe_json_java =
68 base::android::ConvertUTF8ToJavaString(env, unsafe_json);
70 // This will synchronously call either OnSuccess() or OnError().
71 Java_JsonSanitizer_sanitize(env, reinterpret_cast<jlong>(this),
72 unsafe_json_java.obj());
75 void JsonSanitizerAndroid::OnSuccess(const std::string& json) {
76 base::MessageLoop::current()->PostTask(FROM_HERE,
77 base::Bind(success_callback_, json));
80 void JsonSanitizerAndroid::OnError(const std::string& error) {
81 base::MessageLoop::current()->PostTask(FROM_HERE,
82 base::Bind(error_callback_, error));
85 } // namespace
87 void OnSuccess(JNIEnv* env, jclass clazz, jlong jsanitizer, jstring json) {
88 JsonSanitizerAndroid* sanitizer =
89 reinterpret_cast<JsonSanitizerAndroid*>(jsanitizer);
90 sanitizer->OnSuccess(base::android::ConvertJavaStringToUTF8(env, json));
93 void OnError(JNIEnv* env, jclass clazz, jlong jsanitizer, jstring error) {
94 JsonSanitizerAndroid* sanitizer =
95 reinterpret_cast<JsonSanitizerAndroid*>(jsanitizer);
96 sanitizer->OnError(base::android::ConvertJavaStringToUTF8(env, error));
99 // static
100 void JsonSanitizer::Sanitize(const std::string& unsafe_json,
101 const StringCallback& success_callback,
102 const StringCallback& error_callback) {
103 // JsonSanitizerAndroid does all its work synchronously, but posts any
104 // callbacks to the current message loop. This means it can be destroyed at
105 // the end of this method.
106 JsonSanitizerAndroid sanitizer(success_callback, error_callback);
107 sanitizer.Sanitize(unsafe_json);
110 // static
111 bool JsonSanitizer::Register(JNIEnv* env) {
112 return RegisterNativesImpl(env);
115 } // namespace safe_json