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

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

Issue 1915833002: Introduce Platform::cacheMetadataInCacheStorage() to store V8 code cache in CacheStorage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: incorporated vogelheim's comment Created 4 years, 7 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) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
7 7
8 This library is free software; you can redistribute it and/or 8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public 9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either 10 License as published by the Free Software Foundation; either
(...skipping 23 matching lines...) Expand all
34 #include "core/inspector/InspectorInstrumentation.h" 34 #include "core/inspector/InspectorInstrumentation.h"
35 #include "core/inspector/InstanceCounters.h" 35 #include "core/inspector/InstanceCounters.h"
36 #include "platform/Logging.h" 36 #include "platform/Logging.h"
37 #include "platform/SharedBuffer.h" 37 #include "platform/SharedBuffer.h"
38 #include "platform/TraceEvent.h" 38 #include "platform/TraceEvent.h"
39 #include "platform/network/HTTPParsers.h" 39 #include "platform/network/HTTPParsers.h"
40 #include "platform/weborigin/KURL.h" 40 #include "platform/weborigin/KURL.h"
41 #include "public/platform/Platform.h" 41 #include "public/platform/Platform.h"
42 #include "public/platform/WebProcessMemoryDump.h" 42 #include "public/platform/WebProcessMemoryDump.h"
43 #include "public/platform/WebScheduler.h" 43 #include "public/platform/WebScheduler.h"
44 #include "public/platform/WebSecurityOrigin.h"
44 #include "wtf/CurrentTime.h" 45 #include "wtf/CurrentTime.h"
45 #include "wtf/MathExtras.h" 46 #include "wtf/MathExtras.h"
46 #include "wtf/StdLibExtras.h" 47 #include "wtf/StdLibExtras.h"
47 #include "wtf/Vector.h" 48 #include "wtf/Vector.h"
48 #include "wtf/text/CString.h" 49 #include "wtf/text/CString.h"
49 #include <algorithm> 50 #include <algorithm>
50 51
51 namespace blink { 52 namespace blink {
52 53
53 // These response headers are not copied from a revalidated response to the 54 // These response headers are not copied from a revalidated response to the
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 if (equalIgnoringCase(header, headersToIgnoreAfterRevalidation[i])) 86 if (equalIgnoringCase(header, headersToIgnoreAfterRevalidation[i]))
86 return false; 87 return false;
87 } 88 }
88 for (size_t i = 0; i < WTF_ARRAY_LENGTH(headerPrefixesToIgnoreAfterRevalidat ion); i++) { 89 for (size_t i = 0; i < WTF_ARRAY_LENGTH(headerPrefixesToIgnoreAfterRevalidat ion); i++) {
89 if (header.startsWith(headerPrefixesToIgnoreAfterRevalidation[i], TextCa seInsensitive)) 90 if (header.startsWith(headerPrefixesToIgnoreAfterRevalidation[i], TextCa seInsensitive))
90 return false; 91 return false;
91 } 92 }
92 return true; 93 return true;
93 } 94 }
94 95
95 class Resource::CacheHandler : public CachedMetadataHandler { 96 class Resource::CachedMetadataHandlerImpl : public CachedMetadataHandler {
96 public: 97 public:
97 static CacheHandler* create(Resource* resource) 98 static Resource::CachedMetadataHandlerImpl* create(Resource* resource)
98 { 99 {
99 return new CacheHandler(resource); 100 return new CachedMetadataHandlerImpl(resource);
100 } 101 }
101 ~CacheHandler() override { } 102 ~CachedMetadataHandlerImpl() override {}
102 DECLARE_VIRTUAL_TRACE(); 103 DECLARE_VIRTUAL_TRACE();
103 void setCachedMetadata(unsigned, const char*, size_t, CacheType) override; 104 void setCachedMetadata(unsigned, const char*, size_t, CacheType) override;
104 void clearCachedMetadata(CacheType) override; 105 void clearCachedMetadata(CacheType) override;
105 CachedMetadata* cachedMetadata(unsigned) const override; 106 CachedMetadata* cachedMetadata(unsigned) const override;
106 String encoding() const override; 107 String encoding() const override;
108 // Sets the serialized metadata retrieved from the platform's cache.
109 void setSerializedCachedMetadata(const char*, size_t);
110
111 protected:
112 explicit CachedMetadataHandlerImpl(Resource*);
113 virtual void sendToPlatform();
114 const ResourceResponse& response() const { return m_resource->response(); }
115
116 RefPtr<CachedMetadata> m_cachedMetadata;
107 117
108 private: 118 private:
109 explicit CacheHandler(Resource*);
110 Member<Resource> m_resource; 119 Member<Resource> m_resource;
111 }; 120 };
112 121
113 Resource::CacheHandler::CacheHandler(Resource* resource) 122 Resource::CachedMetadataHandlerImpl::CachedMetadataHandlerImpl(Resource* resourc e)
114 : m_resource(resource) 123 : m_resource(resource)
115 { 124 {
116 } 125 }
117 126
118 DEFINE_TRACE(Resource::CacheHandler) 127 DEFINE_TRACE(Resource::CachedMetadataHandlerImpl)
119 { 128 {
120 visitor->trace(m_resource); 129 visitor->trace(m_resource);
121 CachedMetadataHandler::trace(visitor); 130 CachedMetadataHandler::trace(visitor);
122 } 131 }
123 132
124 void Resource::CacheHandler::setCachedMetadata(unsigned dataTypeID, const char* data, size_t size, CacheType type) 133 void Resource::CachedMetadataHandlerImpl::setCachedMetadata(unsigned dataTypeID, const char* data, size_t size, CachedMetadataHandler::CacheType cacheType)
125 { 134 {
126 m_resource->setCachedMetadata(dataTypeID, data, size, type); 135 // Currently, only one type of cached metadata per resource is supported.
136 // If the need arises for multiple types of metadata per resource this could
137 // be enhanced to store types of metadata in a map.
138 ASSERT(!m_cachedMetadata);
139 m_cachedMetadata = CachedMetadata::create(dataTypeID, data, size);
140 if (cacheType == CachedMetadataHandler::SendToPlatform)
141 sendToPlatform();
127 } 142 }
128 143
129 void Resource::CacheHandler::clearCachedMetadata(CacheType type) 144 void Resource::CachedMetadataHandlerImpl::clearCachedMetadata(CachedMetadataHand ler::CacheType cacheType)
130 { 145 {
131 m_resource->clearCachedMetadata(type); 146 m_cachedMetadata.clear();
147 if (cacheType == CachedMetadataHandler::SendToPlatform)
148 sendToPlatform();
132 } 149 }
133 150
134 CachedMetadata* Resource::CacheHandler::cachedMetadata(unsigned dataTypeID) cons t 151 CachedMetadata* Resource::CachedMetadataHandlerImpl::cachedMetadata(unsigned dat aTypeID) const
135 { 152 {
136 return m_resource->cachedMetadata(dataTypeID); 153 if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID)
154 return nullptr;
155 return m_cachedMetadata.get();
137 } 156 }
138 157
139 String Resource::CacheHandler::encoding() const 158 String Resource::CachedMetadataHandlerImpl::encoding() const
140 { 159 {
141 return m_resource->encoding(); 160 return m_resource->encoding();
142 } 161 }
143 162
163 void Resource::CachedMetadataHandlerImpl::setSerializedCachedMetadata(const char * data, size_t size)
164 {
165 // We only expect to receive cached metadata from the platform once.
166 // If this triggers, it indicates an efficiency problem which is most
167 // likely unexpected in code designed to improve performance.
168 ASSERT(!m_cachedMetadata);
169 m_cachedMetadata = CachedMetadata::deserialize(data, size);
170 }
171
172 void Resource::CachedMetadataHandlerImpl::sendToPlatform()
173 {
174 if (m_cachedMetadata) {
175 const Vector<char>& serializedData = m_cachedMetadata->serialize();
176 Platform::current()->cacheMetadata(response().url(), response().response Time(), serializedData.data(), serializedData.size());
177 } else {
178 Platform::current()->cacheMetadata(response().url(), response().response Time(), nullptr, 0);
179 }
180 }
181
182 class Resource::ServiceWorkerResponseCachedMetadataHandler : public Resource::Ca chedMetadataHandlerImpl {
183 public:
184 static Resource::CachedMetadataHandlerImpl* create(Resource* resource, Secur ityOrigin* securityOrigin)
185 {
186 return new ServiceWorkerResponseCachedMetadataHandler(resource, security Origin);
187 }
188 ~ServiceWorkerResponseCachedMetadataHandler() override {}
189 DECLARE_VIRTUAL_TRACE();
190
191 protected:
192 void sendToPlatform() override;
193
194 private:
195 explicit ServiceWorkerResponseCachedMetadataHandler(Resource*, SecurityOrigi n*);
196 String m_cacheStorageCacheName;
197 RefPtr<SecurityOrigin> m_securityOrigin;
198 };
199
200 Resource::ServiceWorkerResponseCachedMetadataHandler::ServiceWorkerResponseCache dMetadataHandler(Resource* resource, SecurityOrigin* securityOrigin)
201 : CachedMetadataHandlerImpl(resource)
202 , m_securityOrigin(securityOrigin)
203 {
204 }
205
206 DEFINE_TRACE(Resource::ServiceWorkerResponseCachedMetadataHandler)
207 {
208 CachedMetadataHandlerImpl::trace(visitor);
209 }
210
211 void Resource::ServiceWorkerResponseCachedMetadataHandler::sendToPlatform()
212 {
213 // We don't support sending the metadata to the platform when the response
214 // was directly fetched via a ServiceWorker
215 // (eg: FetchEvent.respondWith(fetch(FetchEvent.request))) to prevent an
216 // attacker's Service Worker from poisoning the metadata cache of HTTPCache.
217 if (response().cacheStorageCacheName().isNull())
218 return;
219
220 if (m_cachedMetadata) {
221 const Vector<char>& serializedData = m_cachedMetadata->serialize();
222 Platform::current()->cacheMetadataInCacheStorage(response().url(), respo nse().responseTime(), serializedData.data(), serializedData.size(), WebSecurityO rigin(m_securityOrigin), response().cacheStorageCacheName());
223 } else {
224 Platform::current()->cacheMetadataInCacheStorage(response().url(), respo nse().responseTime(), nullptr, 0, WebSecurityOrigin(m_securityOrigin), response( ).cacheStorageCacheName());
225 }
226 }
227
144 class Resource::ResourceCallback final : public GarbageCollectedFinalized<Resour ceCallback> { 228 class Resource::ResourceCallback final : public GarbageCollectedFinalized<Resour ceCallback> {
145 public: 229 public:
146 static ResourceCallback& callbackHandler(); 230 static ResourceCallback& callbackHandler();
147 DECLARE_TRACE(); 231 DECLARE_TRACE();
148 void schedule(Resource*); 232 void schedule(Resource*);
149 void cancel(Resource*); 233 void cancel(Resource*);
150 bool isScheduled(Resource*) const; 234 bool isScheduled(Resource*) const;
151 private: 235 private:
152 ResourceCallback(); 236 ResourceCallback();
153 237
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 , m_type(type) 308 , m_type(type)
225 , m_status(NotStarted) 309 , m_status(NotStarted)
226 , m_needsSynchronousCacheHit(false) 310 , m_needsSynchronousCacheHit(false)
227 , m_linkPreload(false) 311 , m_linkPreload(false)
228 { 312 {
229 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car eless updates of the enum. 313 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car eless updates of the enum.
230 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter); 314 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter);
231 315
232 // Currently we support the metadata caching only for HTTP family. 316 // Currently we support the metadata caching only for HTTP family.
233 if (m_resourceRequest.url().protocolIsInHTTPFamily()) 317 if (m_resourceRequest.url().protocolIsInHTTPFamily())
234 m_cacheHandler = CacheHandler::create(this); 318 m_cacheHandler = CachedMetadataHandlerImpl::create(this);
235 } 319 }
236 320
237 Resource::~Resource() 321 Resource::~Resource()
238 { 322 {
239 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter); 323 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter);
240 } 324 }
241 325
242 void Resource::removedFromMemoryCache() 326 void Resource::removedFromMemoryCache()
243 { 327 {
244 InspectorInstrumentation::removedResourceFromMemoryCache(this); 328 InspectorInstrumentation::removedResourceFromMemoryCache(this);
(...skipping 13 matching lines...) Expand all
258 return; 342 return;
259 343
260 RELEASE_ASSERT(!m_loader); 344 RELEASE_ASSERT(!m_loader);
261 ASSERT(stillNeedsLoad()); 345 ASSERT(stillNeedsLoad());
262 m_status = Pending; 346 m_status = Pending;
263 347
264 ResourceRequest& request(m_revalidatingRequest.isNull() ? m_resourceRequest : m_revalidatingRequest); 348 ResourceRequest& request(m_revalidatingRequest.isNull() ? m_resourceRequest : m_revalidatingRequest);
265 KURL url = request.url(); 349 KURL url = request.url();
266 request.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredC redentials); 350 request.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredC redentials);
267 351
352 m_fetcherSecurityOrigin = fetcher->context().getSecurityOrigin();
268 m_loader = ResourceLoader::create(fetcher, this); 353 m_loader = ResourceLoader::create(fetcher, this);
269 m_loader->start(request); 354 m_loader->start(request);
270 // If the request reference is null (i.e., a synchronous revalidation will 355 // If the request reference is null (i.e., a synchronous revalidation will
271 // null the request), don't make the request non-null by setting the url. 356 // null the request), don't make the request non-null by setting the url.
272 if (!request.isNull()) 357 if (!request.isNull())
273 request.setURL(url); 358 request.setURL(url);
274 } 359 }
275 360
276 void Resource::checkNotify() 361 void Resource::checkNotify()
277 { 362 {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 m_revalidatingRequest = request; 549 m_revalidatingRequest = request;
465 m_status = NotStarted; 550 m_status = NotStarted;
466 } 551 }
467 552
468 void Resource::willFollowRedirect(ResourceRequest& newRequest, const ResourceRes ponse& redirectResponse) 553 void Resource::willFollowRedirect(ResourceRequest& newRequest, const ResourceRes ponse& redirectResponse)
469 { 554 {
470 newRequest.setAllowStoredCredentials(m_options.allowCredentials == AllowStor edCredentials); 555 newRequest.setAllowStoredCredentials(m_options.allowCredentials == AllowStor edCredentials);
471 m_redirectChain.append(RedirectPair(newRequest, redirectResponse)); 556 m_redirectChain.append(RedirectPair(newRequest, redirectResponse));
472 } 557 }
473 558
559 void Resource::setResponse(const ResourceResponse& response)
560 {
561 m_response = response;
562 if (m_response.wasFetchedViaServiceWorker())
563 m_cacheHandler = ServiceWorkerResponseCachedMetadataHandler::create(this , m_fetcherSecurityOrigin.get());
564 }
565
474 bool Resource::unlock() 566 bool Resource::unlock()
475 { 567 {
476 if (!m_data) 568 if (!m_data)
477 return false; 569 return false;
478 570
479 if (!m_data->isLocked()) 571 if (!m_data->isLocked())
480 return true; 572 return true;
481 573
482 if (!memoryCache()->contains(this) || hasClientsOrObservers() || !m_revalida tingRequest.isNull() || !m_loadFinishTime || !isSafeToUnlock()) 574 if (!memoryCache()->contains(this) || hasClientsOrObservers() || !m_revalida tingRequest.isNull() || !m_loadFinishTime || !isSafeToUnlock())
483 return false; 575 return false;
(...skipping 14 matching lines...) Expand all
498 revalidationFailed(); 590 revalidationFailed();
499 } 591 }
500 setResponse(response); 592 setResponse(response);
501 String encoding = response.textEncodingName(); 593 String encoding = response.textEncodingName();
502 if (!encoding.isNull()) 594 if (!encoding.isNull())
503 setEncoding(encoding); 595 setEncoding(encoding);
504 } 596 }
505 597
506 void Resource::setSerializedCachedMetadata(const char* data, size_t size) 598 void Resource::setSerializedCachedMetadata(const char* data, size_t size)
507 { 599 {
508 // We only expect to receive cached metadata from the platform once.
509 // If this triggers, it indicates an efficiency problem which is most
510 // likely unexpected in code designed to improve performance.
511 ASSERT(!m_cachedMetadata);
512 ASSERT(m_revalidatingRequest.isNull()); 600 ASSERT(m_revalidatingRequest.isNull());
513 601 ASSERT(!m_response.isNull());
514 m_cachedMetadata = CachedMetadata::deserialize(data, size); 602 if (m_cacheHandler)
603 m_cacheHandler->setSerializedCachedMetadata(data, size);
515 } 604 }
516 605
517 CachedMetadataHandler* Resource::cacheHandler() 606 CachedMetadataHandler* Resource::cacheHandler()
518 { 607 {
519 return m_cacheHandler.get(); 608 return m_cacheHandler.get();
520 } 609 }
521 610
522 void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t s ize, CachedMetadataHandler::CacheType cacheType)
523 {
524 // Currently, only one type of cached metadata per resource is supported.
525 // If the need arises for multiple types of metadata per resource this could
526 // be enhanced to store types of metadata in a map.
527 ASSERT(!m_cachedMetadata);
528
529 m_cachedMetadata = CachedMetadata::create(dataTypeID, data, size);
530
531 // We don't support sending the metadata to the platform when the response
532 // was fetched via a ServiceWorker to prevent an attacker's Service Worker
533 // from poisoning the metadata cache.
534 // FIXME: Support sending the metadata even if the response was fetched via
535 // a ServiceWorker. https://crbug.com/448706
536 if (cacheType == CachedMetadataHandler::SendToPlatform && !m_response.wasFet chedViaServiceWorker()) {
537 const Vector<char>& serializedData = m_cachedMetadata->serialize();
538 Platform::current()->cacheMetadata(m_response.url(), m_response.response Time(), serializedData.data(), serializedData.size());
539 }
540 }
541
542 void Resource::clearCachedMetadata(CachedMetadataHandler::CacheType cacheType)
543 {
544 m_cachedMetadata.clear();
545
546 if (cacheType == CachedMetadataHandler::SendToPlatform)
547 Platform::current()->cacheMetadata(m_response.url(), m_response.response Time(), 0, 0);
548 }
549 611
550 String Resource::reasonNotDeletable() const 612 String Resource::reasonNotDeletable() const
551 { 613 {
552 StringBuilder builder; 614 StringBuilder builder;
553 if (hasClientsOrObservers()) { 615 if (hasClientsOrObservers()) {
554 builder.append("hasClients("); 616 builder.append("hasClients(");
555 builder.appendNumber(m_clients.size()); 617 builder.appendNumber(m_clients.size());
556 if (!m_clientsAwaitingCallback.isEmpty()) { 618 if (!m_clientsAwaitingCallback.isEmpty()) {
557 builder.append(", AwaitingCallback="); 619 builder.append(", AwaitingCallback=");
558 builder.appendNumber(m_clientsAwaitingCallback.size()); 620 builder.appendNumber(m_clientsAwaitingCallback.size());
(...skipping 17 matching lines...) Expand all
576 builder.append(")"); 638 builder.append(")");
577 } 639 }
578 if (memoryCache()->contains(this)) { 640 if (memoryCache()->contains(this)) {
579 if (!builder.isEmpty()) 641 if (!builder.isEmpty())
580 builder.append(' '); 642 builder.append(' ');
581 builder.append("in_memory_cache"); 643 builder.append("in_memory_cache");
582 } 644 }
583 return builder.toString(); 645 return builder.toString();
584 } 646 }
585 647
586 CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const
587 {
588 if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID)
589 return nullptr;
590 return m_cachedMetadata.get();
591 }
592
593 void Resource::clearLoader() 648 void Resource::clearLoader()
594 { 649 {
595 m_loader = nullptr; 650 m_loader = nullptr;
596 } 651 }
597 652
598 void Resource::didAddClient(ResourceClient* c) 653 void Resource::didAddClient(ResourceClient* c)
599 { 654 {
600 if (isLoaded()) { 655 if (isLoaded()) {
601 c->notifyFinished(this); 656 c->notifyFinished(this);
602 if (m_clients.contains(c)) { 657 if (m_clients.contains(c)) {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 m_resourceRequest = m_revalidatingRequest; 923 m_resourceRequest = m_revalidatingRequest;
869 m_revalidatingRequest = ResourceRequest(); 924 m_revalidatingRequest = ResourceRequest();
870 } 925 }
871 926
872 void Resource::revalidationFailed() 927 void Resource::revalidationFailed()
873 { 928 {
874 m_resourceRequest = m_revalidatingRequest; 929 m_resourceRequest = m_revalidatingRequest;
875 m_revalidatingRequest = ResourceRequest(); 930 m_revalidatingRequest = ResourceRequest();
876 m_redirectChain.clear(); 931 m_redirectChain.clear();
877 m_data.clear(); 932 m_data.clear();
878 m_cachedMetadata.clear(); 933 m_cacheHandler.clear();
879 destroyDecodedDataForFailedRevalidation(); 934 destroyDecodedDataForFailedRevalidation();
880 } 935 }
881 936
882 bool Resource::canReuseRedirectChain() 937 bool Resource::canReuseRedirectChain()
883 { 938 {
884 for (auto& redirect : m_redirectChain) { 939 for (auto& redirect : m_redirectChain) {
885 if (!canUseResponse(redirect.m_redirectResponse, m_responseTimestamp)) 940 if (!canUseResponse(redirect.m_redirectResponse, m_responseTimestamp))
886 return false; 941 return false;
887 if (redirect.m_request.cacheControlContainsNoCache() || redirect.m_reque st.cacheControlContainsNoStore()) 942 if (redirect.m_request.cacheControlContainsNoCache() || redirect.m_reque st.cacheControlContainsNoStore())
888 return false; 943 return false;
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 case Resource::Media: 1129 case Resource::Media:
1075 return "Media"; 1130 return "Media";
1076 case Resource::Manifest: 1131 case Resource::Manifest:
1077 return "Manifest"; 1132 return "Manifest";
1078 } 1133 }
1079 ASSERT_NOT_REACHED(); 1134 ASSERT_NOT_REACHED();
1080 return "Unknown"; 1135 return "Unknown";
1081 } 1136 }
1082 1137
1083 } // namespace blink 1138 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698