Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp

Issue 1667843003: Make Resource RefCountedWillBeGarbageCollectedFinalized, attempt #2 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase + address review comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014, Google Inc. All rights reserved. 2 * Copyright (c) 2014, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 16 matching lines...) Expand all
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "core/fetch/FetchContext.h" 31 #include "core/fetch/FetchContext.h"
32 #include "core/fetch/ImageResource.h" 32 #include "core/fetch/ImageResource.h"
33 #include "core/fetch/MemoryCache.h" 33 #include "core/fetch/MemoryCache.h"
34 #include "core/fetch/RawResource.h" 34 #include "core/fetch/RawResource.h"
35 #include "core/fetch/Resource.h" 35 #include "core/fetch/Resource.h"
36 #include "core/fetch/ResourceFetcher.h" 36 #include "core/fetch/ResourceFetcher.h"
37 #include "core/fetch/ResourcePtr.h"
38 #include "platform/network/ResourceRequest.h" 37 #include "platform/network/ResourceRequest.h"
39 #include "platform/testing/TestingPlatformSupport.h" 38 #include "platform/testing/TestingPlatformSupport.h"
40 #include "public/platform/Platform.h" 39 #include "public/platform/Platform.h"
41 #include "testing/gtest/include/gtest/gtest.h" 40 #include "testing/gtest/include/gtest/gtest.h"
42 #include "wtf/OwnPtr.h" 41 #include "wtf/OwnPtr.h"
43 #include "wtf/RefPtr.h" 42 #include "wtf/RefPtr.h"
44 43
45 namespace blink { 44 namespace blink {
46 45
47 // An URL for the original request. 46 // An URL for the original request.
(...skipping 22 matching lines...) Expand all
70 MockFetchContext() { } 69 MockFetchContext() { }
71 }; 70 };
72 71
73 class CachingCorrectnessTest : public ::testing::Test { 72 class CachingCorrectnessTest : public ::testing::Test {
74 protected: 73 protected:
75 void advanceClock(double seconds) 74 void advanceClock(double seconds)
76 { 75 {
77 m_proxyPlatform.advanceClock(seconds); 76 m_proxyPlatform.advanceClock(seconds);
78 } 77 }
79 78
80 ResourcePtr<Resource> resourceFromResourceResponse(ResourceResponse response , Resource::Type type = Resource::Raw) 79 PassRefPtrWillBeRawPtr<Resource> resourceFromResourceResponse(ResourceRespon se response, Resource::Type type = Resource::Raw)
81 { 80 {
82 if (response.url().isNull()) 81 if (response.url().isNull())
83 response.setURL(KURL(ParsedURLString, kResourceURL)); 82 response.setURL(KURL(ParsedURLString, kResourceURL));
84 ResourcePtr<Resource> resource; 83 RefPtrWillBeRawPtr<Resource> resource = nullptr;
85 switch (type) { 84 switch (type) {
86 case Resource::Raw: 85 case Resource::Raw:
87 resource = new Resource(ResourceRequest(response.url()), type); 86 resource = Resource::create(ResourceRequest(response.url()), type);
88 break; 87 break;
89 case Resource::Image: 88 case Resource::Image:
90 resource = new ImageResource(ResourceRequest(response.url()), nullpt r); 89 resource = ImageResource::create(ResourceRequest(response.url()), nu llptr);
91 break; 90 break;
92 default: 91 default:
93 EXPECT_TRUE(false) << "'Unreachable' code was reached"; 92 EXPECT_TRUE(false) << "'Unreachable' code was reached";
94 return nullptr; 93 return nullptr;
95 } 94 }
96 resource->setResponse(response); 95 resource->setResponse(response);
97 memoryCache()->add(resource.get()); 96 memoryCache()->add(resource.get());
98 97
99 return resource; 98 return resource;
100 } 99 }
101 100
102 ResourcePtr<Resource> resourceFromResourceRequest(ResourceRequest request, R esource::Type type = Resource::Raw) 101 PassRefPtrWillBeRawPtr<Resource> resourceFromResourceRequest(ResourceRequest request, Resource::Type type = Resource::Raw)
103 { 102 {
104 if (request.url().isNull()) 103 if (request.url().isNull())
105 request.setURL(KURL(ParsedURLString, kResourceURL)); 104 request.setURL(KURL(ParsedURLString, kResourceURL));
106 ResourcePtr<Resource> resource = 105 RefPtrWillBeRawPtr<Resource> resource =
107 new Resource(request, type); 106 Resource::create(request, type);
108 resource->setResponse(ResourceResponse(KURL(ParsedURLString, kResourceUR L), "text/html", 0, nullAtom, String())); 107 resource->setResponse(ResourceResponse(KURL(ParsedURLString, kResourceUR L), "text/html", 0, nullAtom, String()));
109 memoryCache()->add(resource.get()); 108 memoryCache()->add(resource.get());
110 109
111 return resource; 110 return resource;
112 } 111 }
113 112
114 ResourcePtr<Resource> fetch() 113 PassRefPtrWillBeRawPtr<Resource> fetch()
115 { 114 {
116 FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourc eURL)), FetchInitiatorInfo()); 115 FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourc eURL)), FetchInitiatorInfo());
117 return RawResource::fetchSynchronously(fetchRequest, fetcher()); 116 return RawResource::fetchSynchronously(fetchRequest, fetcher());
118 } 117 }
119 118
120 ResourcePtr<Resource> fetchImage() 119 PassRefPtrWillBeRawPtr<Resource> fetchImage()
121 { 120 {
122 FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourc eURL)), FetchInitiatorInfo()); 121 FetchRequest fetchRequest(ResourceRequest(KURL(ParsedURLString, kResourc eURL)), FetchInitiatorInfo());
123 return ImageResource::fetch(fetchRequest, fetcher()); 122 return ImageResource::fetch(fetchRequest, fetcher());
124 } 123 }
125 124
126 ResourceFetcher* fetcher() const { return m_fetcher.get(); } 125 ResourceFetcher* fetcher() const { return m_fetcher.get(); }
127 126
128 private: 127 private:
129 // A simple platform that mocks out the clock, for cache freshness testing. 128 // A simple platform that mocks out the clock, for cache freshness testing.
130 class ProxyPlatform : public TestingPlatformSupport { 129 class ProxyPlatform : public TestingPlatformSupport {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 Persistent<ResourceFetcher> m_fetcher; 167 Persistent<ResourceFetcher> m_fetcher;
169 }; 168 };
170 169
171 TEST_F(CachingCorrectnessTest, FreshFromLastModified) 170 TEST_F(CachingCorrectnessTest, FreshFromLastModified)
172 { 171 {
173 ResourceResponse fresh200Response; 172 ResourceResponse fresh200Response;
174 fresh200Response.setHTTPStatusCode(200); 173 fresh200Response.setHTTPStatusCode(200);
175 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 174 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
176 fresh200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRe quest); 175 fresh200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginalRe quest);
177 176
178 ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Respon se); 177 RefPtrWillBeRawPtr<Resource> fresh200 = resourceFromResourceResponse(fresh20 0Response);
179 178
180 // Advance the clock within the implicit freshness period of this resource b efore we make a request. 179 // Advance the clock within the implicit freshness period of this resource b efore we make a request.
181 advanceClock(600.); 180 advanceClock(600.);
182 181
183 ResourcePtr<Resource> fetched = fetch(); 182 RefPtrWillBeRawPtr<Resource> fetched = fetch();
184 EXPECT_EQ(fresh200, fetched); 183 EXPECT_EQ(fresh200, fetched);
185 } 184 }
186 185
187 TEST_F(CachingCorrectnessTest, FreshFromExpires) 186 TEST_F(CachingCorrectnessTest, FreshFromExpires)
188 { 187 {
189 ResourceResponse fresh200Response; 188 ResourceResponse fresh200Response;
190 fresh200Response.setHTTPStatusCode(200); 189 fresh200Response.setHTTPStatusCode(200);
191 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 190 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
192 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest); 191 fresh200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest);
193 192
194 ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Respon se); 193 RefPtrWillBeRawPtr<Resource> fresh200 = resourceFromResourceResponse(fresh20 0Response);
195 194
196 // Advance the clock within the freshness period of this resource before we make a request. 195 // Advance the clock within the freshness period of this resource before we make a request.
197 advanceClock(24. * 60. * 60. - 15.); 196 advanceClock(24. * 60. * 60. - 15.);
198 197
199 ResourcePtr<Resource> fetched = fetch(); 198 RefPtrWillBeRawPtr<Resource> fetched = fetch();
200 EXPECT_EQ(fresh200, fetched); 199 EXPECT_EQ(fresh200, fetched);
201 } 200 }
202 201
203 TEST_F(CachingCorrectnessTest, FreshFromMaxAge) 202 TEST_F(CachingCorrectnessTest, FreshFromMaxAge)
204 { 203 {
205 ResourceResponse fresh200Response; 204 ResourceResponse fresh200Response;
206 fresh200Response.setHTTPStatusCode(200); 205 fresh200Response.setHTTPStatusCode(200);
207 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 206 fresh200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
208 fresh200Response.setHTTPHeaderField("Cache-Control", "max-age=600"); 207 fresh200Response.setHTTPHeaderField("Cache-Control", "max-age=600");
209 208
210 ResourcePtr<Resource> fresh200 = resourceFromResourceResponse(fresh200Respon se); 209 RefPtrWillBeRawPtr<Resource> fresh200 = resourceFromResourceResponse(fresh20 0Response);
211 210
212 // Advance the clock within the freshness period of this resource before we make a request. 211 // Advance the clock within the freshness period of this resource before we make a request.
213 advanceClock(500.); 212 advanceClock(500.);
214 213
215 ResourcePtr<Resource> fetched = fetch(); 214 RefPtrWillBeRawPtr<Resource> fetched = fetch();
216 EXPECT_EQ(fresh200, fetched); 215 EXPECT_EQ(fresh200, fetched);
217 } 216 }
218 217
219 // The strong validator causes a revalidation to be launched, and the proxy and original resources leak because of their reference loop. 218 // The strong validator causes a revalidation to be launched, and the proxy and original resources leak because of their reference loop.
220 TEST_F(CachingCorrectnessTest, DISABLED_ExpiredFromLastModified) 219 TEST_F(CachingCorrectnessTest, DISABLED_ExpiredFromLastModified)
221 { 220 {
222 ResourceResponse expired200Response; 221 ResourceResponse expired200Response;
223 expired200Response.setHTTPStatusCode(200); 222 expired200Response.setHTTPStatusCode(200);
224 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 223 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
225 expired200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginal Request); 224 expired200Response.setHTTPHeaderField("Last-Modified", kOneDayBeforeOriginal Request);
226 225
227 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Re sponse); 226 RefPtrWillBeRawPtr<Resource> expired200 = resourceFromResourceResponse(expir ed200Response);
228 227
229 // Advance the clock beyond the implicit freshness period. 228 // Advance the clock beyond the implicit freshness period.
230 advanceClock(24. * 60. * 60. * 0.2); 229 advanceClock(24. * 60. * 60. * 0.2);
231 230
232 ResourcePtr<Resource> fetched = fetch(); 231 RefPtrWillBeRawPtr<Resource> fetched = fetch();
233 EXPECT_NE(expired200, fetched); 232 EXPECT_NE(expired200, fetched);
234 } 233 }
235 234
236 TEST_F(CachingCorrectnessTest, ExpiredFromExpires) 235 TEST_F(CachingCorrectnessTest, ExpiredFromExpires)
237 { 236 {
238 ResourceResponse expired200Response; 237 ResourceResponse expired200Response;
239 expired200Response.setHTTPStatusCode(200); 238 expired200Response.setHTTPStatusCode(200);
240 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 239 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
241 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest ); 240 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest );
242 241
243 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Re sponse); 242 RefPtrWillBeRawPtr<Resource> expired200 = resourceFromResourceResponse(expir ed200Response);
244 243
245 // Advance the clock within the expiredness period of this resource before w e make a request. 244 // Advance the clock within the expiredness period of this resource before w e make a request.
246 advanceClock(24. * 60. * 60. + 15.); 245 advanceClock(24. * 60. * 60. + 15.);
247 246
248 ResourcePtr<Resource> fetched = fetch(); 247 RefPtrWillBeRawPtr<Resource> fetched = fetch();
249 EXPECT_NE(expired200, fetched); 248 EXPECT_NE(expired200, fetched);
250 } 249 }
251 250
252 // If the image hasn't been loaded in this "document" before, then it shouldn't have list of available images logic. 251 // If the image hasn't been loaded in this "document" before, then it shouldn't have list of available images logic.
253 TEST_F(CachingCorrectnessTest, NewImageExpiredFromExpires) 252 TEST_F(CachingCorrectnessTest, NewImageExpiredFromExpires)
254 { 253 {
255 ResourceResponse expired200Response; 254 ResourceResponse expired200Response;
256 expired200Response.setHTTPStatusCode(200); 255 expired200Response.setHTTPStatusCode(200);
257 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 256 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
258 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest ); 257 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest );
259 258
260 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Re sponse, Resource::Image); 259 RefPtrWillBeRawPtr<Resource> expired200 = resourceFromResourceResponse(expir ed200Response, Resource::Image);
261 260
262 // Advance the clock within the expiredness period of this resource before w e make a request. 261 // Advance the clock within the expiredness period of this resource before w e make a request.
263 advanceClock(24. * 60. * 60. + 15.); 262 advanceClock(24. * 60. * 60. + 15.);
264 263
265 ResourcePtr<Resource> fetched = fetchImage(); 264 RefPtrWillBeRawPtr<Resource> fetched = fetchImage();
266 EXPECT_NE(expired200, fetched); 265 EXPECT_NE(expired200, fetched);
267 } 266 }
268 267
269 // If the image has been loaded in this "document" before, then it should have l ist of available images logic, and so 268 // If the image has been loaded in this "document" before, then it should have l ist of available images logic, and so
270 // normal cache testing should be bypassed. 269 // normal cache testing should be bypassed.
271 TEST_F(CachingCorrectnessTest, ReuseImageExpiredFromExpires) 270 TEST_F(CachingCorrectnessTest, ReuseImageExpiredFromExpires)
272 { 271 {
273 ResourceResponse expired200Response; 272 ResourceResponse expired200Response;
274 expired200Response.setHTTPStatusCode(200); 273 expired200Response.setHTTPStatusCode(200);
275 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 274 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
276 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest ); 275 expired200Response.setHTTPHeaderField("Expires", kOneDayAfterOriginalRequest );
277 276
278 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Re sponse, Resource::Image); 277 RefPtrWillBeRawPtr<Resource> expired200 = resourceFromResourceResponse(expir ed200Response, Resource::Image);
279 278
280 // Advance the clock within the freshness period, and make a request to add this image to the document resources. 279 // Advance the clock within the freshness period, and make a request to add this image to the document resources.
281 advanceClock(15.); 280 advanceClock(15.);
282 ResourcePtr<Resource> firstFetched = fetchImage(); 281 RefPtrWillBeRawPtr<Resource> firstFetched = fetchImage();
283 EXPECT_EQ(expired200, firstFetched); 282 EXPECT_EQ(expired200, firstFetched);
284 283
285 // Advance the clock within the expiredness period of this resource before w e make a request. 284 // Advance the clock within the expiredness period of this resource before w e make a request.
286 advanceClock(24. * 60. * 60. + 15.); 285 advanceClock(24. * 60. * 60. + 15.);
287 286
288 ResourcePtr<Resource> fetched = fetchImage(); 287 RefPtrWillBeRawPtr<Resource> fetched = fetchImage();
289 EXPECT_EQ(expired200, fetched); 288 EXPECT_EQ(expired200, fetched);
290 } 289 }
291 290
292 TEST_F(CachingCorrectnessTest, ExpiredFromMaxAge) 291 TEST_F(CachingCorrectnessTest, ExpiredFromMaxAge)
293 { 292 {
294 ResourceResponse expired200Response; 293 ResourceResponse expired200Response;
295 expired200Response.setHTTPStatusCode(200); 294 expired200Response.setHTTPStatusCode(200);
296 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString); 295 expired200Response.setHTTPHeaderField("Date", kOriginalRequestDateAsString);
297 expired200Response.setHTTPHeaderField("Cache-Control", "max-age=600"); 296 expired200Response.setHTTPHeaderField("Cache-Control", "max-age=600");
298 297
299 ResourcePtr<Resource> expired200 = resourceFromResourceResponse(expired200Re sponse); 298 RefPtrWillBeRawPtr<Resource> expired200 = resourceFromResourceResponse(expir ed200Response);
300 299
301 // Advance the clock within the expiredness period of this resource before w e make a request. 300 // Advance the clock within the expiredness period of this resource before w e make a request.
302 advanceClock(700.); 301 advanceClock(700.);
303 302
304 ResourcePtr<Resource> fetched = fetch(); 303 RefPtrWillBeRawPtr<Resource> fetched = fetch();
305 EXPECT_NE(expired200, fetched); 304 EXPECT_NE(expired200, fetched);
306 } 305 }
307 306
308 TEST_F(CachingCorrectnessTest, FreshButNoCache) 307 TEST_F(CachingCorrectnessTest, FreshButNoCache)
309 { 308 {
310 ResourceResponse fresh200NocacheResponse; 309 ResourceResponse fresh200NocacheResponse;
311 fresh200NocacheResponse.setHTTPStatusCode(200); 310 fresh200NocacheResponse.setHTTPStatusCode(200);
312 fresh200NocacheResponse.setHTTPHeaderField(HTTPNames::Date, kOriginalRequest DateAsString); 311 fresh200NocacheResponse.setHTTPHeaderField(HTTPNames::Date, kOriginalRequest DateAsString);
313 fresh200NocacheResponse.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterO riginalRequest); 312 fresh200NocacheResponse.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterO riginalRequest);
314 fresh200NocacheResponse.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cac he"); 313 fresh200NocacheResponse.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cac he");
315 314
316 ResourcePtr<Resource> fresh200Nocache = resourceFromResourceResponse(fresh20 0NocacheResponse); 315 RefPtrWillBeRawPtr<Resource> fresh200Nocache = resourceFromResourceResponse( fresh200NocacheResponse);
317 316
318 // Advance the clock within the freshness period of this resource before we make a request. 317 // Advance the clock within the freshness period of this resource before we make a request.
319 advanceClock(24. * 60. * 60. - 15.); 318 advanceClock(24. * 60. * 60. - 15.);
320 319
321 ResourcePtr<Resource> fetched = fetch(); 320 RefPtrWillBeRawPtr<Resource> fetched = fetch();
322 EXPECT_NE(fresh200Nocache, fetched); 321 EXPECT_NE(fresh200Nocache, fetched);
323 } 322 }
324 323
325 TEST_F(CachingCorrectnessTest, RequestWithNoCahe) 324 TEST_F(CachingCorrectnessTest, RequestWithNoCahe)
326 { 325 {
327 ResourceRequest noCacheRequest; 326 ResourceRequest noCacheRequest;
328 noCacheRequest.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cache"); 327 noCacheRequest.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cache");
329 ResourcePtr<Resource> noCacheResource = resourceFromResourceRequest(noCacheR equest); 328 RefPtrWillBeRawPtr<Resource> noCacheResource = resourceFromResourceRequest(n oCacheRequest);
330 ResourcePtr<Resource> fetched = fetch(); 329 RefPtrWillBeRawPtr<Resource> fetched = fetch();
331 EXPECT_NE(noCacheResource, fetched); 330 EXPECT_NE(noCacheResource, fetched);
332 } 331 }
333 332
334 TEST_F(CachingCorrectnessTest, FreshButNoStore) 333 TEST_F(CachingCorrectnessTest, FreshButNoStore)
335 { 334 {
336 ResourceResponse fresh200NostoreResponse; 335 ResourceResponse fresh200NostoreResponse;
337 fresh200NostoreResponse.setHTTPStatusCode(200); 336 fresh200NostoreResponse.setHTTPStatusCode(200);
338 fresh200NostoreResponse.setHTTPHeaderField(HTTPNames::Date, kOriginalRequest DateAsString); 337 fresh200NostoreResponse.setHTTPHeaderField(HTTPNames::Date, kOriginalRequest DateAsString);
339 fresh200NostoreResponse.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterO riginalRequest); 338 fresh200NostoreResponse.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterO riginalRequest);
340 fresh200NostoreResponse.setHTTPHeaderField(HTTPNames::Cache_Control, "no-sto re"); 339 fresh200NostoreResponse.setHTTPHeaderField(HTTPNames::Cache_Control, "no-sto re");
341 340
342 ResourcePtr<Resource> fresh200Nostore = resourceFromResourceResponse(fresh20 0NostoreResponse); 341 RefPtrWillBeRawPtr<Resource> fresh200Nostore = resourceFromResourceResponse( fresh200NostoreResponse);
343 342
344 // Advance the clock within the freshness period of this resource before we make a request. 343 // Advance the clock within the freshness period of this resource before we make a request.
345 advanceClock(24. * 60. * 60. - 15.); 344 advanceClock(24. * 60. * 60. - 15.);
346 345
347 ResourcePtr<Resource> fetched = fetch(); 346 RefPtrWillBeRawPtr<Resource> fetched = fetch();
348 EXPECT_NE(fresh200Nostore, fetched); 347 EXPECT_NE(fresh200Nostore, fetched);
349 } 348 }
350 349
351 TEST_F(CachingCorrectnessTest, RequestWithNoStore) 350 TEST_F(CachingCorrectnessTest, RequestWithNoStore)
352 { 351 {
353 ResourceRequest noStoreRequest; 352 ResourceRequest noStoreRequest;
354 noStoreRequest.setHTTPHeaderField(HTTPNames::Cache_Control, "no-store"); 353 noStoreRequest.setHTTPHeaderField(HTTPNames::Cache_Control, "no-store");
355 ResourcePtr<Resource> noStoreResource = resourceFromResourceRequest(noStoreR equest); 354 RefPtrWillBeRawPtr<Resource> noStoreResource = resourceFromResourceRequest(n oStoreRequest);
356 ResourcePtr<Resource> fetched = fetch(); 355 RefPtrWillBeRawPtr<Resource> fetched = fetch();
357 EXPECT_NE(noStoreResource, fetched); 356 EXPECT_NE(noStoreResource, fetched);
358 } 357 }
359 358
360 // FIXME: Determine if ignoring must-revalidate for blink is correct behaviour. 359 // FIXME: Determine if ignoring must-revalidate for blink is correct behaviour.
361 // See crbug.com/340088 . 360 // See crbug.com/340088 .
362 TEST_F(CachingCorrectnessTest, DISABLED_FreshButMustRevalidate) 361 TEST_F(CachingCorrectnessTest, DISABLED_FreshButMustRevalidate)
363 { 362 {
364 ResourceResponse fresh200MustRevalidateResponse; 363 ResourceResponse fresh200MustRevalidateResponse;
365 fresh200MustRevalidateResponse.setHTTPStatusCode(200); 364 fresh200MustRevalidateResponse.setHTTPStatusCode(200);
366 fresh200MustRevalidateResponse.setHTTPHeaderField(HTTPNames::Date, kOriginal RequestDateAsString); 365 fresh200MustRevalidateResponse.setHTTPHeaderField(HTTPNames::Date, kOriginal RequestDateAsString);
367 fresh200MustRevalidateResponse.setHTTPHeaderField(HTTPNames::Expires, kOneDa yAfterOriginalRequest); 366 fresh200MustRevalidateResponse.setHTTPHeaderField(HTTPNames::Expires, kOneDa yAfterOriginalRequest);
368 fresh200MustRevalidateResponse.setHTTPHeaderField(HTTPNames::Cache_Control, "must-revalidate"); 367 fresh200MustRevalidateResponse.setHTTPHeaderField(HTTPNames::Cache_Control, "must-revalidate");
369 368
370 ResourcePtr<Resource> fresh200MustRevalidate = resourceFromResourceResponse( fresh200MustRevalidateResponse); 369 RefPtrWillBeRawPtr<Resource> fresh200MustRevalidate = resourceFromResourceRe sponse(fresh200MustRevalidateResponse);
371 370
372 // Advance the clock within the freshness period of this resource before we make a request. 371 // Advance the clock within the freshness period of this resource before we make a request.
373 advanceClock(24. * 60. * 60. - 15.); 372 advanceClock(24. * 60. * 60. - 15.);
374 373
375 ResourcePtr<Resource> fetched = fetch(); 374 RefPtrWillBeRawPtr<Resource> fetched = fetch();
376 EXPECT_NE(fresh200MustRevalidate, fetched); 375 EXPECT_NE(fresh200MustRevalidate, fetched);
377 } 376 }
378 377
379 TEST_F(CachingCorrectnessTest, FreshWithFreshRedirect) 378 TEST_F(CachingCorrectnessTest, FreshWithFreshRedirect)
380 { 379 {
381 KURL redirectUrl(ParsedURLString, kResourceURL); 380 KURL redirectUrl(ParsedURLString, kResourceURL);
382 const char redirectTargetUrlString[] = "http://redirect-target.com"; 381 const char redirectTargetUrlString[] = "http://redirect-target.com";
383 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); 382 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
384 383
385 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectU rl), Resource::Raw); 384 RefPtrWillBeRawPtr<Resource> firstResource = Resource::create(ResourceReques t(redirectUrl), Resource::Raw);
386 385
387 ResourceResponse fresh301Response; 386 ResourceResponse fresh301Response;
388 fresh301Response.setURL(redirectUrl); 387 fresh301Response.setURL(redirectUrl);
389 fresh301Response.setHTTPStatusCode(301); 388 fresh301Response.setHTTPStatusCode(301);
390 fresh301Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 389 fresh301Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
391 fresh301Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring); 390 fresh301Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring);
392 fresh301Response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=600") ; 391 fresh301Response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=600") ;
393 392
394 // Add the redirect to our request. 393 // Add the redirect to our request.
395 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); 394 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
396 firstResource->willFollowRedirect(redirectRequest, fresh301Response); 395 firstResource->willFollowRedirect(redirectRequest, fresh301Response);
397 396
398 // Add the final response to our request. 397 // Add the final response to our request.
399 ResourceResponse fresh200Response; 398 ResourceResponse fresh200Response;
400 fresh200Response.setURL(redirectTargetUrl); 399 fresh200Response.setURL(redirectTargetUrl);
401 fresh200Response.setHTTPStatusCode(200); 400 fresh200Response.setHTTPStatusCode(200);
402 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 401 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
403 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request); 402 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request);
404 403
405 firstResource->setResponse(fresh200Response); 404 firstResource->setResponse(fresh200Response);
406 memoryCache()->add(firstResource.get()); 405 memoryCache()->add(firstResource.get());
407 406
408 advanceClock(500.); 407 advanceClock(500.);
409 408
410 ResourcePtr<Resource> fetched = fetch(); 409 RefPtrWillBeRawPtr<Resource> fetched = fetch();
411 EXPECT_EQ(firstResource, fetched); 410 EXPECT_EQ(firstResource, fetched);
412 } 411 }
413 412
414 TEST_F(CachingCorrectnessTest, FreshWithStaleRedirect) 413 TEST_F(CachingCorrectnessTest, FreshWithStaleRedirect)
415 { 414 {
416 KURL redirectUrl(ParsedURLString, kResourceURL); 415 KURL redirectUrl(ParsedURLString, kResourceURL);
417 const char redirectTargetUrlString[] = "http://redirect-target.com"; 416 const char redirectTargetUrlString[] = "http://redirect-target.com";
418 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); 417 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
419 418
420 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectU rl), Resource::Raw); 419 RefPtrWillBeRawPtr<Resource> firstResource = Resource::create(ResourceReques t(redirectUrl), Resource::Raw);
421 420
422 ResourceResponse stale301Response; 421 ResourceResponse stale301Response;
423 stale301Response.setURL(redirectUrl); 422 stale301Response.setURL(redirectUrl);
424 stale301Response.setHTTPStatusCode(301); 423 stale301Response.setHTTPStatusCode(301);
425 stale301Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 424 stale301Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
426 stale301Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring); 425 stale301Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring);
427 426
428 // Add the redirect to our request. 427 // Add the redirect to our request.
429 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); 428 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
430 firstResource->willFollowRedirect(redirectRequest, stale301Response); 429 firstResource->willFollowRedirect(redirectRequest, stale301Response);
431 430
432 // Add the final response to our request. 431 // Add the final response to our request.
433 ResourceResponse fresh200Response; 432 ResourceResponse fresh200Response;
434 fresh200Response.setURL(redirectTargetUrl); 433 fresh200Response.setURL(redirectTargetUrl);
435 fresh200Response.setHTTPStatusCode(200); 434 fresh200Response.setHTTPStatusCode(200);
436 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 435 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
437 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request); 436 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request);
438 437
439 firstResource->setResponse(fresh200Response); 438 firstResource->setResponse(fresh200Response);
440 memoryCache()->add(firstResource.get()); 439 memoryCache()->add(firstResource.get());
441 440
442 advanceClock(500.); 441 advanceClock(500.);
443 442
444 ResourcePtr<Resource> fetched = fetch(); 443 RefPtrWillBeRawPtr<Resource> fetched = fetch();
445 EXPECT_NE(firstResource, fetched); 444 EXPECT_NE(firstResource, fetched);
446 } 445 }
447 446
448 TEST_F(CachingCorrectnessTest, PostToSameURLTwice) 447 TEST_F(CachingCorrectnessTest, PostToSameURLTwice)
449 { 448 {
450 ResourceRequest request1(KURL(ParsedURLString, kResourceURL)); 449 ResourceRequest request1(KURL(ParsedURLString, kResourceURL));
451 request1.setHTTPMethod(HTTPNames::POST); 450 request1.setHTTPMethod(HTTPNames::POST);
452 ResourcePtr<Resource> resource1 = new Resource(ResourceRequest(request1.url( )), Resource::Raw); 451 RefPtrWillBeRawPtr<Resource> resource1 = Resource::create(ResourceRequest(re quest1.url()), Resource::Raw);
453 resource1->setLoading(true); 452 resource1->setLoading(true);
454 memoryCache()->add(resource1.get()); 453 memoryCache()->add(resource1.get());
455 454
456 ResourceRequest request2(KURL(ParsedURLString, kResourceURL)); 455 ResourceRequest request2(KURL(ParsedURLString, kResourceURL));
457 request2.setHTTPMethod(HTTPNames::POST); 456 request2.setHTTPMethod(HTTPNames::POST);
458 FetchRequest fetch2(request2, FetchInitiatorInfo()); 457 FetchRequest fetch2(request2, FetchInitiatorInfo());
459 ResourcePtr<Resource> resource2 = RawResource::fetchSynchronously(fetch2, fe tcher()); 458 RefPtrWillBeRawPtr<Resource> resource2 = RawResource::fetchSynchronously(fet ch2, fetcher());
460 459
461 EXPECT_EQ(resource2, memoryCache()->resourceForURL(request2.url())); 460 EXPECT_EQ(resource2, memoryCache()->resourceForURL(request2.url()));
462 EXPECT_NE(resource1, resource2); 461 EXPECT_NE(resource1, resource2);
463 } 462 }
464 463
465 TEST_F(CachingCorrectnessTest, 302RedirectNotImplicitlyFresh) 464 TEST_F(CachingCorrectnessTest, 302RedirectNotImplicitlyFresh)
466 { 465 {
467 KURL redirectUrl(ParsedURLString, kResourceURL); 466 KURL redirectUrl(ParsedURLString, kResourceURL);
468 const char redirectTargetUrlString[] = "http://redirect-target.com"; 467 const char redirectTargetUrlString[] = "http://redirect-target.com";
469 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); 468 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
470 469
471 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectU rl), Resource::Raw); 470 RefPtrWillBeRawPtr<Resource> firstResource = Resource::create(ResourceReques t(redirectUrl), Resource::Raw);
472 471
473 ResourceResponse fresh302Response; 472 ResourceResponse fresh302Response;
474 fresh302Response.setURL(redirectUrl); 473 fresh302Response.setURL(redirectUrl);
475 fresh302Response.setHTTPStatusCode(302); 474 fresh302Response.setHTTPStatusCode(302);
476 fresh302Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 475 fresh302Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
477 fresh302Response.setHTTPHeaderField(HTTPNames::Last_Modified, kOneDayBeforeO riginalRequest); 476 fresh302Response.setHTTPHeaderField(HTTPNames::Last_Modified, kOneDayBeforeO riginalRequest);
478 fresh302Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring); 477 fresh302Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring);
479 478
480 // Add the redirect to our request. 479 // Add the redirect to our request.
481 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); 480 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
482 firstResource->willFollowRedirect(redirectRequest, fresh302Response); 481 firstResource->willFollowRedirect(redirectRequest, fresh302Response);
483 482
484 // Add the final response to our request. 483 // Add the final response to our request.
485 ResourceResponse fresh200Response; 484 ResourceResponse fresh200Response;
486 fresh200Response.setURL(redirectTargetUrl); 485 fresh200Response.setURL(redirectTargetUrl);
487 fresh200Response.setHTTPStatusCode(200); 486 fresh200Response.setHTTPStatusCode(200);
488 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 487 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
489 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request); 488 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request);
490 489
491 firstResource->setResponse(fresh200Response); 490 firstResource->setResponse(fresh200Response);
492 memoryCache()->add(firstResource.get()); 491 memoryCache()->add(firstResource.get());
493 492
494 advanceClock(500.); 493 advanceClock(500.);
495 494
496 ResourcePtr<Resource> fetched = fetch(); 495 RefPtrWillBeRawPtr<Resource> fetched = fetch();
497 EXPECT_NE(firstResource, fetched); 496 EXPECT_NE(firstResource, fetched);
498 } 497 }
499 498
500 TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshMaxAge) 499 TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshMaxAge)
501 { 500 {
502 KURL redirectUrl(ParsedURLString, kResourceURL); 501 KURL redirectUrl(ParsedURLString, kResourceURL);
503 const char redirectTargetUrlString[] = "http://redirect-target.com"; 502 const char redirectTargetUrlString[] = "http://redirect-target.com";
504 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); 503 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
505 504
506 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectU rl), Resource::Raw); 505 RefPtrWillBeRawPtr<Resource> firstResource = Resource::create(ResourceReques t(redirectUrl), Resource::Raw);
507 506
508 ResourceResponse fresh302Response; 507 ResourceResponse fresh302Response;
509 fresh302Response.setURL(redirectUrl); 508 fresh302Response.setURL(redirectUrl);
510 fresh302Response.setHTTPStatusCode(302); 509 fresh302Response.setHTTPStatusCode(302);
511 fresh302Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 510 fresh302Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
512 fresh302Response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=600") ; 511 fresh302Response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=600") ;
513 fresh302Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring); 512 fresh302Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring);
514 513
515 // Add the redirect to our request. 514 // Add the redirect to our request.
516 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); 515 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
517 firstResource->willFollowRedirect(redirectRequest, fresh302Response); 516 firstResource->willFollowRedirect(redirectRequest, fresh302Response);
518 517
519 // Add the final response to our request. 518 // Add the final response to our request.
520 ResourceResponse fresh200Response; 519 ResourceResponse fresh200Response;
521 fresh200Response.setURL(redirectTargetUrl); 520 fresh200Response.setURL(redirectTargetUrl);
522 fresh200Response.setHTTPStatusCode(200); 521 fresh200Response.setHTTPStatusCode(200);
523 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 522 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
524 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request); 523 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request);
525 524
526 firstResource->setResponse(fresh200Response); 525 firstResource->setResponse(fresh200Response);
527 memoryCache()->add(firstResource.get()); 526 memoryCache()->add(firstResource.get());
528 527
529 advanceClock(500.); 528 advanceClock(500.);
530 529
531 ResourcePtr<Resource> fetched = fetch(); 530 RefPtrWillBeRawPtr<Resource> fetched = fetch();
532 EXPECT_EQ(firstResource, fetched); 531 EXPECT_EQ(firstResource, fetched);
533 } 532 }
534 533
535 TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshExpires) 534 TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshExpires)
536 { 535 {
537 KURL redirectUrl(ParsedURLString, kResourceURL); 536 KURL redirectUrl(ParsedURLString, kResourceURL);
538 const char redirectTargetUrlString[] = "http://redirect-target.com"; 537 const char redirectTargetUrlString[] = "http://redirect-target.com";
539 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); 538 KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString);
540 539
541 ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectU rl), Resource::Raw); 540 RefPtrWillBeRawPtr<Resource> firstResource = Resource::create(ResourceReques t(redirectUrl), Resource::Raw);
542 541
543 ResourceResponse fresh302Response; 542 ResourceResponse fresh302Response;
544 fresh302Response.setURL(redirectUrl); 543 fresh302Response.setURL(redirectUrl);
545 fresh302Response.setHTTPStatusCode(302); 544 fresh302Response.setHTTPStatusCode(302);
546 fresh302Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 545 fresh302Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
547 fresh302Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request); 546 fresh302Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request);
548 fresh302Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring); 547 fresh302Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlSt ring);
549 548
550 // Add the redirect to our request. 549 // Add the redirect to our request.
551 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); 550 ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl);
552 firstResource->willFollowRedirect(redirectRequest, fresh302Response); 551 firstResource->willFollowRedirect(redirectRequest, fresh302Response);
553 552
554 // Add the final response to our request. 553 // Add the final response to our request.
555 ResourceResponse fresh200Response; 554 ResourceResponse fresh200Response;
556 fresh200Response.setURL(redirectTargetUrl); 555 fresh200Response.setURL(redirectTargetUrl);
557 fresh200Response.setHTTPStatusCode(200); 556 fresh200Response.setHTTPStatusCode(200);
558 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring); 557 fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsS tring);
559 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request); 558 fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginal Request);
560 559
561 firstResource->setResponse(fresh200Response); 560 firstResource->setResponse(fresh200Response);
562 memoryCache()->add(firstResource.get()); 561 memoryCache()->add(firstResource.get());
563 562
564 advanceClock(500.); 563 advanceClock(500.);
565 564
566 ResourcePtr<Resource> fetched = fetch(); 565 RefPtrWillBeRawPtr<Resource> fetched = fetch();
567 EXPECT_EQ(firstResource, fetched); 566 EXPECT_EQ(firstResource, fetched);
568 } 567 }
569 568
570 } // namespace blink 569 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698