OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/payments/content/android/payment_manifest_parser_android.h" | 5 #include "components/payments/content/payment_manifest_parser_host.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <algorithm> |
| 8 #include <utility> |
8 | 9 |
9 #include <climits> | |
10 | |
11 #include "base/android/jni_array.h" | |
12 #include "base/android/jni_string.h" | |
13 #include "base/bind.h" | 10 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
15 #include "base/logging.h" | 12 #include "base/logging.h" |
16 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
17 #include "base/numerics/safe_conversions.h" | |
18 #include "components/strings/grit/components_strings.h" | 14 #include "components/strings/grit/components_strings.h" |
19 #include "content/public/browser/utility_process_mojo_client.h" | 15 #include "content/public/browser/utility_process_mojo_client.h" |
20 #include "jni/PaymentManifestParser_jni.h" | |
21 #include "ui/base/l10n/l10n_util.h" | 16 #include "ui/base/l10n/l10n_util.h" |
22 | 17 |
23 namespace payments { | 18 namespace payments { |
24 | 19 |
25 class PaymentManifestParserAndroid::ParseCallback { | 20 PaymentManifestParserHost::PaymentManifestParserHost() {} |
26 public: | |
27 explicit ParseCallback(const base::android::JavaParamRef<jobject>& jcallback) | |
28 : jcallback_(jcallback) {} | |
29 | 21 |
30 ~ParseCallback() {} | 22 PaymentManifestParserHost::~PaymentManifestParserHost() {} |
31 | 23 |
32 void OnManifestParseSuccess( | 24 void PaymentManifestParserHost::StartUtilityProcess() { |
33 std::vector<mojom::PaymentManifestSectionPtr> manifest) { | |
34 DCHECK(!manifest.empty()); | |
35 | |
36 JNIEnv* env = base::android::AttachCurrentThread(); | |
37 base::android::ScopedJavaLocalRef<jobjectArray> jmanifest = | |
38 Java_PaymentManifestParser_createManifest(env, manifest.size()); | |
39 | |
40 // Java array indices must be integers. | |
41 for (size_t i = 0; i < manifest.size() && i <= static_cast<size_t>(INT_MAX); | |
42 ++i) { | |
43 const mojom::PaymentManifestSectionPtr& section = manifest[i]; | |
44 if (section->sha256_cert_fingerprints.size() > | |
45 static_cast<size_t>(INT_MAX)) { | |
46 continue; | |
47 } | |
48 | |
49 Java_PaymentManifestParser_addSectionToManifest( | |
50 env, jmanifest.obj(), base::checked_cast<int>(i), | |
51 base::android::ConvertUTF8ToJavaString(env, section->package_name), | |
52 section->version, | |
53 base::checked_cast<int>(section->sha256_cert_fingerprints.size())); | |
54 | |
55 for (size_t j = 0; j < section->sha256_cert_fingerprints.size() && | |
56 j <= static_cast<size_t>(INT_MAX); | |
57 ++j) { | |
58 const std::vector<uint8_t>& fingerprint = | |
59 section->sha256_cert_fingerprints[j]; | |
60 Java_PaymentManifestParser_addFingerprintToSection( | |
61 env, jmanifest.obj(), base::checked_cast<int>(i), | |
62 base::checked_cast<int>(j), | |
63 base::android::ToJavaByteArray(env, fingerprint)); | |
64 } | |
65 } | |
66 | |
67 // Can trigger synchronous deletion of PaymentManifestParserAndroid. | |
68 Java_ManifestParseCallback_onManifestParseSuccess(env, jcallback_, | |
69 jmanifest.obj()); | |
70 } | |
71 | |
72 void OnManifestParseFailure() { | |
73 // Can trigger synchronous deletion of PaymentManifestParserAndroid. | |
74 Java_ManifestParseCallback_onManifestParseFailure( | |
75 base::android::AttachCurrentThread(), jcallback_); | |
76 } | |
77 | |
78 private: | |
79 base::android::ScopedJavaGlobalRef<jobject> jcallback_; | |
80 | |
81 DISALLOW_COPY_AND_ASSIGN(ParseCallback); | |
82 }; | |
83 | |
84 PaymentManifestParserAndroid::PaymentManifestParserAndroid() {} | |
85 | |
86 PaymentManifestParserAndroid::~PaymentManifestParserAndroid() {} | |
87 | |
88 void PaymentManifestParserAndroid::StartUtilityProcess( | |
89 JNIEnv* env, | |
90 const base::android::JavaParamRef<jobject>& jcaller) { | |
91 mojo_client_ = base::MakeUnique< | 25 mojo_client_ = base::MakeUnique< |
92 content::UtilityProcessMojoClient<mojom::PaymentManifestParser>>( | 26 content::UtilityProcessMojoClient<mojom::PaymentManifestParser>>( |
93 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_MANIFEST_PARSER_NAME)); | 27 l10n_util::GetStringUTF16( |
| 28 IDS_UTILITY_PROCESS_PAYMENT_MANIFEST_PARSER_NAME)); |
94 mojo_client_->set_error_callback( | 29 mojo_client_->set_error_callback( |
95 base::Bind(&PaymentManifestParserAndroid::OnUtilityProcessStopped, | 30 base::Bind(&PaymentManifestParserHost::OnUtilityProcessStopped, |
96 base::Unretained(this))); | 31 base::Unretained(this))); |
97 mojo_client_->Start(); | 32 mojo_client_->Start(); |
98 } | 33 } |
99 | 34 |
100 void PaymentManifestParserAndroid::ParsePaymentManifest( | 35 void PaymentManifestParserHost::ParsePaymentManifest(const std::string& content, |
101 JNIEnv* env, | 36 Callback callback) { |
102 const base::android::JavaParamRef<jobject>& jcaller, | |
103 const base::android::JavaParamRef<jstring>& jcontent, | |
104 const base::android::JavaParamRef<jobject>& jcallback) { | |
105 std::unique_ptr<ParseCallback> pending_callback = | |
106 base::MakeUnique<ParseCallback>(jcallback); | |
107 | |
108 if (!mojo_client_) { | 37 if (!mojo_client_) { |
109 pending_callback->OnManifestParseFailure(); | 38 std::move(callback).Run(std::vector<mojom::PaymentManifestSectionPtr>()); |
110 return; | 39 return; |
111 } | 40 } |
112 | 41 |
113 ParseCallback* callback_identifier = pending_callback.get(); | 42 pending_callbacks_.push_back(std::move(callback)); |
114 pending_callbacks_.push_back(std::move(pending_callback)); | |
115 DCHECK_GE(10U, pending_callbacks_.size()); | 43 DCHECK_GE(10U, pending_callbacks_.size()); |
| 44 Callback* callback_identifier = &pending_callbacks_.back(); |
116 | 45 |
117 mojo_client_->service()->Parse( | 46 mojo_client_->service()->Parse( |
118 base::android::ConvertJavaStringToUTF8(env, jcontent), | 47 content, base::Bind(&PaymentManifestParserHost::OnParse, |
119 base::Bind(&PaymentManifestParserAndroid::OnParse, base::Unretained(this), | 48 base::Unretained(this), callback_identifier)); |
120 callback_identifier)); | |
121 } | 49 } |
122 | 50 |
123 void PaymentManifestParserAndroid::StopUtilityProcess( | 51 void PaymentManifestParserHost::OnParse( |
124 JNIEnv* env, | 52 const Callback* callback_identifier, |
125 const base::android::JavaParamRef<jobject>& jcaller) { | 53 std::vector<mojom::PaymentManifestSectionPtr> manifest) { |
126 delete this; | 54 // At most 10 manifests to parse, so iterating a vector is not too slow. |
| 55 const auto& pending_callback_it = |
| 56 std::find_if(pending_callbacks_.begin(), pending_callbacks_.end(), |
| 57 [callback_identifier](const Callback& pending_callback) { |
| 58 return &pending_callback == callback_identifier; |
| 59 }); |
| 60 if (pending_callback_it == pending_callbacks_.end()) { |
| 61 // If unable to find the pending callback, then something went wrong in the |
| 62 // utility process. Stop the utility process and notify all callbacks. |
| 63 OnUtilityProcessStopped(); |
| 64 return; |
| 65 } |
| 66 |
| 67 Callback callback = std::move(*pending_callback_it); |
| 68 pending_callbacks_.erase(pending_callback_it); |
| 69 |
| 70 // Can trigger synchronous deletion of this object, so can't access any of |
| 71 // the member variables after this block. |
| 72 std::move(callback).Run(std::move(manifest)); |
127 } | 73 } |
128 | 74 |
129 void PaymentManifestParserAndroid::OnParse( | 75 void PaymentManifestParserHost::OnUtilityProcessStopped() { |
130 ParseCallback* callback_identifier, | |
131 std::vector<mojom::PaymentManifestSectionPtr> manifest) { | |
132 // At most 10 manifests to parse, so iterating a vector is not too slow. | |
133 for (auto it = pending_callbacks_.begin(); it != pending_callbacks_.end(); | |
134 ++it) { | |
135 if (it->get() == callback_identifier) { | |
136 std::unique_ptr<ParseCallback> pending_callback = std::move(*it); | |
137 pending_callbacks_.erase(it); | |
138 | |
139 // Can trigger synchronous deletion of this object, so can't access any of | |
140 // the member variables after this block. | |
141 if (manifest.empty()) | |
142 pending_callback->OnManifestParseFailure(); | |
143 else | |
144 pending_callback->OnManifestParseSuccess(std::move(manifest)); | |
145 return; | |
146 } | |
147 } | |
148 | |
149 // If unable to find the pending callback, then something went wrong in the | |
150 // utility process. Stop the utility process and notify all callbacks. | |
151 OnUtilityProcessStopped(); | |
152 } | |
153 | |
154 void PaymentManifestParserAndroid::OnUtilityProcessStopped() { | |
155 mojo_client_.reset(); | 76 mojo_client_.reset(); |
156 std::vector<std::unique_ptr<ParseCallback>> callbacks = | 77 std::vector<Callback> callbacks = std::move(pending_callbacks_); |
157 std::move(pending_callbacks_); | 78 for (Callback& callback : callbacks) { |
158 for (const auto& callback : callbacks) { | |
159 // Can trigger synchronous deletion of this object, so can't access any of | 79 // Can trigger synchronous deletion of this object, so can't access any of |
160 // the member variables after this line. | 80 // the member variables after this line. |
161 callback->OnManifestParseFailure(); | 81 std::move(callback).Run(std::vector<mojom::PaymentManifestSectionPtr>()); |
162 } | 82 } |
163 } | 83 } |
164 | 84 |
165 bool RegisterPaymentManifestParser(JNIEnv* env) { | |
166 return RegisterNativesImpl(env); | |
167 } | |
168 | |
169 // Caller owns the result. | |
170 jlong CreatePaymentManifestParserAndroid( | |
171 JNIEnv* env, | |
172 const base::android::JavaParamRef<jclass>& jcaller) { | |
173 return reinterpret_cast<jlong>(new PaymentManifestParserAndroid); | |
174 } | |
175 | |
176 } // namespace payments | 85 } // namespace payments |
OLD | NEW |