blob: 608ce6926efa26bc3282271a4a05536813e28683 [file] [log] [blame]
Aurimas Liutikas88c7ff12023-08-10 12:42:26 -07001/*
2 * Copyright (C) 2015 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
17package com.android.statementservice.retriever;
18
19import com.android.statementservice.utils.StatementUtils;
20
21import org.json.JSONObject;
22
23import java.net.MalformedURLException;
24import java.net.URL;
25import java.util.Locale;
26
27/**
28 * Immutable value type that names a web asset.
29 *
30 * <p>A web asset can be named by its protocol, domain, and port using this JSON string:
31 * { "namespace": "web",
32 * "site": "[protocol]://[fully-qualified domain]{:[optional port]}" }
33 *
34 * <p>For example, a website hosted on a https server at www.test.com can be named using
35 * { "namespace": "web",
36 * "site": "https://www.test.com" }
37 *
38 * <p>The only protocol supported now are https and http. If the optional port is not specified,
39 * the default for each protocol will be used (i.e. 80 for http and 443 for https).
40 */
41public final class WebAsset extends AbstractAsset {
42
43 private static final String MISSING_FIELD_FORMAT_STRING = "Expected %s to be set.";
44 private static final String SCHEME_HTTP = "http";
45
46 private final URL mUrl;
47
48 private WebAsset(URL url) {
49 int port = url.getPort() != -1 ? url.getPort() : url.getDefaultPort();
50 try {
51 mUrl = new URL(url.getProtocol().toLowerCase(), url.getHost().toLowerCase(), port, "");
52 } catch (MalformedURLException e) {
53 throw new AssertionError(
54 "Url should always be validated before calling the constructor.");
55 }
56 }
57
58 public String getDomain() {
59 return mUrl.getHost();
60 }
61
62 public String getPath() {
63 return mUrl.getPath();
64 }
65
66 public String getScheme() {
67 return mUrl.getProtocol();
68 }
69
70 public int getPort() {
71 return mUrl.getPort();
72 }
73
74 @Override
75 public String toJson() {
76 AssetJsonWriter writer = new AssetJsonWriter();
77
78 writer.writeFieldLower(StatementUtils.NAMESPACE_FIELD, StatementUtils.NAMESPACE_WEB);
79 writer.writeFieldLower(StatementUtils.WEB_ASSET_FIELD_SITE, mUrl.toExternalForm());
80
81 return writer.closeAndGetString();
82 }
83
84 @Override
85 public String toString() {
86 StringBuilder asset = new StringBuilder();
87 asset.append("WebAsset: ");
88 asset.append(toJson());
89 return asset.toString();
90 }
91
92 @Override
93 public boolean equals(Object o) {
94 if (!(o instanceof WebAsset)) {
95 return false;
96 }
97
98 return ((WebAsset) o).toJson().equals(toJson());
99 }
100
101 @Override
102 public int hashCode() {
103 return toJson().hashCode();
104 }
105
106 @Override
107 public int lookupKey() {
108 return toJson().hashCode();
109 }
110
111 @Override
112 public boolean followInsecureInclude() {
113 // Only allow insecure include file if the asset scheme is http.
114 return SCHEME_HTTP.equals(getScheme());
115 }
116
117 /**
118 * Checks that the input is a valid web asset.
119 *
120 * @throws AssociationServiceException if the asset is not well formatted.
121 */
122 protected static WebAsset create(JSONObject asset)
123 throws AssociationServiceException {
124 if (asset.optString(StatementUtils.WEB_ASSET_FIELD_SITE).equals("")) {
125 throw new AssociationServiceException(String.format(MISSING_FIELD_FORMAT_STRING,
126 StatementUtils.WEB_ASSET_FIELD_SITE));
127 }
128
129 URL url;
130 try {
131 url = new URL(asset.optString(StatementUtils.WEB_ASSET_FIELD_SITE));
132 } catch (MalformedURLException e) {
133 throw new AssociationServiceException("Url is not well formatted.", e);
134 }
135
136 String scheme = url.getProtocol().toLowerCase(Locale.US);
137 if (!scheme.equals("https") && !scheme.equals("http")) {
138 throw new AssociationServiceException("Expected scheme to be http or https.");
139 }
140
141 if (url.getUserInfo() != null) {
142 throw new AssociationServiceException("The url should not contain user info.");
143 }
144
145 String path = url.getFile(); // This is url.getPath() + url.getQuery().
146 if (!path.equals("/") && !path.equals("")) {
147 throw new AssociationServiceException(
148 "Site should only have scheme, domain, and port.");
149 }
150
151 return new WebAsset(url);
152 }
153}