Merge "TextClassifier: normalize uri for browser intent."

This commit is contained in:
Abodunrinwa Toki
2019-02-08 21:39:09 +00:00
committed by Android (Google) Code Review
7 changed files with 215 additions and 86 deletions

View File

@@ -85,15 +85,16 @@ public final class ExtrasUtils {
}
/**
* Returns the first "translate" action found in the {@code classification} object.
* Returns the first action found in the {@code classification} object with an intent
* action string, {@code intentAction}.
*/
@Nullable
public static RemoteAction findTranslateAction(TextClassification classification) {
public static RemoteAction findAction(TextClassification classification, String intentAction) {
final ArrayList<Intent> actionIntents = getActionsIntents(classification);
if (actionIntents != null) {
final int size = actionIntents.size();
for (int i = 0; i < size; i++) {
if (Intent.ACTION_TRANSLATE.equals(actionIntents.get(i).getAction())) {
if (intentAction.equals(actionIntents.get(i).getAction())) {
return classification.getActions().get(i);
}
}
@@ -101,6 +102,14 @@ public final class ExtrasUtils {
return null;
}
/**
* Returns the first "translate" action found in the {@code classification} object.
*/
@Nullable
public static RemoteAction findTranslateAction(TextClassification classification) {
return findAction(classification, Intent.ACTION_TRANSLATE);
}
/**
* Returns the entity type contained in the {@code extra}.
*/

View File

@@ -182,7 +182,8 @@ public final class LegacyIntentFactory implements IntentFactory {
actions.add(new LabeledIntent(
context.getString(com.android.internal.R.string.browse),
context.getString(com.android.internal.R.string.browse_desc),
new Intent(Intent.ACTION_VIEW, Uri.parse(text))
new Intent(Intent.ACTION_VIEW)
.setDataAndNormalize(Uri.parse(text))
.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()),
LabeledIntent.DEFAULT_REQUEST_CODE));
return actions;

View File

@@ -49,20 +49,18 @@ public final class TemplateIntentFactory {
}
final List<TextClassifierImpl.LabeledIntent> labeledIntents = new ArrayList<>();
for (RemoteActionTemplate remoteActionTemplate : remoteActionTemplates) {
Intent intent = createIntent(remoteActionTemplate);
if (intent == null) {
if (!isValidTemplate(remoteActionTemplate)) {
Log.w(TAG, "Invalid RemoteActionTemplate skipped.");
continue;
}
TextClassifierImpl.LabeledIntent
labeledIntent = new TextClassifierImpl.LabeledIntent(
remoteActionTemplate.title,
remoteActionTemplate.description,
intent,
remoteActionTemplate.requestCode == null
? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
: remoteActionTemplate.requestCode
);
labeledIntents.add(labeledIntent);
labeledIntents.add(
new TextClassifierImpl.LabeledIntent(
remoteActionTemplate.title,
remoteActionTemplate.description,
createIntent(remoteActionTemplate),
remoteActionTemplate.requestCode == null
? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
: remoteActionTemplate.requestCode));
}
labeledIntents.forEach(
action -> action.getIntent()
@@ -70,29 +68,43 @@ public final class TemplateIntentFactory {
return labeledIntents;
}
@Nullable
private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
Intent intent = new Intent();
private static boolean isValidTemplate(@Nullable RemoteActionTemplate remoteActionTemplate) {
if (remoteActionTemplate == null) {
Log.w(TAG, "Invalid RemoteActionTemplate: is null");
return false;
}
if (TextUtils.isEmpty(remoteActionTemplate.title)) {
Log.w(TAG, "Invalid RemoteActionTemplate: title is null");
return false;
}
if (TextUtils.isEmpty(remoteActionTemplate.description)) {
Log.w(TAG, "Invalid RemoteActionTemplate: description is null");
return false;
}
if (!TextUtils.isEmpty(remoteActionTemplate.packageName)) {
Log.w(TAG, "A RemoteActionTemplate is skipped as package name is set.");
return null;
Log.w(TAG, "Invalid RemoteActionTemplate: package name is set");
return false;
}
if (!TextUtils.isEmpty(remoteActionTemplate.action)) {
intent.setAction(remoteActionTemplate.action);
}
Uri data = null;
if (!TextUtils.isEmpty(remoteActionTemplate.data)) {
data = Uri.parse(remoteActionTemplate.data);
}
if (data != null || !TextUtils.isEmpty(remoteActionTemplate.type)) {
intent.setDataAndType(data, remoteActionTemplate.type);
}
if (remoteActionTemplate.flags != null) {
intent.setFlags(remoteActionTemplate.flags);
if (TextUtils.isEmpty(remoteActionTemplate.action)) {
Log.w(TAG, "Invalid RemoteActionTemplate: intent action not set");
return false;
}
return true;
}
private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
final Intent intent = new Intent(remoteActionTemplate.action);
final Uri uri = TextUtils.isEmpty(remoteActionTemplate.data)
? null : Uri.parse(remoteActionTemplate.data).normalizeScheme();
final String type = TextUtils.isEmpty(remoteActionTemplate.type)
? null : Intent.normalizeMimeType(remoteActionTemplate.type);
intent.setDataAndType(uri, type);
intent.setFlags(remoteActionTemplate.flags == null ? 0 : remoteActionTemplate.flags);
if (remoteActionTemplate.category != null) {
for (String category : remoteActionTemplate.category) {
intent.addCategory(category);
if (category != null) {
intent.addCategory(category);
}
}
}
intent.putExtras(createExtras(remoteActionTemplate.extras));
@@ -105,6 +117,9 @@ public final class TemplateIntentFactory {
}
Bundle bundle = new Bundle();
for (NamedVariant namedVariant : namedVariants) {
if (namedVariant == null) {
continue;
}
switch (namedVariant.getType()) {
case NamedVariant.TYPE_INT:
bundle.putInt(namedVariant.getName(), namedVariant.getInt());

View File

@@ -41,6 +41,7 @@ public class TemplateClassificationIntentFactoryTest {
private static final String TEXT = "text";
private static final String TITLE = "Map";
private static final String DESCRIPTION = "Opens in Maps";
private static final String ACTION = Intent.ACTION_VIEW;
@Mock
@@ -57,19 +58,6 @@ public class TemplateClassificationIntentFactoryTest {
@Test
public void create_foreignText() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
null,
ACTION,
null,
null,
null,
null,
null,
null,
null
);
AnnotatorModel.ClassificationResult classificationResult =
new AnnotatorModel.ClassificationResult(
TextClassifier.TYPE_ADDRESS,
@@ -81,7 +69,7 @@ public class TemplateClassificationIntentFactoryTest {
null,
null,
null,
new RemoteActionTemplate[]{remoteActionTemplate});
createRemoteActionTemplates());
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateClassificationIntentFactory.create(
@@ -106,19 +94,6 @@ public class TemplateClassificationIntentFactoryTest {
@Test
public void create_notForeignText() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
null,
ACTION,
null,
null,
null,
null,
null,
null,
null
);
AnnotatorModel.ClassificationResult classificationResult =
new AnnotatorModel.ClassificationResult(
TextClassifier.TYPE_ADDRESS,
@@ -130,7 +105,7 @@ public class TemplateClassificationIntentFactoryTest {
null,
null,
null,
new RemoteActionTemplate[]{remoteActionTemplate});
createRemoteActionTemplates());
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateClassificationIntentFactory.create(
@@ -147,4 +122,21 @@ public class TemplateClassificationIntentFactoryTest {
assertThat(intent.getAction()).isEqualTo(ACTION);
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
}
private static RemoteActionTemplate[] createRemoteActionTemplates() {
return new RemoteActionTemplate[]{
new RemoteActionTemplate(
TITLE,
DESCRIPTION,
ACTION,
null,
null,
null,
null,
null,
null,
null
)
};
}
}

View File

@@ -81,7 +81,6 @@ public class TemplateIntentFactoryTest {
REQUEST_CODE
);
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
@@ -97,14 +96,79 @@ public class TemplateIntentFactoryTest {
assertThat(intent.getFlags()).isEqualTo(FLAG);
assertThat(intent.getCategories()).containsExactly((Object[]) CATEGORY);
assertThat(intent.getPackage()).isNull();
assertThat(
intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
assertThat(intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
assertThat(intent.getIntExtra(KEY_TWO, 0)).isEqualTo(VALUE_TWO);
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
}
@Test
public void create_packageIsNotNull() {
public void normalizesScheme() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
DESCRIPTION,
ACTION,
"HTTp://www.android.com",
TYPE,
FLAG,
CATEGORY,
/* packageName */ null,
NAMED_VARIANTS,
REQUEST_CODE
);
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
String data = intents.get(0).getIntent().getData().toString();
assertThat(data).isEqualTo("http://www.android.com");
}
@Test
public void create_minimal() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
DESCRIPTION,
ACTION,
null,
null,
null,
null,
null,
null,
null
);
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
assertThat(intents).hasSize(1);
TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
assertThat(labeledIntent.getTitle()).isEqualTo(TITLE);
assertThat(labeledIntent.getDescription()).isEqualTo(DESCRIPTION);
assertThat(labeledIntent.getRequestCode()).isEqualTo(
TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
Intent intent = labeledIntent.getIntent();
assertThat(intent.getAction()).isEqualTo(ACTION);
assertThat(intent.getData()).isNull();
assertThat(intent.getType()).isNull();
assertThat(intent.getFlags()).isEqualTo(0);
assertThat(intent.getCategories()).isNull();
assertThat(intent.getPackage()).isNull();
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
}
@Test
public void invalidTemplate_nullTemplate() {
RemoteActionTemplate remoteActionTemplate = null;
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
assertThat(intents).isEmpty();
}
@Test
public void invalidTemplate_nonEmptyPackageName() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
DESCRIPTION,
@@ -121,41 +185,69 @@ public class TemplateIntentFactoryTest {
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
assertThat(intents).hasSize(0);
assertThat(intents).isEmpty();
}
@Test
public void create_minimal() {
public void invalidTemplate_emptyTitle() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
null,
DESCRIPTION,
ACTION,
null,
null,
null,
null,
null,
null,
null
);
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
assertThat(intents).isEmpty();
}
@Test
public void invalidTemplate_emptyDescription() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
null,
ACTION,
null,
null,
null,
null,
null,
null,
null
);
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
assertThat(intents).isEmpty();
}
@Test
public void invalidTemplate_emptyIntentAction() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
DESCRIPTION,
null,
null,
null,
null,
null,
null,
null,
null
);
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
assertThat(intents).hasSize(1);
TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
assertThat(labeledIntent.getTitle()).isNull();
assertThat(labeledIntent.getDescription()).isNull();
assertThat(labeledIntent.getRequestCode()).isEqualTo(
TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
Intent intent = labeledIntent.getIntent();
assertThat(intent.getAction()).isNull();
assertThat(intent.getData()).isNull();
assertThat(intent.getType()).isNull();
assertThat(intent.getFlags()).isEqualTo(0);
assertThat(intent.getCategories()).isNull();
assertThat(intent.getPackage()).isNull();
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
assertThat(intents).isEmpty();
}
}

View File

@@ -176,6 +176,7 @@ public class TextClassifierTest {
TextClassification classification = mClassifier.classifyText(request);
assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
}
@Test
@@ -207,6 +208,7 @@ public class TextClassifierTest {
TextClassification classification = mClassifier.classifyText(request);
assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
}
@Test
@@ -517,6 +519,24 @@ public class TextClassifierTest {
};
}
private static Matcher<TextClassification> containsIntentWithAction(final String action) {
return new BaseMatcher<TextClassification>() {
@Override
public boolean matches(Object o) {
if (o instanceof TextClassification) {
TextClassification result = (TextClassification) o;
return ExtrasUtils.findAction(result, action) != null;
}
return false;
}
@Override
public void describeTo(Description description) {
description.appendText("intent action=").appendValue(action);
}
};
}
private static Matcher<TextLanguage> isTextLanguage(final String languageTag) {
return new BaseMatcher<TextLanguage>() {
@Override

View File

@@ -91,8 +91,8 @@ public class TextClassifierEventTronLoggerTest {
.isEqualTo(ConversationAction.TYPE_CALL_PHONE);
assertThat((float) logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_SCORE))
.isWithin(0.00001f).of(0.5f);
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME))
.isEqualTo(EVENT_TIME);
// Never write event time.
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME)).isNull();
assertThat(logMaker.getPackageName()).isEqualTo(PACKAGE_NAME);
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_WIDGET_TYPE))
.isEqualTo(WIDGET_TYPE);