Chromium Code Reviews| Index: chrome/browser/android/physical_web/physical_web_data_source_android.cc |
| diff --git a/chrome/browser/android/physical_web/physical_web_data_source_android.cc b/chrome/browser/android/physical_web/physical_web_data_source_android.cc |
| index 2f8eed56b84a066eacf4b440260fec8cb4f1d7a6..4b669eac55677d7f7a02d55810052e81a8b6a625 100644 |
| --- a/chrome/browser/android/physical_web/physical_web_data_source_android.cc |
| +++ b/chrome/browser/android/physical_web/physical_web_data_source_android.cc |
| @@ -6,15 +6,37 @@ |
| #include <jni.h> |
| +#include "base/android/jni_string.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "jni/UrlManager_jni.h" |
| using base::android::AttachCurrentThread; |
| +using base::android::ConvertJavaStringToUTF8; |
| using base::android::JavaParamRef; |
| using base::android::ScopedJavaLocalRef; |
| +namespace { |
| + |
| +// Fully-qualified class names. |
|
gone
2016/10/13 22:48:30
I think that doing anything this deep in JNI (hard
mattreynolds
2016/10/18 00:59:30
I decided to go a different route, now the native
|
| +const char kPwCollectionClassPath[] = |
| + "org/chromium/chrome/browser/physicalweb/PwCollection"; |
| +const char kPwsResultClassPath[] = |
| + "org/chromium/chrome/browser/physicalweb/PwsResult"; |
| +const char kUrlInfoClassPath[] = |
| + "org/chromium/chrome/browser/physicalweb/UrlInfo"; |
| + |
| +// Field descriptors. |
| +const char kPwsResultsFieldDescriptor[] = |
| + "[Lorg/chromium/chrome/browser/physicalweb/PwsResult;"; |
| +const char kUrlInfosFieldDescriptor[] = |
| + "[Lorg/chromium/chrome/browser/physicalweb/UrlInfo;"; |
| +const char kStringFieldDescriptor[] = "Ljava/lang/String;"; |
| +const char kDoubleFieldDescriptor[] = "D"; |
| +const char kLongFieldDescriptor[] = "J"; |
| +} // namespace |
| + |
| PhysicalWebDataSourceAndroid::PhysicalWebDataSourceAndroid() { |
| Initialize(); |
| } |
| @@ -27,6 +49,51 @@ void PhysicalWebDataSourceAndroid::Initialize() { |
| // Cache a reference to the singleton instance of UrlManager. |
| url_manager_.Reset(Java_UrlManager_getInstance(env)); |
| DCHECK(url_manager_.obj()); |
| + |
| + // Cache field IDs for PwCollection fields. |
| + auto pw_collection_cls = |
| + ScopedJavaLocalRef<jclass>(env, env->FindClass(kPwCollectionClassPath)); |
| + DCHECK(pw_collection_cls.obj()); |
| + url_infos_fid_ = env->GetFieldID(pw_collection_cls.obj(), "urlInfos", |
| + kUrlInfosFieldDescriptor); |
| + DCHECK(url_infos_fid_); |
| + pws_results_fid_ = env->GetFieldID(pw_collection_cls.obj(), "pwsResults", |
| + kPwsResultsFieldDescriptor); |
| + DCHECK(pws_results_fid_); |
| + |
| + // Cache field IDs for UrlInfo fields. |
| + auto url_info_cls = |
| + ScopedJavaLocalRef<jclass>(env, env->FindClass(kUrlInfoClassPath)); |
| + DCHECK(url_info_cls.obj()); |
| + url_fid_ = |
| + env->GetFieldID(url_info_cls.obj(), "mUrl", kStringFieldDescriptor); |
| + DCHECK(url_fid_); |
| + distance_fid_ = |
| + env->GetFieldID(url_info_cls.obj(), "mDistance", kDoubleFieldDescriptor); |
| + DCHECK(distance_fid_); |
| + scan_timestamp_fid_ = env->GetFieldID(url_info_cls.obj(), "mScanTimestamp", |
| + kLongFieldDescriptor); |
| + DCHECK(scan_timestamp_fid_); |
| + |
| + // Cache field IDs for PwsResult fields. |
| + auto pws_result_cls = |
| + ScopedJavaLocalRef<jclass>(env, env->FindClass(kPwsResultClassPath)); |
| + DCHECK(pws_result_cls.obj()); |
| + site_url_fid_ = |
| + env->GetFieldID(pws_result_cls.obj(), "siteUrl", kStringFieldDescriptor); |
| + DCHECK(site_url_fid_); |
| + icon_url_fid_ = |
| + env->GetFieldID(pws_result_cls.obj(), "iconUrl", kStringFieldDescriptor); |
| + DCHECK(icon_url_fid_); |
| + title_fid_ = |
| + env->GetFieldID(pws_result_cls.obj(), "title", kStringFieldDescriptor); |
| + DCHECK(title_fid_); |
| + description_fid_ = env->GetFieldID(pws_result_cls.obj(), "description", |
| + kStringFieldDescriptor); |
| + DCHECK(description_fid_); |
| + group_id_fid_ = |
| + env->GetFieldID(pws_result_cls.obj(), "groupId", kStringFieldDescriptor); |
| + DCHECK(group_id_fid_); |
| } |
| void PhysicalWebDataSourceAndroid::StartDiscovery( |
| @@ -41,8 +108,104 @@ void PhysicalWebDataSourceAndroid::StopDiscovery() { |
| } |
| std::unique_ptr<base::ListValue> PhysicalWebDataSourceAndroid::GetMetadata() { |
| - // TODO(mattreynolds): get the metadata from the Java layer |
| - return base::MakeUnique<base::ListValue>(); |
| + JNIEnv* env = AttachCurrentThread(); |
| + |
| + // PwCollection contains parallel arrays urlInfos and pwsResults. urlInfos |
| + // holds data related to the devices broadcasting the URLs. pwsResults holds |
| + // the site-related data fetched from the Physical Web service. The arrays |
| + // should have the same size; if there is a URL in urlInfos for which we have |
| + // not received metadata, the corresponding element of pwsResults will be |
| + // null. |
| + ScopedJavaLocalRef<jobject> pw_collection = |
| + Java_UrlManager_getPwCollection(env, url_manager_.obj()); |
| + DCHECK(pw_collection.obj()); |
| + |
| + auto url_infos = ScopedJavaLocalRef<jobjectArray>( |
| + env, static_cast<jobjectArray>( |
| + env->GetObjectField(pw_collection.obj(), url_infos_fid_))); |
| + jsize url_infos_count = env->GetArrayLength(url_infos.obj()); |
| + DCHECK_GE(url_infos_count, 0); |
| + url_infos_count = std::max(0, url_infos_count); |
| + |
| + auto pws_results = ScopedJavaLocalRef<jobjectArray>( |
| + env, static_cast<jobjectArray>( |
| + env->GetObjectField(pw_collection.obj(), pws_results_fid_))); |
| + jsize pws_results_count = env->GetArrayLength(pws_results.obj()); |
| + DCHECK_GE(pws_results_count, 0); |
| + pws_results_count = std::max(0, pws_results_count); |
| + |
| + DCHECK_EQ(url_infos_count, pws_results_count); |
| + |
| + auto metadata = base::MakeUnique<base::ListValue>(); |
| + for (jsize i = 0; i < url_infos_count; i++) { |
| + auto url_info = ScopedJavaLocalRef<jobject>( |
| + env, env->GetObjectArrayElement(url_infos.obj(), i)); |
| + auto pws_result = ScopedJavaLocalRef<jobject>( |
| + env, env->GetObjectArrayElement(pws_results.obj(), i)); |
| + |
| + // Only include URLs for which we have metadata. |
| + if (!url_info.obj() || !pws_result.obj()) { |
| + continue; |
| + } |
| + |
| + // Extract UrlInfo fields. |
| + jstring url_java = |
| + static_cast<jstring>(env->GetObjectField(url_info.obj(), url_fid_)); |
| + double distance_estimate = |
| + env->GetDoubleField(url_info.obj(), distance_fid_); |
| + long scan_timestamp = |
| + env->GetLongField(url_info.obj(), scan_timestamp_fid_); |
| + |
| + // Extract PwsResult fields. |
| + jstring site_url_java = static_cast<jstring>( |
| + env->GetObjectField(pws_result.obj(), site_url_fid_)); |
| + jstring icon_url_java = static_cast<jstring>( |
| + env->GetObjectField(pws_result.obj(), icon_url_fid_)); |
| + jstring title_java = |
| + static_cast<jstring>(env->GetObjectField(pws_result.obj(), title_fid_)); |
| + jstring description_java = static_cast<jstring>( |
| + env->GetObjectField(pws_result.obj(), description_fid_)); |
| + jstring group_id_java = static_cast<jstring>( |
| + env->GetObjectField(pws_result.obj(), group_id_fid_)); |
| + |
| + // Convert strings. |
| + std::string url; |
| + std::string site_url; |
| + std::string icon_url; |
| + std::string title; |
| + std::string description; |
| + std::string group_id; |
| + ConvertJavaStringToUTF8(env, url_java, &url); |
| + if (site_url_java) { |
| + ConvertJavaStringToUTF8(env, site_url_java, &site_url); |
| + } |
| + if (icon_url_java) { |
| + ConvertJavaStringToUTF8(env, icon_url_java, &icon_url); |
| + } |
| + if (title_java) { |
| + ConvertJavaStringToUTF8(env, title_java, &title); |
| + } |
| + if (description_java) { |
| + ConvertJavaStringToUTF8(env, description_java, &description); |
| + } |
| + if (group_id_java) { |
| + ConvertJavaStringToUTF8(env, group_id_java, &group_id); |
| + } |
| + |
| + // Append the new URL and associated metadata. |
| + auto metadata_item = base::MakeUnique<base::DictionaryValue>(); |
| + metadata_item->SetString("scannedUrl", url); |
| + metadata_item->SetDouble("distanceEstimate", distance_estimate); |
| + metadata_item->SetInteger("scanTimestamp", |
| + static_cast<int>(scan_timestamp)); |
| + metadata_item->SetString("resolvedUrl", site_url); |
| + metadata_item->SetString("icon", icon_url); |
| + metadata_item->SetString("title", title); |
| + metadata_item->SetString("description", description); |
| + metadata_item->SetString("groupId", group_id); |
| + metadata->Append(std::move(metadata_item)); |
| + } |
| + return metadata; |
| } |
| bool PhysicalWebDataSourceAndroid::HasUnresolvedDiscoveries() { |