http_cache_transaction.cc 142 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/http/http_cache_transaction.h"
  5. #include "build/build_config.h" // For IS_POSIX
  6. #if BUILDFLAG(IS_POSIX)
  7. #include <unistd.h>
  8. #endif
  9. #include <algorithm>
  10. #include <memory>
  11. #include <string>
  12. #include <utility>
  13. #include "base/auto_reset.h"
  14. #include "base/bind.h"
  15. #include "base/callback_helpers.h"
  16. #include "base/compiler_specific.h"
  17. #include "base/containers/fixed_flat_set.h"
  18. #include "base/cxx17_backports.h"
  19. #include "base/format_macros.h"
  20. #include "base/location.h"
  21. #include "base/metrics/histogram_functions.h"
  22. #include "base/metrics/histogram_macros.h"
  23. #include "base/power_monitor/power_monitor.h"
  24. #include "base/strings/string_number_conversions.h" // For HexEncode.
  25. #include "base/strings/string_piece.h"
  26. #include "base/strings/string_util.h" // For EqualsCaseInsensitiveASCII.
  27. #include "base/task/single_thread_task_runner.h"
  28. #include "base/threading/thread_task_runner_handle.h"
  29. #include "base/time/clock.h"
  30. #include "base/trace_event/common/trace_event_common.h"
  31. #include "base/trace_event/trace_event.h"
  32. #include "base/values.h"
  33. #include "crypto/secure_hash.h"
  34. #include "crypto/sha2.h"
  35. #include "net/base/auth.h"
  36. #include "net/base/cache_metrics.h"
  37. #include "net/base/features.h"
  38. #include "net/base/load_flags.h"
  39. #include "net/base/load_timing_info.h"
  40. #include "net/base/trace_constants.h"
  41. #include "net/base/transport_info.h"
  42. #include "net/base/upload_data_stream.h"
  43. #include "net/cert/cert_status_flags.h"
  44. #include "net/cert/x509_certificate.h"
  45. #include "net/disk_cache/disk_cache.h"
  46. #include "net/http/http_cache_writers.h"
  47. #include "net/http/http_log_util.h"
  48. #include "net/http/http_network_session.h"
  49. #include "net/http/http_request_info.h"
  50. #include "net/http/http_status_code.h"
  51. #include "net/http/http_util.h"
  52. #include "net/http/webfonts_histogram.h"
  53. #include "net/log/net_log_event_type.h"
  54. #include "net/ssl/ssl_cert_request_info.h"
  55. #include "net/ssl/ssl_config_service.h"
  56. using base::Time;
  57. using base::TimeTicks;
  58. namespace net {
  59. using CacheEntryStatus = HttpResponseInfo::CacheEntryStatus;
  60. namespace {
  61. constexpr base::TimeDelta kStaleRevalidateTimeout = base::Seconds(60);
  62. uint64_t GetNextTraceId(HttpCache* cache) {
  63. static uint32_t sNextTraceId = 0;
  64. DCHECK(cache);
  65. return (reinterpret_cast<uint64_t>(cache) << 32) | sNextTraceId++;
  66. }
  67. // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
  68. // a "non-error response" is one with a 2xx (Successful) or 3xx
  69. // (Redirection) status code.
  70. bool NonErrorResponse(int status_code) {
  71. int status_code_range = status_code / 100;
  72. return status_code_range == 2 || status_code_range == 3;
  73. }
  74. bool IsOnBatteryPower() {
  75. if (base::PowerMonitor::IsInitialized())
  76. return base::PowerMonitor::IsOnBatteryPower();
  77. return false;
  78. }
  79. enum ExternallyConditionalizedType {
  80. EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION,
  81. EXTERNALLY_CONDITIONALIZED_CACHE_USABLE,
  82. EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS,
  83. EXTERNALLY_CONDITIONALIZED_MAX
  84. };
  85. // These values are persisted to logs. Entries should not be renumbered and
  86. // numeric values should never be reused.
  87. enum class RestrictedPrefetchReused {
  88. kNotReused = 0,
  89. kReused = 1,
  90. kMaxValue = kReused
  91. };
  92. void RecordPervasivePayloadIndex(const char* histogram_name, int index) {
  93. if (index != -1) {
  94. base::UmaHistogramExactLinear(histogram_name, index, 101);
  95. }
  96. }
  97. } // namespace
  98. #define CACHE_STATUS_HISTOGRAMS(type) \
  99. UMA_HISTOGRAM_ENUMERATION("HttpCache.Pattern" type, cache_entry_status_, \
  100. CacheEntryStatus::ENTRY_MAX)
  101. struct HeaderNameAndValue {
  102. const char* name;
  103. const char* value;
  104. };
  105. // If the request includes one of these request headers, then avoid caching
  106. // to avoid getting confused.
  107. static const HeaderNameAndValue kPassThroughHeaders[] = {
  108. {"if-unmodified-since", nullptr}, // causes unexpected 412s
  109. {"if-match", nullptr}, // causes unexpected 412s
  110. {"if-range", nullptr},
  111. {nullptr, nullptr}};
  112. struct ValidationHeaderInfo {
  113. const char* request_header_name;
  114. const char* related_response_header_name;
  115. };
  116. static const ValidationHeaderInfo kValidationHeaders[] = {
  117. { "if-modified-since", "last-modified" },
  118. { "if-none-match", "etag" },
  119. };
  120. // If the request includes one of these request headers, then avoid reusing
  121. // our cached copy if any.
  122. static const HeaderNameAndValue kForceFetchHeaders[] = {
  123. {"cache-control", "no-cache"},
  124. {"pragma", "no-cache"},
  125. {nullptr, nullptr}};
  126. // If the request includes one of these request headers, then force our
  127. // cached copy (if any) to be revalidated before reusing it.
  128. static const HeaderNameAndValue kForceValidateHeaders[] = {
  129. {"cache-control", "max-age=0"},
  130. {nullptr, nullptr}};
  131. static bool HeaderMatches(const HttpRequestHeaders& headers,
  132. const HeaderNameAndValue* search) {
  133. for (; search->name; ++search) {
  134. std::string header_value;
  135. if (!headers.GetHeader(search->name, &header_value))
  136. continue;
  137. if (!search->value)
  138. return true;
  139. HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ',');
  140. while (v.GetNext()) {
  141. if (base::EqualsCaseInsensitiveASCII(v.value_piece(), search->value))
  142. return true;
  143. }
  144. }
  145. return false;
  146. }
  147. //-----------------------------------------------------------------------------
  148. HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache)
  149. : trace_id_(GetNextTraceId(cache)),
  150. priority_(priority),
  151. cache_(cache->GetWeakPtr()) {
  152. TRACE_EVENT1("net", "HttpCacheTransaction::Transaction", "priority",
  153. RequestPriorityToString(priority));
  154. static_assert(HttpCache::Transaction::kNumValidationHeaders ==
  155. std::size(kValidationHeaders),
  156. "invalid number of validation headers");
  157. io_callback_ = base::BindRepeating(&Transaction::OnIOComplete,
  158. weak_factory_.GetWeakPtr());
  159. }
  160. HttpCache::Transaction::~Transaction() {
  161. TRACE_EVENT0("net", "HttpCacheTransaction::~Transaction");
  162. RecordHistograms();
  163. // We may have to issue another IO, but we should never invoke the callback_
  164. // after this point.
  165. callback_.Reset();
  166. if (cache_) {
  167. if (entry_) {
  168. DoneWithEntry(false /* entry_is_complete */);
  169. } else if (cache_pending_) {
  170. cache_->RemovePendingTransaction(this);
  171. }
  172. }
  173. }
  174. HttpCache::Transaction::Mode HttpCache::Transaction::mode() const {
  175. return mode_;
  176. }
  177. LoadState HttpCache::Transaction::GetWriterLoadState() const {
  178. const HttpTransaction* transaction = network_transaction();
  179. if (transaction)
  180. return transaction->GetLoadState();
  181. if (entry_ || !request_)
  182. return LOAD_STATE_IDLE;
  183. return LOAD_STATE_WAITING_FOR_CACHE;
  184. }
  185. const NetLogWithSource& HttpCache::Transaction::net_log() const {
  186. return net_log_;
  187. }
  188. int HttpCache::Transaction::Start(const HttpRequestInfo* request,
  189. CompletionOnceCallback callback,
  190. const NetLogWithSource& net_log) {
  191. DCHECK(request);
  192. DCHECK(!callback.is_null());
  193. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::Start",
  194. TRACE_ID_LOCAL(trace_id_), TRACE_EVENT_FLAG_FLOW_OUT,
  195. "url", request->url.spec());
  196. // Ensure that we only have one asynchronous call at a time.
  197. DCHECK(callback_.is_null());
  198. DCHECK(!reading_);
  199. DCHECK(!network_trans_.get());
  200. DCHECK(!entry_);
  201. DCHECK_EQ(next_state_, STATE_NONE);
  202. if (!cache_.get())
  203. return ERR_UNEXPECTED;
  204. initial_request_ = request;
  205. SetRequest(net_log);
  206. // We have to wait until the backend is initialized so we start the SM.
  207. next_state_ = STATE_GET_BACKEND;
  208. int rv = DoLoop(OK);
  209. // Setting this here allows us to check for the existence of a callback_ to
  210. // determine if we are still inside Start.
  211. if (rv == ERR_IO_PENDING)
  212. callback_ = std::move(callback);
  213. return rv;
  214. }
  215. int HttpCache::Transaction::RestartIgnoringLastError(
  216. CompletionOnceCallback callback) {
  217. DCHECK(!callback.is_null());
  218. // Ensure that we only have one asynchronous call at a time.
  219. DCHECK(callback_.is_null());
  220. if (!cache_.get())
  221. return ERR_UNEXPECTED;
  222. int rv = RestartNetworkRequest();
  223. if (rv == ERR_IO_PENDING)
  224. callback_ = std::move(callback);
  225. return rv;
  226. }
  227. int HttpCache::Transaction::RestartWithCertificate(
  228. scoped_refptr<X509Certificate> client_cert,
  229. scoped_refptr<SSLPrivateKey> client_private_key,
  230. CompletionOnceCallback callback) {
  231. DCHECK(!callback.is_null());
  232. // Ensure that we only have one asynchronous call at a time.
  233. DCHECK(callback_.is_null());
  234. if (!cache_.get())
  235. return ERR_UNEXPECTED;
  236. int rv = RestartNetworkRequestWithCertificate(std::move(client_cert),
  237. std::move(client_private_key));
  238. if (rv == ERR_IO_PENDING)
  239. callback_ = std::move(callback);
  240. return rv;
  241. }
  242. int HttpCache::Transaction::RestartWithAuth(const AuthCredentials& credentials,
  243. CompletionOnceCallback callback) {
  244. DCHECK(auth_response_.headers.get());
  245. DCHECK(!callback.is_null());
  246. // Ensure that we only have one asynchronous call at a time.
  247. DCHECK(callback_.is_null());
  248. if (!cache_.get())
  249. return ERR_UNEXPECTED;
  250. // Clear the intermediate response since we are going to start over.
  251. SetAuthResponse(HttpResponseInfo());
  252. int rv = RestartNetworkRequestWithAuth(credentials);
  253. if (rv == ERR_IO_PENDING)
  254. callback_ = std::move(callback);
  255. return rv;
  256. }
  257. bool HttpCache::Transaction::IsReadyToRestartForAuth() {
  258. if (!network_trans_.get())
  259. return false;
  260. return network_trans_->IsReadyToRestartForAuth();
  261. }
  262. int HttpCache::Transaction::Read(IOBuffer* buf,
  263. int buf_len,
  264. CompletionOnceCallback callback) {
  265. TRACE_EVENT_WITH_FLOW1(
  266. "net", "HttpCacheTransaction::Read", TRACE_ID_LOCAL(trace_id_),
  267. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "buf_len", buf_len);
  268. DCHECK_EQ(next_state_, STATE_NONE);
  269. DCHECK(buf);
  270. // TODO(https://crbug.com/1335423): Change to DCHECK_GT() or remove after bug
  271. // is fixed.
  272. CHECK_GT(buf_len, 0);
  273. DCHECK(!callback.is_null());
  274. DCHECK(callback_.is_null());
  275. if (!cache_.get())
  276. return ERR_UNEXPECTED;
  277. // If we have an intermediate auth response at this point, then it means the
  278. // user wishes to read the network response (the error page). If there is a
  279. // previous response in the cache then we should leave it intact.
  280. if (auth_response_.headers.get() && mode_ != NONE) {
  281. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  282. DCHECK(mode_ & WRITE);
  283. bool stopped = StopCachingImpl(mode_ == READ_WRITE);
  284. DCHECK(stopped);
  285. }
  286. reading_ = true;
  287. read_buf_ = buf;
  288. read_buf_len_ = buf_len;
  289. int rv = TransitionToReadingState();
  290. if (rv != OK || next_state_ == STATE_NONE)
  291. return rv;
  292. rv = DoLoop(OK);
  293. if (rv == ERR_IO_PENDING) {
  294. DCHECK(callback_.is_null());
  295. callback_ = std::move(callback);
  296. }
  297. return rv;
  298. }
  299. int HttpCache::Transaction::TransitionToReadingState() {
  300. if (!entry_) {
  301. if (network_trans_) {
  302. // This can happen when the request should be handled exclusively by
  303. // the network layer (skipping the cache entirely using
  304. // LOAD_DISABLE_CACHE) or there was an error during the headers phase
  305. // due to which the transaction cannot write to the cache or the consumer
  306. // is reading the auth response from the network.
  307. // TODO(http://crbug.com/740947) to get rid of this state in future.
  308. next_state_ = STATE_NETWORK_READ;
  309. return OK;
  310. }
  311. // If there is no network, and no cache entry, then there is nothing to read
  312. // from.
  313. next_state_ = STATE_NONE;
  314. // An error state should be set for the next read, else this transaction
  315. // should have been terminated once it reached this state. To assert we
  316. // could dcheck that shared_writing_error_ is set to a valid error value but
  317. // in some specific conditions (http://crbug.com/806344) it's possible that
  318. // the consumer does an extra Read in which case the assert will fail.
  319. return shared_writing_error_;
  320. }
  321. // If entry_ is present, the transaction is either a member of entry_->writers
  322. // or readers.
  323. if (!InWriters()) {
  324. // Since transaction is not a writer and we are in Read(), it must be a
  325. // reader.
  326. DCHECK(entry_->TransactionInReaders(this));
  327. DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
  328. next_state_ = STATE_CACHE_READ_DATA;
  329. return OK;
  330. }
  331. DCHECK(mode_ & WRITE || mode_ == NONE);
  332. // If it's a writer and it is partial then it may need to read from the cache
  333. // or from the network based on whether network transaction is present or not.
  334. if (partial_) {
  335. if (entry_->writers->network_transaction())
  336. next_state_ = STATE_NETWORK_READ_CACHE_WRITE;
  337. else
  338. next_state_ = STATE_CACHE_READ_DATA;
  339. return OK;
  340. }
  341. // Full request.
  342. // If it's a writer and a full request then it may read from the cache if its
  343. // offset is behind the current offset else from the network.
  344. int disk_entry_size = entry_->GetEntry()->GetDataSize(kResponseContentIndex);
  345. if (read_offset_ == disk_entry_size || entry_->writers->network_read_only()) {
  346. next_state_ = STATE_NETWORK_READ_CACHE_WRITE;
  347. } else {
  348. DCHECK_LT(read_offset_, disk_entry_size);
  349. next_state_ = STATE_CACHE_READ_DATA;
  350. }
  351. return OK;
  352. }
  353. void HttpCache::Transaction::StopCaching() {
  354. // We really don't know where we are now. Hopefully there is no operation in
  355. // progress, but nothing really prevents this method to be called after we
  356. // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this
  357. // point because we need the state machine for that (and even if we are really
  358. // free, that would be an asynchronous operation). In other words, keep the
  359. // entry how it is (it will be marked as truncated at destruction), and let
  360. // the next piece of code that executes know that we are now reading directly
  361. // from the net.
  362. if (cache_.get() && (mode_ & WRITE) && !is_sparse_ && !range_requested_ &&
  363. network_transaction()) {
  364. StopCachingImpl(false);
  365. }
  366. }
  367. int64_t HttpCache::Transaction::GetTotalReceivedBytes() const {
  368. int64_t total_received_bytes = network_transaction_info_.total_received_bytes;
  369. const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
  370. if (transaction)
  371. total_received_bytes += transaction->GetTotalReceivedBytes();
  372. return total_received_bytes;
  373. }
  374. int64_t HttpCache::Transaction::GetTotalSentBytes() const {
  375. int64_t total_sent_bytes = network_transaction_info_.total_sent_bytes;
  376. const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
  377. if (transaction)
  378. total_sent_bytes += transaction->GetTotalSentBytes();
  379. return total_sent_bytes;
  380. }
  381. void HttpCache::Transaction::DoneReading() {
  382. if (cache_.get() && entry_) {
  383. DCHECK_NE(mode_, UPDATE);
  384. DoneWithEntry(true);
  385. }
  386. }
  387. const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
  388. // Null headers means we encountered an error or haven't a response yet
  389. if (auth_response_.headers.get()) {
  390. DCHECK_EQ(cache_entry_status_, auth_response_.cache_entry_status)
  391. << "These must be in sync via SetResponse and SetAuthResponse.";
  392. return &auth_response_;
  393. }
  394. // TODO(https://crbug.com/1219402): This should check in `response_`
  395. return &response_;
  396. }
  397. LoadState HttpCache::Transaction::GetLoadState() const {
  398. // If there's no pending callback, the ball is not in the
  399. // HttpCache::Transaction's court, whatever else may be going on.
  400. if (!callback_)
  401. return LOAD_STATE_IDLE;
  402. LoadState state = GetWriterLoadState();
  403. if (state != LOAD_STATE_WAITING_FOR_CACHE)
  404. return state;
  405. if (cache_.get())
  406. return cache_->GetLoadStateForPendingTransaction(this);
  407. return LOAD_STATE_IDLE;
  408. }
  409. void HttpCache::Transaction::SetQuicServerInfo(
  410. QuicServerInfo* quic_server_info) {}
  411. bool HttpCache::Transaction::GetLoadTimingInfo(
  412. LoadTimingInfo* load_timing_info) const {
  413. const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
  414. if (transaction)
  415. return transaction->GetLoadTimingInfo(load_timing_info);
  416. if (network_transaction_info_.old_network_trans_load_timing) {
  417. *load_timing_info =
  418. *network_transaction_info_.old_network_trans_load_timing;
  419. return true;
  420. }
  421. if (first_cache_access_since_.is_null())
  422. return false;
  423. // If the cache entry was opened, return that time.
  424. load_timing_info->send_start = first_cache_access_since_;
  425. // This time doesn't make much sense when reading from the cache, so just use
  426. // the same time as send_start.
  427. load_timing_info->send_end = first_cache_access_since_;
  428. // Provide the time immediately before parsing a cached entry.
  429. load_timing_info->receive_headers_start = read_headers_since_;
  430. return true;
  431. }
  432. bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
  433. const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
  434. if (transaction)
  435. return transaction->GetRemoteEndpoint(endpoint);
  436. if (!network_transaction_info_.old_remote_endpoint.address().empty()) {
  437. *endpoint = network_transaction_info_.old_remote_endpoint;
  438. return true;
  439. }
  440. return false;
  441. }
  442. void HttpCache::Transaction::PopulateNetErrorDetails(
  443. NetErrorDetails* details) const {
  444. const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
  445. if (transaction)
  446. return transaction->PopulateNetErrorDetails(details);
  447. return;
  448. }
  449. void HttpCache::Transaction::SetPriority(RequestPriority priority) {
  450. priority_ = priority;
  451. if (network_trans_)
  452. network_trans_->SetPriority(priority_);
  453. if (InWriters()) {
  454. DCHECK(!network_trans_ || partial_);
  455. entry_->writers->UpdatePriority();
  456. }
  457. }
  458. void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
  459. WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
  460. websocket_handshake_stream_base_create_helper_ = create_helper;
  461. // TODO(shivanisha). Since this function must be invoked before Start() as
  462. // per the API header, a network transaction should not exist at that point.
  463. HttpTransaction* transaction = network_transaction();
  464. if (transaction)
  465. transaction->SetWebSocketHandshakeStreamCreateHelper(create_helper);
  466. }
  467. void HttpCache::Transaction::SetBeforeNetworkStartCallback(
  468. BeforeNetworkStartCallback callback) {
  469. DCHECK(!network_trans_);
  470. before_network_start_callback_ = std::move(callback);
  471. }
  472. void HttpCache::Transaction::SetConnectedCallback(
  473. const ConnectedCallback& callback) {
  474. DCHECK(!network_trans_);
  475. connected_callback_ = callback;
  476. }
  477. void HttpCache::Transaction::SetRequestHeadersCallback(
  478. RequestHeadersCallback callback) {
  479. DCHECK(!network_trans_);
  480. request_headers_callback_ = std::move(callback);
  481. }
  482. void HttpCache::Transaction::SetResponseHeadersCallback(
  483. ResponseHeadersCallback callback) {
  484. DCHECK(!network_trans_);
  485. response_headers_callback_ = std::move(callback);
  486. }
  487. void HttpCache::Transaction::SetEarlyResponseHeadersCallback(
  488. ResponseHeadersCallback callback) {
  489. DCHECK(!network_trans_);
  490. early_response_headers_callback_ = std::move(callback);
  491. }
  492. int HttpCache::Transaction::ResumeNetworkStart() {
  493. if (network_trans_)
  494. return network_trans_->ResumeNetworkStart();
  495. return ERR_UNEXPECTED;
  496. }
  497. ConnectionAttempts HttpCache::Transaction::GetConnectionAttempts() const {
  498. ConnectionAttempts attempts;
  499. const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
  500. if (transaction)
  501. attempts = transaction->GetConnectionAttempts();
  502. attempts.insert(attempts.begin(),
  503. network_transaction_info_.old_connection_attempts.begin(),
  504. network_transaction_info_.old_connection_attempts.end());
  505. return attempts;
  506. }
  507. void HttpCache::Transaction::CloseConnectionOnDestruction() {
  508. if (network_trans_) {
  509. network_trans_->CloseConnectionOnDestruction();
  510. } else if (InWriters()) {
  511. entry_->writers->CloseConnectionOnDestruction();
  512. }
  513. }
  514. void HttpCache::Transaction::SetValidatingCannotProceed() {
  515. DCHECK(!reading_);
  516. // Ensure this transaction is waiting for a callback.
  517. DCHECK_NE(STATE_UNSET, next_state_);
  518. next_state_ = STATE_HEADERS_PHASE_CANNOT_PROCEED;
  519. entry_ = nullptr;
  520. }
  521. void HttpCache::Transaction::WriterAboutToBeRemovedFromEntry(int result) {
  522. TRACE_EVENT_WITH_FLOW1(
  523. "net", "HttpCacheTransaction::WriterAboutToBeRemovedFromEntry",
  524. TRACE_ID_LOCAL(trace_id_),
  525. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result", result);
  526. // Since the transaction can no longer access the network transaction, save
  527. // all network related info now.
  528. if (moved_network_transaction_to_writers_ &&
  529. entry_->writers->network_transaction()) {
  530. SaveNetworkTransactionInfo(*(entry_->writers->network_transaction()));
  531. }
  532. entry_ = nullptr;
  533. mode_ = NONE;
  534. // Transactions in the midst of a Read call through writers will get any error
  535. // code through the IO callback but for idle transactions/transactions reading
  536. // from the cache, the error for a future Read must be stored here.
  537. if (result < 0)
  538. shared_writing_error_ = result;
  539. }
  540. void HttpCache::Transaction::WriteModeTransactionAboutToBecomeReader() {
  541. TRACE_EVENT_WITH_FLOW0(
  542. "net", "HttpCacheTransaction::WriteModeTransactionAboutToBecomeReader",
  543. TRACE_ID_LOCAL(trace_id_),
  544. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  545. mode_ = READ;
  546. if (moved_network_transaction_to_writers_ &&
  547. entry_->writers->network_transaction()) {
  548. SaveNetworkTransactionInfo(*(entry_->writers->network_transaction()));
  549. }
  550. }
  551. bool HttpCache::Transaction::ResponseChecksumMatches(
  552. std::unique_ptr<crypto::SecureHash> checksum) const {
  553. DCHECK(checksum);
  554. uint8_t result[crypto::kSHA256Length];
  555. checksum->Finish(result, crypto::kSHA256Length);
  556. const std::string hex_result = base::HexEncode(result);
  557. if (hex_result != request_->checksum) {
  558. DVLOG(2) << "Pervasive payload checksum mismatch for \"" << request_->url
  559. << "\": got " << hex_result << ", expected " << request_->checksum;
  560. RecordPervasivePayloadIndex("Network.CacheTransparency.MismatchedChecksums",
  561. request_->pervasive_payloads_index_for_logging);
  562. return false;
  563. }
  564. RecordPervasivePayloadIndex(
  565. "Network.CacheTransparency.SingleKeyedCacheIsUsed",
  566. request_->pervasive_payloads_index_for_logging);
  567. return true;
  568. }
  569. //-----------------------------------------------------------------------------
  570. // A few common patterns: (Foo* means Foo -> FooComplete)
  571. //
  572. // 1. Not-cached entry:
  573. // Start():
  574. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
  575. // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
  576. // CacheWriteResponse* -> TruncateCachedData* -> PartialHeadersReceived ->
  577. // FinishHeaders*
  578. //
  579. // Read():
  580. // NetworkReadCacheWrite*/CacheReadData* (if other writers are also writing to
  581. // the cache)
  582. //
  583. // 2. Cached entry, no validation:
  584. // Start():
  585. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
  586. // CacheReadResponse* -> CacheDispatchValidation ->
  587. // BeginPartialCacheValidation() -> BeginCacheValidation() ->
  588. // ConnectedCallback* -> SetupEntryForRead() -> FinishHeaders*
  589. //
  590. // Read():
  591. // CacheReadData*
  592. //
  593. // 3. Cached entry, validation (304):
  594. // Start():
  595. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
  596. // CacheReadResponse* -> CacheDispatchValidation ->
  597. // BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
  598. // SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteUpdatedResponse*
  599. // -> UpdateCachedResponseComplete -> OverwriteCachedResponse ->
  600. // PartialHeadersReceived -> FinishHeaders*
  601. //
  602. // Read():
  603. // CacheReadData*
  604. //
  605. // 4. Cached entry, validation and replace (200):
  606. // Start():
  607. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
  608. // CacheReadResponse* -> CacheDispatchValidation ->
  609. // BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
  610. // SuccessfulSendRequest -> OverwriteCachedResponse -> CacheWriteResponse* ->
  611. // DoTruncateCachedData* -> PartialHeadersReceived -> FinishHeaders*
  612. //
  613. // Read():
  614. // NetworkReadCacheWrite*/CacheReadData* (if other writers are also writing to
  615. // the cache)
  616. //
  617. // 5. Sparse entry, partially cached, byte range request:
  618. // Start():
  619. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
  620. // CacheReadResponse* -> CacheDispatchValidation ->
  621. // BeginPartialCacheValidation() -> CacheQueryData* ->
  622. // ValidateEntryHeadersAndContinue() -> StartPartialCacheValidation ->
  623. // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
  624. // SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteUpdatedResponse*
  625. // -> UpdateCachedResponseComplete -> OverwriteCachedResponse ->
  626. // PartialHeadersReceived -> FinishHeaders*
  627. //
  628. // Read() 1:
  629. // NetworkReadCacheWrite*
  630. //
  631. // Read() 2:
  632. // NetworkReadCacheWrite* -> StartPartialCacheValidation ->
  633. // CompletePartialCacheValidation -> ConnectedCallback* -> CacheReadData*
  634. //
  635. // Read() 3:
  636. // CacheReadData* -> StartPartialCacheValidation ->
  637. // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
  638. // SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse
  639. // -> PartialHeadersReceived -> NetworkReadCacheWrite*
  640. //
  641. // 6. HEAD. Not-cached entry:
  642. // Pass through. Don't save a HEAD by itself.
  643. // Start():
  644. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> SendRequest*
  645. //
  646. // 7. HEAD. Cached entry, no validation:
  647. // Start():
  648. // The same flow as for a GET request (example #2)
  649. //
  650. // Read():
  651. // CacheReadData (returns 0)
  652. //
  653. // 8. HEAD. Cached entry, validation (304):
  654. // The request updates the stored headers.
  655. // Start(): Same as for a GET request (example #3)
  656. //
  657. // Read():
  658. // CacheReadData (returns 0)
  659. //
  660. // 9. HEAD. Cached entry, validation and replace (200):
  661. // Pass through. The request dooms the old entry, as a HEAD won't be stored by
  662. // itself.
  663. // Start():
  664. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
  665. // CacheReadResponse* -> CacheDispatchValidation ->
  666. // BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
  667. // SuccessfulSendRequest -> OverwriteCachedResponse -> FinishHeaders*
  668. //
  669. // 10. HEAD. Sparse entry, partially cached:
  670. // Serve the request from the cache, as long as it doesn't require
  671. // revalidation. Ignore missing ranges when deciding to revalidate. If the
  672. // entry requires revalidation, ignore the whole request and go to full pass
  673. // through (the result of the HEAD request will NOT update the entry).
  674. //
  675. // Start(): Basically the same as example 7, as we never create a partial_
  676. // object for this request.
  677. //
  678. // 11. Prefetch, not-cached entry:
  679. // The same as example 1. The "unused_since_prefetch" bit is stored as true in
  680. // UpdateCachedResponse.
  681. //
  682. // 12. Prefetch, cached entry:
  683. // Like examples 2-4, only CacheWriteUpdatedPrefetchResponse* is inserted
  684. // between CacheReadResponse* and CacheDispatchValidation if the
  685. // unused_since_prefetch bit is unset.
  686. //
  687. // 13. Cached entry less than 5 minutes old, unused_since_prefetch is true:
  688. // Skip validation, similar to example 2.
  689. // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
  690. // CacheReadResponse* -> CacheToggleUnusedSincePrefetch* ->
  691. // CacheDispatchValidation -> BeginPartialCacheValidation() ->
  692. // BeginCacheValidation() -> ConnectedCallback* -> SetupEntryForRead() ->
  693. // FinishHeaders*
  694. //
  695. // Read():
  696. // CacheReadData*
  697. //
  698. // 14. Cached entry more than 5 minutes old, unused_since_prefetch is true:
  699. // Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between
  700. // CacheReadResponse* and CacheDispatchValidation.
  701. int HttpCache::Transaction::DoLoop(int result) {
  702. DCHECK_NE(STATE_UNSET, next_state_);
  703. DCHECK_NE(STATE_NONE, next_state_);
  704. DCHECK(!in_do_loop_);
  705. int rv = result;
  706. State state = next_state_;
  707. do {
  708. state = next_state_;
  709. next_state_ = STATE_UNSET;
  710. base::AutoReset<bool> scoped_in_do_loop(&in_do_loop_, true);
  711. switch (state) {
  712. case STATE_GET_BACKEND:
  713. DCHECK_EQ(OK, rv);
  714. rv = DoGetBackend();
  715. break;
  716. case STATE_GET_BACKEND_COMPLETE:
  717. rv = DoGetBackendComplete(rv);
  718. break;
  719. case STATE_INIT_ENTRY:
  720. DCHECK_EQ(OK, rv);
  721. rv = DoInitEntry();
  722. break;
  723. case STATE_OPEN_OR_CREATE_ENTRY:
  724. DCHECK_EQ(OK, rv);
  725. rv = DoOpenOrCreateEntry();
  726. break;
  727. case STATE_OPEN_OR_CREATE_ENTRY_COMPLETE:
  728. rv = DoOpenOrCreateEntryComplete(rv);
  729. break;
  730. case STATE_DOOM_ENTRY:
  731. DCHECK_EQ(OK, rv);
  732. rv = DoDoomEntry();
  733. break;
  734. case STATE_DOOM_ENTRY_COMPLETE:
  735. rv = DoDoomEntryComplete(rv);
  736. break;
  737. case STATE_CREATE_ENTRY:
  738. DCHECK_EQ(OK, rv);
  739. rv = DoCreateEntry();
  740. break;
  741. case STATE_CREATE_ENTRY_COMPLETE:
  742. rv = DoCreateEntryComplete(rv);
  743. break;
  744. case STATE_ADD_TO_ENTRY:
  745. DCHECK_EQ(OK, rv);
  746. rv = DoAddToEntry();
  747. break;
  748. case STATE_ADD_TO_ENTRY_COMPLETE:
  749. rv = DoAddToEntryComplete(rv);
  750. break;
  751. case STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE:
  752. rv = DoDoneHeadersAddToEntryComplete(rv);
  753. break;
  754. case STATE_CACHE_READ_RESPONSE:
  755. DCHECK_EQ(OK, rv);
  756. rv = DoCacheReadResponse();
  757. break;
  758. case STATE_CACHE_READ_RESPONSE_COMPLETE:
  759. rv = DoCacheReadResponseComplete(rv);
  760. break;
  761. case STATE_WRITE_UPDATED_PREFETCH_RESPONSE:
  762. DCHECK_EQ(OK, rv);
  763. rv = DoCacheWriteUpdatedPrefetchResponse(rv);
  764. break;
  765. case STATE_WRITE_UPDATED_PREFETCH_RESPONSE_COMPLETE:
  766. rv = DoCacheWriteUpdatedPrefetchResponseComplete(rv);
  767. break;
  768. case STATE_CACHE_DISPATCH_VALIDATION:
  769. DCHECK_EQ(OK, rv);
  770. rv = DoCacheDispatchValidation();
  771. break;
  772. case STATE_CACHE_QUERY_DATA:
  773. DCHECK_EQ(OK, rv);
  774. rv = DoCacheQueryData();
  775. break;
  776. case STATE_CACHE_QUERY_DATA_COMPLETE:
  777. rv = DoCacheQueryDataComplete(rv);
  778. break;
  779. case STATE_START_PARTIAL_CACHE_VALIDATION:
  780. DCHECK_EQ(OK, rv);
  781. rv = DoStartPartialCacheValidation();
  782. break;
  783. case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION:
  784. rv = DoCompletePartialCacheValidation(rv);
  785. break;
  786. case STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT:
  787. DCHECK_EQ(OK, rv);
  788. rv = DoCacheUpdateStaleWhileRevalidateTimeout();
  789. break;
  790. case STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT_COMPLETE:
  791. rv = DoCacheUpdateStaleWhileRevalidateTimeoutComplete(rv);
  792. break;
  793. case STATE_CONNECTED_CALLBACK:
  794. rv = DoConnectedCallback();
  795. break;
  796. case STATE_CONNECTED_CALLBACK_COMPLETE:
  797. rv = DoConnectedCallbackComplete(rv);
  798. break;
  799. case STATE_SETUP_ENTRY_FOR_READ:
  800. DCHECK_EQ(OK, rv);
  801. rv = DoSetupEntryForRead();
  802. break;
  803. case STATE_SEND_REQUEST:
  804. DCHECK_EQ(OK, rv);
  805. rv = DoSendRequest();
  806. break;
  807. case STATE_SEND_REQUEST_COMPLETE:
  808. rv = DoSendRequestComplete(rv);
  809. break;
  810. case STATE_SUCCESSFUL_SEND_REQUEST:
  811. DCHECK_EQ(OK, rv);
  812. rv = DoSuccessfulSendRequest();
  813. break;
  814. case STATE_UPDATE_CACHED_RESPONSE:
  815. DCHECK_EQ(OK, rv);
  816. rv = DoUpdateCachedResponse();
  817. break;
  818. case STATE_CACHE_WRITE_UPDATED_RESPONSE:
  819. DCHECK_EQ(OK, rv);
  820. rv = DoCacheWriteUpdatedResponse();
  821. break;
  822. case STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE:
  823. rv = DoCacheWriteUpdatedResponseComplete(rv);
  824. break;
  825. case STATE_UPDATE_CACHED_RESPONSE_COMPLETE:
  826. rv = DoUpdateCachedResponseComplete(rv);
  827. break;
  828. case STATE_OVERWRITE_CACHED_RESPONSE:
  829. DCHECK_EQ(OK, rv);
  830. rv = DoOverwriteCachedResponse();
  831. break;
  832. case STATE_CACHE_WRITE_RESPONSE:
  833. DCHECK_EQ(OK, rv);
  834. rv = DoCacheWriteResponse();
  835. break;
  836. case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
  837. rv = DoCacheWriteResponseComplete(rv);
  838. break;
  839. case STATE_TRUNCATE_CACHED_DATA:
  840. DCHECK_EQ(OK, rv);
  841. rv = DoTruncateCachedData();
  842. break;
  843. case STATE_TRUNCATE_CACHED_DATA_COMPLETE:
  844. rv = DoTruncateCachedDataComplete(rv);
  845. break;
  846. case STATE_PARTIAL_HEADERS_RECEIVED:
  847. DCHECK_EQ(OK, rv);
  848. rv = DoPartialHeadersReceived();
  849. break;
  850. case STATE_HEADERS_PHASE_CANNOT_PROCEED:
  851. rv = DoHeadersPhaseCannotProceed(rv);
  852. break;
  853. case STATE_FINISH_HEADERS:
  854. rv = DoFinishHeaders(rv);
  855. break;
  856. case STATE_FINISH_HEADERS_COMPLETE:
  857. rv = DoFinishHeadersComplete(rv);
  858. break;
  859. case STATE_NETWORK_READ_CACHE_WRITE:
  860. DCHECK_EQ(OK, rv);
  861. rv = DoNetworkReadCacheWrite();
  862. break;
  863. case STATE_NETWORK_READ_CACHE_WRITE_COMPLETE:
  864. rv = DoNetworkReadCacheWriteComplete(rv);
  865. break;
  866. case STATE_CACHE_READ_DATA:
  867. DCHECK_EQ(OK, rv);
  868. rv = DoCacheReadData();
  869. break;
  870. case STATE_CACHE_READ_DATA_COMPLETE:
  871. rv = DoCacheReadDataComplete(rv);
  872. break;
  873. case STATE_NETWORK_READ:
  874. DCHECK_EQ(OK, rv);
  875. rv = DoNetworkRead();
  876. break;
  877. case STATE_NETWORK_READ_COMPLETE:
  878. rv = DoNetworkReadComplete(rv);
  879. break;
  880. case STATE_MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE:
  881. DCHECK_EQ(0, rv); // Here "rv" is a count of bytes.
  882. rv = DoMarkSingleKeyedCacheEntryUnusable();
  883. break;
  884. case STATE_MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE_COMPLETE:
  885. rv = DoMarkSingleKeyedCacheEntryUnusableComplete(rv);
  886. break;
  887. default:
  888. NOTREACHED() << "bad state " << state;
  889. rv = ERR_FAILED;
  890. break;
  891. }
  892. DCHECK(next_state_ != STATE_UNSET) << "Previous state was " << state;
  893. } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
  894. // Assert Start() state machine's allowed last state in successful cases when
  895. // caching is happening.
  896. DCHECK(reading_ || rv != OK || !entry_ ||
  897. state == STATE_FINISH_HEADERS_COMPLETE);
  898. if (rv != ERR_IO_PENDING && !callback_.is_null()) {
  899. read_buf_ = nullptr; // Release the buffer before invoking the callback.
  900. std::move(callback_).Run(rv);
  901. }
  902. return rv;
  903. }
  904. int HttpCache::Transaction::DoGetBackend() {
  905. cache_pending_ = true;
  906. TransitionToState(STATE_GET_BACKEND_COMPLETE);
  907. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_GET_BACKEND);
  908. return cache_->GetBackendForTransaction(this);
  909. }
  910. int HttpCache::Transaction::DoGetBackendComplete(int result) {
  911. DCHECK(result == OK || result == ERR_FAILED);
  912. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_GET_BACKEND,
  913. result);
  914. cache_pending_ = false;
  915. // Reset mode_ that might get set in this function. This is done because this
  916. // function can be invoked multiple times for a transaction.
  917. mode_ = NONE;
  918. if (!ShouldPassThrough()) {
  919. // The flag `use_single_keyed_cache_` will have been changed back to false
  920. // if the entry was marked unusable and the transaction was restarted in
  921. // DoCacheReadResponseComplete(), even though `request_` will still have a
  922. // checksum. So it needs to be passed explicitly.
  923. cache_key_ =
  924. *cache_->GenerateCacheKeyForRequest(request_, use_single_keyed_cache_);
  925. // Requested cache access mode.
  926. if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
  927. if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
  928. // The client has asked for nonsense.
  929. TransitionToState(STATE_FINISH_HEADERS);
  930. return ERR_CACHE_MISS;
  931. }
  932. mode_ = READ;
  933. } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
  934. mode_ = WRITE;
  935. } else {
  936. mode_ = READ_WRITE;
  937. }
  938. // Downgrade to UPDATE if the request has been externally conditionalized.
  939. if (external_validation_.initialized) {
  940. if (mode_ & WRITE) {
  941. // Strip off the READ_DATA bit (and maybe add back a READ_META bit
  942. // in case READ was off).
  943. mode_ = UPDATE;
  944. } else {
  945. mode_ = NONE;
  946. }
  947. }
  948. }
  949. // Use PUT, DELETE, and PATCH only to invalidate existing stored entries.
  950. if ((method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH") &&
  951. mode_ != READ_WRITE && mode_ != WRITE) {
  952. mode_ = NONE;
  953. }
  954. // Note that if mode_ == UPDATE (which is tied to external_validation_), the
  955. // transaction behaves the same for GET and HEAD requests at this point: if it
  956. // was not modified, the entry is updated and a response is not returned from
  957. // the cache. If we receive 200, it doesn't matter if there was a validation
  958. // header or not.
  959. if (method_ == "HEAD" && mode_ == WRITE)
  960. mode_ = NONE;
  961. // If must use cache, then we must fail. This can happen for back/forward
  962. // navigations to a page generated via a form post.
  963. if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
  964. TransitionToState(STATE_FINISH_HEADERS);
  965. return ERR_CACHE_MISS;
  966. }
  967. if (mode_ == NONE) {
  968. if (partial_) {
  969. partial_->RestoreHeaders(&custom_request_->extra_headers);
  970. partial_.reset();
  971. }
  972. TransitionToState(STATE_SEND_REQUEST);
  973. } else {
  974. TransitionToState(STATE_INIT_ENTRY);
  975. }
  976. // This is only set if we have something to do with the response.
  977. range_requested_ = (partial_.get() != nullptr);
  978. return OK;
  979. }
  980. int HttpCache::Transaction::DoInitEntry() {
  981. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoInitEntry",
  982. TRACE_ID_LOCAL(trace_id_),
  983. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  984. DCHECK(!new_entry_);
  985. if (!cache_.get()) {
  986. TransitionToState(STATE_FINISH_HEADERS);
  987. return ERR_UNEXPECTED;
  988. }
  989. if (mode_ == WRITE) {
  990. TransitionToState(STATE_DOOM_ENTRY);
  991. return OK;
  992. }
  993. TransitionToState(STATE_OPEN_OR_CREATE_ENTRY);
  994. return OK;
  995. }
  996. int HttpCache::Transaction::DoOpenOrCreateEntry() {
  997. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoOpenOrCreateEntry",
  998. TRACE_ID_LOCAL(trace_id_),
  999. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1000. DCHECK(!new_entry_);
  1001. TransitionToState(STATE_OPEN_OR_CREATE_ENTRY_COMPLETE);
  1002. cache_pending_ = true;
  1003. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY);
  1004. first_cache_access_since_ = TimeTicks::Now();
  1005. const bool has_opened_or_created_entry = has_opened_or_created_entry_;
  1006. has_opened_or_created_entry_ = true;
  1007. record_entry_open_or_creation_time_ = false;
  1008. // See if we already have something working with this cache key.
  1009. new_entry_ = cache_->FindActiveEntry(cache_key_);
  1010. if (new_entry_)
  1011. return OK;
  1012. // See if we could potentially doom the entry based on hints the backend keeps
  1013. // in memory.
  1014. // Currently only SimpleCache utilizes in memory hints. If an entry is found
  1015. // unsuitable, and thus Doomed, SimpleCache can also optimize the
  1016. // OpenOrCreateEntry() call to reduce the overhead of trying to open an entry
  1017. // we know is doomed.
  1018. uint8_t in_memory_info =
  1019. cache_->GetCurrentBackend()->GetEntryInMemoryData(cache_key_);
  1020. bool entry_not_suitable = false;
  1021. if (MaybeRejectBasedOnEntryInMemoryData(in_memory_info)) {
  1022. cache_->GetCurrentBackend()->DoomEntry(cache_key_, priority_,
  1023. base::DoNothing());
  1024. entry_not_suitable = true;
  1025. // Documents the case this applies in
  1026. DCHECK_EQ(mode_, READ_WRITE);
  1027. // Record this as CantConditionalize, but otherwise proceed as we would
  1028. // below --- as we've already dropped the old entry.
  1029. couldnt_conditionalize_request_ = true;
  1030. validation_cause_ = VALIDATION_CAUSE_ZERO_FRESHNESS;
  1031. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
  1032. }
  1033. if (!has_opened_or_created_entry) {
  1034. record_entry_open_or_creation_time_ = true;
  1035. }
  1036. // mode_ can be anything but NONE or WRITE at this point (READ, UPDATE, or
  1037. // READ_WRITE).
  1038. // READ, UPDATE, certain READ_WRITEs, and some methods shouldn't create, so
  1039. // try only opening.
  1040. if (mode_ != READ_WRITE || ShouldOpenOnlyMethods()) {
  1041. if (entry_not_suitable) {
  1042. // The entry isn't suitable and we can't create a new one.
  1043. return net::ERR_CACHE_ENTRY_NOT_SUITABLE;
  1044. }
  1045. return cache_->OpenEntry(cache_key_, &new_entry_, this);
  1046. }
  1047. return cache_->OpenOrCreateEntry(cache_key_, &new_entry_, this);
  1048. }
  1049. int HttpCache::Transaction::DoOpenOrCreateEntryComplete(int result) {
  1050. TRACE_EVENT_WITH_FLOW1(
  1051. "net", "HttpCacheTransaction::DoOpenOrCreateEntryComplete",
  1052. TRACE_ID_LOCAL(trace_id_),
  1053. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result",
  1054. (result == OK ? (new_entry_->opened ? "opened" : "created") : "failed"));
  1055. const bool record_uma =
  1056. record_entry_open_or_creation_time_ && cache_ &&
  1057. cache_->GetCurrentBackend() &&
  1058. cache_->GetCurrentBackend()->GetCacheType() != MEMORY_CACHE;
  1059. record_entry_open_or_creation_time_ = false;
  1060. // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
  1061. // OK, otherwise the cache will end up with an active entry without any
  1062. // transaction attached.
  1063. net_log_.EndEventWithNetErrorCode(
  1064. NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY, result);
  1065. cache_pending_ = false;
  1066. if (result == OK) {
  1067. if (new_entry_->opened) {
  1068. if (record_uma) {
  1069. base::UmaHistogramTimes(
  1070. "HttpCache.OpenDiskEntry",
  1071. base::TimeTicks::Now() - first_cache_access_since_);
  1072. }
  1073. } else {
  1074. if (record_uma) {
  1075. base::UmaHistogramTimes(
  1076. "HttpCache.CreateDiskEntry",
  1077. base::TimeTicks::Now() - first_cache_access_since_);
  1078. }
  1079. // Entry was created so mode changes to WRITE.
  1080. mode_ = WRITE;
  1081. }
  1082. TransitionToState(STATE_ADD_TO_ENTRY);
  1083. return OK;
  1084. }
  1085. if (result == ERR_CACHE_RACE) {
  1086. TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
  1087. return OK;
  1088. }
  1089. // No need to explicitly handle ERR_CACHE_ENTRY_NOT_SUITABLE as the
  1090. // ShouldOpenOnlyMethods() check will handle it.
  1091. // We were unable to open or create an entry.
  1092. DLOG(WARNING) << "Unable to open or create cache entry";
  1093. if (ShouldOpenOnlyMethods()) {
  1094. // These methods, on failure, should bypass the cache.
  1095. mode_ = NONE;
  1096. TransitionToState(STATE_SEND_REQUEST);
  1097. return OK;
  1098. }
  1099. // Since the operation failed, what we do next depends on the mode_ which can
  1100. // be the following: READ, READ_WRITE, or UPDATE. Note: mode_ cannot be WRITE
  1101. // or NONE at this point as DoInitEntry() handled those cases.
  1102. switch (mode_) {
  1103. case READ:
  1104. // The entry does not exist, and we are not permitted to create a new
  1105. // entry, so we must fail.
  1106. TransitionToState(STATE_FINISH_HEADERS);
  1107. return ERR_CACHE_MISS;
  1108. case READ_WRITE:
  1109. // Unable to open or create; set the mode to NONE in order to bypass the
  1110. // cache entry and read from the network directly.
  1111. mode_ = NONE;
  1112. if (partial_)
  1113. partial_->RestoreHeaders(&custom_request_->extra_headers);
  1114. TransitionToState(STATE_SEND_REQUEST);
  1115. break;
  1116. case UPDATE:
  1117. // There is no cache entry to update; proceed without caching.
  1118. DCHECK(!partial_);
  1119. mode_ = NONE;
  1120. TransitionToState(STATE_SEND_REQUEST);
  1121. break;
  1122. default:
  1123. NOTREACHED();
  1124. }
  1125. return OK;
  1126. }
  1127. int HttpCache::Transaction::DoDoomEntry() {
  1128. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoDoomEntry",
  1129. TRACE_ID_LOCAL(trace_id_),
  1130. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1131. TransitionToState(STATE_DOOM_ENTRY_COMPLETE);
  1132. cache_pending_ = true;
  1133. if (first_cache_access_since_.is_null())
  1134. first_cache_access_since_ = TimeTicks::Now();
  1135. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_DOOM_ENTRY);
  1136. return cache_->DoomEntry(cache_key_, this);
  1137. }
  1138. int HttpCache::Transaction::DoDoomEntryComplete(int result) {
  1139. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoDoomEntryComplete",
  1140. TRACE_ID_LOCAL(trace_id_),
  1141. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  1142. "result", result);
  1143. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_DOOM_ENTRY,
  1144. result);
  1145. cache_pending_ = false;
  1146. TransitionToState(result == ERR_CACHE_RACE
  1147. ? STATE_HEADERS_PHASE_CANNOT_PROCEED
  1148. : STATE_CREATE_ENTRY);
  1149. return OK;
  1150. }
  1151. int HttpCache::Transaction::DoCreateEntry() {
  1152. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoCreateEntry",
  1153. TRACE_ID_LOCAL(trace_id_),
  1154. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1155. DCHECK(!new_entry_);
  1156. TransitionToState(STATE_CREATE_ENTRY_COMPLETE);
  1157. cache_pending_ = true;
  1158. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_CREATE_ENTRY);
  1159. return cache_->CreateEntry(cache_key_, &new_entry_, this);
  1160. }
  1161. int HttpCache::Transaction::DoCreateEntryComplete(int result) {
  1162. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoCreateEntryComplete",
  1163. TRACE_ID_LOCAL(trace_id_),
  1164. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  1165. "result", result);
  1166. // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
  1167. // OK, otherwise the cache will end up with an active entry without any
  1168. // transaction attached.
  1169. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_CREATE_ENTRY,
  1170. result);
  1171. cache_pending_ = false;
  1172. switch (result) {
  1173. case OK:
  1174. TransitionToState(STATE_ADD_TO_ENTRY);
  1175. break;
  1176. case ERR_CACHE_RACE:
  1177. TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
  1178. break;
  1179. default:
  1180. DLOG(WARNING) << "Unable to create cache entry";
  1181. // Set the mode to NONE in order to bypass the cache entry and read from
  1182. // the network directly.
  1183. mode_ = NONE;
  1184. if (!done_headers_create_new_entry_) {
  1185. if (partial_)
  1186. partial_->RestoreHeaders(&custom_request_->extra_headers);
  1187. TransitionToState(STATE_SEND_REQUEST);
  1188. return OK;
  1189. }
  1190. // The headers have already been received as a result of validation,
  1191. // triggering the doom of the old entry. So no network request needs to
  1192. // be sent. Note that since mode_ is NONE, the response won't be written
  1193. // to cache. Transition to STATE_CACHE_WRITE_RESPONSE as that's the state
  1194. // the transaction left off on when it tried to create the new entry.
  1195. done_headers_create_new_entry_ = false;
  1196. TransitionToState(STATE_CACHE_WRITE_RESPONSE);
  1197. }
  1198. return OK;
  1199. }
  1200. int HttpCache::Transaction::DoAddToEntry() {
  1201. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoAddToEntry",
  1202. TRACE_ID_LOCAL(trace_id_),
  1203. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1204. DCHECK(new_entry_);
  1205. cache_pending_ = true;
  1206. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY);
  1207. DCHECK(entry_lock_waiting_since_.is_null());
  1208. // By this point whether the entry was created or opened is no longer relevant
  1209. // for this transaction. However there may be queued transactions that want to
  1210. // use this entry and from their perspective the entry was opened, so change
  1211. // the flag to reflect that.
  1212. new_entry_->opened = true;
  1213. int rv = cache_->AddTransactionToEntry(new_entry_, this);
  1214. DCHECK_EQ(rv, ERR_IO_PENDING);
  1215. // If headers phase is already done then we are here because of validation not
  1216. // matching and creating a new entry. This transaction should be the
  1217. // first transaction of that new entry and thus it will not have cache lock
  1218. // delays, thus returning early from here.
  1219. if (done_headers_create_new_entry_) {
  1220. DCHECK_EQ(mode_, WRITE);
  1221. TransitionToState(STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE);
  1222. return rv;
  1223. }
  1224. TransitionToState(STATE_ADD_TO_ENTRY_COMPLETE);
  1225. entry_lock_waiting_since_ = TimeTicks::Now();
  1226. AddCacheLockTimeoutHandler(new_entry_);
  1227. return rv;
  1228. }
  1229. void HttpCache::Transaction::AddCacheLockTimeoutHandler(ActiveEntry* entry) {
  1230. DCHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
  1231. next_state_ == STATE_FINISH_HEADERS_COMPLETE);
  1232. if ((bypass_lock_for_test_ && next_state_ == STATE_ADD_TO_ENTRY_COMPLETE) ||
  1233. (bypass_lock_after_headers_for_test_ &&
  1234. next_state_ == STATE_FINISH_HEADERS_COMPLETE)) {
  1235. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1236. FROM_HERE,
  1237. base::BindOnce(&HttpCache::Transaction::OnCacheLockTimeout,
  1238. weak_factory_.GetWeakPtr(), entry_lock_waiting_since_));
  1239. } else {
  1240. int timeout_milliseconds = 20 * 1000;
  1241. if (partial_ && entry->writers && !entry->writers->IsEmpty() &&
  1242. entry->writers->IsExclusive()) {
  1243. // Even though entry_->writers takes care of allowing multiple writers to
  1244. // simultaneously govern reading from the network and writing to the cache
  1245. // for full requests, partial requests are still blocked by the
  1246. // reader/writer lock.
  1247. // Bypassing the cache after 25 ms of waiting for the cache lock
  1248. // eliminates a long running issue, http://crbug.com/31014, where
  1249. // two of the same media resources could not be played back simultaneously
  1250. // due to one locking the cache entry until the entire video was
  1251. // downloaded.
  1252. // Bypassing the cache is not ideal, as we are now ignoring the cache
  1253. // entirely for all range requests to a resource beyond the first. This
  1254. // is however a much more succinct solution than the alternatives, which
  1255. // would require somewhat significant changes to the http caching logic.
  1256. //
  1257. // Allow some timeout slack for the entry addition to complete in case
  1258. // the writer lock is imminently released; we want to avoid skipping
  1259. // the cache if at all possible. See http://crbug.com/408765
  1260. timeout_milliseconds = 25;
  1261. }
  1262. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  1263. FROM_HERE,
  1264. base::BindOnce(&HttpCache::Transaction::OnCacheLockTimeout,
  1265. weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
  1266. base::Milliseconds(timeout_milliseconds));
  1267. }
  1268. }
  1269. int HttpCache::Transaction::DoAddToEntryComplete(int result) {
  1270. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoAddToEntryComplete",
  1271. TRACE_ID_LOCAL(trace_id_),
  1272. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  1273. "result", result);
  1274. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY,
  1275. result);
  1276. if (cache_ && cache_->GetCurrentBackend() &&
  1277. cache_->GetCurrentBackend()->GetCacheType() != MEMORY_CACHE) {
  1278. const base::TimeDelta entry_lock_wait =
  1279. TimeTicks::Now() - entry_lock_waiting_since_;
  1280. base::UmaHistogramTimes("HttpCache.AddTransactionToEntry", entry_lock_wait);
  1281. }
  1282. entry_lock_waiting_since_ = TimeTicks();
  1283. DCHECK(new_entry_);
  1284. cache_pending_ = false;
  1285. if (result == OK)
  1286. entry_ = new_entry_;
  1287. // If there is a failure, the cache should have taken care of new_entry_.
  1288. new_entry_ = nullptr;
  1289. if (result == ERR_CACHE_RACE) {
  1290. TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
  1291. return OK;
  1292. }
  1293. if (result == ERR_CACHE_LOCK_TIMEOUT) {
  1294. if (mode_ == READ) {
  1295. TransitionToState(STATE_FINISH_HEADERS);
  1296. return ERR_CACHE_MISS;
  1297. }
  1298. // The cache is busy, bypass it for this transaction.
  1299. mode_ = NONE;
  1300. TransitionToState(STATE_SEND_REQUEST);
  1301. if (partial_) {
  1302. partial_->RestoreHeaders(&custom_request_->extra_headers);
  1303. partial_.reset();
  1304. }
  1305. return OK;
  1306. }
  1307. // TODO(crbug.com/713354) Access timestamp for histograms only if entry is
  1308. // already written, to avoid data race since cache thread can also access
  1309. // this.
  1310. if (!cache_->IsWritingInProgress(entry()))
  1311. open_entry_last_used_ = entry_->GetEntry()->GetLastUsed();
  1312. // TODO(jkarlin): We should either handle the case or DCHECK.
  1313. if (result != OK) {
  1314. NOTREACHED();
  1315. TransitionToState(STATE_FINISH_HEADERS);
  1316. return result;
  1317. }
  1318. if (mode_ == WRITE) {
  1319. if (partial_)
  1320. partial_->RestoreHeaders(&custom_request_->extra_headers);
  1321. TransitionToState(STATE_SEND_REQUEST);
  1322. } else {
  1323. // We have to read the headers from the cached entry.
  1324. DCHECK(mode_ & READ_META);
  1325. TransitionToState(STATE_CACHE_READ_RESPONSE);
  1326. }
  1327. return OK;
  1328. }
  1329. int HttpCache::Transaction::DoDoneHeadersAddToEntryComplete(int result) {
  1330. TRACE_EVENT_WITH_FLOW1(
  1331. "net", "HttpCacheTransaction::DoDoneHeadersAddToEntryComplete",
  1332. TRACE_ID_LOCAL(trace_id_),
  1333. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result", result);
  1334. // This transaction's response headers did not match its ActiveEntry so it
  1335. // created a new ActiveEntry (new_entry_) to write to (and doomed the old
  1336. // one). Now that the new entry has been created, start writing the response.
  1337. DCHECK_EQ(result, OK);
  1338. DCHECK_EQ(mode_, WRITE);
  1339. DCHECK(new_entry_);
  1340. DCHECK(response_.headers);
  1341. cache_pending_ = false;
  1342. done_headers_create_new_entry_ = false;
  1343. // It is unclear exactly how this state is reached with an ERR_CACHE_RACE, but
  1344. // this check appears to fix a rare crash. See crbug.com/959194.
  1345. if (result == ERR_CACHE_RACE) {
  1346. TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
  1347. return OK;
  1348. }
  1349. entry_ = new_entry_;
  1350. DCHECK_NE(response_.headers->response_code(), net::HTTP_NOT_MODIFIED);
  1351. DCHECK(cache_->CanTransactionWriteResponseHeaders(
  1352. entry_, this, partial_ != nullptr, false));
  1353. TransitionToState(STATE_CACHE_WRITE_RESPONSE);
  1354. return OK;
  1355. }
  1356. int HttpCache::Transaction::DoCacheReadResponse() {
  1357. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoCacheReadResponse",
  1358. TRACE_ID_LOCAL(trace_id_),
  1359. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1360. DCHECK(entry_);
  1361. TransitionToState(STATE_CACHE_READ_RESPONSE_COMPLETE);
  1362. io_buf_len_ = entry_->GetEntry()->GetDataSize(kResponseInfoIndex);
  1363. read_buf_ = base::MakeRefCounted<IOBuffer>(io_buf_len_);
  1364. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_INFO);
  1365. return entry_->GetEntry()->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
  1366. io_buf_len_, io_callback_);
  1367. }
  1368. int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
  1369. TRACE_EVENT_WITH_FLOW2("net",
  1370. "HttpCacheTransaction::DoCacheReadResponseComplete",
  1371. TRACE_ID_LOCAL(trace_id_),
  1372. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  1373. "result", result, "io_buf_len", io_buf_len_);
  1374. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO,
  1375. result);
  1376. // Record the time immediately before the cached response is parsed.
  1377. read_headers_since_ = TimeTicks::Now();
  1378. if (result != io_buf_len_ ||
  1379. !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, &response_,
  1380. &truncated_)) {
  1381. return OnCacheReadError(result, true);
  1382. }
  1383. if (response_.single_keyed_cache_entry_unusable) {
  1384. RecordPervasivePayloadIndex("Network.CacheTransparency.MarkedUnusable",
  1385. request_->pervasive_payloads_index_for_logging);
  1386. // We've read the single keyed entry and it turned out to be unusable. Let's
  1387. // retry reading from the split cache.
  1388. if (use_single_keyed_cache_) {
  1389. DCHECK(!network_trans_);
  1390. use_single_keyed_cache_ = false;
  1391. DoneWithEntryForRestartWithCache();
  1392. TransitionToState(STATE_GET_BACKEND);
  1393. return OK;
  1394. } else {
  1395. LOG(WARNING) << "Unusable flag set on non-single-keyed cache entry; "
  1396. << "possible disk corruption? (cache key: " << cache_key_
  1397. << ")";
  1398. }
  1399. }
  1400. // TODO(crbug.com/713354) Only get data size if there is no other transaction
  1401. // currently writing the response body due to the data race mentioned in the
  1402. // associated bug.
  1403. if (!cache_->IsWritingInProgress(entry())) {
  1404. int current_size = entry_->GetEntry()->GetDataSize(kResponseContentIndex);
  1405. int64_t full_response_length = response_.headers->GetContentLength();
  1406. // Some resources may have slipped in as truncated when they're not.
  1407. if (full_response_length == current_size)
  1408. truncated_ = false;
  1409. // The state machine's handling of StopCaching unfortunately doesn't deal
  1410. // well with resources that are larger than 2GB when there is a truncated or
  1411. // sparse cache entry. While the state machine is reworked to resolve this,
  1412. // the following logic is put in place to defer such requests to the
  1413. // network. The cache should not be storing multi gigabyte resources. See
  1414. // http://crbug.com/89567.
  1415. if ((truncated_ ||
  1416. response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT) &&
  1417. !range_requested_ &&
  1418. full_response_length > std::numeric_limits<int32_t>::max()) {
  1419. DCHECK(!partial_);
  1420. // Doom the entry so that no other transaction gets added to this entry
  1421. // and avoid a race of not being able to check this condition because
  1422. // writing is in progress.
  1423. DoneWithEntry(false);
  1424. TransitionToState(STATE_SEND_REQUEST);
  1425. return OK;
  1426. }
  1427. }
  1428. if (response_.restricted_prefetch &&
  1429. !(request_->load_flags & LOAD_CAN_USE_RESTRICTED_PREFETCH)) {
  1430. TransitionToState(STATE_SEND_REQUEST);
  1431. return OK;
  1432. }
  1433. // When a restricted prefetch is reused, we lift its reuse restriction.
  1434. bool restricted_prefetch_reuse =
  1435. response_.restricted_prefetch &&
  1436. request_->load_flags & LOAD_CAN_USE_RESTRICTED_PREFETCH;
  1437. DCHECK(!restricted_prefetch_reuse || response_.unused_since_prefetch);
  1438. if (response_.unused_since_prefetch !=
  1439. !!(request_->load_flags & LOAD_PREFETCH)) {
  1440. // Either this is the first use of an entry since it was prefetched XOR
  1441. // this is a prefetch. The value of response.unused_since_prefetch is
  1442. // valid for this transaction but the bit needs to be flipped in storage.
  1443. DCHECK(!updated_prefetch_response_);
  1444. updated_prefetch_response_ = std::make_unique<HttpResponseInfo>(response_);
  1445. updated_prefetch_response_->unused_since_prefetch =
  1446. !response_.unused_since_prefetch;
  1447. if (response_.restricted_prefetch &&
  1448. request_->load_flags & LOAD_CAN_USE_RESTRICTED_PREFETCH) {
  1449. updated_prefetch_response_->restricted_prefetch = false;
  1450. }
  1451. base::UmaHistogramEnumeration("HttpCache.RestrictedPrefetchReuse",
  1452. restricted_prefetch_reuse
  1453. ? RestrictedPrefetchReused::kReused
  1454. : RestrictedPrefetchReused::kNotReused);
  1455. TransitionToState(STATE_WRITE_UPDATED_PREFETCH_RESPONSE);
  1456. return OK;
  1457. }
  1458. TransitionToState(STATE_CACHE_DISPATCH_VALIDATION);
  1459. return OK;
  1460. }
  1461. int HttpCache::Transaction::DoCacheWriteUpdatedPrefetchResponse(int result) {
  1462. TRACE_EVENT_WITH_FLOW0(
  1463. "net", "HttpCacheTransaction::DoCacheWriteUpdatedPrefetchResponse",
  1464. TRACE_ID_LOCAL(trace_id_),
  1465. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1466. DCHECK(updated_prefetch_response_);
  1467. // TODO(jkarlin): If DoUpdateCachedResponse is also called for this
  1468. // transaction then metadata will be written to cache twice. If prefetching
  1469. // becomes more common, consider combining the writes.
  1470. TransitionToState(STATE_WRITE_UPDATED_PREFETCH_RESPONSE_COMPLETE);
  1471. return WriteResponseInfoToEntry(*updated_prefetch_response_.get(), false);
  1472. }
  1473. int HttpCache::Transaction::DoCacheWriteUpdatedPrefetchResponseComplete(
  1474. int result) {
  1475. TRACE_EVENT_WITH_FLOW0(
  1476. "net",
  1477. "HttpCacheTransaction::DoCacheWriteUpdatedPrefetchResponseComplete",
  1478. TRACE_ID_LOCAL(trace_id_),
  1479. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1480. updated_prefetch_response_.reset();
  1481. TransitionToState(STATE_CACHE_DISPATCH_VALIDATION);
  1482. return OnWriteResponseInfoToEntryComplete(result);
  1483. }
  1484. int HttpCache::Transaction::DoCacheDispatchValidation() {
  1485. TRACE_EVENT_WITH_FLOW0("net",
  1486. "HttpCacheTransaction::DoCacheDispatchValidation",
  1487. TRACE_ID_LOCAL(trace_id_),
  1488. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1489. if (!entry_) {
  1490. // Entry got destroyed when twiddling unused-since-prefetch bit.
  1491. TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
  1492. return OK;
  1493. }
  1494. // We now have access to the cache entry.
  1495. //
  1496. // o if we are a reader for the transaction, then we can start reading the
  1497. // cache entry.
  1498. //
  1499. // o if we can read or write, then we should check if the cache entry needs
  1500. // to be validated and then issue a network request if needed or just read
  1501. // from the cache if the cache entry is already valid.
  1502. //
  1503. // o if we are set to UPDATE, then we are handling an externally
  1504. // conditionalized request (if-modified-since / if-none-match). We check
  1505. // if the request headers define a validation request.
  1506. //
  1507. int result = ERR_FAILED;
  1508. switch (mode_) {
  1509. case READ:
  1510. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
  1511. result = BeginCacheRead();
  1512. break;
  1513. case READ_WRITE:
  1514. result = BeginPartialCacheValidation();
  1515. break;
  1516. case UPDATE:
  1517. result = BeginExternallyConditionalizedRequest();
  1518. break;
  1519. case WRITE:
  1520. default:
  1521. NOTREACHED();
  1522. }
  1523. return result;
  1524. }
  1525. int HttpCache::Transaction::DoCacheQueryData() {
  1526. TransitionToState(STATE_CACHE_QUERY_DATA_COMPLETE);
  1527. return entry_->GetEntry()->ReadyForSparseIO(io_callback_);
  1528. }
  1529. int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
  1530. DCHECK_EQ(OK, result);
  1531. if (!cache_.get()) {
  1532. TransitionToState(STATE_FINISH_HEADERS);
  1533. return ERR_UNEXPECTED;
  1534. }
  1535. return ValidateEntryHeadersAndContinue();
  1536. }
  1537. // We may end up here multiple times for a given request.
  1538. int HttpCache::Transaction::DoStartPartialCacheValidation() {
  1539. if (mode_ == NONE) {
  1540. TransitionToState(STATE_FINISH_HEADERS);
  1541. return OK;
  1542. }
  1543. TransitionToState(STATE_COMPLETE_PARTIAL_CACHE_VALIDATION);
  1544. return partial_->ShouldValidateCache(entry_->GetEntry(), io_callback_);
  1545. }
  1546. int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
  1547. if (!result) {
  1548. // This is the end of the request.
  1549. DoneWithEntry(true);
  1550. TransitionToState(STATE_FINISH_HEADERS);
  1551. return result;
  1552. }
  1553. if (result < 0) {
  1554. TransitionToState(STATE_FINISH_HEADERS);
  1555. return result;
  1556. }
  1557. partial_->PrepareCacheValidation(entry_->GetEntry(),
  1558. &custom_request_->extra_headers);
  1559. if (reading_ && partial_->IsCurrentRangeCached()) {
  1560. // We're about to read a range of bytes from the cache. Signal it to the
  1561. // consumer through the "connected" callback.
  1562. TransitionToState(STATE_CONNECTED_CALLBACK);
  1563. return OK;
  1564. }
  1565. return BeginCacheValidation();
  1566. }
  1567. int HttpCache::Transaction::DoCacheUpdateStaleWhileRevalidateTimeout() {
  1568. TRACE_EVENT_WITH_FLOW0(
  1569. "net", "HttpCacheTransaction::DoCacheUpdateStaleWhileRevalidateTimeout",
  1570. TRACE_ID_LOCAL(trace_id_),
  1571. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1572. response_.stale_revalidate_timeout =
  1573. cache_->clock_->Now() + kStaleRevalidateTimeout;
  1574. TransitionToState(STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT_COMPLETE);
  1575. return WriteResponseInfoToEntry(response_, false);
  1576. }
  1577. int HttpCache::Transaction::DoCacheUpdateStaleWhileRevalidateTimeoutComplete(
  1578. int result) {
  1579. TRACE_EVENT_WITH_FLOW0(
  1580. "net",
  1581. "HttpCacheTransaction::DoCacheUpdateStaleWhileRevalidateTimeoutComplete",
  1582. TRACE_ID_LOCAL(trace_id_),
  1583. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1584. DCHECK(!reading_);
  1585. TransitionToState(STATE_CONNECTED_CALLBACK);
  1586. return OnWriteResponseInfoToEntryComplete(result);
  1587. }
  1588. int HttpCache::Transaction::DoSendRequest() {
  1589. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoSendRequest",
  1590. TRACE_ID_LOCAL(trace_id_),
  1591. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1592. DCHECK(mode_ & WRITE || mode_ == NONE);
  1593. DCHECK(!network_trans_.get());
  1594. send_request_since_ = TimeTicks::Now();
  1595. // Create a network transaction.
  1596. int rv =
  1597. cache_->network_layer_->CreateTransaction(priority_, &network_trans_);
  1598. if (rv != OK) {
  1599. TransitionToState(STATE_FINISH_HEADERS);
  1600. return rv;
  1601. }
  1602. network_trans_->SetBeforeNetworkStartCallback(
  1603. std::move(before_network_start_callback_));
  1604. network_trans_->SetConnectedCallback(connected_callback_);
  1605. network_trans_->SetRequestHeadersCallback(request_headers_callback_);
  1606. network_trans_->SetEarlyResponseHeadersCallback(
  1607. early_response_headers_callback_);
  1608. network_trans_->SetResponseHeadersCallback(response_headers_callback_);
  1609. // Old load timing information, if any, is now obsolete.
  1610. network_transaction_info_.old_network_trans_load_timing.reset();
  1611. network_transaction_info_.old_remote_endpoint = IPEndPoint();
  1612. if (websocket_handshake_stream_base_create_helper_)
  1613. network_trans_->SetWebSocketHandshakeStreamCreateHelper(
  1614. websocket_handshake_stream_base_create_helper_);
  1615. TransitionToState(STATE_SEND_REQUEST_COMPLETE);
  1616. rv = network_trans_->Start(request_, io_callback_, net_log_);
  1617. return rv;
  1618. }
  1619. int HttpCache::Transaction::DoSendRequestComplete(int result) {
  1620. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoSendRequestComplete",
  1621. TRACE_ID_LOCAL(trace_id_),
  1622. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  1623. "result", result);
  1624. if (!cache_.get()) {
  1625. TransitionToState(STATE_FINISH_HEADERS);
  1626. return ERR_UNEXPECTED;
  1627. }
  1628. // If we tried to conditionalize the request and failed, we know
  1629. // we won't be reading from the cache after this point.
  1630. if (couldnt_conditionalize_request_)
  1631. mode_ = WRITE;
  1632. if (result == OK) {
  1633. TransitionToState(STATE_SUCCESSFUL_SEND_REQUEST);
  1634. return OK;
  1635. }
  1636. const HttpResponseInfo* response = network_trans_->GetResponseInfo();
  1637. response_.network_accessed = response->network_accessed;
  1638. response_.was_fetched_via_proxy = response->was_fetched_via_proxy;
  1639. response_.proxy_server = response->proxy_server;
  1640. response_.restricted_prefetch = response->restricted_prefetch;
  1641. response_.resolve_error_info = response->resolve_error_info;
  1642. // Do not record requests that have network errors or restarts.
  1643. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  1644. if (IsCertificateError(result)) {
  1645. // If we get a certificate error, then there is a certificate in ssl_info,
  1646. // so GetResponseInfo() should never return NULL here.
  1647. DCHECK(response);
  1648. response_.ssl_info = response->ssl_info;
  1649. } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
  1650. DCHECK(response);
  1651. response_.cert_request_info = response->cert_request_info;
  1652. } else if (result == ERR_INCONSISTENT_IP_ADDRESS_SPACE) {
  1653. DoomInconsistentEntry();
  1654. } else if (response_.was_cached) {
  1655. DoneWithEntry(/*entry_is_complete=*/true);
  1656. }
  1657. TransitionToState(STATE_FINISH_HEADERS);
  1658. return result;
  1659. }
  1660. // We received the response headers and there is no error.
  1661. int HttpCache::Transaction::DoSuccessfulSendRequest() {
  1662. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoSuccessfulSendRequest",
  1663. TRACE_ID_LOCAL(trace_id_),
  1664. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1665. DCHECK(!new_response_);
  1666. const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
  1667. if (new_response->headers->response_code() == net::HTTP_UNAUTHORIZED ||
  1668. new_response->headers->response_code() ==
  1669. net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
  1670. SetAuthResponse(*new_response);
  1671. if (!reading_) {
  1672. TransitionToState(STATE_FINISH_HEADERS);
  1673. return OK;
  1674. }
  1675. // We initiated a second request the caller doesn't know about. We should be
  1676. // able to authenticate this request because we should have authenticated
  1677. // this URL moments ago.
  1678. if (IsReadyToRestartForAuth()) {
  1679. TransitionToState(STATE_SEND_REQUEST_COMPLETE);
  1680. // In theory we should check to see if there are new cookies, but there
  1681. // is no way to do that from here.
  1682. return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_);
  1683. }
  1684. // We have to perform cleanup at this point so that at least the next
  1685. // request can succeed. We do not retry at this point, because data
  1686. // has been read and we have no way to gather credentials. We would
  1687. // fail again, and potentially loop. This can happen if the credentials
  1688. // expire while chrome is suspended.
  1689. if (entry_)
  1690. DoomPartialEntry(false);
  1691. mode_ = NONE;
  1692. partial_.reset();
  1693. ResetNetworkTransaction();
  1694. TransitionToState(STATE_FINISH_HEADERS);
  1695. return ERR_CACHE_AUTH_FAILURE_AFTER_READ;
  1696. }
  1697. // The single-keyed cache only accepts responses with code 200 or 304.
  1698. // Anything else is considered unusable.
  1699. if (use_single_keyed_cache_ &&
  1700. !(new_response->headers->response_code() == 200 ||
  1701. new_response->headers->response_code() == 304)) {
  1702. // Either the new response will be written back to the cache, in which case
  1703. // it will not be reused due to the flag, or it will not be, in which case
  1704. // it will not be reused anyway.
  1705. mark_single_keyed_cache_entry_unusable_ = true;
  1706. }
  1707. new_response_ = new_response;
  1708. if (!ValidatePartialResponse() && !auth_response_.headers.get()) {
  1709. // Something went wrong with this request and we have to restart it.
  1710. // If we have an authentication response, we are exposed to weird things
  1711. // hapenning if the user cancels the authentication before we receive
  1712. // the new response.
  1713. net_log_.AddEvent(NetLogEventType::HTTP_CACHE_RE_SEND_PARTIAL_REQUEST);
  1714. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  1715. SetResponse(HttpResponseInfo());
  1716. ResetNetworkTransaction();
  1717. new_response_ = nullptr;
  1718. TransitionToState(STATE_SEND_REQUEST);
  1719. return OK;
  1720. }
  1721. if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
  1722. // We have stored the full entry, but it changed and the server is
  1723. // sending a range. We have to delete the old entry.
  1724. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  1725. DoneWithEntry(false);
  1726. }
  1727. if (mode_ == WRITE &&
  1728. cache_entry_status_ != CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) {
  1729. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_NOT_IN_CACHE);
  1730. }
  1731. // Invalidate any cached GET with a successful PUT, DELETE, or PATCH.
  1732. if (mode_ == WRITE &&
  1733. (method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH")) {
  1734. if (NonErrorResponse(new_response_->headers->response_code()) &&
  1735. (entry_ && !entry_->doomed)) {
  1736. int ret = cache_->DoomEntry(cache_key_, nullptr);
  1737. DCHECK_EQ(OK, ret);
  1738. }
  1739. // Do not invalidate the entry if the request failed.
  1740. DoneWithEntry(true);
  1741. }
  1742. // Invalidate any cached GET with a successful POST. If the network isolation
  1743. // key isn't populated with the split cache active, there will be nothing to
  1744. // invalidate in the cache.
  1745. if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) && method_ == "POST" &&
  1746. NonErrorResponse(new_response_->headers->response_code()) &&
  1747. (!HttpCache::IsSplitCacheEnabled() ||
  1748. request_->network_isolation_key.IsFullyPopulated())) {
  1749. cache_->DoomMainEntryForUrl(request_->url, request_->network_isolation_key,
  1750. request_->is_subframe_document_resource);
  1751. }
  1752. if (new_response_->headers->response_code() ==
  1753. net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE &&
  1754. (method_ == "GET" || method_ == "POST")) {
  1755. // If there is an active entry it may be destroyed with this transaction.
  1756. SetResponse(*new_response_);
  1757. TransitionToState(STATE_FINISH_HEADERS);
  1758. return OK;
  1759. }
  1760. // Are we expecting a response to a conditional query?
  1761. if (mode_ == READ_WRITE || mode_ == UPDATE) {
  1762. if (new_response->headers->response_code() == net::HTTP_NOT_MODIFIED ||
  1763. handling_206_) {
  1764. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
  1765. TransitionToState(STATE_UPDATE_CACHED_RESPONSE);
  1766. return OK;
  1767. }
  1768. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
  1769. mode_ = WRITE;
  1770. }
  1771. TransitionToState(STATE_OVERWRITE_CACHED_RESPONSE);
  1772. return OK;
  1773. }
  1774. // We received 304 or 206 and we want to update the cached response headers.
  1775. int HttpCache::Transaction::DoUpdateCachedResponse() {
  1776. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoUpdateCachedResponse",
  1777. TRACE_ID_LOCAL(trace_id_),
  1778. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1779. int rv = OK;
  1780. // Update the cached response based on the headers and properties of
  1781. // new_response_.
  1782. response_.headers->Update(*new_response_->headers.get());
  1783. response_.stale_revalidate_timeout = base::Time();
  1784. response_.response_time = new_response_->response_time;
  1785. response_.request_time = new_response_->request_time;
  1786. response_.network_accessed = new_response_->network_accessed;
  1787. response_.unused_since_prefetch = new_response_->unused_since_prefetch;
  1788. response_.restricted_prefetch = new_response_->restricted_prefetch;
  1789. response_.ssl_info = new_response_->ssl_info;
  1790. response_.dns_aliases = new_response_->dns_aliases;
  1791. // Be careful never to set single_keyed_cache_entry_unusable back to false
  1792. // from true.
  1793. if (mark_single_keyed_cache_entry_unusable_) {
  1794. response_.single_keyed_cache_entry_unusable = true;
  1795. }
  1796. // If the new response didn't have a vary header, we continue to use the
  1797. // header from the stored response per the effect of headers->Update().
  1798. // Update the data with the new/updated request headers.
  1799. response_.vary_data.Init(*request_, *response_.headers);
  1800. if (ShouldDisableCaching(*response_.headers)) {
  1801. if (!entry_->doomed) {
  1802. int ret = cache_->DoomEntry(cache_key_, nullptr);
  1803. DCHECK_EQ(OK, ret);
  1804. }
  1805. TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
  1806. } else {
  1807. if (use_single_keyed_cache_) {
  1808. DCHECK_EQ(method_, "GET");
  1809. ChecksumHeaders();
  1810. }
  1811. // If we are already reading, we already updated the headers for this
  1812. // request; doing it again will change Content-Length.
  1813. if (!reading_) {
  1814. TransitionToState(STATE_CACHE_WRITE_UPDATED_RESPONSE);
  1815. rv = OK;
  1816. } else {
  1817. TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
  1818. }
  1819. }
  1820. return rv;
  1821. }
  1822. int HttpCache::Transaction::DoCacheWriteUpdatedResponse() {
  1823. TRACE_EVENT_WITH_FLOW0("net",
  1824. "HttpCacheTransaction::DoCacheWriteUpdatedResponse",
  1825. TRACE_ID_LOCAL(trace_id_),
  1826. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1827. TransitionToState(STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE);
  1828. return WriteResponseInfoToEntry(response_, false);
  1829. }
  1830. int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) {
  1831. TRACE_EVENT_WITH_FLOW0(
  1832. "net", "HttpCacheTransaction::DoCacheWriteUpdatedResponseComplete",
  1833. TRACE_ID_LOCAL(trace_id_),
  1834. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1835. TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
  1836. return OnWriteResponseInfoToEntryComplete(result);
  1837. }
  1838. int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
  1839. TRACE_EVENT_WITH_FLOW1(
  1840. "net", "HttpCacheTransaction::DoUpdateCachedResponseComplete",
  1841. TRACE_ID_LOCAL(trace_id_),
  1842. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result", result);
  1843. if (mode_ == UPDATE) {
  1844. DCHECK(!handling_206_);
  1845. // We got a "not modified" response and already updated the corresponding
  1846. // cache entry above.
  1847. //
  1848. // By stopping to write to the cache now, we make sure that the 304 rather
  1849. // than the cached 200 response, is what will be returned to the user.
  1850. UpdateSecurityHeadersBeforeForwarding();
  1851. DoneWithEntry(true);
  1852. } else if (entry_ && !handling_206_) {
  1853. DCHECK_EQ(READ_WRITE, mode_);
  1854. if ((!partial_ && !cache_->IsWritingInProgress(entry_)) ||
  1855. (partial_ && partial_->IsLastRange())) {
  1856. mode_ = READ;
  1857. }
  1858. // We no longer need the network transaction, so destroy it.
  1859. if (network_trans_)
  1860. ResetNetworkTransaction();
  1861. } else if (entry_ && handling_206_ && truncated_ &&
  1862. partial_->initial_validation()) {
  1863. // We just finished the validation of a truncated entry, and the server
  1864. // is willing to resume the operation. Now we go back and start serving
  1865. // the first part to the user.
  1866. if (network_trans_)
  1867. ResetNetworkTransaction();
  1868. new_response_ = nullptr;
  1869. TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
  1870. partial_->SetRangeToStartDownload();
  1871. return OK;
  1872. }
  1873. TransitionToState(STATE_OVERWRITE_CACHED_RESPONSE);
  1874. return OK;
  1875. }
  1876. int HttpCache::Transaction::DoOverwriteCachedResponse() {
  1877. TRACE_EVENT_WITH_FLOW0("net",
  1878. "HttpCacheTransaction::DoOverwriteCachedResponse",
  1879. TRACE_ID_LOCAL(trace_id_),
  1880. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1881. if (mode_ & READ) {
  1882. TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
  1883. return OK;
  1884. }
  1885. // We change the value of Content-Length for partial content.
  1886. if (handling_206_ && partial_)
  1887. partial_->FixContentLength(new_response_->headers.get());
  1888. SetResponse(*new_response_);
  1889. if (use_single_keyed_cache_) {
  1890. DCHECK_EQ(method_, "GET");
  1891. ChecksumHeaders();
  1892. }
  1893. if (method_ == "HEAD") {
  1894. // This response is replacing the cached one.
  1895. DoneWithEntry(false);
  1896. new_response_ = nullptr;
  1897. TransitionToState(STATE_FINISH_HEADERS);
  1898. return OK;
  1899. }
  1900. if (handling_206_ && !CanResume(false)) {
  1901. // There is no point in storing this resource because it will never be used.
  1902. // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries.
  1903. DoneWithEntry(false);
  1904. if (partial_)
  1905. partial_->FixResponseHeaders(response_.headers.get(), true);
  1906. TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
  1907. return OK;
  1908. }
  1909. TransitionToState(STATE_CACHE_WRITE_RESPONSE);
  1910. return OK;
  1911. }
  1912. int HttpCache::Transaction::DoCacheWriteResponse() {
  1913. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoCacheWriteResponse",
  1914. TRACE_ID_LOCAL(trace_id_),
  1915. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1916. DCHECK(response_.headers);
  1917. // Invalidate any current entry with a successful response if this transaction
  1918. // cannot write to this entry. This transaction then continues to read from
  1919. // the network without writing to the backend.
  1920. bool is_match = response_.headers->response_code() == net::HTTP_NOT_MODIFIED;
  1921. if (entry_ && !cache_->CanTransactionWriteResponseHeaders(
  1922. entry_, this, partial_ != nullptr, is_match)) {
  1923. done_headers_create_new_entry_ = true;
  1924. // The transaction needs to overwrite this response. Doom the current entry,
  1925. // create a new one (by going to STATE_INIT_ENTRY), and then jump straight
  1926. // to writing out the response, bypassing the headers checks. The mode_ is
  1927. // set to WRITE in order to doom any other existing entries that might exist
  1928. // so that this transaction can go straight to writing a response.
  1929. mode_ = WRITE;
  1930. TransitionToState(STATE_INIT_ENTRY);
  1931. cache_->DoomEntryValidationNoMatch(entry_);
  1932. entry_ = nullptr;
  1933. return OK;
  1934. }
  1935. // Be careful never to set single_keyed_cache_entry_unusable back to false
  1936. // from true.
  1937. if (mark_single_keyed_cache_entry_unusable_) {
  1938. response_.single_keyed_cache_entry_unusable = true;
  1939. }
  1940. TransitionToState(STATE_CACHE_WRITE_RESPONSE_COMPLETE);
  1941. return WriteResponseInfoToEntry(response_, truncated_);
  1942. }
  1943. int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
  1944. TRACE_EVENT_WITH_FLOW1(
  1945. "net", "HttpCacheTransaction::DoCacheWriteResponseComplete",
  1946. TRACE_ID_LOCAL(trace_id_),
  1947. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result", result);
  1948. TransitionToState(STATE_TRUNCATE_CACHED_DATA);
  1949. return OnWriteResponseInfoToEntryComplete(result);
  1950. }
  1951. int HttpCache::Transaction::DoTruncateCachedData() {
  1952. TRACE_EVENT_WITH_FLOW0("net", "HttpCacheTransaction::DoTruncateCachedData",
  1953. TRACE_ID_LOCAL(trace_id_),
  1954. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  1955. TransitionToState(STATE_TRUNCATE_CACHED_DATA_COMPLETE);
  1956. if (!entry_)
  1957. return OK;
  1958. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
  1959. // Truncate the stream.
  1960. return entry_->GetEntry()->WriteData(kResponseContentIndex, /*offset=*/0,
  1961. /*buf=*/nullptr, /*buf_len=*/0,
  1962. io_callback_, /*truncate=*/true);
  1963. }
  1964. int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
  1965. TRACE_EVENT_WITH_FLOW1(
  1966. "net", "HttpCacheTransaction::DoTruncateCachedDataComplete",
  1967. TRACE_ID_LOCAL(trace_id_),
  1968. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result", result);
  1969. if (entry_) {
  1970. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
  1971. result);
  1972. }
  1973. TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
  1974. return OK;
  1975. }
  1976. int HttpCache::Transaction::DoPartialHeadersReceived() {
  1977. new_response_ = nullptr;
  1978. if (partial_ && mode_ != NONE && !reading_) {
  1979. // We are about to return the headers for a byte-range request to the user,
  1980. // so let's fix them.
  1981. partial_->FixResponseHeaders(response_.headers.get(), true);
  1982. }
  1983. TransitionToState(STATE_FINISH_HEADERS);
  1984. return OK;
  1985. }
  1986. int HttpCache::Transaction::DoHeadersPhaseCannotProceed(int result) {
  1987. // If its the Start state machine and it cannot proceed due to a cache
  1988. // failure, restart this transaction.
  1989. DCHECK(!reading_);
  1990. // Reset before invoking SetRequest() which can reset the request info sent to
  1991. // network transaction.
  1992. if (network_trans_)
  1993. network_trans_.reset();
  1994. new_response_ = nullptr;
  1995. SetRequest(net_log_);
  1996. entry_ = nullptr;
  1997. new_entry_ = nullptr;
  1998. // TODO(https://crbug.com/1219402): This should probably clear `response_`,
  1999. // too, once things are fixed so it's safe to do so.
  2000. // Bypass the cache for timeout scenario.
  2001. if (result == ERR_CACHE_LOCK_TIMEOUT)
  2002. effective_load_flags_ |= LOAD_DISABLE_CACHE;
  2003. TransitionToState(STATE_GET_BACKEND);
  2004. return OK;
  2005. }
  2006. int HttpCache::Transaction::DoFinishHeaders(int result) {
  2007. TRACE_EVENT_WITH_FLOW1(
  2008. "net", "HttpCacheTransaction::DoFinishHeaders", TRACE_ID_LOCAL(trace_id_),
  2009. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result", result);
  2010. if (!cache_.get() || !entry_ || result != OK) {
  2011. TransitionToState(STATE_NONE);
  2012. return result;
  2013. }
  2014. TransitionToState(STATE_FINISH_HEADERS_COMPLETE);
  2015. // If it was an auth failure, this transaction should continue to be
  2016. // headers_transaction till consumer takes an action, so no need to do
  2017. // anything now.
  2018. // TODO(crbug.com/740947). See the issue for a suggestion for cleaning the
  2019. // state machine to be able to remove this condition.
  2020. if (auth_response_.headers.get())
  2021. return OK;
  2022. // If the transaction needs to wait because another transaction is still
  2023. // writing the response body, it will return ERR_IO_PENDING now and the
  2024. // io_callback_ will be invoked when the wait is done.
  2025. int rv = cache_->DoneWithResponseHeaders(entry_, this, partial_ != nullptr);
  2026. DCHECK(!reading_ || rv == OK) << "Expected OK, but got " << rv;
  2027. if (rv == ERR_IO_PENDING) {
  2028. DCHECK(entry_lock_waiting_since_.is_null());
  2029. entry_lock_waiting_since_ = TimeTicks::Now();
  2030. AddCacheLockTimeoutHandler(entry_);
  2031. }
  2032. return rv;
  2033. }
  2034. int HttpCache::Transaction::DoFinishHeadersComplete(int rv) {
  2035. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoFinishHeadersComplete",
  2036. TRACE_ID_LOCAL(trace_id_),
  2037. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  2038. "result", rv);
  2039. entry_lock_waiting_since_ = TimeTicks();
  2040. if (rv == ERR_CACHE_RACE || rv == ERR_CACHE_LOCK_TIMEOUT) {
  2041. TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
  2042. return rv;
  2043. }
  2044. if (network_trans_ && InWriters()) {
  2045. entry_->writers->SetNetworkTransaction(this, std::move(network_trans_),
  2046. std::move(checksum_));
  2047. moved_network_transaction_to_writers_ = true;
  2048. }
  2049. // If already reading, that means it is a partial request coming back to the
  2050. // headers phase, continue to the appropriate reading state.
  2051. if (reading_) {
  2052. int reading_state_rv = TransitionToReadingState();
  2053. DCHECK_EQ(OK, reading_state_rv);
  2054. return OK;
  2055. }
  2056. TransitionToState(STATE_NONE);
  2057. return rv;
  2058. }
  2059. int HttpCache::Transaction::DoNetworkReadCacheWrite() {
  2060. TRACE_EVENT_WITH_FLOW2("net", "HttpCacheTransaction::DoNetworkReadCacheWrite",
  2061. TRACE_ID_LOCAL(trace_id_),
  2062. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  2063. "read_offset", read_offset_, "read_buf_len",
  2064. read_buf_len_);
  2065. DCHECK(InWriters());
  2066. TransitionToState(STATE_NETWORK_READ_CACHE_WRITE_COMPLETE);
  2067. return entry_->writers->Read(read_buf_, read_buf_len_, io_callback_, this);
  2068. }
  2069. int HttpCache::Transaction::DoNetworkReadCacheWriteComplete(int result) {
  2070. TRACE_EVENT_WITH_FLOW1(
  2071. "net", "HttpCacheTransaction::DoNetworkReadCacheWriteComplete",
  2072. TRACE_ID_LOCAL(trace_id_),
  2073. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result", result);
  2074. if (!cache_.get()) {
  2075. TransitionToState(STATE_NONE);
  2076. return ERR_UNEXPECTED;
  2077. }
  2078. // |result| will be error code in case of network read failure and |this|
  2079. // cannot proceed further, so set entry_ to null. |result| will not be error
  2080. // in case of cache write failure since |this| can continue to read from the
  2081. // network. If response is completed, then also set entry to null.
  2082. if (result < 0) {
  2083. // We should have discovered this error in WriterAboutToBeRemovedFromEntry
  2084. DCHECK_EQ(result, shared_writing_error_);
  2085. DCHECK_EQ(NONE, mode_);
  2086. DCHECK(!entry_);
  2087. TransitionToState(STATE_NONE);
  2088. return result;
  2089. }
  2090. if (partial_) {
  2091. return DoPartialNetworkReadCompleted(result);
  2092. }
  2093. if (result == 0) {
  2094. DCHECK_EQ(NONE, mode_);
  2095. DCHECK(!entry_);
  2096. } else {
  2097. read_offset_ += result;
  2098. if (checksum_)
  2099. checksum_->Update(read_buf_->data(), result);
  2100. }
  2101. TransitionToState(STATE_NONE);
  2102. return result;
  2103. }
  2104. int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
  2105. DCHECK(partial_);
  2106. // Go to the next range if nothing returned or return the result.
  2107. // TODO(shivanisha) Simplify this condition if possible. It was introduced
  2108. // in https://codereview.chromium.org/545101
  2109. if (result != 0 || truncated_ ||
  2110. !(partial_->IsLastRange() || mode_ == WRITE)) {
  2111. partial_->OnNetworkReadCompleted(result);
  2112. if (result == 0) {
  2113. // We need to move on to the next range.
  2114. if (network_trans_) {
  2115. ResetNetworkTransaction();
  2116. } else if (InWriters() && entry_->writers->network_transaction()) {
  2117. SaveNetworkTransactionInfo(*(entry_->writers->network_transaction()));
  2118. entry_->writers->ResetNetworkTransaction();
  2119. }
  2120. TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
  2121. } else {
  2122. TransitionToState(STATE_NONE);
  2123. }
  2124. return result;
  2125. }
  2126. // Request completed.
  2127. if (result == 0) {
  2128. DoneWithEntry(true);
  2129. }
  2130. TransitionToState(STATE_NONE);
  2131. return result;
  2132. }
  2133. int HttpCache::Transaction::DoNetworkRead() {
  2134. TRACE_EVENT_WITH_FLOW2(
  2135. "net", "HttpCacheTransaction::DoNetworkRead", TRACE_ID_LOCAL(trace_id_),
  2136. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "read_offset",
  2137. read_offset_, "read_buf_len", read_buf_len_);
  2138. TransitionToState(STATE_NETWORK_READ_COMPLETE);
  2139. return network_trans_->Read(read_buf_.get(), read_buf_len_, io_callback_);
  2140. }
  2141. int HttpCache::Transaction::DoNetworkReadComplete(int result) {
  2142. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoNetworkReadComplete",
  2143. TRACE_ID_LOCAL(trace_id_),
  2144. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  2145. "result", result);
  2146. if (!cache_.get()) {
  2147. TransitionToState(STATE_NONE);
  2148. return ERR_UNEXPECTED;
  2149. }
  2150. if (partial_)
  2151. return DoPartialNetworkReadCompleted(result);
  2152. TransitionToState(STATE_NONE);
  2153. return result;
  2154. }
  2155. int HttpCache::Transaction::DoCacheReadData() {
  2156. TRACE_EVENT_WITH_FLOW2(
  2157. "net", "HttpCacheTransaction::DoCacheReadData", TRACE_ID_LOCAL(trace_id_),
  2158. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "read_offset",
  2159. read_offset_, "read_buf_len", read_buf_len_);
  2160. if (method_ == "HEAD") {
  2161. TransitionToState(STATE_NONE);
  2162. return 0;
  2163. }
  2164. DCHECK(entry_);
  2165. TransitionToState(STATE_CACHE_READ_DATA_COMPLETE);
  2166. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA);
  2167. if (partial_) {
  2168. return partial_->CacheRead(entry_->GetEntry(), read_buf_.get(),
  2169. read_buf_len_, io_callback_);
  2170. }
  2171. return entry_->GetEntry()->ReadData(kResponseContentIndex, read_offset_,
  2172. read_buf_.get(), read_buf_len_,
  2173. io_callback_);
  2174. }
  2175. int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
  2176. TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoCacheReadDataComplete",
  2177. TRACE_ID_LOCAL(trace_id_),
  2178. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  2179. "result", result);
  2180. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_DATA,
  2181. result);
  2182. if (!cache_.get()) {
  2183. TransitionToState(STATE_NONE);
  2184. return ERR_UNEXPECTED;
  2185. }
  2186. if (partial_) {
  2187. // Partial requests are confusing to report in histograms because they may
  2188. // have multiple underlying requests.
  2189. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2190. return DoPartialCacheReadCompleted(result);
  2191. }
  2192. if (result > 0) {
  2193. read_offset_ += result;
  2194. if (checksum_)
  2195. checksum_->Update(read_buf_->data(), result);
  2196. } else if (result == 0) { // End of file.
  2197. if (!FinishAndCheckChecksum()) {
  2198. TransitionToState(STATE_MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE);
  2199. return result;
  2200. }
  2201. DoneWithEntry(true);
  2202. } else {
  2203. return OnCacheReadError(result, false);
  2204. }
  2205. TransitionToState(STATE_NONE);
  2206. return result;
  2207. }
  2208. int HttpCache::Transaction::DoMarkSingleKeyedCacheEntryUnusable() {
  2209. DCHECK(use_single_keyed_cache_);
  2210. response_.single_keyed_cache_entry_unusable = true;
  2211. TransitionToState(STATE_MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE_COMPLETE);
  2212. return WriteResponseInfoToEntry(response_, /*truncated=*/false);
  2213. }
  2214. int HttpCache::Transaction::DoMarkSingleKeyedCacheEntryUnusableComplete(
  2215. int result) {
  2216. DCHECK_NE(result, ERR_IO_PENDING);
  2217. TransitionToState(STATE_NONE);
  2218. DoneWithEntry(/*entry_is_complete=*/true);
  2219. if (result < 0)
  2220. return result;
  2221. // Return 0 to indicate that we've finished reading the body.
  2222. return 0;
  2223. }
  2224. //-----------------------------------------------------------------------------
  2225. void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log) {
  2226. net_log_ = net_log;
  2227. // Reset the variables that might get set in this function. This is done
  2228. // because this function can be invoked multiple times for a transaction.
  2229. cache_entry_status_ = CacheEntryStatus::ENTRY_UNDEFINED;
  2230. external_validation_.Reset();
  2231. range_requested_ = false;
  2232. partial_.reset();
  2233. request_ = initial_request_;
  2234. custom_request_.reset();
  2235. effective_load_flags_ = request_->load_flags;
  2236. method_ = request_->method;
  2237. if (!request_->checksum.empty())
  2238. use_single_keyed_cache_ = true;
  2239. if (cache_->mode() == DISABLE)
  2240. effective_load_flags_ |= LOAD_DISABLE_CACHE;
  2241. // Some headers imply load flags. The order here is significant.
  2242. //
  2243. // LOAD_DISABLE_CACHE : no cache read or write
  2244. // LOAD_BYPASS_CACHE : no cache read
  2245. // LOAD_VALIDATE_CACHE : no cache read unless validation
  2246. //
  2247. // The former modes trump latter modes, so if we find a matching header we
  2248. // can stop iterating kSpecialHeaders.
  2249. //
  2250. static const struct {
  2251. const HeaderNameAndValue* search;
  2252. int load_flag;
  2253. } kSpecialHeaders[] = {
  2254. { kPassThroughHeaders, LOAD_DISABLE_CACHE },
  2255. { kForceFetchHeaders, LOAD_BYPASS_CACHE },
  2256. { kForceValidateHeaders, LOAD_VALIDATE_CACHE },
  2257. };
  2258. bool range_found = false;
  2259. bool external_validation_error = false;
  2260. bool special_headers = false;
  2261. if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange))
  2262. range_found = true;
  2263. for (const auto& special_header : kSpecialHeaders) {
  2264. if (HeaderMatches(request_->extra_headers, special_header.search)) {
  2265. effective_load_flags_ |= special_header.load_flag;
  2266. special_headers = true;
  2267. break;
  2268. }
  2269. }
  2270. // Check for conditionalization headers which may correspond with a
  2271. // cache validation request.
  2272. for (size_t i = 0; i < std::size(kValidationHeaders); ++i) {
  2273. const ValidationHeaderInfo& info = kValidationHeaders[i];
  2274. std::string validation_value;
  2275. if (request_->extra_headers.GetHeader(
  2276. info.request_header_name, &validation_value)) {
  2277. if (!external_validation_.values[i].empty() ||
  2278. validation_value.empty()) {
  2279. external_validation_error = true;
  2280. }
  2281. external_validation_.values[i] = validation_value;
  2282. external_validation_.initialized = true;
  2283. }
  2284. }
  2285. if (range_found || special_headers || external_validation_.initialized) {
  2286. // Log the headers before request_ is modified.
  2287. std::string empty;
  2288. NetLogRequestHeaders(net_log_,
  2289. NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS,
  2290. empty, &request_->extra_headers);
  2291. }
  2292. // We don't support ranges and validation headers.
  2293. if (range_found && external_validation_.initialized) {
  2294. LOG(WARNING) << "Byte ranges AND validation headers found.";
  2295. effective_load_flags_ |= LOAD_DISABLE_CACHE;
  2296. }
  2297. // If there is more than one validation header, we can't treat this request as
  2298. // a cache validation, since we don't know for sure which header the server
  2299. // will give us a response for (and they could be contradictory).
  2300. if (external_validation_error) {
  2301. LOG(WARNING) << "Multiple or malformed validation headers found.";
  2302. effective_load_flags_ |= LOAD_DISABLE_CACHE;
  2303. }
  2304. if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
  2305. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2306. partial_ = std::make_unique<PartialData>();
  2307. if (method_ == "GET" && partial_->Init(request_->extra_headers)) {
  2308. // We will be modifying the actual range requested to the server, so
  2309. // let's remove the header here.
  2310. // Note that custom_request_ is a shallow copy so will keep the same
  2311. // pointer to upload data stream as in the original request.
  2312. custom_request_ = std::make_unique<HttpRequestInfo>(*request_);
  2313. custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
  2314. request_ = custom_request_.get();
  2315. partial_->SetHeaders(custom_request_->extra_headers);
  2316. } else {
  2317. // The range is invalid or we cannot handle it properly.
  2318. VLOG(1) << "Invalid byte range found.";
  2319. effective_load_flags_ |= LOAD_DISABLE_CACHE;
  2320. partial_.reset(nullptr);
  2321. }
  2322. }
  2323. }
  2324. bool HttpCache::Transaction::ShouldPassThrough() {
  2325. bool cacheable = true;
  2326. // We may have a null disk_cache if there is an error we cannot recover from,
  2327. // like not enough disk space, or sharing violations.
  2328. if (!cache_->disk_cache_.get()) {
  2329. cacheable = false;
  2330. } else if (effective_load_flags_ & LOAD_DISABLE_CACHE) {
  2331. cacheable = false;
  2332. }
  2333. // Prevent resources whose origin is opaque from being cached. Blink's memory
  2334. // cache should take care of reusing resources within the current page load,
  2335. // but otherwise a resource with an opaque top-frame origin won’t be used
  2336. // again. Also, if the request does not have a top frame origin, bypass the
  2337. // cache otherwise resources from different pages could share a cached entry
  2338. // in such cases.
  2339. else if (HttpCache::IsSplitCacheEnabled() &&
  2340. request_->network_isolation_key.IsTransient()) {
  2341. cacheable = false;
  2342. } else if (method_ == "GET" || method_ == "HEAD") {
  2343. } else if (method_ == "POST" && request_->upload_data_stream &&
  2344. request_->upload_data_stream->identifier()) {
  2345. } else if (method_ == "PUT" && request_->upload_data_stream) {
  2346. }
  2347. // DELETE and PATCH requests may result in invalidating the cache, so cannot
  2348. // just pass through.
  2349. else if (method_ == "DELETE" || method_ == "PATCH") {
  2350. } else {
  2351. cacheable = false;
  2352. }
  2353. NetworkIsolationKeyPresent nik_present_enum =
  2354. request_->network_isolation_key.IsFullyPopulated()
  2355. ? NetworkIsolationKeyPresent::kPresent
  2356. : cacheable
  2357. ? NetworkIsolationKeyPresent::kNotPresentCacheableRequest
  2358. : NetworkIsolationKeyPresent::kNotPresentNonCacheableRequest;
  2359. UMA_HISTOGRAM_ENUMERATION("HttpCache.NetworkIsolationKeyPresent2",
  2360. nik_present_enum);
  2361. return !cacheable;
  2362. }
  2363. int HttpCache::Transaction::BeginCacheRead() {
  2364. // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges.
  2365. // TODO(jkarlin): Either handle this case or DCHECK.
  2366. if (response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT ||
  2367. partial_) {
  2368. NOTREACHED();
  2369. TransitionToState(STATE_FINISH_HEADERS);
  2370. return ERR_CACHE_MISS;
  2371. }
  2372. // We don't have the whole resource.
  2373. if (truncated_) {
  2374. TransitionToState(STATE_FINISH_HEADERS);
  2375. return ERR_CACHE_MISS;
  2376. }
  2377. if (RequiresValidation() != VALIDATION_NONE) {
  2378. TransitionToState(STATE_FINISH_HEADERS);
  2379. return ERR_CACHE_MISS;
  2380. }
  2381. if (method_ == "HEAD")
  2382. FixHeadersForHead();
  2383. TransitionToState(STATE_FINISH_HEADERS);
  2384. return OK;
  2385. }
  2386. int HttpCache::Transaction::BeginCacheValidation() {
  2387. DCHECK_EQ(mode_, READ_WRITE);
  2388. ValidationType required_validation = RequiresValidation();
  2389. bool skip_validation = (required_validation == VALIDATION_NONE);
  2390. bool needs_stale_while_revalidate_cache_update = false;
  2391. if ((effective_load_flags_ & LOAD_SUPPORT_ASYNC_REVALIDATION) &&
  2392. required_validation == VALIDATION_ASYNCHRONOUS) {
  2393. DCHECK_EQ(request_->method, "GET");
  2394. skip_validation = true;
  2395. response_.async_revalidation_requested = true;
  2396. needs_stale_while_revalidate_cache_update =
  2397. response_.stale_revalidate_timeout.is_null();
  2398. }
  2399. if (method_ == "HEAD" && (truncated_ || response_.headers->response_code() ==
  2400. net::HTTP_PARTIAL_CONTENT)) {
  2401. DCHECK(!partial_);
  2402. if (skip_validation) {
  2403. DCHECK(!reading_);
  2404. TransitionToState(STATE_CONNECTED_CALLBACK);
  2405. return OK;
  2406. }
  2407. // Bail out!
  2408. TransitionToState(STATE_SEND_REQUEST);
  2409. mode_ = NONE;
  2410. return OK;
  2411. }
  2412. if (truncated_) {
  2413. // Truncated entries can cause partial gets, so we shouldn't record this
  2414. // load in histograms.
  2415. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2416. skip_validation = !partial_->initial_validation();
  2417. }
  2418. // If this is the first request (!reading_) of a 206 entry (is_sparse_) that
  2419. // doesn't actually cover the entire file (which with !reading would require
  2420. // partial->IsLastRange()), and the user is requesting the whole thing
  2421. // (!partial_->range_requested()), make sure to validate the first chunk,
  2422. // since afterwards it will be too late if it's actually out-of-date (or the
  2423. // server bungles invalidation). This is limited to the whole-file request
  2424. // as a targeted fix for https://crbug.com/888742 while avoiding extra
  2425. // requests in other cases, but the problem can occur more generally as well;
  2426. // it's just a lot less likely with applications actively using ranges.
  2427. // See https://crbug.com/902724 for the more general case.
  2428. bool first_read_of_full_from_partial =
  2429. is_sparse_ && !reading_ &&
  2430. (partial_ && !partial_->range_requested() && !partial_->IsLastRange());
  2431. if (partial_ && (is_sparse_ || truncated_) &&
  2432. (!partial_->IsCurrentRangeCached() || invalid_range_ ||
  2433. first_read_of_full_from_partial)) {
  2434. // Force revalidation for sparse or truncated entries. Note that we don't
  2435. // want to ignore the regular validation logic just because a byte range was
  2436. // part of the request.
  2437. skip_validation = false;
  2438. }
  2439. if (skip_validation) {
  2440. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
  2441. DCHECK(!reading_);
  2442. TransitionToState(needs_stale_while_revalidate_cache_update
  2443. ? STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT
  2444. : STATE_CONNECTED_CALLBACK);
  2445. return OK;
  2446. } else {
  2447. // Make the network request conditional, to see if we may reuse our cached
  2448. // response. If we cannot do so, then we just resort to a normal fetch.
  2449. // Our mode remains READ_WRITE for a conditional request. Even if the
  2450. // conditionalization fails, we don't switch to WRITE mode until we
  2451. // know we won't be falling back to using the cache entry in the
  2452. // LOAD_FROM_CACHE_IF_OFFLINE case.
  2453. if (!ConditionalizeRequest()) {
  2454. couldnt_conditionalize_request_ = true;
  2455. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
  2456. if (partial_)
  2457. return DoRestartPartialRequest();
  2458. DCHECK_NE(net::HTTP_PARTIAL_CONTENT, response_.headers->response_code());
  2459. }
  2460. TransitionToState(STATE_SEND_REQUEST);
  2461. }
  2462. return OK;
  2463. }
  2464. int HttpCache::Transaction::BeginPartialCacheValidation() {
  2465. DCHECK_EQ(mode_, READ_WRITE);
  2466. if (response_.headers->response_code() != net::HTTP_PARTIAL_CONTENT &&
  2467. !partial_ && !truncated_)
  2468. return BeginCacheValidation();
  2469. // Partial requests should not be recorded in histograms.
  2470. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2471. if (method_ == "HEAD")
  2472. return BeginCacheValidation();
  2473. if (!range_requested_) {
  2474. // The request is not for a range, but we have stored just ranges.
  2475. partial_ = std::make_unique<PartialData>();
  2476. partial_->SetHeaders(request_->extra_headers);
  2477. if (!custom_request_.get()) {
  2478. custom_request_ = std::make_unique<HttpRequestInfo>(*request_);
  2479. request_ = custom_request_.get();
  2480. }
  2481. }
  2482. TransitionToState(STATE_CACHE_QUERY_DATA);
  2483. return OK;
  2484. }
  2485. // This should only be called once per request.
  2486. int HttpCache::Transaction::ValidateEntryHeadersAndContinue() {
  2487. DCHECK_EQ(mode_, READ_WRITE);
  2488. if (!partial_->UpdateFromStoredHeaders(
  2489. response_.headers.get(), entry_->GetEntry(), truncated_,
  2490. cache_->IsWritingInProgress(entry()))) {
  2491. return DoRestartPartialRequest();
  2492. }
  2493. if (response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT)
  2494. is_sparse_ = true;
  2495. if (!partial_->IsRequestedRangeOK()) {
  2496. // The stored data is fine, but the request may be invalid.
  2497. invalid_range_ = true;
  2498. }
  2499. TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
  2500. return OK;
  2501. }
  2502. bool HttpCache::Transaction::
  2503. ExternallyConditionalizedValidationHeadersMatchEntry() const {
  2504. DCHECK(external_validation_.initialized);
  2505. for (size_t i = 0; i < std::size(kValidationHeaders); i++) {
  2506. if (external_validation_.values[i].empty())
  2507. continue;
  2508. // Retrieve either the cached response's "etag" or "last-modified" header.
  2509. std::string validator;
  2510. response_.headers->EnumerateHeader(
  2511. nullptr, kValidationHeaders[i].related_response_header_name,
  2512. &validator);
  2513. if (validator != external_validation_.values[i]) {
  2514. return false;
  2515. }
  2516. }
  2517. return true;
  2518. }
  2519. int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
  2520. DCHECK_EQ(UPDATE, mode_);
  2521. if (response_.headers->response_code() != net::HTTP_OK || truncated_ ||
  2522. !ExternallyConditionalizedValidationHeadersMatchEntry()) {
  2523. // The externally conditionalized request is not a validation request
  2524. // for our existing cache entry. Proceed with caching disabled.
  2525. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2526. DoneWithEntry(true);
  2527. }
  2528. TransitionToState(STATE_SEND_REQUEST);
  2529. return OK;
  2530. }
  2531. int HttpCache::Transaction::RestartNetworkRequest() {
  2532. DCHECK(mode_ & WRITE || mode_ == NONE);
  2533. DCHECK(network_trans_.get());
  2534. DCHECK_EQ(STATE_NONE, next_state_);
  2535. next_state_ = STATE_SEND_REQUEST_COMPLETE;
  2536. int rv = network_trans_->RestartIgnoringLastError(io_callback_);
  2537. if (rv != ERR_IO_PENDING)
  2538. return DoLoop(rv);
  2539. return rv;
  2540. }
  2541. int HttpCache::Transaction::RestartNetworkRequestWithCertificate(
  2542. scoped_refptr<X509Certificate> client_cert,
  2543. scoped_refptr<SSLPrivateKey> client_private_key) {
  2544. DCHECK(mode_ & WRITE || mode_ == NONE);
  2545. DCHECK(network_trans_.get());
  2546. DCHECK_EQ(STATE_NONE, next_state_);
  2547. next_state_ = STATE_SEND_REQUEST_COMPLETE;
  2548. int rv = network_trans_->RestartWithCertificate(
  2549. std::move(client_cert), std::move(client_private_key), io_callback_);
  2550. if (rv != ERR_IO_PENDING)
  2551. return DoLoop(rv);
  2552. return rv;
  2553. }
  2554. int HttpCache::Transaction::RestartNetworkRequestWithAuth(
  2555. const AuthCredentials& credentials) {
  2556. DCHECK(mode_ & WRITE || mode_ == NONE);
  2557. DCHECK(network_trans_.get());
  2558. DCHECK_EQ(STATE_NONE, next_state_);
  2559. next_state_ = STATE_SEND_REQUEST_COMPLETE;
  2560. int rv = network_trans_->RestartWithAuth(credentials, io_callback_);
  2561. if (rv != ERR_IO_PENDING)
  2562. return DoLoop(rv);
  2563. return rv;
  2564. }
  2565. ValidationType HttpCache::Transaction::RequiresValidation() {
  2566. // TODO(darin): need to do more work here:
  2567. // - make sure we have a matching request method
  2568. // - watch out for cached responses that depend on authentication
  2569. if (!(effective_load_flags_ & LOAD_SKIP_VARY_CHECK) &&
  2570. response_.vary_data.is_valid() &&
  2571. !response_.vary_data.MatchesRequest(*request_,
  2572. *response_.headers.get())) {
  2573. vary_mismatch_ = true;
  2574. validation_cause_ = VALIDATION_CAUSE_VARY_MISMATCH;
  2575. return VALIDATION_SYNCHRONOUS;
  2576. }
  2577. if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION)
  2578. return VALIDATION_NONE;
  2579. base::TimeDelta response_time_in_cache =
  2580. cache_->clock_->Now() - response_.response_time;
  2581. if (response_.unused_since_prefetch &&
  2582. !(effective_load_flags_ & LOAD_PREFETCH) &&
  2583. (response_time_in_cache < base::Minutes(kPrefetchReuseMins)) &&
  2584. (response_time_in_cache >= base::TimeDelta())) {
  2585. // The first use of a resource after prefetch within a short window skips
  2586. // validation.
  2587. return VALIDATION_NONE;
  2588. }
  2589. if (effective_load_flags_ & LOAD_VALIDATE_CACHE) {
  2590. validation_cause_ = VALIDATION_CAUSE_VALIDATE_FLAG;
  2591. return VALIDATION_SYNCHRONOUS;
  2592. }
  2593. if (method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH")
  2594. return VALIDATION_SYNCHRONOUS;
  2595. ValidationType validation_required_by_headers =
  2596. response_.headers->RequiresValidation(response_.request_time,
  2597. response_.response_time,
  2598. cache_->clock_->Now());
  2599. if (validation_required_by_headers != VALIDATION_NONE) {
  2600. HttpResponseHeaders::FreshnessLifetimes lifetimes =
  2601. response_.headers->GetFreshnessLifetimes(response_.response_time);
  2602. if (lifetimes.freshness == base::TimeDelta()) {
  2603. validation_cause_ = VALIDATION_CAUSE_ZERO_FRESHNESS;
  2604. } else {
  2605. validation_cause_ = VALIDATION_CAUSE_STALE;
  2606. }
  2607. }
  2608. if (validation_required_by_headers == VALIDATION_ASYNCHRONOUS) {
  2609. // Asynchronous revalidation is only supported for GET methods.
  2610. if (request_->method != "GET")
  2611. return VALIDATION_SYNCHRONOUS;
  2612. // If the timeout on the staleness revalidation is set don't hand out
  2613. // a resource that hasn't been async validated.
  2614. if (!response_.stale_revalidate_timeout.is_null() &&
  2615. response_.stale_revalidate_timeout < cache_->clock_->Now()) {
  2616. return VALIDATION_SYNCHRONOUS;
  2617. }
  2618. }
  2619. return validation_required_by_headers;
  2620. }
  2621. bool HttpCache::Transaction::IsResponseConditionalizable(
  2622. std::string* etag_value,
  2623. std::string* last_modified_value) const {
  2624. DCHECK(response_.headers.get());
  2625. // This only makes sense for cached 200 or 206 responses.
  2626. if (response_.headers->response_code() != net::HTTP_OK &&
  2627. response_.headers->response_code() != net::HTTP_PARTIAL_CONTENT) {
  2628. return false;
  2629. }
  2630. // Just use the first available ETag and/or Last-Modified header value.
  2631. // TODO(darin): Or should we use the last?
  2632. if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1))
  2633. response_.headers->EnumerateHeader(nullptr, "etag", etag_value);
  2634. response_.headers->EnumerateHeader(nullptr, "last-modified",
  2635. last_modified_value);
  2636. if (etag_value->empty() && last_modified_value->empty())
  2637. return false;
  2638. return true;
  2639. }
  2640. bool HttpCache::Transaction::ShouldOpenOnlyMethods() const {
  2641. // These methods indicate that we should only try to open an entry and not
  2642. // fallback to create.
  2643. return method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH" ||
  2644. (method_ == "HEAD" && mode_ == READ_WRITE);
  2645. }
  2646. bool HttpCache::Transaction::ConditionalizeRequest() {
  2647. DCHECK(response_.headers.get());
  2648. if (method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH")
  2649. return false;
  2650. if (fail_conditionalization_for_test_)
  2651. return false;
  2652. std::string etag_value;
  2653. std::string last_modified_value;
  2654. if (!IsResponseConditionalizable(&etag_value, &last_modified_value))
  2655. return false;
  2656. DCHECK(response_.headers->response_code() != net::HTTP_PARTIAL_CONTENT ||
  2657. response_.headers->HasStrongValidators());
  2658. if (vary_mismatch_) {
  2659. // Can't rely on last-modified if vary is different.
  2660. last_modified_value.clear();
  2661. if (etag_value.empty())
  2662. return false;
  2663. }
  2664. if (!partial_) {
  2665. // Need to customize the request, so this forces us to allocate :(
  2666. custom_request_ = std::make_unique<HttpRequestInfo>(*request_);
  2667. request_ = custom_request_.get();
  2668. }
  2669. DCHECK(custom_request_.get());
  2670. bool use_if_range =
  2671. partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_;
  2672. if (!etag_value.empty()) {
  2673. if (use_if_range) {
  2674. // We don't want to switch to WRITE mode if we don't have this block of a
  2675. // byte-range request because we may have other parts cached.
  2676. custom_request_->extra_headers.SetHeader(
  2677. HttpRequestHeaders::kIfRange, etag_value);
  2678. } else {
  2679. custom_request_->extra_headers.SetHeader(
  2680. HttpRequestHeaders::kIfNoneMatch, etag_value);
  2681. }
  2682. // For byte-range requests, make sure that we use only one way to validate
  2683. // the request.
  2684. if (partial_ && !partial_->IsCurrentRangeCached())
  2685. return true;
  2686. }
  2687. if (!last_modified_value.empty()) {
  2688. if (use_if_range) {
  2689. custom_request_->extra_headers.SetHeader(
  2690. HttpRequestHeaders::kIfRange, last_modified_value);
  2691. } else {
  2692. custom_request_->extra_headers.SetHeader(
  2693. HttpRequestHeaders::kIfModifiedSince, last_modified_value);
  2694. }
  2695. }
  2696. return true;
  2697. }
  2698. bool HttpCache::Transaction::MaybeRejectBasedOnEntryInMemoryData(
  2699. uint8_t in_memory_info) {
  2700. // Not going to be clever with those...
  2701. if (partial_)
  2702. return false;
  2703. // Avoiding open based on in-memory hints requires us to be permitted to
  2704. // modify the cache, including deleting an old entry. Only the READ_WRITE
  2705. // and WRITE modes permit that... and WRITE never tries to open entries in the
  2706. // first place, so we shouldn't see it here.
  2707. DCHECK_NE(mode_, WRITE);
  2708. if (mode_ != READ_WRITE)
  2709. return false;
  2710. // If we are loading ignoring cache validity (aka back button), obviously
  2711. // can't reject things based on it. Also if LOAD_ONLY_FROM_CACHE there is no
  2712. // hope of network offering anything better.
  2713. if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION ||
  2714. effective_load_flags_ & LOAD_ONLY_FROM_CACHE)
  2715. return false;
  2716. return (in_memory_info & HINT_UNUSABLE_PER_CACHING_HEADERS) ==
  2717. HINT_UNUSABLE_PER_CACHING_HEADERS;
  2718. }
  2719. bool HttpCache::Transaction::ComputeUnusablePerCachingHeaders() {
  2720. // unused_since_prefetch overrides some caching headers, so it may be useful
  2721. // regardless of what they say.
  2722. if (response_.unused_since_prefetch)
  2723. return false;
  2724. // Has an e-tag or last-modified: we can probably send a conditional request,
  2725. // so it's potentially useful.
  2726. std::string etag_ignored, last_modified_ignored;
  2727. if (IsResponseConditionalizable(&etag_ignored, &last_modified_ignored))
  2728. return false;
  2729. // If none of the above is true and the entry has zero freshness, then it
  2730. // won't be usable absent load flag override.
  2731. return response_.headers->GetFreshnessLifetimes(response_.response_time)
  2732. .freshness.is_zero();
  2733. }
  2734. // We just received some headers from the server. We may have asked for a range,
  2735. // in which case partial_ has an object. This could be the first network request
  2736. // we make to fulfill the original request, or we may be already reading (from
  2737. // the net and / or the cache). If we are not expecting a certain response, we
  2738. // just bypass the cache for this request (but again, maybe we are reading), and
  2739. // delete partial_ (so we are not able to "fix" the headers that we return to
  2740. // the user). This results in either a weird response for the caller (we don't
  2741. // expect it after all), or maybe a range that was not exactly what it was asked
  2742. // for.
  2743. //
  2744. // If the server is simply telling us that the resource has changed, we delete
  2745. // the cached entry and restart the request as the caller intended (by returning
  2746. // false from this method). However, we may not be able to do that at any point,
  2747. // for instance if we already returned the headers to the user.
  2748. //
  2749. // WARNING: Whenever this code returns false, it has to make sure that the next
  2750. // time it is called it will return true so that we don't keep retrying the
  2751. // request.
  2752. bool HttpCache::Transaction::ValidatePartialResponse() {
  2753. const HttpResponseHeaders* headers = new_response_->headers.get();
  2754. int response_code = headers->response_code();
  2755. bool partial_response = (response_code == net::HTTP_PARTIAL_CONTENT);
  2756. handling_206_ = false;
  2757. if (!entry_ || method_ != "GET")
  2758. return true;
  2759. if (invalid_range_) {
  2760. // We gave up trying to match this request with the stored data. If the
  2761. // server is ok with the request, delete the entry, otherwise just ignore
  2762. // this request
  2763. DCHECK(!reading_);
  2764. if (partial_response || response_code == net::HTTP_OK) {
  2765. DoomPartialEntry(true);
  2766. mode_ = NONE;
  2767. } else {
  2768. if (response_code == net::HTTP_NOT_MODIFIED) {
  2769. // Change the response code of the request to be 416 (Requested range
  2770. // not satisfiable).
  2771. SetResponse(*new_response_);
  2772. partial_->FixResponseHeaders(response_.headers.get(), false);
  2773. }
  2774. IgnoreRangeRequest();
  2775. }
  2776. return true;
  2777. }
  2778. if (!partial_) {
  2779. // We are not expecting 206 but we may have one.
  2780. if (partial_response)
  2781. IgnoreRangeRequest();
  2782. return true;
  2783. }
  2784. // TODO(rvargas): Do we need to consider other results here?.
  2785. bool failure = response_code == net::HTTP_OK ||
  2786. response_code == net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE;
  2787. if (partial_->IsCurrentRangeCached()) {
  2788. // We asked for "If-None-Match: " so a 206 means a new object.
  2789. if (partial_response)
  2790. failure = true;
  2791. if (response_code == net::HTTP_NOT_MODIFIED &&
  2792. partial_->ResponseHeadersOK(headers))
  2793. return true;
  2794. } else {
  2795. // We asked for "If-Range: " so a 206 means just another range.
  2796. if (partial_response) {
  2797. if (partial_->ResponseHeadersOK(headers)) {
  2798. handling_206_ = true;
  2799. return true;
  2800. } else {
  2801. failure = true;
  2802. }
  2803. }
  2804. if (!reading_ && !is_sparse_ && !partial_response) {
  2805. // See if we can ignore the fact that we issued a byte range request.
  2806. // If the server sends 200, just store it. If it sends an error, redirect
  2807. // or something else, we may store the response as long as we didn't have
  2808. // anything already stored.
  2809. if (response_code == net::HTTP_OK ||
  2810. (!truncated_ && response_code != net::HTTP_NOT_MODIFIED &&
  2811. response_code != net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE)) {
  2812. // The server is sending something else, and we can save it.
  2813. DCHECK((truncated_ && !partial_->IsLastRange()) || range_requested_);
  2814. partial_.reset();
  2815. truncated_ = false;
  2816. return true;
  2817. }
  2818. }
  2819. // 304 is not expected here, but we'll spare the entry (unless it was
  2820. // truncated).
  2821. if (truncated_)
  2822. failure = true;
  2823. }
  2824. if (failure) {
  2825. // We cannot truncate this entry, it has to be deleted.
  2826. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2827. mode_ = NONE;
  2828. if (is_sparse_ || truncated_) {
  2829. // There was something cached to start with, either sparsed data (206), or
  2830. // a truncated 200, which means that we probably modified the request,
  2831. // adding a byte range or modifying the range requested by the caller.
  2832. if (!reading_ && !partial_->IsLastRange()) {
  2833. // We have not returned anything to the caller yet so it should be safe
  2834. // to issue another network request, this time without us messing up the
  2835. // headers.
  2836. ResetPartialState(true);
  2837. return false;
  2838. }
  2839. LOG(WARNING) << "Failed to revalidate partial entry";
  2840. }
  2841. DoomPartialEntry(true);
  2842. return true;
  2843. }
  2844. IgnoreRangeRequest();
  2845. return true;
  2846. }
  2847. void HttpCache::Transaction::IgnoreRangeRequest() {
  2848. // We have a problem. We may or may not be reading already (in which case we
  2849. // returned the headers), but we'll just pretend that this request is not
  2850. // using the cache and see what happens. Most likely this is the first
  2851. // response from the server (it's not changing its mind midway, right?).
  2852. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2853. DoneWithEntry(mode_ != WRITE);
  2854. partial_.reset(nullptr);
  2855. }
  2856. // Called to signal to the consumer that we are about to read headers from a
  2857. // cached entry originally read from a given IP endpoint.
  2858. int HttpCache::Transaction::DoConnectedCallback() {
  2859. TransitionToState(STATE_CONNECTED_CALLBACK_COMPLETE);
  2860. if (connected_callback_.is_null()) {
  2861. return OK;
  2862. }
  2863. auto type = response_.was_fetched_via_proxy ? TransportType::kCachedFromProxy
  2864. : TransportType::kCached;
  2865. return connected_callback_.Run(
  2866. TransportInfo(type, response_.remote_endpoint, ""), io_callback_);
  2867. }
  2868. int HttpCache::Transaction::DoConnectedCallbackComplete(int result) {
  2869. if (result != OK) {
  2870. if (result ==
  2871. ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY) {
  2872. DoomInconsistentEntry();
  2873. UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
  2874. TransitionToState(reading_ ? STATE_SEND_REQUEST
  2875. : STATE_HEADERS_PHASE_CANNOT_PROCEED);
  2876. return OK;
  2877. }
  2878. if (result == ERR_INCONSISTENT_IP_ADDRESS_SPACE) {
  2879. DoomInconsistentEntry();
  2880. } else {
  2881. // Release the entry for further use - we are done using it.
  2882. DoneWithEntry(/*entry_is_complete=*/true);
  2883. }
  2884. TransitionToState(STATE_NONE);
  2885. return result;
  2886. }
  2887. if (reading_) {
  2888. // We can only get here if we're reading a partial range of bytes from the
  2889. // cache. In that case, proceed to read the bytes themselves.
  2890. DCHECK(partial_);
  2891. TransitionToState(STATE_CACHE_READ_DATA);
  2892. } else {
  2893. // Otherwise, we have just read headers from the cache.
  2894. TransitionToState(STATE_SETUP_ENTRY_FOR_READ);
  2895. }
  2896. return OK;
  2897. }
  2898. void HttpCache::Transaction::DoomInconsistentEntry() {
  2899. // Explicitly call `DoomActiveEntry()` ourselves before calling
  2900. // `DoneWithEntry()` because we cannot rely on the latter doing it for us.
  2901. // Indeed, `DoneWithEntry(false)` does not call `DoomActiveEntry()` if either
  2902. // of the following conditions hold:
  2903. //
  2904. // - the transaction uses the cache in read-only mode
  2905. // - the transaction has passed the headers phase and is reading
  2906. //
  2907. // Inconsistent cache entries can cause deterministic failures even in
  2908. // read-only mode, so they should be doomed anyway. They can also be detected
  2909. // during the reading phase in the case of split range requests, since those
  2910. // requests can result in multiple connections being obtained to different
  2911. // remote endpoints.
  2912. cache_->DoomActiveEntry(cache_key_);
  2913. DoneWithEntry(/*entry_is_complete=*/false);
  2914. }
  2915. void HttpCache::Transaction::FixHeadersForHead() {
  2916. if (response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT) {
  2917. response_.headers->RemoveHeader("Content-Range");
  2918. response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK");
  2919. }
  2920. }
  2921. int HttpCache::Transaction::DoSetupEntryForRead() {
  2922. if (network_trans_)
  2923. ResetNetworkTransaction();
  2924. if (!entry_) {
  2925. // Entry got destroyed when twiddling SWR bits.
  2926. TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
  2927. return OK;
  2928. }
  2929. if (partial_) {
  2930. if (truncated_ || is_sparse_ ||
  2931. (!invalid_range_ &&
  2932. (response_.headers->response_code() == net::HTTP_OK ||
  2933. response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT))) {
  2934. // We are going to return the saved response headers to the caller, so
  2935. // we may need to adjust them first. In cases we are handling a range
  2936. // request to a regular entry, we want the response to be a 200 or 206,
  2937. // since others can't really be turned into a 206.
  2938. TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
  2939. return OK;
  2940. } else {
  2941. partial_.reset();
  2942. }
  2943. }
  2944. if (!cache_->IsWritingInProgress(entry_))
  2945. mode_ = READ;
  2946. if (method_ == "HEAD")
  2947. FixHeadersForHead();
  2948. TransitionToState(STATE_FINISH_HEADERS);
  2949. return OK;
  2950. }
  2951. int HttpCache::Transaction::WriteResponseInfoToEntry(
  2952. const HttpResponseInfo& response,
  2953. bool truncated) {
  2954. DCHECK(response.headers);
  2955. if (!entry_)
  2956. return OK;
  2957. net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO);
  2958. // Do not cache content with cert errors. This is to prevent not reporting net
  2959. // errors when loading a resource from the cache. When we load a page over
  2960. // HTTPS with a cert error we show an SSL blocking page. If the user clicks
  2961. // proceed we reload the resource ignoring the errors. The loaded resource is
  2962. // then cached. If that resource is subsequently loaded from the cache, no
  2963. // net error is reported (even though the cert status contains the actual
  2964. // errors) and no SSL blocking page is shown. An alternative would be to
  2965. // reverse-map the cert status to a net error and replay the net error.
  2966. if (IsCertStatusError(response.ssl_info.cert_status) ||
  2967. ShouldDisableCaching(*response.headers)) {
  2968. if (partial_)
  2969. partial_->FixResponseHeaders(response_.headers.get(), true);
  2970. bool stopped = StopCachingImpl(false);
  2971. DCHECK(stopped);
  2972. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
  2973. OK);
  2974. return OK;
  2975. }
  2976. if (truncated)
  2977. DCHECK_EQ(net::HTTP_OK, response.headers->response_code());
  2978. // When writing headers, we normally only write the non-transient headers.
  2979. bool skip_transient_headers = true;
  2980. auto data = base::MakeRefCounted<PickledIOBuffer>();
  2981. response.Persist(data->pickle(), skip_transient_headers, truncated);
  2982. data->Done();
  2983. io_buf_len_ = data->pickle()->size();
  2984. // Summarize some info on cacheability in memory. Don't do it if doomed
  2985. // since then |entry_| isn't definitive for |cache_key_|.
  2986. if (!entry_->doomed) {
  2987. cache_->GetCurrentBackend()->SetEntryInMemoryData(
  2988. cache_key_, ComputeUnusablePerCachingHeaders()
  2989. ? HINT_UNUSABLE_PER_CACHING_HEADERS
  2990. : 0);
  2991. }
  2992. return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
  2993. io_buf_len_, io_callback_, true);
  2994. }
  2995. int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
  2996. if (!entry_)
  2997. return OK;
  2998. net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
  2999. result);
  3000. if (result != io_buf_len_) {
  3001. DLOG(ERROR) << "failed to write response info to cache";
  3002. DoneWithEntry(false);
  3003. }
  3004. return OK;
  3005. }
  3006. bool HttpCache::Transaction::StopCachingImpl(bool success) {
  3007. bool stopped = false;
  3008. // Let writers know so that it doesn't attempt to write to the cache.
  3009. if (InWriters()) {
  3010. stopped = entry_->writers->StopCaching(success /* keep_entry */);
  3011. if (stopped)
  3012. mode_ = NONE;
  3013. } else if (entry_) {
  3014. stopped = true;
  3015. DoneWithEntry(success /* entry_is_complete */);
  3016. }
  3017. return stopped;
  3018. }
  3019. void HttpCache::Transaction::DoneWithEntry(bool entry_is_complete) {
  3020. if (!entry_)
  3021. return;
  3022. cache_->DoneWithEntry(entry_, this, entry_is_complete, partial_ != nullptr);
  3023. entry_ = nullptr;
  3024. mode_ = NONE; // switch to 'pass through' mode
  3025. }
  3026. void HttpCache::Transaction::DoneWithEntryForRestartWithCache() {
  3027. if (!entry_)
  3028. return;
  3029. cache_->DoneWithEntry(entry_, this, /*entry_is_complete=*/true,
  3030. partial_ != nullptr);
  3031. entry_ = nullptr;
  3032. new_entry_ = nullptr;
  3033. }
  3034. int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
  3035. DLOG(ERROR) << "ReadData failed: " << result;
  3036. const int result_for_histogram = std::max(0, -result);
  3037. if (restart) {
  3038. base::UmaHistogramSparse("HttpCache.ReadErrorRestartable",
  3039. result_for_histogram);
  3040. } else {
  3041. base::UmaHistogramSparse("HttpCache.ReadErrorNonRestartable",
  3042. result_for_histogram);
  3043. }
  3044. // Avoid using this entry in the future.
  3045. if (cache_.get())
  3046. cache_->DoomActiveEntry(cache_key_);
  3047. if (restart) {
  3048. DCHECK(!reading_);
  3049. DCHECK(!network_trans_.get());
  3050. // Since we are going to add this to a new entry, not recording histograms
  3051. // or setting mode to NONE at this point by invoking the wrapper
  3052. // DoneWithEntry.
  3053. cache_->DoneWithEntry(entry_, this, true /* entry_is_complete */,
  3054. partial_ != nullptr);
  3055. entry_ = nullptr;
  3056. is_sparse_ = false;
  3057. // It's OK to use PartialData::RestoreHeaders here as |restart| is only set
  3058. // when the HttpResponseInfo couldn't even be read, at which point it's
  3059. // too early for range info in |partial_| to have changed.
  3060. if (partial_)
  3061. partial_->RestoreHeaders(&custom_request_->extra_headers);
  3062. partial_.reset();
  3063. TransitionToState(STATE_GET_BACKEND);
  3064. return OK;
  3065. }
  3066. TransitionToState(STATE_NONE);
  3067. return ERR_CACHE_READ_FAILURE;
  3068. }
  3069. void HttpCache::Transaction::OnCacheLockTimeout(base::TimeTicks start_time) {
  3070. if (entry_lock_waiting_since_ != start_time)
  3071. return;
  3072. DCHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
  3073. next_state_ == STATE_FINISH_HEADERS_COMPLETE);
  3074. if (!cache_)
  3075. return;
  3076. if (next_state_ == STATE_ADD_TO_ENTRY_COMPLETE)
  3077. cache_->RemovePendingTransaction(this);
  3078. else
  3079. DoneWithEntry(false /* entry_is_complete */);
  3080. OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
  3081. }
  3082. void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
  3083. DVLOG(2) << "DoomPartialEntry";
  3084. if (entry_ && !entry_->doomed) {
  3085. int rv = cache_->DoomEntry(cache_key_, nullptr);
  3086. DCHECK_EQ(OK, rv);
  3087. }
  3088. cache_->DoneWithEntry(entry_, this, false /* entry_is_complete */,
  3089. partial_ != nullptr);
  3090. entry_ = nullptr;
  3091. is_sparse_ = false;
  3092. truncated_ = false;
  3093. if (delete_object)
  3094. partial_.reset(nullptr);
  3095. }
  3096. int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
  3097. partial_->OnCacheReadCompleted(result);
  3098. if (result == 0 && mode_ == READ_WRITE) {
  3099. // We need to move on to the next range.
  3100. TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
  3101. } else if (result < 0) {
  3102. return OnCacheReadError(result, false);
  3103. } else {
  3104. TransitionToState(STATE_NONE);
  3105. }
  3106. return result;
  3107. }
  3108. int HttpCache::Transaction::DoRestartPartialRequest() {
  3109. // The stored data cannot be used. Get rid of it and restart this request.
  3110. net_log_.AddEvent(NetLogEventType::HTTP_CACHE_RESTART_PARTIAL_REQUEST);
  3111. // WRITE + Doom + STATE_INIT_ENTRY == STATE_CREATE_ENTRY (without an attempt
  3112. // to Doom the entry again).
  3113. ResetPartialState(!range_requested_);
  3114. // Change mode to WRITE after ResetPartialState as that may have changed the
  3115. // mode to NONE.
  3116. mode_ = WRITE;
  3117. TransitionToState(STATE_CREATE_ENTRY);
  3118. return OK;
  3119. }
  3120. void HttpCache::Transaction::ResetPartialState(bool delete_object) {
  3121. partial_->RestoreHeaders(&custom_request_->extra_headers);
  3122. DoomPartialEntry(delete_object);
  3123. if (!delete_object) {
  3124. // The simplest way to re-initialize partial_ is to create a new object.
  3125. partial_ = std::make_unique<PartialData>();
  3126. // Reset the range header to the original value (http://crbug.com/820599).
  3127. custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
  3128. if (partial_->Init(initial_request_->extra_headers))
  3129. partial_->SetHeaders(custom_request_->extra_headers);
  3130. else
  3131. partial_.reset();
  3132. }
  3133. }
  3134. void HttpCache::Transaction::ResetNetworkTransaction() {
  3135. SaveNetworkTransactionInfo(*network_trans_);
  3136. network_trans_.reset();
  3137. }
  3138. const HttpTransaction* HttpCache::Transaction::network_transaction() const {
  3139. if (network_trans_)
  3140. return network_trans_.get();
  3141. if (InWriters())
  3142. return entry_->writers->network_transaction();
  3143. return nullptr;
  3144. }
  3145. const HttpTransaction*
  3146. HttpCache::Transaction::GetOwnedOrMovedNetworkTransaction() const {
  3147. if (network_trans_)
  3148. return network_trans_.get();
  3149. if (InWriters() && moved_network_transaction_to_writers_)
  3150. return entry_->writers->network_transaction();
  3151. return nullptr;
  3152. }
  3153. HttpTransaction* HttpCache::Transaction::network_transaction() {
  3154. return const_cast<HttpTransaction*>(
  3155. static_cast<const Transaction*>(this)->network_transaction());
  3156. }
  3157. // Histogram data from the end of 2010 show the following distribution of
  3158. // response headers:
  3159. //
  3160. // Content-Length............... 87%
  3161. // Date......................... 98%
  3162. // Last-Modified................ 49%
  3163. // Etag......................... 19%
  3164. // Accept-Ranges: bytes......... 25%
  3165. // Accept-Ranges: none.......... 0.4%
  3166. // Strong Validator............. 50%
  3167. // Strong Validator + ranges.... 24%
  3168. // Strong Validator + CL........ 49%
  3169. //
  3170. bool HttpCache::Transaction::CanResume(bool has_data) {
  3171. // Double check that there is something worth keeping.
  3172. if (has_data && !entry_->GetEntry()->GetDataSize(kResponseContentIndex))
  3173. return false;
  3174. if (method_ != "GET")
  3175. return false;
  3176. // Note that if this is a 206, content-length was already fixed after calling
  3177. // PartialData::ResponseHeadersOK().
  3178. if (response_.headers->GetContentLength() <= 0 ||
  3179. response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
  3180. !response_.headers->HasStrongValidators()) {
  3181. return false;
  3182. }
  3183. return true;
  3184. }
  3185. void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) {
  3186. response_ = response;
  3187. if (response_.headers) {
  3188. DCHECK(request_);
  3189. response_.vary_data.Init(*request_, *response_.headers);
  3190. }
  3191. SyncCacheEntryStatusToResponse();
  3192. }
  3193. void HttpCache::Transaction::SetAuthResponse(
  3194. const HttpResponseInfo& auth_response) {
  3195. auth_response_ = auth_response;
  3196. SyncCacheEntryStatusToResponse();
  3197. }
  3198. void HttpCache::Transaction::UpdateCacheEntryStatus(
  3199. CacheEntryStatus new_cache_entry_status) {
  3200. DCHECK_NE(CacheEntryStatus::ENTRY_UNDEFINED, new_cache_entry_status);
  3201. if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER)
  3202. return;
  3203. DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED ||
  3204. new_cache_entry_status == CacheEntryStatus::ENTRY_OTHER);
  3205. cache_entry_status_ = new_cache_entry_status;
  3206. SyncCacheEntryStatusToResponse();
  3207. }
  3208. void HttpCache::Transaction::SyncCacheEntryStatusToResponse() {
  3209. if (cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED)
  3210. return;
  3211. response_.cache_entry_status = cache_entry_status_;
  3212. if (auth_response_.headers.get()) {
  3213. auth_response_.cache_entry_status = cache_entry_status_;
  3214. }
  3215. }
  3216. void HttpCache::Transaction::RecordHistograms() {
  3217. DCHECK(!recorded_histograms_);
  3218. recorded_histograms_ = true;
  3219. web_fonts_histogram::MaybeRecordCacheStatus(
  3220. cache_entry_status_,
  3221. HttpCache::GetResourceURLFromHttpCacheKey(cache_key_));
  3222. if (CacheEntryStatus::ENTRY_UNDEFINED == cache_entry_status_)
  3223. return;
  3224. if (!cache_.get() || !cache_->GetCurrentBackend() ||
  3225. cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE ||
  3226. cache_->mode() != NORMAL || method_ != "GET") {
  3227. return;
  3228. }
  3229. bool validation_request =
  3230. cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
  3231. cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED;
  3232. bool is_third_party = false;
  3233. // Given that cache_entry_status_ is not ENTRY_UNDEFINED, the request must
  3234. // have started and so request_ should exist.
  3235. DCHECK(request_);
  3236. if (request_->possibly_top_frame_origin) {
  3237. is_third_party =
  3238. !request_->possibly_top_frame_origin->IsSameOriginWith(request_->url);
  3239. }
  3240. std::string mime_type;
  3241. HttpResponseHeaders* response_headers = GetResponseInfo()->headers.get();
  3242. if (response_headers && response_headers->GetMimeType(&mime_type)) {
  3243. // Record the cache pattern by resource type. The type is inferred by
  3244. // response header mime type, which could be incorrect, so this is just an
  3245. // estimate.
  3246. if (mime_type == "text/html" &&
  3247. (effective_load_flags_ & LOAD_MAIN_FRAME_DEPRECATED)) {
  3248. CACHE_STATUS_HISTOGRAMS(".MainFrameHTML");
  3249. } else if (mime_type == "text/html") {
  3250. CACHE_STATUS_HISTOGRAMS(".NonMainFrameHTML");
  3251. } else if (mime_type == "text/css") {
  3252. if (is_third_party) {
  3253. CACHE_STATUS_HISTOGRAMS(".CSSThirdParty");
  3254. }
  3255. CACHE_STATUS_HISTOGRAMS(".CSS");
  3256. } else if (base::StartsWith(mime_type, "image/",
  3257. base::CompareCase::SENSITIVE)) {
  3258. int64_t content_length = response_headers->GetContentLength();
  3259. if (content_length >= 0 && content_length < 100) {
  3260. CACHE_STATUS_HISTOGRAMS(".TinyImage");
  3261. } else if (content_length >= 100) {
  3262. CACHE_STATUS_HISTOGRAMS(".NonTinyImage");
  3263. }
  3264. CACHE_STATUS_HISTOGRAMS(".Image");
  3265. } else if (base::EndsWith(mime_type, "javascript",
  3266. base::CompareCase::SENSITIVE) ||
  3267. base::EndsWith(mime_type, "ecmascript",
  3268. base::CompareCase::SENSITIVE)) {
  3269. if (is_third_party) {
  3270. CACHE_STATUS_HISTOGRAMS(".JavaScriptThirdParty");
  3271. }
  3272. CACHE_STATUS_HISTOGRAMS(".JavaScript");
  3273. } else if (mime_type.find("font") != std::string::npos) {
  3274. if (is_third_party) {
  3275. CACHE_STATUS_HISTOGRAMS(".FontThirdParty");
  3276. }
  3277. CACHE_STATUS_HISTOGRAMS(".Font");
  3278. } else if (base::StartsWith(mime_type, "audio/",
  3279. base::CompareCase::SENSITIVE)) {
  3280. CACHE_STATUS_HISTOGRAMS(".Audio");
  3281. } else if (base::StartsWith(mime_type, "video/",
  3282. base::CompareCase::SENSITIVE)) {
  3283. CACHE_STATUS_HISTOGRAMS(".Video");
  3284. }
  3285. }
  3286. CACHE_STATUS_HISTOGRAMS("");
  3287. if (validation_request) {
  3288. UMA_HISTOGRAM_ENUMERATION("HttpCache.ValidationCause", validation_cause_,
  3289. VALIDATION_CAUSE_MAX);
  3290. }
  3291. if (cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) {
  3292. UMA_HISTOGRAM_ENUMERATION("HttpCache.CantConditionalizeCause",
  3293. validation_cause_, VALIDATION_CAUSE_MAX);
  3294. }
  3295. if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER)
  3296. return;
  3297. DCHECK(!range_requested_) << "Cache entry status " << cache_entry_status_;
  3298. DCHECK(!first_cache_access_since_.is_null());
  3299. base::TimeTicks now = base::TimeTicks::Now();
  3300. base::TimeDelta total_time = now - first_cache_access_since_;
  3301. UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
  3302. bool did_send_request = !send_request_since_.is_null();
  3303. DCHECK(
  3304. (did_send_request &&
  3305. (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
  3306. cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
  3307. cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
  3308. cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)) ||
  3309. (!did_send_request &&
  3310. (cache_entry_status_ == CacheEntryStatus::ENTRY_USED ||
  3311. cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)));
  3312. if (!did_send_request) {
  3313. if (cache_entry_status_ == CacheEntryStatus::ENTRY_USED)
  3314. UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time);
  3315. return;
  3316. }
  3317. base::TimeDelta before_send_time =
  3318. send_request_since_ - first_cache_access_since_;
  3319. base::TimeDelta after_send_time = now - send_request_since_;
  3320. UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time);
  3321. UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
  3322. // TODO(gavinp): Remove or minimize these histograms, particularly the ones
  3323. // below this comment after we have received initial data.
  3324. switch (cache_entry_status_) {
  3325. case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: {
  3326. UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize",
  3327. before_send_time);
  3328. UMA_HISTOGRAM_TIMES("HttpCache.AfterSend.CantConditionalize",
  3329. after_send_time);
  3330. break;
  3331. }
  3332. case CacheEntryStatus::ENTRY_NOT_IN_CACHE: {
  3333. UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
  3334. UMA_HISTOGRAM_TIMES("HttpCache.AfterSend.NotCached", after_send_time);
  3335. break;
  3336. }
  3337. case CacheEntryStatus::ENTRY_VALIDATED: {
  3338. UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
  3339. UMA_HISTOGRAM_TIMES("HttpCache.AfterSend.Validated", after_send_time);
  3340. break;
  3341. }
  3342. case CacheEntryStatus::ENTRY_UPDATED: {
  3343. UMA_HISTOGRAM_TIMES("HttpCache.AfterSend.Updated", after_send_time);
  3344. UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
  3345. break;
  3346. }
  3347. default:
  3348. NOTREACHED();
  3349. }
  3350. }
  3351. bool HttpCache::Transaction::InWriters() const {
  3352. return entry_ && entry_->writers && entry_->writers->HasTransaction(this);
  3353. }
  3354. HttpCache::Transaction::NetworkTransactionInfo::NetworkTransactionInfo() =
  3355. default;
  3356. HttpCache::Transaction::NetworkTransactionInfo::~NetworkTransactionInfo() =
  3357. default;
  3358. void HttpCache::Transaction::SaveNetworkTransactionInfo(
  3359. const HttpTransaction& transaction) {
  3360. DCHECK(!network_transaction_info_.old_network_trans_load_timing);
  3361. LoadTimingInfo load_timing;
  3362. if (transaction.GetLoadTimingInfo(&load_timing)) {
  3363. network_transaction_info_.old_network_trans_load_timing =
  3364. std::make_unique<LoadTimingInfo>(load_timing);
  3365. }
  3366. network_transaction_info_.total_received_bytes +=
  3367. transaction.GetTotalReceivedBytes();
  3368. network_transaction_info_.total_sent_bytes += transaction.GetTotalSentBytes();
  3369. ConnectionAttempts attempts = transaction.GetConnectionAttempts();
  3370. for (const auto& attempt : attempts)
  3371. network_transaction_info_.old_connection_attempts.push_back(attempt);
  3372. network_transaction_info_.old_remote_endpoint = IPEndPoint();
  3373. transaction.GetRemoteEndpoint(&network_transaction_info_.old_remote_endpoint);
  3374. }
  3375. void HttpCache::Transaction::OnIOComplete(int result) {
  3376. DoLoop(result);
  3377. }
  3378. void HttpCache::Transaction::TransitionToState(State state) {
  3379. // Ensure that the state is only set once per Do* state.
  3380. DCHECK(in_do_loop_);
  3381. DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state;
  3382. next_state_ = state;
  3383. }
  3384. bool HttpCache::Transaction::ShouldDisableCaching(
  3385. const HttpResponseHeaders& headers) const {
  3386. // Do not cache no-store content.
  3387. if (headers.HasHeaderValue("cache-control", "no-store")) {
  3388. return true;
  3389. }
  3390. bool disable_caching = false;
  3391. if (base::FeatureList::IsEnabled(
  3392. features::kTurnOffStreamingMediaCachingAlways) ||
  3393. (base::FeatureList::IsEnabled(
  3394. features::kTurnOffStreamingMediaCachingOnBattery) &&
  3395. IsOnBatteryPower())) {
  3396. // If the feature is always enabled or enabled while we're running on
  3397. // battery, and the acquired content is 'large' and not already cached, and
  3398. // we have a MIME type of audio or video, then disable the cache for this
  3399. // response. We based our initial definition of 'large' on the disk cache
  3400. // maximum block size of 16K, which we observed captures the majority of
  3401. // responses from various MSE implementations.
  3402. static constexpr int kMaxContentSize = 4096 * 4;
  3403. std::string mime_type;
  3404. base::CompareCase insensitive_ascii = base::CompareCase::INSENSITIVE_ASCII;
  3405. if (headers.GetContentLength() > kMaxContentSize &&
  3406. headers.response_code() != net::HTTP_NOT_MODIFIED &&
  3407. headers.GetMimeType(&mime_type) &&
  3408. (base::StartsWith(mime_type, "video", insensitive_ascii) ||
  3409. base::StartsWith(mime_type, "audio", insensitive_ascii))) {
  3410. disable_caching = true;
  3411. MediaCacheStatusResponseHistogram(
  3412. MediaResponseCacheType::kMediaResponseTransactionCacheDisabled);
  3413. } else {
  3414. MediaCacheStatusResponseHistogram(
  3415. MediaResponseCacheType::kMediaResponseTransactionCacheEnabled);
  3416. }
  3417. }
  3418. return disable_caching;
  3419. }
  3420. void HttpCache::Transaction::UpdateSecurityHeadersBeforeForwarding() {
  3421. // Because of COEP, we need to add CORP to the 304 of resources that set it
  3422. // previously. It will be blocked in the network service otherwise.
  3423. std::string stored_corp_header;
  3424. response_.headers->GetNormalizedHeader("Cross-Origin-Resource-Policy",
  3425. &stored_corp_header);
  3426. if (!stored_corp_header.empty()) {
  3427. new_response_->headers->SetHeader("Cross-Origin-Resource-Policy",
  3428. stored_corp_header);
  3429. }
  3430. return;
  3431. }
  3432. void HttpCache::Transaction::ChecksumHeaders() {
  3433. DCHECK(use_single_keyed_cache_);
  3434. DCHECK(!checksum_);
  3435. checksum_ = crypto::SecureHash::Create(crypto::SecureHash::SHA256);
  3436. // For efficiency and concision, we list known headers matching a wildcard
  3437. // explicitly rather than doing prefix matching.
  3438. constexpr auto kHeadersToInclude = base::MakeFixedFlatSet<base::StringPiece>({
  3439. "access-control-allow-credentials",
  3440. "access-control-allow-headers",
  3441. "access-control-allow-methods",
  3442. "access-control-allow-origin",
  3443. "access-control-expose-headers",
  3444. "access-control-max-age",
  3445. "access-control-request-headers",
  3446. "access-control-request-method",
  3447. "clear-site-data",
  3448. "content-encoding",
  3449. "content-security-policy",
  3450. "content-type",
  3451. "cross-origin-embedder-policy",
  3452. "cross-origin-opener-policy",
  3453. "cross-origin-resource-policy",
  3454. "location",
  3455. "sec-websocket-accept",
  3456. "sec-websocket-extensions",
  3457. "sec-websocket-key",
  3458. "sec-websocket-protocol",
  3459. "sec-websocket-version",
  3460. "upgrade",
  3461. "vary",
  3462. });
  3463. // Pairs of (lower_case_header_name, header_value).
  3464. std::vector<std::pair<std::string, std::string>> filtered_headers;
  3465. // It's good to set the initial allocation size of the vector to the
  3466. // expected size to avoid a lot of reallocations. This value was chosen as
  3467. // it is a nice round number.
  3468. filtered_headers.reserve(16);
  3469. {
  3470. // Iterate the response headers looking for matches.
  3471. size_t iter = 0;
  3472. std::string name;
  3473. std::string value;
  3474. while (response_.headers->EnumerateHeaderLines(&iter, &name, &value)) {
  3475. std::string lowered_name = base::ToLowerASCII(name);
  3476. if (kHeadersToInclude.contains(lowered_name)) {
  3477. filtered_headers.emplace_back(lowered_name, value);
  3478. }
  3479. }
  3480. }
  3481. std::sort(filtered_headers.begin(), filtered_headers.end());
  3482. for (const auto& [name, value] : filtered_headers) {
  3483. checksum_->Update(name.data(), name.size());
  3484. checksum_->Update(": ", 2);
  3485. checksum_->Update(value.data(), value.size());
  3486. checksum_->Update("\n", 1);
  3487. }
  3488. checksum_->Update("\n", 1);
  3489. }
  3490. bool HttpCache::Transaction::FinishAndCheckChecksum() {
  3491. if (!checksum_)
  3492. return true;
  3493. DCHECK(use_single_keyed_cache_);
  3494. return ResponseChecksumMatches(std::move(checksum_));
  3495. }
  3496. } // namespace net