Skip to content

Commit

Permalink
[remoteobjects] Convert JavaScript strings to Java types.
Browse files Browse the repository at this point in the history
A fairly direct copy of CoerceJavaScriptStringToJavaValue.

Bug: 794320
Change-Id: I4e7cbd020fe9702d59c84a32e0e986f970feace1
Reviewed-on: https://chromium-review.googlesource.com/941788
Reviewed-by: Bo <boliu@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540180}
  • Loading branch information
jeremyroman authored and Commit Bot committed Mar 1, 2018
1 parent 5964cda commit 3ef79c4
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.chromium.blink.mojom.RemoteInvocationResult;
import org.chromium.blink.mojom.RemoteObject;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojo_base.mojom.String16;

import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
Expand All @@ -23,6 +24,9 @@

/**
* Exposes limited access to a Java object over a Mojo interface.
*
* For LiveConnect references, an archived version is available at:
* http://web.archive.org/web/20141022204935/http://jdk6.java.net/plugin2/liveconnect/
*/
class RemoteObjectImpl implements RemoteObject {
/**
Expand Down Expand Up @@ -252,6 +256,24 @@ private Object convertArgument(RemoteInvocationArgument argument, Class<?> param
assert !parameterType.isPrimitive();
return null;
}
case RemoteInvocationArgument.Tag.StringValue:
// See http://jdk6.java.net/plugin2/liveconnect/#JS_STRING_VALUES.
if (parameterType == String.class) {
return mojoStringToJavaString(argument.getStringValue());
} else if (parameterType.isPrimitive()) {
// LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
// requires using valueOf() method of corresponding object type, or
// converting to boolean based on whether the string is empty.
return getPrimitiveZero(parameterType);
} else if (parameterType.isArray()) {
// LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
// requires raising a JavaScript exception.
return null;
} else {
// LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
// requires handling java.lang.Object.
return null;
}
default:
throw new RuntimeException("invalid wire argument type");
}
Expand Down Expand Up @@ -330,4 +352,13 @@ private static Object getPrimitiveZero(Class<?> parameterType) {
throw new RuntimeException("unexpected primitive type " + parameterType);
}
}

private static String mojoStringToJavaString(String16 mojoString) {
short[] data = mojoString.data;
char[] chars = new char[data.length];
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) data[i];
}
return String.valueOf(chars);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.chromium.blink.mojom.RemoteInvocationError;
import org.chromium.blink.mojom.RemoteInvocationResult;
import org.chromium.blink.mojom.RemoteObject;
import org.chromium.mojo_base.mojom.String16;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down Expand Up @@ -457,6 +458,52 @@ public void testArgumentConversionBoolean() {
inOrder.verify(consumer, times(2)).accept(null);
}

@Test
public void testArgumentConversionString() {
final Consumer<Object> consumer = (Consumer<Object>) mock(Consumer.class);
Object target = new VariantConsumer(consumer);
String stringWithNonAsciiCharacterAndUnpairedSurrogate = "caf\u00e9\ud800";

RemoteObject remoteObject = new RemoteObjectImpl(target, TestJavascriptInterface.class);
RemoteObject.InvokeMethodResponse response = mock(RemoteObject.InvokeMethodResponse.class);
remoteObject.invokeMethod(
"consumeByte", new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod(
"consumeChar", new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod(
"consumeShort", new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod(
"consumeInt", new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod(
"consumeLong", new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod(
"consumeFloat", new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod("consumeDouble",
new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod("consumeString",
new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod("consumeString",
new RemoteInvocationArgument[] {
stringArgument(stringWithNonAsciiCharacterAndUnpairedSurrogate)},
response);
remoteObject.invokeMethod("consumeObjectArray",
new RemoteInvocationArgument[] {stringArgument("hello")}, response);
remoteObject.invokeMethod("consumeObject",
new RemoteInvocationArgument[] {stringArgument("hello")}, response);

InOrder inOrder = inOrder(consumer);
inOrder.verify(consumer).accept((byte) 0);
inOrder.verify(consumer).accept('\u0000');
inOrder.verify(consumer).accept((short) 0);
inOrder.verify(consumer).accept((int) 0);
inOrder.verify(consumer).accept((long) 0);
inOrder.verify(consumer).accept((float) 0);
inOrder.verify(consumer).accept((double) 0);
inOrder.verify(consumer).accept("hello");
inOrder.verify(consumer).accept(stringWithNonAsciiCharacterAndUnpairedSurrogate);
inOrder.verify(consumer, times(2)).accept(null);
}

private RemoteInvocationResult resultHasError(final int error) {
return ArgumentMatchers.argThat(result -> result.error == error);
}
Expand All @@ -476,4 +523,15 @@ private RemoteInvocationArgument booleanArgument(boolean booleanValue) {
argument.setBooleanValue(booleanValue);
return argument;
}

private RemoteInvocationArgument stringArgument(String stringValue) {
String16 string16 = new String16();
string16.data = new short[stringValue.length()];
for (int i = 0; i < stringValue.length(); i++) {
string16.data[i] = (short) stringValue.charAt(i);
}
RemoteInvocationArgument argument = new RemoteInvocationArgument();
argument.setStringValue(string16);
return argument;
}
}
3 changes: 3 additions & 0 deletions third_party/WebKit/public/web/remote_objects.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

module blink.mojom;

import "mojo/public/mojom/base/string16.mojom";

// These interfaces allow an object implemented outside the Blink renderer
// process to be exposed to JavaScript via synchronous IPC.
//
Expand All @@ -22,6 +24,7 @@ interface RemoteObject {
union RemoteInvocationArgument {
double number_value;
bool boolean_value;
mojo_base.mojom.String16 string_value;
};

enum RemoteInvocationError {
Expand Down

0 comments on commit 3ef79c4

Please sign in to comment.