Skip to content

Commit c8d9c94

Browse files
committed
8254049: Update WebView to public suffix list 2020-04-24
Reviewed-by: kcr, ghb
1 parent bd51089 commit c8d9c94

File tree

4 files changed

+149
-5276
lines changed

4 files changed

+149
-5276
lines changed

modules/javafx.web/src/main/java/com/sun/webkit/network/CookieManager.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,17 @@ private void put(URI uri, Cookie cookie) {
179179
}
180180
host = canonicalize(host);
181181

182-
if (PublicSuffixes.isPublicSuffix(cookie.getDomain())) {
183-
if (cookie.getDomain().equals(host)) {
184-
cookie.setDomain("");
185-
} else {
186-
logger.finest("Domain is public suffix, "
187-
+ "ignoring cookie");
188-
return;
182+
if (!PublicSuffixes.pslFileExists()) {
183+
cookie.setDomain("");
184+
} else {
185+
if (PublicSuffixes.isPublicSuffix(cookie.getDomain())) {
186+
if (cookie.getDomain().equals(host)) {
187+
cookie.setDomain("");
188+
} else {
189+
logger.finest("Domain is public suffix, "
190+
+ "ignoring cookie");
191+
return;
192+
}
189193
}
190194
}
191195

modules/javafx.web/src/main/java/com/sun/webkit/network/PublicSuffixes.java

Lines changed: 135 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,20 @@
2929
import com.sun.javafx.logging.PlatformLogger.Level;
3030

3131
import java.io.BufferedReader;
32+
import java.io.File;
33+
import java.io.FileInputStream;
34+
import java.io.FileNotFoundException;
3235
import java.io.IOException;
3336
import java.io.InputStream;
3437
import java.io.InputStreamReader;
3538
import java.net.IDN;
36-
import java.util.Collections;
37-
import java.util.LinkedHashMap;
39+
import java.security.AccessController;
40+
import java.security.PrivilegedAction;
41+
import java.util.HashMap;
3842
import java.util.Map;
43+
import java.util.concurrent.ConcurrentHashMap;
44+
import java.util.zip.ZipEntry;
45+
import java.util.zip.ZipInputStream;
3946

4047
/**
4148
* A collection of static utility methods dealing with "public suffixes".
@@ -57,10 +64,30 @@ private enum Rule {
5764

5865

5966
/**
60-
* The mapping from domain names to public suffix list rules.
67+
* The mapping from top-level domain names to public suffix list rules.
6168
*/
62-
private static final Map<String,Rule> RULES =
63-
loadRules("effective_tld_names.dat");
69+
private static final Map<String, Rules> rulesCache = new ConcurrentHashMap<>();
70+
71+
72+
/**
73+
* The public suffix list file.
74+
*/
75+
private static final File pslFile = AccessController.doPrivileged((PrivilegedAction<File>)
76+
() -> new File(System.getProperty("java.home"), "lib/security/public_suffix_list.dat"));
77+
78+
79+
/*
80+
* Determines whether the public suffix list file is available.
81+
*/
82+
private static final boolean pslFileExists = AccessController.doPrivileged(
83+
(PrivilegedAction<Boolean>) () -> {
84+
if (!pslFile.exists()) {
85+
logger.warning("Resource not found: " +
86+
"lib/security/public_suffix_list.dat");
87+
return false;
88+
}
89+
return true;
90+
});
6491

6592

6693
/**
@@ -71,101 +98,132 @@ private PublicSuffixes() {
7198
}
7299

73100

101+
/**
102+
* Returns whether the public suffix list file is available.
103+
*/
104+
static boolean pslFileExists() {
105+
return pslFileExists;
106+
}
107+
108+
74109
/**
75110
* Determines if a domain is a public suffix.
76111
*/
77112
static boolean isPublicSuffix(String domain) {
78113
if (domain.length() == 0) {
79114
return false;
80115
}
81-
Rule rule = RULES.get(domain);
82-
if (rule == Rule.EXCEPTION_RULE) {
116+
117+
if (!pslFileExists()) {
83118
return false;
84-
} else if (rule == Rule.SIMPLE_RULE || rule == Rule.WILDCARD_RULE) {
85-
return true;
86-
} else {
87-
int pos = domain.indexOf('.') + 1;
88-
if (pos == 0) {
89-
pos = domain.length();
90-
}
91-
String parent = domain.substring(pos);
92-
return RULES.get(parent) == Rule.WILDCARD_RULE;
93119
}
120+
121+
Rules rules = Rules.getRules(domain);
122+
return rules == null ? false : rules.match(domain);
94123
}
95124

96-
/**
97-
* Loads the public suffix list from a given resource.
98-
*/
99-
private static Map<String,Rule> loadRules(String resourceName) {
100-
logger.finest("resourceName: [{0}]", resourceName);
101-
Map<String,Rule> result = null;
102-
103-
InputStream is = PublicSuffixes.class.getResourceAsStream(resourceName);
104-
if (is != null) {
105-
BufferedReader reader = null;
106-
try {
107-
reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
108-
result = loadRules(reader);
109-
} catch (IOException ex) {
110-
logger.warning("Unexpected error", ex);
111-
} finally {
125+
private static class Rules {
126+
127+
private final Map<String, Rule> rules = new HashMap<>();
128+
129+
private Rules(InputStream is) throws IOException {
130+
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
131+
BufferedReader reader = new BufferedReader(isr);
132+
133+
String line;
134+
int type = reader.read();
135+
while (type != -1 && (line = reader.readLine()) != null) {
136+
Rule rule;
137+
if (line.startsWith("!")) {
138+
line = line.substring(1);
139+
rule = Rule.EXCEPTION_RULE;
140+
} else if (line.startsWith("*.")) {
141+
line = line.substring(2);
142+
rule = Rule.WILDCARD_RULE;
143+
} else {
144+
rule = Rule.SIMPLE_RULE;
145+
}
112146
try {
113-
if (reader != null) {
114-
reader.close();
115-
}
116-
} catch (IOException ex) {
117-
logger.warning("Unexpected error", ex);
147+
line = IDN.toASCII(line, IDN.ALLOW_UNASSIGNED);
148+
} catch (Exception ex) {
149+
logger.warning(String.format("Error parsing rule: [%s]", line), ex);
150+
continue;
118151
}
152+
rules.put(line, rule);
153+
type = reader.read();
154+
}
155+
if (logger.isLoggable(Level.FINEST)) {
156+
logger.finest("rules: {0}", toLogString(rules));
119157
}
120-
} else {
121-
logger.warning("Resource not found: [{0}]",
122-
resourceName);
123158
}
124159

125-
result = result != null
126-
? Collections.unmodifiableMap(result)
127-
: Collections.<String,Rule>emptyMap();
128-
if (logger.isLoggable(Level.FINEST)) {
129-
logger.finest("result: {0}", toLogString(result));
160+
static Rules getRules(String domain) {
161+
String tld = getTopLevelDomain(domain);
162+
if (tld.isEmpty()) {
163+
return null;
164+
}
165+
return rulesCache.computeIfAbsent(tld, k -> createRules(tld));
130166
}
131-
return result;
132-
}
133167

134-
/**
135-
* Loads the public suffix list from a given reader.
136-
*/
137-
private static Map<String,Rule> loadRules(BufferedReader reader)
138-
throws IOException
139-
{
140-
Map<String,Rule> result = new LinkedHashMap<String, Rule>();
141-
String line;
142-
while ((line = reader.readLine()) != null) {
143-
line = line.split("\\s+", 2)[0];
144-
if (line.length() == 0) {
145-
continue;
168+
private static String getTopLevelDomain(String domain) {
169+
domain = IDN.toUnicode(domain, IDN.ALLOW_UNASSIGNED);
170+
int n = domain.lastIndexOf('.');
171+
if (n == -1) {
172+
return domain;
146173
}
147-
if (line.startsWith("//")) {
148-
continue;
174+
return domain.substring(n + 1);
175+
}
176+
177+
private static Rules createRules(String tld) {
178+
try (InputStream pubSuffixStream = getPubSuffixStream()) {
179+
if (pubSuffixStream == null) {
180+
return null;
181+
}
182+
ZipInputStream zis = new ZipInputStream(pubSuffixStream);
183+
ZipEntry ze = zis.getNextEntry();
184+
while (ze != null) {
185+
if (ze.getName().equals(tld)) {
186+
return new Rules(zis);
187+
} else {
188+
ze = zis.getNextEntry();
189+
}
190+
}
191+
} catch (IOException ex) {
192+
logger.warning("Unexpected error", ex);
149193
}
150-
Rule rule;
151-
if (line.startsWith("!")) {
152-
line = line.substring(1);
153-
rule = Rule.EXCEPTION_RULE;
154-
} else if (line.startsWith("*.")) {
155-
line = line.substring(2);
156-
rule = Rule.WILDCARD_RULE;
194+
return null;
195+
}
196+
197+
private static InputStream getPubSuffixStream() {
198+
InputStream is = AccessController.doPrivileged(
199+
(PrivilegedAction<InputStream>) () -> {
200+
try {
201+
return new FileInputStream(pslFile);
202+
} catch (FileNotFoundException ex) {
203+
logger.warning("Resource not found: " +
204+
"lib/security/public_suffix_list.dat");
205+
return null;
206+
}
207+
}
208+
);
209+
return is;
210+
}
211+
212+
boolean match(String domain) {
213+
Rule rule = rules.get(domain);
214+
if (rule == Rule.EXCEPTION_RULE) {
215+
return false;
216+
} else if (rule == Rule.SIMPLE_RULE || rule == Rule.WILDCARD_RULE) {
217+
return true;
157218
} else {
158-
rule = Rule.SIMPLE_RULE;
159-
}
160-
try {
161-
line = IDN.toASCII(line, IDN.ALLOW_UNASSIGNED);
162-
} catch (Exception ex) {
163-
logger.warning(String.format("Error parsing rule: [%s]", line), ex);
164-
continue;
219+
int pos = domain.indexOf('.') + 1;
220+
if (pos == 0) {
221+
pos = domain.length();
222+
}
223+
String parent = domain.substring(pos);
224+
return rules.get(parent) == Rule.WILDCARD_RULE;
165225
}
166-
result.put(line, rule);
167226
}
168-
return result;
169227
}
170228

171229
/**

0 commit comments

Comments
 (0)