Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.cookies; | 5 package org.chromium.chrome.browser.cookies; |
| 6 | 6 |
| 7 import java.io.ByteArrayOutputStream; | |
| 7 import java.io.DataInputStream; | 8 import java.io.DataInputStream; |
| 8 import java.io.DataOutputStream; | 9 import java.io.DataOutputStream; |
| 10 import java.io.EOFException; | |
| 11 import java.io.File; | |
| 12 import java.io.FileInputStream; | |
| 9 import java.io.IOException; | 13 import java.io.IOException; |
| 14 import java.util.ArrayList; | |
| 15 import java.util.List; | |
| 16 | |
| 17 import javax.crypto.Cipher; | |
| 18 import javax.crypto.CipherInputStream; | |
| 19 import javax.crypto.CipherOutputStream; | |
| 10 | 20 |
| 11 /** | 21 /** |
| 12 * Java representation of net/cookies/canonical_cookie.h. | 22 * Java representation of net/cookies/canonical_cookie.h. |
| 23 * | |
| 24 * Also has static methods to write and restore list of CanonicalCookies to and from disk. | |
| 13 */ | 25 */ |
| 14 class CanonicalCookie { | 26 class CanonicalCookie { |
| 15 private final String mUrl; | 27 private final String mUrl; |
| 16 private final String mName; | 28 private final String mName; |
| 17 private final String mValue; | 29 private final String mValue; |
| 18 private final String mDomain; | 30 private final String mDomain; |
| 19 private final String mPath; | 31 private final String mPath; |
| 20 private final long mCreation; | 32 private final long mCreation; |
| 21 private final long mExpiration; | 33 private final long mExpiration; |
| 22 private final long mLastAccess; | 34 private final long mLastAccess; |
| 23 private final boolean mSecure; | 35 private final boolean mSecure; |
| 24 private final boolean mHttpOnly; | 36 private final boolean mHttpOnly; |
| 25 private final boolean mSameSite; | 37 private final int mSameSite; |
| 26 private final int mPriority; | 38 private final int mPriority; |
| 27 | 39 |
| 28 /** Constructs a CanonicalCookie */ | 40 /** Constructs a CanonicalCookie */ |
| 29 CanonicalCookie(String url, String name, String value, String domain, String path, | 41 CanonicalCookie(String url, String name, String value, String domain, String path, |
| 30 long creation, long expiration, long lastAccess, boolean secure, boo lean httpOnly, | 42 long creation, long expiration, long lastAccess, boolean secure, boo lean httpOnly, |
| 31 boolean sameSite, int priority) { | 43 int sameSite, int priority) { |
| 32 mUrl = url; | 44 mUrl = url; |
| 33 mName = name; | 45 mName = name; |
| 34 mValue = value; | 46 mValue = value; |
| 35 mDomain = domain; | 47 mDomain = domain; |
| 36 mPath = path; | 48 mPath = path; |
| 37 mCreation = creation; | 49 mCreation = creation; |
| 38 mExpiration = expiration; | 50 mExpiration = expiration; |
| 39 mLastAccess = lastAccess; | 51 mLastAccess = lastAccess; |
| 40 mSecure = secure; | 52 mSecure = secure; |
| 41 mHttpOnly = httpOnly; | 53 mHttpOnly = httpOnly; |
| 42 mSameSite = sameSite; | 54 mSameSite = sameSite; |
| 43 mPriority = priority; | 55 mPriority = priority; |
| 44 } | 56 } |
| 45 | 57 |
| 46 /** @return Priority of the cookie. */ | 58 /** @return Priority of the cookie. */ |
| 47 int getPriority() { | 59 int getPriority() { |
| 48 return mPriority; | 60 return mPriority; |
| 49 } | 61 } |
| 50 | 62 |
| 51 /** @return True if the cookie is HTTP only. */ | 63 /** @return True if the cookie is HTTP only. */ |
| 52 boolean isHttpOnly() { | 64 boolean isHttpOnly() { |
| 53 return mHttpOnly; | 65 return mHttpOnly; |
| 54 } | 66 } |
| 55 | 67 |
| 56 /** @return True if the cookie is Same-Site. */ | 68 /** @return SameSite enum */ |
| 57 boolean isSameSite() { | 69 int getSameSite() { |
| 58 return mSameSite; | 70 return mSameSite; |
| 59 } | 71 } |
| 60 | 72 |
| 61 /** @return True if the cookie is secure. */ | 73 /** @return True if the cookie is secure. */ |
| 62 boolean isSecure() { | 74 boolean isSecure() { |
| 63 return mSecure; | 75 return mSecure; |
| 64 } | 76 } |
| 65 | 77 |
| 66 /** @return Last accessed time. */ | 78 /** @return Last accessed time. */ |
| 67 long getLastAccessDate() { | 79 long getLastAccessDate() { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 96 /** @return Cookie domain. */ | 108 /** @return Cookie domain. */ |
| 97 String getDomain() { | 109 String getDomain() { |
| 98 return mDomain; | 110 return mDomain; |
| 99 } | 111 } |
| 100 | 112 |
| 101 /** @return Cookie value. */ | 113 /** @return Cookie value. */ |
| 102 String getValue() { | 114 String getValue() { |
| 103 return mValue; | 115 return mValue; |
| 104 } | 116 } |
| 105 | 117 |
| 106 /** | 118 private static final int SERIALIZATION_VERSION = 20160426; |
| 107 * Serializes for saving to disk. Does not close the stream. | 119 |
| 108 * It is up to the caller to do so. | 120 // Not private for tests. |
| 109 * | 121 static void saveToStream(DataOutputStream out, CanonicalCookie[] cookies) th rows IOException { |
| 110 * @param out Stream to write the cookie to. | 122 if (out == null) { |
| 111 */ | 123 throw new IllegalArgumentException("out arg is null"); |
| 112 void saveToStream(DataOutputStream out) throws IOException { | 124 } |
| 125 if (cookies == null) { | |
| 126 throw new IllegalArgumentException("cookies arg is null"); | |
| 127 } | |
| 128 for (CanonicalCookie cookie : cookies) { | |
| 129 if (cookie == null) { | |
| 130 throw new IllegalArgumentException("cookies arg contains null va lue"); | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 int length = cookies.length; | |
| 135 out.writeInt(SERIALIZATION_VERSION); | |
| 136 out.writeInt(length); | |
| 137 for (int i = 0; i < length; ++i) { | |
| 138 cookies[i].saveToStream(out); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 // Not private for tests. | |
| 143 static class UnexpectedFormatException extends Exception { | |
| 144 public UnexpectedFormatException(String message) { | |
| 145 super(message); | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 // Not private for tests. | |
| 150 static List<CanonicalCookie> readFromStream(DataInputStream in) | |
| 151 throws IOException, UnexpectedFormatException { | |
| 152 if (in == null) { | |
| 153 throw new IllegalArgumentException("in arg is null"); | |
| 154 } | |
| 155 | |
| 156 final int version = in.readInt(); | |
| 157 if (version != SERIALIZATION_VERSION) { | |
| 158 throw new UnexpectedFormatException("Unexpected version"); | |
| 159 } | |
| 160 final int length = in.readInt(); | |
| 161 if (length < 0) { | |
| 162 throw new UnexpectedFormatException("Negative length: " + length); | |
| 163 } | |
| 164 | |
| 165 ArrayList<CanonicalCookie> cookies = new ArrayList<>(length); | |
| 166 for (int i = 0; i < length; ++i) { | |
| 167 cookies.add(createFromStream(in)); | |
| 168 } | |
| 169 return cookies; | |
| 170 } | |
| 171 | |
| 172 private void saveToStream(DataOutputStream out) throws IOException { | |
| 113 out.writeUTF(mUrl); | 173 out.writeUTF(mUrl); |
| 114 out.writeUTF(mName); | 174 out.writeUTF(mName); |
| 115 out.writeUTF(mValue); | 175 out.writeUTF(mValue); |
| 116 out.writeUTF(mDomain); | 176 out.writeUTF(mDomain); |
| 117 out.writeUTF(mPath); | 177 out.writeUTF(mPath); |
| 118 out.writeLong(mCreation); | 178 out.writeLong(mCreation); |
| 119 out.writeLong(mExpiration); | 179 out.writeLong(mExpiration); |
| 120 out.writeLong(mLastAccess); | 180 out.writeLong(mLastAccess); |
| 121 out.writeBoolean(mSecure); | 181 out.writeBoolean(mSecure); |
| 122 out.writeBoolean(mHttpOnly); | 182 out.writeBoolean(mHttpOnly); |
| 123 out.writeBoolean(mSameSite); | 183 out.writeInt(mSameSite); |
| 124 out.writeInt(mPriority); | 184 out.writeInt(mPriority); |
| 125 } | 185 } |
| 126 | 186 |
| 127 /** | 187 private static CanonicalCookie createFromStream(DataInputStream in) throws I OException { |
| 128 * Constructs a cookie by deserializing a single entry from the | |
| 129 * input stream. | |
| 130 * | |
| 131 * @param in Stream to read a cookie entry from. | |
| 132 */ | |
| 133 static CanonicalCookie createFromStream(DataInputStream in) | |
| 134 throws IOException { | |
| 135 return new CanonicalCookie(in.readUTF(), in.readUTF(), in.readUTF(), in. readUTF(), | 188 return new CanonicalCookie(in.readUTF(), in.readUTF(), in.readUTF(), in. readUTF(), |
| 136 in.readUTF(), in.readLong(), in.readLong(), in.readLong(), in.re adBoolean(), | 189 in.readUTF(), in.readLong(), in.readLong(), in.readLong(), in.re adBoolean(), |
| 137 in.readBoolean(), in.readBoolean(), in.readInt()); | 190 in.readBoolean(), in.readInt(), in.readInt()); |
| 191 } | |
| 192 | |
| 193 // Not private for tests. | |
| 194 static final String LEGACY_FORMAT_MAGIC_STRING = "c0Ok135"; | |
| 195 | |
| 196 // If this raises UnexpectedFormatException, then caller should rewind the s tream, and try | |
| 197 // readFromStream instead. | |
| 198 // Not private for tests. | |
| 199 static ArrayList<CanonicalCookie> readFromLegacyStream(DataInputStream in) | |
| 200 throws IOException, UnexpectedFormatException { | |
| 201 // Identify legacy format by the magic string. | |
| 202 try { | |
| 203 String check = in.readUTF(); | |
| 204 if (!LEGACY_FORMAT_MAGIC_STRING.equals(check)) { | |
| 205 throw new UnexpectedFormatException("No magic string"); | |
| 206 } | |
| 207 } catch (IOException e) { | |
| 208 throw new UnexpectedFormatException("IOException while reading magic string"); | |
| 209 } | |
| 210 | |
| 211 ArrayList<CanonicalCookie> cookies = new ArrayList<>(); | |
| 212 try { | |
| 213 while (true) { | |
| 214 CanonicalCookie cookie = createFromLegacyStream(in); | |
| 215 cookies.add(cookie); | |
| 216 } | |
| 217 } catch (EOFException ignored) { | |
| 218 // We are done. | |
| 219 } | |
| 220 return cookies; | |
| 221 } | |
| 222 | |
| 223 // Legacy format stored sameSite as a boolean. | |
| 224 private static CanonicalCookie createFromLegacyStream(DataInputStream in) th rows IOException { | |
| 225 return new CanonicalCookie(in.readUTF(), in.readUTF(), in.readUTF(), in. readUTF(), | |
| 226 in.readUTF(), in.readLong(), in.readLong(), in.readLong(), in.re adBoolean(), | |
| 227 in.readBoolean(), in.readBoolean() ? 1 : 0, in.readInt()); | |
| 228 } | |
| 229 | |
| 230 // This leaks implementation details from CookiesFetcher. But CookiesFetcher can't be unit | |
| 231 // tested. | |
| 232 public static List<CanonicalCookie> readFromFileUnknownFormat(File fileIn, C ipher cipher) | |
|
Yaron
2016/04/28 03:43:10
Couldn't you at least omit "public" and leave this
boliu
2016/04/28 17:49:26
I guess .cookies is its own package, so there actu
| |
| 233 throws IOException, UnexpectedFormatException { | |
| 234 DataInputStream in = null; | |
| 235 try { | |
| 236 FileInputStream streamIn = new FileInputStream(fileIn); | |
| 237 in = new DataInputStream(new CipherInputStream(streamIn, cipher)); | |
| 238 return readFromLegacyStream(in); | |
| 239 } catch (UnexpectedFormatException ignored) { | |
| 240 // Maybe in new format. | |
| 241 } finally { | |
| 242 if (in != null) { | |
| 243 in.close(); | |
| 244 } | |
| 245 in = null; | |
|
Yaron
2016/04/28 03:43:10
Do you really need to null this out?
boliu
2016/04/28 17:49:26
I want to make sure that the "in" here and the "in
| |
| 246 } | |
| 247 | |
| 248 try { | |
| 249 FileInputStream streamIn = new FileInputStream(fileIn); | |
| 250 in = new DataInputStream(new CipherInputStream(streamIn, cipher)); | |
| 251 return CanonicalCookie.readFromStream(in); | |
| 252 } finally { | |
| 253 if (in != null) { | |
| 254 in.close(); | |
| 255 } | |
| 256 in = null; | |
|
Yaron
2016/04/28 03:43:10
same here
boliu
2016/04/28 17:49:25
ditto
| |
| 257 } | |
| 258 } | |
| 259 | |
| 260 // This leaks implementation details from CookiesFetcher. But CookiesFetcher can't be unit | |
| 261 // tested. | |
| 262 public static byte[] writeToByteArray(Cipher cipher, CanonicalCookie cookies []) | |
| 263 throws IOException { | |
| 264 ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); | |
| 265 CipherOutputStream cipherOut = new CipherOutputStream(byteOut, cipher); | |
| 266 DataOutputStream out = new DataOutputStream(cipherOut); | |
| 267 CanonicalCookie.saveToStream(out, cookies); | |
| 268 out.close(); | |
| 269 return byteOut.toByteArray(); | |
| 138 } | 270 } |
| 139 } | 271 } |
| OLD | NEW |