1 /* 2 * Copyright (C) 2010 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 /* Licensed to the Apache Software Foundation (ASF) under one or more 18 * contributor license agreements. See the NOTICE file distributed with 19 * this work for additional information regarding copyright ownership. 20 * The ASF licenses this file to You under the Apache License, Version 2.0 21 * (the "License"); you may not use this file except in compliance with 22 * the License. You may obtain a copy of the License at 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, 28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 * See the License for the specific language governing permissions and 30 * limitations under the License. 31 */ 32 33 package libcore.java.net; 34 35 import com.google.mockwebserver.MockResponse; 36 import com.google.mockwebserver.MockWebServer; 37 import com.google.mockwebserver.RecordedRequest; 38 import java.io.IOException; 39 import java.net.CookieHandler; 40 import java.net.CookieManager; 41 import static java.net.CookiePolicy.ACCEPT_ORIGINAL_SERVER; 42 43 import java.net.CookiePolicy; 44 import java.net.CookieStore; 45 import java.net.HttpCookie; 46 import java.net.HttpURLConnection; 47 import java.net.URI; 48 import java.net.URISyntaxException; 49 import java.net.URLConnection; 50 import java.util.ArrayList; 51 import java.util.Arrays; 52 import java.util.Collection; 53 import java.util.Collections; 54 import java.util.Comparator; 55 import java.util.HashMap; 56 import java.util.LinkedHashMap; 57 import java.util.List; 58 import java.util.Locale; 59 import java.util.Map; 60 import java.util.RandomAccess; 61 import java.util.TreeMap; 62 63 import junit.framework.TestCase; 64 65 public abstract class AbstractCookiesTest extends TestCase { 66 67 private static final Map<String, List<String>> EMPTY_COOKIES_MAP = Collections.emptyMap(); 68 69 private CookieHandler defaultHandler; 70 private CookieManager cookieManager; 71 private CookieStore cookieStore; 72 private MockWebServer server; 73 74 75 @Override public void setUp() throws Exception { 76 super.setUp(); 77 server = new MockWebServer(); 78 defaultHandler = CookieHandler.getDefault(); 79 cookieManager = new CookieManager(createCookieStore(), null); 80 cookieStore = cookieManager.getCookieStore(); 81 } 82 83 @Override public void tearDown() throws Exception { 84 CookieHandler.setDefault(defaultHandler); 85 server.shutdown(); 86 super.tearDown(); 87 } 88 89 protected abstract CookieStore createCookieStore(); 90 91 public void testNetscapeResponse() throws Exception { 92 CookieManager cookieManager = new CookieManager(createCookieStore(), 93 ACCEPT_ORIGINAL_SERVER); 94 CookieHandler.setDefault(cookieManager); 95 server.play(); 96 97 server.enqueue(new MockResponse().addHeader("Set-Cookie: a=android; " 98 + "expires=Fri, 31-Dec-9999 23:59:59 GMT; " 99 + "path=/path; " 100 + "domain=" + server.getCookieDomain() + "; " 101 + "secure")); 102 get(server, "/path/foo"); 103 104 List<HttpCookie> cookies = cookieManager.getCookieStore().getCookies(); 105 assertEquals(1, cookies.size()); 106 HttpCookie cookie = cookies.get(0); 107 assertEquals("a", cookie.getName()); 108 assertEquals("android", cookie.getValue()); 109 assertEquals(null, cookie.getComment()); 110 assertEquals(null, cookie.getCommentURL()); 111 assertEquals(false, cookie.getDiscard()); 112 assertEquals(server.getCookieDomain(), cookie.getDomain()); 113 assertTrue(cookie.getMaxAge() > 100000000000L); 114 assertEquals("/path", cookie.getPath()); 115 assertEquals(true, cookie.getSecure()); 116 assertEquals(0, cookie.getVersion()); 117 } 118 119 public void testRfc2109Response() throws Exception { 120 CookieManager cookieManager = new CookieManager(createCookieStore(), 121 ACCEPT_ORIGINAL_SERVER); 122 CookieHandler.setDefault(cookieManager); 123 server.play(); 124 125 server.enqueue(new MockResponse().addHeader("Set-Cookie: a=android; " 126 + "Comment=this cookie is delicious; " 127 + "Domain=" + server.getCookieDomain() + "; " 128 + "Max-Age=60; " 129 + "Path=/path; " 130 + "Secure; " 131 + "Version=1")); 132 get(server, "/path/foo"); 133 134 List<HttpCookie> cookies = cookieManager.getCookieStore().getCookies(); 135 assertEquals(1, cookies.size()); 136 HttpCookie cookie = cookies.get(0); 137 assertEquals("a", cookie.getName()); 138 assertEquals("android", cookie.getValue()); 139 assertEquals("this cookie is delicious", cookie.getComment()); 140 assertEquals(null, cookie.getCommentURL()); 141 assertEquals(false, cookie.getDiscard()); 142 assertEquals(server.getCookieDomain(), cookie.getDomain()); 143 assertEquals(60, cookie.getMaxAge()); 144 assertEquals("/path", cookie.getPath()); 145 assertEquals(true, cookie.getSecure()); 146 assertEquals(1, cookie.getVersion()); 147 } 148 149 public void testRfc2965Response() throws Exception { 150 CookieManager cookieManager = new CookieManager(createCookieStore(), 151 ACCEPT_ORIGINAL_SERVER); 152 CookieHandler.setDefault(cookieManager); 153 server.play(); 154 155 server.enqueue(new MockResponse().addHeader("Set-Cookie2: a=android; " 156 + "Comment=this cookie is delicious; " 157 + "CommentURL=http://google.com/; " 158 + "Discard; " 159 + "Domain=" + server.getCookieDomain() + "; " 160 + "Max-Age=60; " 161 + "Path=/path; " 162 + "Port=\"80,443," + server.getPort() + "\"; " 163 + "Secure; " 164 + "Version=1")); 165 get(server, "/path/foo"); 166 167 List<HttpCookie> cookies = cookieManager.getCookieStore().getCookies(); 168 assertEquals(1, cookies.size()); 169 HttpCookie cookie = cookies.get(0); 170 assertEquals("a", cookie.getName()); 171 assertEquals("android", cookie.getValue()); 172 assertEquals("this cookie is delicious", cookie.getComment()); 173 assertEquals("http://google.com/", cookie.getCommentURL()); 174 assertEquals(true, cookie.getDiscard()); 175 assertEquals(server.getCookieDomain(), cookie.getDomain()); 176 assertEquals(60, cookie.getMaxAge()); 177 assertEquals("/path", cookie.getPath()); 178 assertEquals("80,443," + server.getPort(), cookie.getPortlist()); 179 assertEquals(true, cookie.getSecure()); 180 assertEquals(1, cookie.getVersion()); 181 } 182 183 public void testQuotedAttributeValues() throws Exception { 184 CookieManager cookieManager = new CookieManager(createCookieStore(), 185 ACCEPT_ORIGINAL_SERVER); 186 187 CookieHandler.setDefault(cookieManager); 188 server.play(); 189 190 server.enqueue(new MockResponse().addHeader("Set-Cookie2: a=\"android\"; " 191 + "Comment=\"this cookie is delicious\"; " 192 + "CommentURL=\"http://google.com/\"; " 193 + "Discard; " 194 + "Domain=\"" + server.getCookieDomain() + "\"; " 195 + "Max-Age=\"60\"; " 196 + "Path=\"/path\"; " 197 + "Port=\"80,443," + server.getPort() + "\"; " 198 + "Secure; " 199 + "Version=\"1\"")); 200 get(server, "/path/foo"); 201 202 List<HttpCookie> cookies = cookieManager.getCookieStore().getCookies(); 203 assertEquals(1, cookies.size()); 204 HttpCookie cookie = cookies.get(0); 205 assertEquals("a", cookie.getName()); 206 assertEquals("android", cookie.getValue()); 207 assertEquals("this cookie is delicious", cookie.getComment()); 208 assertEquals("http://google.com/", cookie.getCommentURL()); 209 assertEquals(true, cookie.getDiscard()); 210 assertEquals(server.getCookieDomain(), cookie.getDomain()); 211 assertEquals(60, cookie.getMaxAge()); 212 assertEquals("/path", cookie.getPath()); 213 assertEquals("80,443," + server.getPort(), cookie.getPortlist()); 214 assertEquals(true, cookie.getSecure()); 215 assertEquals(1, cookie.getVersion()); 216 } 217 218 public void testResponseWithMultipleCookieHeaderLines() throws Exception { 219 TestCookieStore cookieStore = new TestCookieStore(); 220 CookieManager cookieManager = new CookieManager(cookieStore, ACCEPT_ORIGINAL_SERVER); 221 cookieManager.put(new URI("http://android.com"), cookieHeaders("a=android", "b=banana")); 222 List<HttpCookie> cookies = sortedCopy(cookieStore.cookies); 223 assertEquals(2, cookies.size()); 224 HttpCookie cookieA = cookies.get(0); 225 assertEquals("a", cookieA.getName()); 226 assertEquals("android", cookieA.getValue()); 227 HttpCookie cookieB = cookies.get(1); 228 assertEquals("b", cookieB.getName()); 229 assertEquals("banana", cookieB.getValue()); 230 } 231 232 public void testDomainDefaulting() throws Exception { 233 TestCookieStore cookieStore = new TestCookieStore(); 234 CookieManager cookieManager = new CookieManager(cookieStore, ACCEPT_ORIGINAL_SERVER); 235 cookieManager.put(new URI("http://android.com/"), cookieHeaders("a=android")); 236 assertEquals("android.com", cookieStore.getCookie("a").getDomain()); 237 } 238 239 public void testNonMatchingDomainsRejected() throws Exception { 240 TestCookieStore cookieStore = new TestCookieStore(); 241 CookieManager cookieManager = new CookieManager(cookieStore, ACCEPT_ORIGINAL_SERVER); 242 cookieManager.put(new URI("http://android.com/"), 243 cookieHeaders("a=android;domain=google.com")); 244 assertEquals(Collections.<HttpCookie>emptyList(), cookieStore.cookies); 245 } 246 247 public void testMatchingDomainsAccepted() throws Exception { 248 TestCookieStore cookieStore = new TestCookieStore(); 249 CookieManager cookieManager = new CookieManager(cookieStore, ACCEPT_ORIGINAL_SERVER); 250 cookieManager.put(new URI("http://www.android.com/"), 251 cookieHeaders("a=android;domain=.android.com")); 252 assertEquals(".android.com", cookieStore.getCookie("a").getDomain()); 253 } 254 255 public void testPathDefaulting() throws Exception { 256 TestCookieStore cookieStore = new TestCookieStore(); 257 CookieManager cookieManager = new CookieManager(cookieStore, ACCEPT_ORIGINAL_SERVER); 258 cookieManager.put(new URI("http://android.com/foo/bar"), cookieHeaders("a=android")); 259 assertEquals("/foo/", cookieStore.getCookie("a").getPath()); 260 cookieManager.put(new URI("http://android.com/"), cookieHeaders("b=banana")); 261 assertEquals("/", cookieStore.getCookie("b").getPath()); 262 cookieManager.put(new URI("http://android.com/foo/"), cookieHeaders("c=carrot")); 263 assertEquals("/foo/", cookieStore.getCookie("c").getPath()); 264 } 265 266 public void testNonMatchingPathsRejected() throws Exception { 267 TestCookieStore cookieStore = new TestCookieStore(); 268 CookieManager cookieManager = new CookieManager(cookieStore, ACCEPT_ORIGINAL_SERVER); 269 cookieManager.put(new URI("http://android.com/foo/bar"), 270 cookieHeaders("a=android;path=/baz/bar")); 271 assertEquals("Expected to reject cookies whose path is not a prefix of the request path", 272 Collections.<HttpCookie>emptyList(), cookieStore.cookies); // RI6 fails this 273 } 274 275 public void testMatchingPathsAccepted() throws Exception { 276 TestCookieStore cookieStore = new TestCookieStore(); 277 CookieManager cookieManager = new CookieManager(cookieStore, ACCEPT_ORIGINAL_SERVER); 278 cookieManager.put(new URI("http://android.com/foo/bar/"), 279 cookieHeaders("a=android;path=/foo")); 280 assertEquals("/foo", cookieStore.getCookie("a").getPath()); 281 } 282 283 public void testNoCookieHeaderSentIfNoCookiesMatch() throws IOException, URISyntaxException { 284 CookieManager cookieManager = new CookieManager(null, ACCEPT_ORIGINAL_SERVER); 285 Map<String, List<String>> cookieHeaders = cookieManager.get( 286 new URI("http://android.com/foo/bar/"), EMPTY_COOKIES_MAP); 287 assertTrue(cookieHeaders.toString(), cookieHeaders.isEmpty() 288 || (cookieHeaders.size() == 1 && cookieHeaders.get("Cookie").isEmpty())); 289 } 290 291 public void testCookieManagerGet_schemeChecks() throws Exception { 292 CookieManager cookieManager = new CookieManager(createCookieStore(), null); 293 294 cookieManager.put(new URI("http://a.com/"), cookieHeaders("a1=android")); 295 cookieManager.put(new URI("https://a.com/"), cookieHeaders("a2=android")); 296 cookieManager.put(new URI("https://a.com/"), cookieHeaders("a3=android; Secure")); 297 298 assertManagerCookiesMatch(cookieManager, "http://a.com/", "a1=android; a2=android"); 299 assertManagerCookiesMatch(cookieManager, "https://a.com/", 300 "a1=android; a2=android; a3=android"); 301 } 302 303 public void testCookieManagerGet_hostChecks() throws Exception { 304 CookieManager cookieManager = new CookieManager(createCookieStore(), null); 305 306 cookieManager.put(new URI("http://a.com/"), cookieHeaders("a1=android")); 307 cookieManager.put(new URI("http://b.com/"), cookieHeaders("b1=android")); 308 309 assertManagerCookiesMatch(cookieManager, "http://a.com/", "a1=android"); 310 assertManagerCookiesMatch(cookieManager, "http://b.com/", "b1=android"); 311 } 312 313 public void testCookieManagerGet_portChecks() throws Exception { 314 CookieManager cookieManager = new CookieManager(createCookieStore(), null); 315 316 cookieManager.put(new URI("http://a.com:443/"), cookieHeaders("a1=android")); 317 cookieManager.put(new URI("http://a.com:8080/"), cookieHeaders("a2=android")); 318 cookieManager.put(new URI("http://a.com:8080/"), cookieHeaders("a3=android; Port=8080")); 319 320 assertManagerCookiesMatch(cookieManager, "http://a.com/", "a1=android; a2=android"); 321 assertManagerCookiesMatch(cookieManager, "http://a.com:8080/", 322 "a1=android; a2=android; a3=android"); 323 } 324 325 public void testCookieManagerGet_pathChecks() throws Exception { 326 CookieManager cookieManager = new CookieManager(createCookieStore(), null); 327 328 cookieManager.put(new URI("http://a.com/"), cookieHeaders("a1=android")); 329 cookieManager.put(new URI("http://a.com/path1"), 330 cookieHeaders("a2=android; Path=\"/path1\"")); 331 cookieManager.put(new URI("http://a.com/path2"), 332 cookieHeaders("a3=android; Path=\"/path2\"")); 333 334 assertManagerCookiesMatch(cookieManager, "http://a.com/notpath", "a1=android"); 335 assertManagerCookiesMatch(cookieManager, "http://a.com/path1", "a1=android; a2=android"); 336 } 337 338 public void testSendingCookiesFromStore() throws Exception { 339 server.enqueue(new MockResponse()); 340 server.play(); 341 342 CookieManager cookieManager = new CookieManager(createCookieStore(), 343 ACCEPT_ORIGINAL_SERVER); 344 HttpCookie cookieA = createCookie("a", "android", server.getCookieDomain(), "/"); 345 cookieManager.getCookieStore().add(server.getUrl("/").toURI(), cookieA); 346 HttpCookie cookieB = createCookie("b", "banana", server.getCookieDomain(), "/"); 347 cookieManager.getCookieStore().add(server.getUrl("/").toURI(), cookieB); 348 CookieHandler.setDefault(cookieManager); 349 350 get(server, "/"); 351 RecordedRequest request = server.takeRequest(); 352 353 List<String> receivedHeaders = request.getHeaders(); 354 assertContains(receivedHeaders, "Cookie: $Version=\"1\"; " 355 + "a=\"android\";$Path=\"/\";$Domain=\"" + server.getCookieDomain() + "\"; " 356 + "b=\"banana\";$Path=\"/\";$Domain=\"" + server.getCookieDomain() + "\""); 357 } 358 359 public void testRedirectsDoNotIncludeTooManyCookies() throws Exception { 360 MockWebServer redirectTarget = new MockWebServer(); 361 redirectTarget.enqueue(new MockResponse().setBody("A")); 362 redirectTarget.play(); 363 364 MockWebServer redirectSource = new MockWebServer(); 365 redirectSource.enqueue(new MockResponse() 366 .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 367 .addHeader("Location: " + redirectTarget.getUrl("/"))); 368 redirectSource.play(); 369 370 CookieManager cookieManager = new CookieManager(createCookieStore(), 371 ACCEPT_ORIGINAL_SERVER); 372 HttpCookie cookie = createCookie("c", "cookie", redirectSource.getCookieDomain(), "/"); 373 String portList = Integer.toString(redirectSource.getPort()); 374 cookie.setPortlist(portList); 375 cookieManager.getCookieStore().add(redirectSource.getUrl("/").toURI(), cookie); 376 CookieHandler.setDefault(cookieManager); 377 378 get(redirectSource, "/"); 379 RecordedRequest request = redirectSource.takeRequest(); 380 381 assertContains(request.getHeaders(), "Cookie: $Version=\"1\"; " 382 + "c=\"cookie\";$Path=\"/\";$Domain=\"" + redirectSource.getCookieDomain() 383 + "\";$Port=\"" + portList + "\""); 384 385 for (String header : redirectTarget.takeRequest().getHeaders()) { 386 if (header.startsWith("Cookie")) { 387 fail(header); 388 } 389 } 390 redirectSource.shutdown(); 391 redirectTarget.shutdown(); 392 } 393 394 /** 395 * Test which headers show up where. The cookie manager should be notified 396 * of both user-specified and derived headers like {@code Host}. Headers 397 * named {@code Cookie} or {@code Cookie2} that are returned by the cookie 398 * manager should show up in the request and in {@code 399 * getRequestProperties}. 400 */ 401 public void testHeadersSentToCookieHandler() throws IOException, InterruptedException { 402 final Map<String, List<String>> cookieHandlerHeaders = new HashMap<String, List<String>>(); 403 CookieHandler.setDefault(new CookieManager(createCookieStore(), null) { 404 @Override 405 public Map<String, List<String>> get(URI uri, 406 Map<String, List<String>> requestHeaders) throws IOException { 407 cookieHandlerHeaders.putAll(requestHeaders); 408 Map<String, List<String>> result = new HashMap<String, List<String>>(); 409 result.put("Cookie", Collections.singletonList("Bar=bar")); 410 result.put("Cookie2", Collections.singletonList("Baz=baz")); 411 result.put("Quux", Collections.singletonList("quux")); 412 return result; 413 } 414 }); 415 server.enqueue(new MockResponse()); 416 server.play(); 417 418 HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 419 assertEquals(Collections.<String, List<String>>emptyMap(), 420 connection.getRequestProperties()); 421 422 connection.setRequestProperty("Foo", "foo"); 423 connection.setDoOutput(true); 424 connection.getOutputStream().write(5); 425 connection.getOutputStream().close(); 426 connection.getInputStream().close(); 427 428 RecordedRequest request = server.takeRequest(); 429 430 assertContainsAll(cookieHandlerHeaders.keySet(), "Foo"); 431 assertContainsAll(cookieHandlerHeaders.keySet(), 432 "Content-Type", "User-Agent", "Connection", "Host"); 433 assertFalse(cookieHandlerHeaders.containsKey("Cookie")); 434 435 /* 436 * The API specifies that calling getRequestProperties() on a connected instance should fail 437 * with an IllegalStateException, but the RI violates the spec and returns a valid map. 438 * http://www.mail-archive.com/net-dev@openjdk.java.net/msg01768.html 439 */ 440 try { 441 assertContainsAll(connection.getRequestProperties().keySet(), "Foo"); 442 assertContainsAll(connection.getRequestProperties().keySet(), 443 "Content-Type", "Content-Length", "User-Agent", "Connection", "Host"); 444 assertContainsAll(connection.getRequestProperties().keySet(), "Cookie", "Cookie2"); 445 assertFalse(connection.getRequestProperties().containsKey("Quux")); 446 } catch (IllegalStateException expected) { 447 } 448 449 assertContainsAll(request.getHeaders(), "Foo: foo", "Cookie: Bar=bar", "Cookie2: Baz=baz"); 450 assertFalse(request.getHeaders().contains("Quux: quux")); 451 } 452 453 public void testCookiesSentIgnoresCase() throws Exception { 454 CookieHandler.setDefault(new CookieManager(createCookieStore(), null) { 455 @Override public Map<String, List<String>> get(URI uri, 456 Map<String, List<String>> requestHeaders) throws IOException { 457 Map<String, List<String>> result = new HashMap<String, List<String>>(); 458 result.put("COOKIE", Collections.singletonList("Bar=bar")); 459 result.put("cooKIE2", Collections.singletonList("Baz=baz")); 460 return result; 461 } 462 }); 463 server. enqueue(new MockResponse()); 464 server.play(); 465 466 get(server, "/"); 467 468 RecordedRequest request = server.takeRequest(); 469 assertContainsAll(request.getHeaders(), "COOKIE: Bar=bar", "cooKIE2: Baz=baz"); 470 assertFalse(request.getHeaders().contains("Quux: quux")); 471 } 472 473 /** 474 * RFC 2109 and RFC 2965 disagree here. 2109 says two equals strings match only if they are 475 * fully-qualified domain names. 2965 says two equal strings always match. We're testing for 476 * 2109 behavior because it's more widely used, it's more conservative, and it's what the RI 477 * does. 478 */ 479 public void testDomainMatchesOnLocalAddresses() { 480 assertFalse(HttpCookie.domainMatches("localhost", "localhost")); 481 assertFalse(HttpCookie.domainMatches("b", "b")); 482 } 483 484 public void testDomainMatchesOnIpAddress() { 485 assertTrue(HttpCookie.domainMatches("127.0.0.1", "127.0.0.1")); 486 assertFalse(HttpCookie.domainMatches("127.0.0.1", "127.0.0.0")); 487 assertFalse(HttpCookie.domainMatches("127.0.0.1", "localhost")); 488 } 489 490 public void testDomainMatchesCaseMapping() { 491 testDomainMatchesCaseMapping(Locale.US); 492 } 493 494 public void testDomainMatchesCaseMappingExoticLocale() { 495 testDomainMatchesCaseMapping(new Locale("tr", "TR")); 496 } 497 498 private void testDomainMatchesCaseMapping(Locale locale) { 499 Locale defaultLocale = Locale.getDefault(); 500 Locale.setDefault(locale); 501 try { 502 assertTrue(HttpCookie.domainMatches(".android.com", "WWW.ANDROID.COM")); 503 assertFalse(HttpCookie.domainMatches("android.com", "WWW.ANDROID.COM")); 504 } finally { 505 Locale.setDefault(defaultLocale); 506 } 507 } 508 509 /** 510 * From the spec, "If an explicitly specified value does not start with a dot, the user agent 511 * supplies a leading dot.". This prepending doesn't happen in setDomain. 512 */ 513 public void testDomainNotAutomaticallyPrefixedWithDot() { 514 HttpCookie cookie = new HttpCookie("Foo", "foo"); 515 cookie.setDomain("localhost"); 516 assertEquals("localhost", cookie.getDomain()); 517 } 518 519 public void testCookieStoreNullUris() { 520 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 521 HttpCookie cookieA = createCookie("a", "android", ".android.com", "/source"); 522 HttpCookie cookieB = createCookie("b", "banana", "code.google.com", "/p/android"); 523 524 try { 525 cookieStore.add(null, cookieA); 526 } catch (NullPointerException expected) { 527 // the RI crashes even though the cookie does get added to the store; sigh 528 expected.printStackTrace(); 529 } 530 assertEquals(Arrays.asList(cookieA), cookieStore.getCookies()); 531 try { 532 cookieStore.add(null, cookieB); 533 } catch (NullPointerException expected) { 534 } 535 assertEquals(Arrays.asList(cookieA, cookieB), cookieStore.getCookies()); 536 537 try { 538 cookieStore.get(null); 539 fail(); 540 } catch (NullPointerException expected) { 541 } 542 543 assertEquals(Collections.<URI>emptyList(), cookieStore.getURIs()); 544 assertTrue(cookieStore.remove(null, cookieA)); 545 assertEquals(Arrays.asList(cookieB), cookieStore.getCookies()); 546 547 assertTrue(cookieStore.removeAll()); 548 assertEquals(Collections.<URI>emptyList(), cookieStore.getURIs()); 549 assertEquals(Collections.<HttpCookie>emptyList(), cookieStore.getCookies()); 550 } 551 552 public void testCookieStoreRemoveAll() throws URISyntaxException { 553 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 554 cookieStore.add(new URI("http://code.google.com/"), new HttpCookie("a", "android")); 555 assertTrue(cookieStore.removeAll()); 556 assertEquals(Collections.<URI>emptyList(), cookieStore.getURIs()); 557 assertEquals(Collections.<HttpCookie>emptyList(), cookieStore.getCookies()); 558 assertFalse("Expected removeAll() to return false when the call doesn't mutate the store", 559 cookieStore.removeAll()); // RI6 fails this 560 } 561 562 public void testCookieStoreAddAcceptsConflictingUri() throws URISyntaxException { 563 CookieStore cookieStore = new CookieManager().getCookieStore(); 564 HttpCookie cookieA = createCookie("a", "android", ".android.com", "/source/"); 565 cookieStore.add(new URI("http://google.com/source/"), cookieA); 566 assertEquals(Arrays.asList(cookieA), cookieStore.getCookies()); 567 } 568 569 public void testCookieStoreRemoveRequiresUri() throws URISyntaxException { 570 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 571 HttpCookie cookieA = new HttpCookie("a", "android"); 572 cookieStore.add(new URI("http://android.com/source/"), cookieA); 573 assertFalse("Expected remove() to take the cookie URI into account.", // RI6 fails this 574 cookieStore.remove(new URI("http://code.google.com/"), cookieA)); 575 assertEquals(Arrays.asList(cookieA), cookieStore.getCookies()); 576 } 577 578 public void testCookieStoreUriUsesHttpSchemeAlways() throws URISyntaxException { 579 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 580 cookieStore.add(new URI("https://a.com/"), new HttpCookie("a", "android")); 581 assertEquals(Arrays.asList(new URI("http://a.com")), cookieStore.getURIs()); 582 } 583 584 public void testCookieStoreUriDropsUserInfo() throws URISyntaxException { 585 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 586 cookieStore.add(new URI("http://jesse:secret@a.com/"), new HttpCookie("a", "android")); 587 assertEquals(Arrays.asList(new URI("http://a.com")), cookieStore.getURIs()); 588 } 589 590 public void testCookieStoreUriKeepsHost() throws URISyntaxException { 591 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 592 cookieStore.add(new URI("http://b.com/"), new HttpCookie("a", "android")); 593 assertEquals(Arrays.asList(new URI("http://b.com")), cookieStore.getURIs()); 594 } 595 596 public void testCookieStoreUriDropsPort() throws URISyntaxException { 597 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 598 cookieStore.add(new URI("http://a.com:443/"), new HttpCookie("a", "android")); 599 assertEquals(Arrays.asList(new URI("http://a.com")), cookieStore.getURIs()); 600 } 601 602 public void testCookieStoreUriDropsPath() throws URISyntaxException { 603 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 604 cookieStore.add(new URI("http://a.com/a/"), new HttpCookie("a", "android")); 605 assertEquals(Arrays.asList(new URI("http://a.com")), cookieStore.getURIs()); 606 } 607 608 public void testCookieStoreUriDropsFragment() throws URISyntaxException { 609 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 610 cookieStore.add(new URI("http://a.com/a/foo#fragment"), new HttpCookie("a", "android")); 611 assertEquals(Arrays.asList(new URI("http://a.com")), cookieStore.getURIs()); 612 } 613 614 public void testCookieStoreUriDropsQuery() throws URISyntaxException { 615 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 616 cookieStore.add(new URI("http://a.com/a/foo?query=value"), new HttpCookie("a", "android")); 617 assertEquals(Arrays.asList(new URI("http://a.com")), cookieStore.getURIs()); 618 } 619 620 public void testCookieStoreGet() throws Exception { 621 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 622 HttpCookie cookiePort1 = createCookie("a1", "android", "a.com", "/path1"); 623 HttpCookie cookiePort2 = createCookie("a2", "android", "a.com", "/path2"); 624 HttpCookie secureCookie = createCookie("a3", "android", "a.com", "/path3"); 625 secureCookie.setSecure(true); 626 HttpCookie notSecureCookie = createCookie("a4", "android", "a.com", "/path4"); 627 628 HttpCookie bCookie = createCookie("b1", "android", "b.com", "/path5"); 629 630 cookieStore.add(new URI("http://a.com:443/path1"), cookiePort1); 631 cookieStore.add(new URI("http://a.com:8080/path2"), cookiePort2); 632 cookieStore.add(new URI("https://a.com:443/path3"), secureCookie); 633 cookieStore.add(new URI("https://a.com:443/path4"), notSecureCookie); 634 cookieStore.add(new URI("https://b.com:8080/path5"), bCookie); 635 636 List<HttpCookie> expectedStoreCookies = new ArrayList<>(); 637 expectedStoreCookies.add(cookiePort1); 638 expectedStoreCookies.add(cookiePort2); 639 expectedStoreCookies.add(secureCookie); 640 expectedStoreCookies.add(notSecureCookie); 641 642 // The default CookieStore implementation on Android is currently responsible for matching 643 // the host/domain but not handling other cookie rules: it ignores the scheme (e.g. "secure" 644 // checks), port and path. 645 // The tests below fail on the RI. It looks like in the RI it is CookieStoreImpl that is 646 // enforcing "secure" checks. 647 assertEquals(expectedStoreCookies, cookieStore.get(new URI("http://a.com:443/anypath"))); 648 assertEquals(expectedStoreCookies, cookieStore.get(new URI("http://a.com:8080/anypath"))); 649 assertEquals(expectedStoreCookies, cookieStore.get(new URI("https://a.com/anypath"))); 650 assertEquals(expectedStoreCookies, cookieStore.get(new URI("http://a.com/anypath"))); 651 } 652 653 /** 654 * Regression test for http://b/25682357 / 655 * https://code.google.com/p/android/issues/detail?id=193475 656 * CookieStoreImpl.get(URI) not handling ports properly in the absence of an explicit cookie 657 * Domain. 658 */ 659 public void testCookieStoreGetWithPort() throws Exception { 660 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 661 HttpCookie cookie = new HttpCookie("theme", "light"); 662 // Deliberately not setting the cookie domain or path. 663 cookieStore.add(new URI("http://a.com:12345"), cookie); 664 665 // CookieStoreImpl must ignore the port during retrieval when domain is not set. 666 assertEquals(1, cookieStore.get(new URI("http://a.com:12345/path1")).size()); 667 assertEquals(1, cookieStore.get(new URI("http://a.com/path1")).size()); 668 } 669 670 public void testCookieStoreGetWithSecure() throws Exception { 671 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 672 HttpCookie cookie = createCookie("theme", "light", "a.com", "/path"); 673 cookie.setSecure(true); 674 cookieStore.add(new URI("https://a.com/path"), cookie); 675 676 // CookieStoreImpl on Android ignores the "Secure" attribute. The RI implements the secure 677 // check in CookieStoreImpl. For safety / app compatibility, if this is changed Android 678 // should probably implement it in both places. 679 assertEquals(1, cookieStore.get(new URI("http://a.com/path")).size()); 680 assertEquals(1, cookieStore.get(new URI("https://a.com/path")).size()); 681 } 682 683 public void testCookieStoreEviction() throws Exception { 684 CookieStore cookieStore = new CookieManager(createCookieStore(), null).getCookieStore(); 685 HttpCookie themeCookie = createCookie("theme", "light", "a.com", "/"); 686 cookieStore.add(new URI("http://a.com/"), themeCookie); 687 688 HttpCookie sidCookie = createCookie("sid", "mysid", "a.com", "/"); 689 cookieStore.add(new URI("http://a.com/"), sidCookie); 690 691 HttpCookie replacementThemeCookie = createCookie("theme", "dark", "a.com", "/"); 692 cookieStore.add(new URI("http://a.com/"), replacementThemeCookie); 693 694 // toString() is used below to avoid confusion with assertEquals(): 695 // HttpCookie.equals() is implemented so that it only checks name, path and domain 696 // attributes but we also want to check the value. 697 assertEquals( 698 "[sid=\"mysid\";$Path=\"/\";$Domain=\"a.com\", " 699 + "theme=\"dark\";$Path=\"/\";$Domain=\"a.com\"]", 700 cookieStore.get(new URI("http://a.com/")).toString()); 701 702 HttpCookie replacementSidCookie = createCookie("sid", "mynewsid", "A.cOm", "/"); 703 cookieStore.add(new URI("http://a.com/"), replacementSidCookie); 704 705 assertEquals( 706 "[theme=\"dark\";$Path=\"/\";$Domain=\"a.com\", " 707 + "sid=\"mynewsid\";$Path=\"/\";$Domain=\"a.com\"]", 708 cookieStore.get(new URI("http://a.com/")).toString()); 709 } 710 711 /** 712 * CookieStoreImpl has a strict requirement on HttpCookie.equals() to enable replacement of 713 * cookies with the same name. 714 */ 715 public void testCookieEquality() throws Exception { 716 HttpCookie baseCookie = createCookie("theme", "light", "a.com", "/"); 717 718 // None of the attributes immediately below should affect equality otherwise CookieStoreImpl 719 // eviction will not work as intended. 720 HttpCookie valueCookie = createCookie("theme", "light", "a.com", "/"); 721 valueCookie.setValue("dark"); 722 valueCookie.setPortlist("1234"); 723 valueCookie.setSecure(true); 724 valueCookie.setComment("comment"); 725 valueCookie.setCommentURL("commentURL"); 726 valueCookie.setDiscard(true); 727 valueCookie.setMaxAge(12345L); 728 valueCookie.setVersion(1); 729 assertEquals(baseCookie, valueCookie); 730 731 // Changing any of the 3 main identity attributes should render cookies unequal. 732 assertNotEquals(createCookie("theme2", "light", "a.com", "/"), baseCookie); 733 assertNotEquals(createCookie("theme", "light", "b.com", "/"), baseCookie); 734 assertNotEquals(createCookie("theme", "light", "a.com", "/path"), baseCookie); 735 } 736 737 private static void assertNotEquals(HttpCookie one, HttpCookie two) { 738 assertFalse(one.equals(two)); 739 assertFalse(two.equals(one)); 740 } 741 742 private void assertContains(Collection<String> collection, String element) { 743 for (String c : collection) { 744 if (c != null && c.equalsIgnoreCase(element)) { 745 return; 746 } 747 } 748 fail("No " + element + " in " + collection); 749 } 750 751 private void assertContainsAll(Collection<String> collection, String... toFind) { 752 for (String s : toFind) { 753 assertContains(collection, s); 754 } 755 } 756 757 private List<HttpCookie> sortedCopy(List<HttpCookie> cookies) { 758 List<HttpCookie> result = new ArrayList<HttpCookie>(cookies); 759 Collections.sort(result, new Comparator<HttpCookie>() { 760 public int compare(HttpCookie a, HttpCookie b) { 761 return a.getName().compareTo(b.getName()); 762 } 763 }); 764 return result; 765 } 766 767 private Map<String,List<String>> get(MockWebServer server, String path) throws Exception { 768 URLConnection connection = server.getUrl(path).openConnection(); 769 Map<String, List<String>> headers = connection.getHeaderFields(); 770 connection.getInputStream().close(); 771 return headers; 772 } 773 774 private static Map<String, List<String>> cookieHeaders(String... headers) { 775 return Collections.singletonMap("Set-Cookie", Arrays.asList(headers)); 776 } 777 778 static class TestCookieStore implements CookieStore { 779 private final List<HttpCookie> cookies = new ArrayList<HttpCookie>(); 780 781 public void add(URI uri, HttpCookie cookie) { 782 cookies.add(cookie); 783 } 784 785 public HttpCookie getCookie(String name) { 786 for (HttpCookie cookie : cookies) { 787 if (cookie.getName().equals(name)) { 788 return cookie; 789 } 790 } 791 throw new IllegalArgumentException("No cookie " + name + " in " + cookies); 792 } 793 794 public List<HttpCookie> get(URI uri) { 795 throw new UnsupportedOperationException(); 796 } 797 798 public List<HttpCookie> getCookies() { 799 throw new UnsupportedOperationException(); 800 } 801 802 public List<URI> getURIs() { 803 throw new UnsupportedOperationException(); 804 } 805 806 public boolean remove(URI uri, HttpCookie cookie) { 807 throw new UnsupportedOperationException(); 808 } 809 810 public boolean removeAll() { 811 throw new UnsupportedOperationException(); 812 } 813 } 814 815 private static void assertManagerCookiesMatch(CookieManager cookieManager, String url, 816 String expectedCookieRequestHeader) throws Exception { 817 818 Map<String, List<String>> cookieHeaders = 819 cookieManager.get(new URI(url), EMPTY_COOKIES_MAP); 820 if (expectedCookieRequestHeader == null) { 821 assertTrue(cookieHeaders.isEmpty()); 822 return; 823 } 824 825 assertEquals(1, cookieHeaders.size()); 826 List<String> actualCookieHeaderStrings = cookieHeaders.get("Cookie"); 827 828 // For simplicity, we concatenate the cookie header strings if there are multiple ones. 829 String actualCookieRequestHeader = actualCookieHeaderStrings.get(0); 830 for (int i = 1; i < actualCookieHeaderStrings.size(); i++) { 831 actualCookieRequestHeader += "; " + actualCookieHeaderStrings.get(i); 832 } 833 assertEquals(expectedCookieRequestHeader, actualCookieRequestHeader); 834 } 835 836 /** 837 * Creates a well-formed cookie. The behavior when domain is unset varies between 838 * RFC 2965 and RFC 6265. CookieStoreImpl assumes these values are set "correctly" by the time 839 * it receives the HttpCookie instance. 840 */ 841 private static HttpCookie createCookie(String name, String value, String domain, String path) { 842 HttpCookie cookie = new HttpCookie(name, value); 843 cookie.setDomain(domain); 844 cookie.setPath(path); 845 return cookie; 846 } 847 848 // 849 // Start of org.apache.harmony.tests.java.net.CookieManagerTest. 850 // 851 852 /** 853 * java.net.CookieStore#add(URI, HttpCookie) 854 * @since 1.6 855 */ 856 public void test_add_LURI_LHttpCookie() throws URISyntaxException { 857 URI uri = new URI("http://harmony.test.unit.org"); 858 HttpCookie cookie = new HttpCookie("name1", "value1"); 859 cookie.setDiscard(true); 860 861 // This needn't throw. We should use the cookie's domain, if set. 862 // If no domain is set, this cookie will languish in the store until 863 // it expires. 864 cookieStore.add(null, cookie); 865 866 try { 867 cookieStore.add(uri, null); 868 fail("should throw NullPointerException"); 869 } catch (NullPointerException e) { 870 // expected 871 } 872 873 try { 874 cookieStore.add(null, null); 875 fail("should throw NullPointerException"); 876 } catch (NullPointerException e) { 877 // expected 878 } 879 880 cookieStore.add(uri, cookie); 881 List<HttpCookie> list = cookieStore.get(uri); 882 assertEquals(1, list.size()); 883 assertTrue(list.contains(cookie)); 884 885 HttpCookie cookie2 = new HttpCookie(" NaME1 ", " TESTVALUE1 "); 886 cookieStore.add(uri, cookie2); 887 list = cookieStore.get(uri); 888 assertEquals(1, list.size()); 889 assertEquals(" TESTVALUE1 ", list.get(0).getValue()); 890 assertTrue(list.contains(cookie2)); 891 892 // domain and path attributes works 893 HttpCookie anotherCookie = new HttpCookie("name1", "value1"); 894 anotherCookie.setDomain("domain"); 895 anotherCookie.setPath("Path"); 896 cookieStore.add(uri, anotherCookie); 897 list = cookieStore.get(uri); 898 assertEquals(2, list.size()); 899 assertNull(list.get(0).getDomain()); 900 assertEquals("domain", list.get(1).getDomain()); 901 assertEquals("Path", list.get(1).getPath()); 902 903 URI uri2 = new URI("http://.test.unit.org"); 904 HttpCookie cookie3 = new HttpCookie("NaME2", "VALUE2"); 905 cookieStore.add(uri2, cookie3); 906 list = cookieStore.get(uri2); 907 assertEquals(1, list.size()); 908 assertEquals("VALUE2", list.get(0).getValue()); 909 list = cookieStore.getCookies(); 910 assertEquals(3, list.size()); 911 912 // expired cookie won't be selected. 913 HttpCookie cookie4 = new HttpCookie("cookie4", "value4"); 914 cookie4.setMaxAge(-2); 915 assertTrue(cookie4.hasExpired()); 916 cookieStore.add(uri2, cookie4); 917 list = cookieStore.getCookies(); 918 assertEquals(3, list.size()); 919 assertFalse(cookieStore.remove(uri2, cookie4)); 920 921 cookie4.setMaxAge(3000); 922 cookie4.setDomain("domain"); 923 cookie4.setPath("path"); 924 cookieStore.add(uri2, cookie4); 925 list = cookieStore.get(uri2); 926 assertEquals(2, list.size()); 927 928 cookieStore.add(uri, cookie4); 929 list = cookieStore.get(uri); 930 assertEquals(3, list.size()); 931 list = cookieStore.get(uri2); 932 assertEquals(2, list.size()); 933 list = cookieStore.getCookies(); 934 assertEquals(4, list.size()); 935 936 URI baduri = new URI("bad_url"); 937 HttpCookie cookie6 = new HttpCookie("cookie5", "value5"); 938 cookieStore.add(baduri, cookie6); 939 list = cookieStore.get(baduri); 940 assertTrue(list.contains(cookie6)); 941 } 942 943 /** 944 * java.net.CookieStore#get(URI) 945 * @since 1.6 946 */ 947 public void test_get_LURI() throws URISyntaxException { 948 try { 949 cookieStore.get(null); 950 fail("should throw NullPointerException"); 951 } catch (NullPointerException e) { 952 // expected 953 } 954 955 URI uri1 = new URI("http://get.uri1.test.org"); 956 List<HttpCookie> list = cookieStore.get(uri1); 957 assertTrue(list.isEmpty()); 958 959 HttpCookie cookie1 = new HttpCookie("cookie_name1", "cookie_value1"); 960 HttpCookie cookie2 = new HttpCookie("cookie_name2", "cookie_value2"); 961 cookieStore.add(uri1, cookie1); 962 cookieStore.add(uri1, cookie2); 963 URI uri2 = new URI("http://get.uri2.test.org"); 964 HttpCookie cookie3 = new HttpCookie("cookie_name3", "cookie_value3"); 965 cookieStore.add(uri2, cookie3); 966 list = cookieStore.get(uri1); 967 assertEquals(2, list.size()); 968 list = cookieStore.get(uri2); 969 assertEquals(1, list.size()); 970 971 // domain-match cookies also be selected. 972 HttpCookie cookie4 = new HttpCookie("cookie_name4", "cookie_value4"); 973 cookie4.setDomain(".uri1.test.org"); 974 cookieStore.add(uri2, cookie4); 975 list = cookieStore.get(uri1); 976 assertEquals(3, list.size()); 977 978 cookieStore.add(uri1, cookie4); 979 list = cookieStore.get(uri1); 980 assertEquals(3, list.size()); 981 list = cookieStore.get(uri2); 982 assertEquals(2, list.size()); 983 984 // expired cookie won't be selected. 985 HttpCookie cookie5 = new HttpCookie("cookie_name5", "cookie_value5"); 986 cookie5.setMaxAge(-333); 987 assertTrue(cookie5.hasExpired()); 988 cookieStore.add(uri1, cookie5); 989 list = cookieStore.get(uri1); 990 assertEquals(3, list.size()); 991 assertFalse(cookieStore.remove(uri1, cookie5)); 992 list = cookieStore.getCookies(); 993 assertEquals(4, list.size()); 994 995 cookie4.setMaxAge(-123); 996 list = cookieStore.get(uri1); 997 assertEquals(2, list.size()); 998 list = cookieStore.getCookies(); 999 assertEquals(3, list.size()); 1000 // expired cookies are also deleted even if it domain-matches the URI 1001 HttpCookie cookie6 = new HttpCookie("cookie_name6", "cookie_value6"); 1002 cookie6.setMaxAge(-2); 1003 cookie6.setDomain(".uri1.test.org"); 1004 cookieStore.add(uri2, cookie6); 1005 list = cookieStore.get(uri1); 1006 assertEquals(2, list.size()); 1007 assertFalse(cookieStore.remove(null, cookie6)); 1008 1009 URI uri3 = new URI("http://get.uri3.test.org"); 1010 assertTrue(cookieStore.get(uri3).isEmpty()); 1011 URI baduri = new URI("invalid_uri"); 1012 assertTrue(cookieStore.get(baduri).isEmpty()); 1013 } 1014 1015 /** 1016 * java.net.CookieStore#getCookies() 1017 * @since 1.6 1018 */ 1019 public void test_getCookies() throws URISyntaxException { 1020 List<HttpCookie> list = cookieStore.getCookies(); 1021 assertTrue(list.isEmpty()); 1022 assertTrue(list instanceof RandomAccess); 1023 1024 HttpCookie cookie1 = new HttpCookie("cookie_name", "cookie_value"); 1025 URI uri1 = new URI("http://getcookies1.test.org"); 1026 cookieStore.add(uri1, cookie1); 1027 list = cookieStore.getCookies(); 1028 assertTrue(list.contains(cookie1)); 1029 1030 HttpCookie cookie2 = new HttpCookie("cookie_name2", "cookie_value2"); 1031 URI uri2 = new URI("http://getcookies2.test.org"); 1032 cookieStore.add(uri2, cookie2); 1033 list = cookieStore.getCookies(); 1034 assertEquals(2, list.size()); 1035 assertTrue(list.contains(cookie1)); 1036 assertTrue(list.contains(cookie2)); 1037 1038 // duplicated cookie won't be selected. 1039 cookieStore.add(uri2, cookie1); 1040 list = cookieStore.getCookies(); 1041 assertEquals(2, list.size()); 1042 // expired cookie won't be selected. 1043 HttpCookie cookie3 = new HttpCookie("cookie_name3", "cookie_value3"); 1044 cookie3.setMaxAge(-1357); 1045 cookieStore.add(uri1, cookie3); 1046 list = cookieStore.getCookies(); 1047 assertEquals(2, list.size()); 1048 1049 try { 1050 list.add(new HttpCookie("readOnlyName", "readOnlyValue")); 1051 fail("should throw UnsupportedOperationException"); 1052 } catch (UnsupportedOperationException e) { 1053 // expected 1054 } 1055 1056 try { 1057 list.remove(new HttpCookie("readOnlyName", "readOnlyValue")); 1058 fail("should throw UnsupportedOperationException"); 1059 } catch (UnsupportedOperationException e) { 1060 // expected 1061 } 1062 } 1063 1064 /** 1065 * java.net.CookieStore#getURIs() 1066 * @since 1.6 1067 */ 1068 public void test_getURIs() throws URISyntaxException { 1069 List<URI> list = cookieStore.getURIs(); 1070 assertTrue(list.isEmpty()); 1071 1072 URI uri1 = new URI("http://geturis1.test.com"); 1073 HttpCookie cookie1 = new HttpCookie("cookie_name1", "cookie_value1"); 1074 cookieStore.add(uri1, cookie1); 1075 list = cookieStore.getURIs(); 1076 assertEquals("geturis1.test.com", list.get(0).getHost()); 1077 1078 HttpCookie cookie2 = new HttpCookie("cookie_name2", "cookie_value2"); 1079 cookieStore.add(uri1, cookie2); 1080 list = cookieStore.getURIs(); 1081 assertEquals(1, list.size()); 1082 1083 URI uri2 = new URI("http://geturis2.test.com"); 1084 cookieStore.add(uri2, cookie2); 1085 list = cookieStore.getURIs(); 1086 assertEquals(2, list.size()); 1087 assertTrue(list.contains(uri1)); 1088 assertTrue(list.contains(uri2)); 1089 } 1090 1091 /** 1092 * java.net.CookieStore#remove(URI, HttpCookie) 1093 * @since 1.6 1094 */ 1095 public void test_remove_LURI_LHttpCookie() throws URISyntaxException { 1096 URI uri1 = new URI("http://remove1.test.com"); 1097 HttpCookie cookie1 = new HttpCookie("cookie_name1", "cookie_value1"); 1098 try { 1099 cookieStore.remove(uri1, null); 1100 fail("should throw NullPointerException"); 1101 } catch (NullPointerException e) { 1102 // expected 1103 } 1104 assertFalse(cookieStore.remove(uri1, cookie1)); 1105 assertFalse(cookieStore.remove(null, cookie1)); 1106 1107 cookieStore.add(uri1, cookie1); 1108 URI uri2 = new URI("http://remove2.test.com"); 1109 HttpCookie cookie2 = new HttpCookie("cookie_name2", "cookie_value2"); 1110 cookieStore.add(uri2, cookie2); 1111 assertTrue(cookieStore.remove(uri1, cookie1)); 1112 assertFalse(cookieStore.remove(uri1, cookie1)); 1113 assertEquals(2, cookieStore.getURIs().size()); 1114 assertEquals(1, cookieStore.getCookies().size()); 1115 assertTrue(cookieStore.remove(uri2, cookie2)); 1116 assertFalse(cookieStore.remove(uri2, cookie2)); 1117 assertEquals(2, cookieStore.getURIs().size()); 1118 assertEquals(0, cookieStore.getCookies().size()); 1119 1120 assertTrue(cookieStore.removeAll()); 1121 cookieStore.add(uri1, cookie1); 1122 cookieStore.add(uri2, cookie2); 1123 HttpCookie cookie3 = new HttpCookie("cookie_name3", "cookie_value3"); 1124 assertFalse(cookieStore.remove(null, cookie3)); 1125 // No guarantees on behavior if we call remove with a different 1126 // uri from the one originally associated with the cookie. 1127 assertFalse(cookieStore.remove(null, cookie1)); 1128 assertTrue(cookieStore.remove(uri1, cookie1)); 1129 assertFalse(cookieStore.remove(uri1, cookie1)); 1130 1131 assertEquals(2, cookieStore.getURIs().size()); 1132 assertEquals(1, cookieStore.getCookies().size()); 1133 assertTrue(cookieStore.remove(uri2, cookie2)); 1134 assertFalse(cookieStore.remove(uri2, cookie2)); 1135 assertEquals(2, cookieStore.getURIs().size()); 1136 assertEquals(0, cookieStore.getCookies().size()); 1137 1138 cookieStore.removeAll(); 1139 // expired cookies can also be deleted. 1140 cookie2.setMaxAge(-34857); 1141 cookieStore.add(uri2, cookie2); 1142 assertTrue(cookieStore.remove(uri2, cookie2)); 1143 assertFalse(cookieStore.remove(uri2, cookie2)); 1144 assertEquals(0, cookieStore.getCookies().size()); 1145 1146 cookie2.setMaxAge(34857); 1147 cookieStore.add(uri1, cookie1); 1148 cookieStore.add(uri2, cookie1); 1149 cookieStore.add(uri2, cookie2); 1150 assertTrue(cookieStore.remove(uri1, cookie1)); 1151 assertFalse(cookieStore.remove(uri1, cookie1)); 1152 assertTrue(cookieStore.get(uri2).contains(cookie1)); 1153 assertTrue(cookieStore.get(uri2).contains(cookie2)); 1154 assertEquals(0, cookieStore.get(uri1).size()); 1155 cookieStore.remove(uri2, cookie2); 1156 1157 cookieStore.removeAll(); 1158 cookieStore.add(uri2, cookie2); 1159 cookieStore.add(uri1, cookie1); 1160 assertEquals(2, cookieStore.getCookies().size()); 1161 assertFalse(cookieStore.remove(uri2, cookie1)); 1162 assertTrue(cookieStore.remove(uri1, cookie1)); 1163 assertEquals(2, cookieStore.getURIs().size()); 1164 assertEquals(1, cookieStore.getCookies().size()); 1165 assertTrue(cookieStore.getCookies().contains(cookie2)); 1166 1167 cookieStore.removeAll(); 1168 URI uri3 = new URI("http://remove3.test.com"); 1169 URI uri4 = new URI("http://test.com"); 1170 HttpCookie cookie4 = new HttpCookie("cookie_name4", "cookie_value4"); 1171 cookie4.setDomain(".test.com"); 1172 cookie2.setMaxAge(-34857); 1173 cookie3.setMaxAge(-22); 1174 cookie4.setMaxAge(-45); 1175 cookieStore.add(uri1, cookie1); 1176 cookieStore.add(uri2, cookie2); 1177 cookieStore.add(uri3, cookie3); 1178 cookieStore.add(uri4, cookie4); 1179 assertEquals(0, cookieStore.get(uri2).size()); 1180 assertFalse(cookieStore.remove(uri2, cookie2)); 1181 assertTrue(cookieStore.remove(uri3, cookie3)); 1182 assertFalse(cookieStore.remove(uri4, cookie4)); 1183 } 1184 1185 /** 1186 * java.net.CookieStore#test_removeAll() 1187 * @since 1.6 1188 */ 1189 public void test_removeAll() throws URISyntaxException { 1190 assertFalse(cookieStore.removeAll()); 1191 1192 URI uri1 = new URI("http://removeAll1.test.com"); 1193 HttpCookie cookie1 = new HttpCookie("cookie_name1", "cookie_value1"); 1194 cookieStore.add(uri1, cookie1); 1195 URI uri2 = new URI("http://removeAll2.test.com"); 1196 HttpCookie cookie2 = new HttpCookie("cookie_name2", "cookie_value2"); 1197 cookieStore.add(uri2, cookie2); 1198 1199 assertTrue(cookieStore.removeAll()); 1200 assertTrue(cookieStore.getURIs().isEmpty()); 1201 assertTrue(cookieStore.getCookies().isEmpty()); 1202 1203 assertFalse(cookieStore.removeAll()); 1204 } 1205 1206 // 1207 // Start of org.apache.harmony.tests.java.net.CookieStoreTest. 1208 // 1209 1210 private void checkValidParams4Get(URI uri, 1211 Map<String, List<String>> map) throws IOException { 1212 CookieManager manager = new CookieManager(createCookieStore(), null); 1213 try { 1214 manager.get(uri, map); 1215 fail("Should throw IllegalArgumentException"); 1216 } catch (IllegalArgumentException e) { 1217 // expected 1218 } 1219 1220 } 1221 1222 private void checkValidParams4Put(URI uri, 1223 Map<String, List<String>> map) throws IOException { 1224 CookieManager manager = new CookieManager(createCookieStore(), null); 1225 try { 1226 manager.put(uri, map); 1227 fail("Should throw IllegalArgumentException"); 1228 } catch (IllegalArgumentException e) { 1229 // expected 1230 } 1231 1232 } 1233 1234 /** 1235 * {@link java.net.CookieManager#get(java.net.URI, java.util.Map)} & 1236 * {@link java.net.CookieManager#put(java.net.URI, java.util.Map)} 1237 * IllegalArgumentException 1238 * @since 1.6 1239 */ 1240 public void test_Put_Get_LURI_LMap_exception() throws IOException, 1241 URISyntaxException { 1242 // get 1243 checkValidParams4Get(new URI(""), null); 1244 checkValidParams4Get(new URI("http://www.test.com"), null); 1245 checkValidParams4Get(null, null); 1246 checkValidParams4Get(null, new HashMap<String, List<String>>()); 1247 1248 // put 1249 checkValidParams4Put(new URI(""), null); 1250 checkValidParams4Put(new URI("http://www.test.com"), null); 1251 checkValidParams4Put(null, null); 1252 checkValidParams4Put(null, new HashMap<String, List<String>>()); 1253 } 1254 1255 private static Map<String, List<String>> addCookie(String[][] cookies) { 1256 Map<String, List<String>> responseHeaders = new LinkedHashMap<String, List<String>>(); 1257 for (int i = 0; i < cookies.length; i++) { 1258 List<String> fields = new ArrayList<String>(); 1259 for (int j = 1; j < cookies[i].length; j += 2) { 1260 fields.add(cookies[i][j]); 1261 } 1262 responseHeaders.put(cookies[i][0], fields); 1263 } 1264 return responseHeaders; 1265 } 1266 1267 private CookieManager store(String[][] cookies, 1268 Map<String, List<String>> responseHeaders, CookiePolicy policy) 1269 throws IOException, URISyntaxException { 1270 CookieManager manager = new CookieManager(createCookieStore(), policy); 1271 // Put all cookies into manager 1272 for (int i = 0; i < cookies.length; i++) { 1273 for (int j = 2; j < cookies[i].length; j += 2) { 1274 URI uri = new URI(cookies[i][j]); 1275 manager.put(uri, responseHeaders); 1276 } 1277 } 1278 return manager; 1279 } 1280 1281 /** 1282 * Unlike the RI, we flatten all matching cookies into a single Cookie header 1283 * instead of sending down multiple cookie headers. Also, when no cookies match 1284 * a given URI, we leave the requestHeaders unmodified. 1285 * 1286 * @since 1.6 1287 */ 1288 public void test_Put_Get_LURI_LMap() throws IOException, URISyntaxException { 1289 // cookie-key | (content, URI)... 1290 String[][] cookies = { 1291 { "Set-cookie", 1292 "Set-cookie:PREF=test;path=/;domain=.b.c;", "http://a.b.c/", 1293 "Set-cookie:PREF1=test2;path=/;domain=.beg.com;", "http://a.b.c/" }, 1294 1295 { "Set-cookie2", 1296 "Set-cookie2:NAME1=VALUE1;path=/te;domain=.b.c;", "http://a.b.c/test" }, 1297 1298 { "Set-cookie", 1299 "Set-cookie2:NAME=VALUE;path=/;domain=.beg.com;", "http://a.beg.com/test", 1300 "Set-cookie2:NAME1=VALUE1;path=/;domain=.beg.com;", "http://a.beg.com/test" }, 1301 1302 { "Set-cookie2", 1303 "Set-cookie3:NAME=VALUE;path=/;domain=.test.org;", "http://a.test.org/test" }, 1304 1305 { null, 1306 "Set-cookie3:NAME=VALUE;path=/te;domain=.test.org;", "http://a.test.org/test" }, 1307 1308 { "Set-cookie2", 1309 "lala", "http://a.test.org/test" } 1310 1311 }; 1312 1313 // requires path of cookie is the prefix of uri 1314 // domain of cookie must match that of uri 1315 Map<String, List<String>> responseHeaders = addCookie(new String[][] { 1316 cookies[0], cookies[1] }); 1317 CookieManager manager = store( 1318 new String[][] { cookies[0], cookies[1] }, responseHeaders, 1319 null); 1320 1321 HashMap<String, List<String>> dummyMap = new HashMap<String, List<String>>(); 1322 Map<String, List<String>> map = manager.get(new URI("http://a.b.c/"), 1323 dummyMap); 1324 1325 assertEquals(1, map.size()); 1326 List<String> list = map.get("Cookie"); 1327 assertEquals(1, list.size()); 1328 1329 // requires path of cookie is the prefix of uri 1330 map = manager.get(new URI("http://a.b.c/te"), dummyMap); 1331 list = map.get("Cookie"); 1332 assertEquals(1, list.size()); 1333 assertTrue(list.get(0).contains("PREF=test")); 1334 // Cookies from "/test" should *not* match the URI "/te". 1335 assertFalse(list.get(0).contains("NAME=VALUE")); 1336 1337 // If all cookies are of version 1, then $version=1 will be added 1338 // ,no matter the value cookie-key 1339 responseHeaders = addCookie(new String[][] { cookies[2] }); 1340 manager = store(new String[][] { cookies[2] }, responseHeaders, null); 1341 map = manager.get(new URI("http://a.beg.com/test"), dummyMap); 1342 list = map.get("Cookie"); 1343 assertEquals(1, list.size()); 1344 assertTrue(list.get(0).startsWith("$Version=\"1\"")); 1345 1346 // cookie-key will not have effect on determining cookie version 1347 responseHeaders = addCookie(new String[][] { cookies[3] }); 1348 manager = store(new String[][] { cookies[3] }, responseHeaders, null); 1349 map = manager.get(new URI("http://a.test.org/"), responseHeaders); 1350 list = map.get("Cookie"); 1351 assertEquals(1, list.size()); 1352 assertEquals("Set-cookie3:NAME=VALUE", list.get(0)); 1353 1354 // When key is null, no cookie can be stored/retrieved, even if policy = 1355 // ACCEPT_ALL 1356 responseHeaders = addCookie(new String[][] { cookies[4] }); 1357 manager = store(new String[][] { cookies[4] }, responseHeaders, 1358 CookiePolicy.ACCEPT_ALL); 1359 map = manager.get(new URI("http://a.test.org/"), responseHeaders); 1360 list = map.get("Cookie"); 1361 assertNull(list); 1362 1363 // All cookies will be rejected if policy == ACCEPT_NONE 1364 responseHeaders = addCookie(new String[][] { cookies[3] }); 1365 manager = store(new String[][] { cookies[3] }, responseHeaders, 1366 CookiePolicy.ACCEPT_NONE); 1367 map = manager.get(new URI("http://a.test.org/"), responseHeaders); 1368 list = map.get("Cookie"); 1369 assertNull(list); 1370 1371 responseHeaders = addCookie(new String[][] { cookies[5] }); 1372 manager = store(new String[][] { cookies[5] }, responseHeaders, 1373 CookiePolicy.ACCEPT_ALL); 1374 list = map.get("Cookie"); 1375 assertNull(list); 1376 1377 try { 1378 map.put(null, null); 1379 fail("Should throw UnsupportedOperationException"); 1380 } catch (UnsupportedOperationException e) { 1381 // expected 1382 } 1383 1384 } 1385 1386 /** 1387 * {@link java.net.CookieManager#CookieManager()} 1388 * @since 1.6 1389 */ 1390 public void test_CookieManager() { 1391 CookieManager cookieManager = new CookieManager(); 1392 assertNotNull(cookieManager); 1393 assertNotNull(cookieManager.getCookieStore()); 1394 } 1395 1396 /** 1397 * {@link java.net.CookieManager#CookieManager(java.net.CookieStore, java.net.CookiePolicy)} 1398 * @since 1.6 1399 */ 1400 public void testCookieManager_LCookieStore_LCookiePolicy() { 1401 class DummyStore implements CookieStore { 1402 public String getName() { 1403 return "A dummy store"; 1404 } 1405 1406 public void add(URI uri, HttpCookie cookie) { 1407 // expected 1408 } 1409 1410 public List<HttpCookie> get(URI uri) { 1411 return null; 1412 } 1413 1414 public List<HttpCookie> getCookies() { 1415 return null; 1416 } 1417 1418 public List<URI> getURIs() { 1419 return null; 1420 } 1421 1422 public boolean remove(URI uri, HttpCookie cookie) { 1423 return false; 1424 } 1425 1426 public boolean removeAll() { 1427 return false; 1428 } 1429 } 1430 CookieStore store = new DummyStore(); 1431 CookieManager cookieManager = new CookieManager(store, 1432 CookiePolicy.ACCEPT_ALL); 1433 assertEquals("A dummy store", ((DummyStore) cookieManager 1434 .getCookieStore()).getName()); 1435 assertSame(store, cookieManager.getCookieStore()); 1436 } 1437 1438 /** 1439 * {@link java.net.CookieManager#setCookiePolicy(java.net.CookiePolicy)} 1440 * @since 1.6 1441 */ 1442 public void test_SetCookiePolicy_LCookiePolicy() throws URISyntaxException, 1443 IOException { 1444 1445 // Policy = ACCEPT_NONE 1446 CookieManager manager = new CookieManager(createCookieStore(), null); 1447 manager.setCookiePolicy(CookiePolicy.ACCEPT_NONE); 1448 Map<String, List<String>> responseHeaders = new TreeMap<String, List<String>>(); 1449 URI uri = new URI("http://a.b.c"); 1450 manager.put(uri, responseHeaders); 1451 Map<String, List<String>> map = manager.get(uri, 1452 new HashMap<String, List<String>>()); 1453 1454 assertEquals(0, map.size()); 1455 1456 // Policy = ACCEPT_ALL 1457 manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); 1458 responseHeaders = new TreeMap<String, List<String>>(); 1459 ArrayList<String> list = new ArrayList<String>(); 1460 list.add("test=null"); 1461 responseHeaders.put("Set-cookie", list); 1462 uri = new URI("http://b.c.d"); 1463 manager.put(uri, responseHeaders); 1464 map = manager.get(uri, new HashMap<String, List<String>>()); 1465 assertEquals(1, map.size()); 1466 } 1467 1468 /** 1469 * {@link java.net.CookieManager#getCookieStore()} 1470 * @since 1.6 1471 */ 1472 public void test_GetCookieStore() { 1473 CookieManager cookieManager = new CookieManager(createCookieStore(), null); 1474 CookieStore store = cookieManager.getCookieStore(); 1475 assertNotNull(store); 1476 } 1477 1478 // http://b/25763487 1479 public void testCookieWithNullPath() throws Exception { 1480 FakeSingleCookieStore fscs = new FakeSingleCookieStore(); 1481 CookieManager cm = new CookieManager(fscs, CookiePolicy.ACCEPT_ALL); 1482 1483 HttpCookie cookie = new HttpCookie("foo", "bar"); 1484 cookie.setDomain("http://www.foo.com"); 1485 cookie.setVersion(0); 1486 1487 fscs.setNextCookie(cookie); 1488 1489 Map<String, List<String>> cookieHeaders = cm.get( 1490 new URI("http://www.foo.com/log/me/in"), Collections.EMPTY_MAP); 1491 1492 List<String> cookies = cookieHeaders.get("Cookie"); 1493 assertEquals("foo=bar", cookies.get(0)); 1494 } 1495 1496 /** 1497 * A cookie store that always returns one cookie per URI (without any sort of 1498 * rule matching). The cookie that's returned is provided via a call to setNextCookie 1499 */ 1500 public static class FakeSingleCookieStore implements CookieStore { 1501 private List<HttpCookie> cookies; 1502 1503 void setNextCookie(HttpCookie cookie) { 1504 cookies = Collections.singletonList(cookie); 1505 } 1506 1507 @Override 1508 public void add(URI uri, HttpCookie cookie) { 1509 } 1510 1511 @Override 1512 public List<HttpCookie> get(URI uri) { 1513 return cookies; 1514 } 1515 1516 @Override 1517 public List<HttpCookie> getCookies() { 1518 return cookies; 1519 } 1520 1521 @Override 1522 public List<URI> getURIs() { 1523 return null; 1524 } 1525 1526 @Override 1527 public boolean remove(URI uri, HttpCookie cookie) { 1528 cookies = Collections.EMPTY_LIST; 1529 return true; 1530 } 1531 1532 @Override 1533 public boolean removeAll() { 1534 cookies = Collections.EMPTY_LIST; 1535 return true; 1536 } 1537 } 1538 } 1539