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.measurement.reporting; 18 19 import android.net.Uri; 20 21 import com.android.adservices.service.measurement.MeasurementHttpClient; 22 import com.android.internal.annotations.VisibleForTesting; 23 24 import org.json.JSONArray; 25 import org.json.JSONObject; 26 27 import java.io.BufferedOutputStream; 28 import java.io.IOException; 29 import java.io.OutputStream; 30 import java.net.HttpURLConnection; 31 import java.net.MalformedURLException; 32 import java.net.URL; 33 34 /** 35 * Class to send reports by making a non-credentialed secure HTTP POST request to the reporting 36 * origin. 37 */ 38 public abstract class MeasurementReportSender { 39 private final MeasurementHttpClient mNetworkConnection = new MeasurementHttpClient(); 40 41 /** 42 * Sends an event report to the reporting origin. 43 */ sendReport(Uri adTechDomain, JSONObject reportJson)44 public int sendReport(Uri adTechDomain, JSONObject reportJson) 45 throws IOException { 46 int returnCode; 47 URL reportingFullUrl = createReportingFullUrl(adTechDomain); 48 49 HttpURLConnection urlConnection = createHttpUrlConnection(reportingFullUrl); 50 returnCode = sendReportPostRequest(urlConnection, reportJson); 51 return returnCode; 52 } 53 54 /** Sends an event report to the reporting origin. */ sendReport(Uri adTechDomain, JSONArray reportJsonArray)55 public int sendReport(Uri adTechDomain, JSONArray reportJsonArray) throws IOException { 56 URL reportingFullUrl = createReportingFullUrl(adTechDomain); 57 58 HttpURLConnection urlConnection = createHttpUrlConnection(reportingFullUrl); 59 return sendReportPostRequest(urlConnection, reportJsonArray); 60 } 61 62 /** 63 * Given a Uri adTechDomain, returns the URL Object 64 * of the URL to send the POST request to. 65 */ createReportingFullUrl(Uri adTechDomain)66 abstract URL createReportingFullUrl(Uri adTechDomain) throws MalformedURLException; 67 68 /** 69 * Opens the HTTPUrlConnection from the URL object. 70 */ 71 @VisibleForTesting createHttpUrlConnection(URL reportingOriginURL)72 public HttpURLConnection createHttpUrlConnection(URL reportingOriginURL) throws IOException { 73 return (HttpURLConnection) mNetworkConnection.setup(reportingOriginURL); 74 } 75 76 /** Posts the reportJsonObject to the HttpUrlConnection. */ sendReportPostRequest(HttpURLConnection urlConnection, JSONObject reportJson)77 private int sendReportPostRequest(HttpURLConnection urlConnection, JSONObject reportJson) 78 throws IOException { 79 return sendReportPostRequest(urlConnection, reportJson.toString().getBytes()); 80 } 81 82 /** Posts the reportJsonArray to the HttpUrlConnection. */ sendReportPostRequest(HttpURLConnection urlConnection, JSONArray reportJsonArray)83 private int sendReportPostRequest(HttpURLConnection urlConnection, JSONArray reportJsonArray) 84 throws IOException { 85 return sendReportPostRequest(urlConnection, reportJsonArray.toString().getBytes()); 86 } 87 88 /** Posts bytes to the HttpUrlConnection. */ sendReportPostRequest(HttpURLConnection urlConnection, byte[] bytes)89 private int sendReportPostRequest(HttpURLConnection urlConnection, byte[] bytes) 90 throws IOException { 91 int code; 92 try { 93 urlConnection.setRequestMethod("POST"); 94 urlConnection.setDoOutput(true); 95 urlConnection.setRequestProperty("Content-Type", "application/json"); 96 urlConnection.setRequestProperty("Origin", "null"); 97 98 OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); 99 out.write(bytes); 100 out.flush(); 101 out.close(); 102 103 code = urlConnection.getResponseCode(); 104 } finally { 105 urlConnection.disconnect(); 106 } 107 return code; 108 } 109 } 110