• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.adservices.service.js;
18 
19 import static java.util.Arrays.asList;
20 
21 import android.adservices.common.AdSelectionSignals;
22 
23 import com.google.common.collect.ImmutableList;
24 
25 import org.json.JSONException;
26 import org.json.JSONObject;
27 
28 import java.util.List;
29 import java.util.Map;
30 import java.util.stream.Collectors;
31 
32 /** Represent an argument to supply to an JS script. */
33 public abstract class JSScriptArgument {
34     protected final String mName;
35 
JSScriptArgument(String name)36     protected JSScriptArgument(String name) {
37         mName = name;
38     }
39 
40     /**
41      * @return an argument with the given {@code name} and the given string value {@code value}
42      */
stringArg(String name, String value)43     public static JSScriptStringArgument stringArg(String name, String value) {
44         return new JSScriptStringArgument(name, value);
45     }
46 
47     /**
48      * @return a JS object with the given {@code name} and value obtained parsing the given {@code
49      *     value}.
50      * @throws JSONException if {@code value} doesn't represent a valid JSON object
51      */
jsonArg(String name, String value)52     public static JSScriptJsonArgument jsonArg(String name, String value) throws JSONException {
53         // Creating the JSONObject just to parse value and cause a JSONException if invalid.
54         new JSONObject(value);
55         return new JSScriptJsonArgument(name, value);
56     }
57 
58     /**
59      * @return a JS object with the given {@code name} and value obtained parsing the given {@code
60      *     value}.
61      * @throws JSONException if {@code value} doesn't represent a valid JSON object
62      */
jsonArg(String name, AdSelectionSignals value)63     public static JSScriptJsonArgument jsonArg(String name, AdSelectionSignals value)
64             throws JSONException {
65         // TODO(b/238849930) Merge this validation with AdSelectionSignals validation
66         new JSONObject(value.toString());
67         return new JSScriptJsonArgument(name, value.toString());
68     }
69 
70     /**
71      * @return a JS object with the given {@code name} and value obtained parsing the given map
72      *     {@code value}.
73      * @throws JSONException if {@code value} doesn't represent a valid JSON object
74      */
stringMapToRecordArg(String name, Map<String, String> stringMap)75     public static JSScriptArgument stringMapToRecordArg(String name, Map<String, String> stringMap)
76             throws JSONException {
77         ImmutableList.Builder<JSScriptArgument> mapArg = ImmutableList.builder();
78         for (Map.Entry<String, String> signal : stringMap.entrySet()) {
79             mapArg.add(jsonArg(signal.getKey(), signal.getValue()));
80         }
81         return recordArg(name, mapArg.build());
82     }
83 
84     /**
85      * @return a JS array argument with the given {@code name} initialized with the values specified
86      *     with {@code items}.
87      */
arrayArg( String name, T... items)88     public static <T extends JSScriptArgument> JSScriptArrayArgument<T> arrayArg(
89             String name, T... items) {
90         return new JSScriptArrayArgument<>(name, asList(items));
91     }
92 
93     /**
94      * @return a JS array argument with the given {@code name} initialized with the values specified
95      *     with {@code items}.
96      */
arrayArg( String name, List<T> items)97     public static <T extends JSScriptArgument> JSScriptArrayArgument<T> arrayArg(
98             String name, List<T> items) {
99         return new JSScriptArrayArgument<>(name, items);
100     }
101 
102     /**
103      * @return a JS array argument with the given {@code name} initialized with the values specified
104      *     with {@code items}.
105      */
stringArrayArg( String name, List<String> items)106     public static JSScriptArrayArgument<JSScriptStringArgument> stringArrayArg(
107             String name, List<String> items) {
108         return new JSScriptArrayArgument<>(
109                 name,
110                 items.stream().map(str -> stringArg("ignored", str)).collect(Collectors.toList()));
111     }
112 
113     /**
114      * @return a JS object with the given {@code name} and {@code fields} as fields values.
115      */
recordArg(String name, JSScriptArgument... fields)116     public static JSScriptRecordArgument recordArg(String name, JSScriptArgument... fields) {
117         return new JSScriptRecordArgument(name, asList(fields));
118     }
119 
120     /**
121      * @return a JS object with the given {@code name} and {@code fields} as fields values.
122      */
recordArg(String name, List<JSScriptArgument> fields)123     public static JSScriptRecordArgument recordArg(String name, List<JSScriptArgument> fields) {
124         return new JSScriptRecordArgument(name, fields);
125     }
126 
127     /**
128      * @return a numeric variable with the given {@code name} and {@code value}.
129      */
numericArg(String name, T value)130     public static <T extends Number> JSScriptNumericArgument<T> numericArg(String name, T value) {
131         return new JSScriptNumericArgument<>(name, value);
132     }
133 
134     /**
135      * @return the JS code to use to initialize the variable.
136      */
variableDeclaration()137     public String variableDeclaration() {
138         return String.format("const %s = %s;", name(), initializationValue());
139     }
140 
141     /**
142      * @return name of the argument as referred in the call to the auction script function.
143      */
name()144     public String name() {
145         return mName;
146     }
147 
148     /**
149      * @return the JS code to use to initialize the newly declared variable.
150      */
initializationValue()151     abstract String initializationValue();
152 }
153