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.ondevicepersonalization.services.data.events;
18 
19 import android.annotation.NonNull;
20 import android.net.Uri;
21 
22 import com.android.ondevicepersonalization.services.util.CryptUtils;
23 
24 /**
25  * Helper class to manage creation of ODP event URLs.
26  */
27 public class EventUrlHelper {
28     public static final String URI_AUTHORITY = "localhost";
29     public static final String URI_SCHEME = "odp";
30     public static final String URL_LANDING_PAGE_EVENT_KEY = "r";
31 
32     private static final String BASE_URL = URI_SCHEME + "://" + URI_AUTHORITY;
33     private static final String URL_EVENT_KEY = "e";
34 
EventUrlHelper()35     private EventUrlHelper() {
36     }
37 
encryptEvent(EventUrlPayload event)38     private static String encryptEvent(EventUrlPayload event) throws Exception {
39         return CryptUtils.encrypt(event);
40     }
41 
decryptEvent(String base64Event)42     private static EventUrlPayload decryptEvent(String base64Event) throws Exception {
43         return (EventUrlPayload) CryptUtils.decrypt(base64Event);
44     }
45 
46     /**
47      * Creates an encrypted ODP event URL for the given event
48      *
49      * @param event The event to create the URL for.
50      * @return Encrypted ODP event URL
51      */
getEncryptedOdpEventUrl(@onNull EventUrlPayload event)52     public static Uri getEncryptedOdpEventUrl(@NonNull EventUrlPayload event) throws Exception {
53         String encryptedEvent = encryptEvent(event);
54         return Uri.parse(BASE_URL).buildUpon().appendQueryParameter(URL_EVENT_KEY,
55                 encryptedEvent).build();
56     }
57 
58     /**
59      * Creates an encrypted ODP event URL for the given event and landing page
60      *
61      * @param event The event to create the URL for.
62      * @return Encrypted ODP event URL with a landingPage parameter
63      */
getEncryptedClickTrackingUrl(@onNull EventUrlPayload event, @NonNull String landingPage)64     public static Uri getEncryptedClickTrackingUrl(@NonNull EventUrlPayload event,
65             @NonNull String landingPage)
66             throws Exception {
67         return getEncryptedOdpEventUrl(event).buildUpon().appendQueryParameter(
68                 URL_LANDING_PAGE_EVENT_KEY, landingPage).build();
69     }
70 
71     /**
72      * Retrieved the event from the encrypted ODP event URL
73      *
74      * @param url The encrypted ODP event URL
75      * @return Event object retrieved from the URL
76      */
getEventFromOdpEventUrl(@onNull String url)77     public static EventUrlPayload getEventFromOdpEventUrl(@NonNull String url) throws Exception {
78         Uri uri = Uri.parse(url);
79         String encryptedEvent = uri.getQueryParameter(URL_EVENT_KEY);
80         if (encryptedEvent == null || !isOdpUrl(url)) {
81             throw new IllegalArgumentException("Invalid url: " + url);
82         }
83         return decryptEvent(encryptedEvent);
84     }
85 
86     /**
87      * Returns whether a given URL is an ODP url
88      *
89      * @return true if URL is an ODP url, false otherwise
90      */
isOdpUrl(@onNull String url)91     public static boolean isOdpUrl(@NonNull String url) {
92         Uri uri = Uri.parse(url);
93         return URI_SCHEME.equals(uri.getScheme())
94                 && URI_AUTHORITY.equals(uri.getAuthority());
95     }
96 }
97