1 /*
2  * Copyright (C) 2023 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.adselection;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.net.Uri;
23 
24 import com.android.adservices.LoggerFactory;
25 import com.android.adservices.service.common.httpclient.AdServicesHttpClientRequest;
26 import com.android.adservices.service.devapi.DevContext;
27 import com.android.internal.annotations.VisibleForTesting;
28 
29 import com.google.common.collect.ImmutableBiMap;
30 import com.google.common.collect.ImmutableList;
31 import com.google.common.collect.ImmutableMap;
32 
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Optional;
38 import java.util.stream.Collectors;
39 
40 /** Provides JS version related payload helper methods. */
41 public class JsVersionHelper {
42     private static final LoggerFactory.Logger LOGGER = LoggerFactory.getFledgeLogger();
43     public static final Long DEFAULT_JS_VERSION_IF_ABSENT = 0L;
44 
45     @VisibleForTesting
46     public static final String VERSION_HEADER_NAME_FORMAT = "X_FLEDGE_%s_VERSION";
47 
48     /** JS payload name. */
49     @Retention(RetentionPolicy.SOURCE)
50     @IntDef(
51             prefix = "JS_PAYLOAD_TYPE_",
52             value = {
53                 JS_PAYLOAD_TYPE_BUYER_BIDDING_LOGIC_JS,
54             })
55     public @interface JsPayloadType {}
56 
57     public static final int JS_PAYLOAD_TYPE_BUYER_BIDDING_LOGIC_JS = 1;
58 
59     @VisibleForTesting
60     static final String JS_PAYLOAD_NAME_BUYER_BIDDING_LOGIC_JS = "BUYER_BIDDING_LOGIC";
61 
62     @VisibleForTesting
63     static final ImmutableBiMap<Integer, String> JS_PAYLOAD_TYPE_HEADER_NAME_MAP =
64             ImmutableBiMap.<Integer, String>builder()
65                     .put(
66                             JS_PAYLOAD_TYPE_BUYER_BIDDING_LOGIC_JS,
67                             String.format(
68                                     VERSION_HEADER_NAME_FORMAT,
69                                     JS_PAYLOAD_NAME_BUYER_BIDDING_LOGIC_JS))
70                     .build();
71 
72     /** Returns the URI with appended version query parameter. */
getRequestWithVersionHeader( @onNull Uri uri, @NonNull Map<Integer, Long> jsVersionMap, boolean useCache, @NonNull DevContext devContext)73     public static AdServicesHttpClientRequest getRequestWithVersionHeader(
74             @NonNull Uri uri,
75             @NonNull Map<Integer, Long> jsVersionMap,
76             boolean useCache,
77             @NonNull DevContext devContext) {
78         ImmutableMap<String, String> requestProperties =
79                 ImmutableMap.copyOf(
80                         jsVersionMap.entrySet().stream()
81                                 .collect(
82                                         Collectors.toMap(
83                                                 e -> getVersionHeaderName(e.getKey()),
84                                                 e -> Long.toString(e.getValue()))));
85         return AdServicesHttpClientRequest.builder()
86                 .setUri(uri)
87                 .setRequestProperties(requestProperties)
88                 .setUseCache(useCache)
89                 .setResponseHeaderKeys(requestProperties.keySet())
90                 .setDevContext(devContext)
91                 .build();
92     }
93 
94     /** Returns a payload header contains the js version attribute. */
constructVersionHeader( @sPayloadType int jsPayloadType, Long version)95     public static ImmutableMap<String, List<String>> constructVersionHeader(
96             @JsPayloadType int jsPayloadType, Long version) {
97         final long nonNullVersion = Optional.ofNullable(version).orElse(0L);
98         return ImmutableMap.of(
99                 getVersionHeaderName(jsPayloadType),
100                 ImmutableList.of(Long.toString(nonNullVersion)));
101     }
102 
103     @VisibleForTesting
getVersionHeaderName(@sPayloadType int jsPayloadType)104     public static String getVersionHeaderName(@JsPayloadType int jsPayloadType) {
105         return JS_PAYLOAD_TYPE_HEADER_NAME_MAP.get(jsPayloadType);
106     }
107 
108     @Nullable
getJsPayloadType(@onNull String versionHeaderName)109     static Integer getJsPayloadType(@NonNull String versionHeaderName) {
110         return JS_PAYLOAD_TYPE_HEADER_NAME_MAP.inverse().get(versionHeaderName);
111     }
112 }
113